From: Patrick Franz Date: Sat, 31 Aug 2024 22:24:23 +0000 (+0200) Subject: Import qt6-connectivity_6.7.2.orig.tar.xz X-Git-Tag: archive/raspbian/6.7.2-5+rpi1^2~2 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=9b77ca659c287fd90e2bb40c622e08fa135833e9;p=qt6-connectivity.git Import qt6-connectivity_6.7.2.orig.tar.xz [dgit import orig qt6-connectivity_6.7.2.orig.tar.xz] --- 9b77ca659c287fd90e2bb40c622e08fa135833e9 diff --git a/.QT-ENTERPRISE-LICENSE-AGREEMENT b/.QT-ENTERPRISE-LICENSE-AGREEMENT new file mode 100644 index 0000000..2d225ec --- /dev/null +++ b/.QT-ENTERPRISE-LICENSE-AGREEMENT @@ -0,0 +1,262 @@ +Qt Frame Agreement +Version 2024-02 + +1. PARTIES OF THIS AGREEMENT +1.1. This Qt Frame Agreement—comprised of these general terms together with the appendices attached hereto, (hereinafter “Agreement”) is made by and between: The Qt Company, as defined below (hereinafter ”The Qt Company”) AND Customer name (hereinafter “Customer"):___________________ Business Id (e.g. VAT or EIN number):___________________ +1.2. The parties above are hereinafter individually referred to as a "Party" and collectively as the "Parties". + +2. STRUCTURE AND OBJECT OF THE AGREEMENT +2.1. The Parties have entered into this Agreement to agree on the terms and conditions applicable to The Qt Company's delivery of products and services ("Services") to Customer. +2.2. This Agreement is comprised of the following components: +(i) This Agreement, which contains the general terms applicable to all Services, +(ii) Appendices for each of the Services, containing terms applicable to that individual set of Services ("Service Terms"), +(iii) a Qt Appendix for Pricing, if applicable, which contains pricing for specific Services, and +(iv) other topic-specific appendices, such as Support or Marketing Rights. +2.3. Any and all Services purchased shall be specified in, and agreed upon between, the Parties under a separate purchase order, statement of work, quote, or similar document ("Purchase Document"). Each Purchase Document concluded under this Agreement shall include a reference to this Agreement and be governed by this Agreement. + +3. DEFINITIONS +3.1. "Affiliate" of a Party shall mean an entity (i) which is directly or indirectly controlling such Party; (ii) which is under the same direct or indirect ownership or control as such Party; or (iii) which is directly or indirectly owned or controlled by such Party. For these purposes, an entity shall be treated as being controlled by another if that other entity has fifty percent (50 %) or more of the votes in such entity, is able to direct its affairs and/or to control the composition of its board of directors or equivalent body. +3.2. "Contractor" shall mean third-party consultants, distributors and contractors performing services to Customer under an applicable contractual arrangement. +3.3. "Customer" shall mean the individual or legal entity specified in Section 1 above, that is a Party to this Agreement. +3.4. "Force Majeure Event" shall have the meaning set forth in Section 11.7. +3.5. "Licensed Software" shall mean The Qt Company's commercial software product which is licensed for use by Customer under this Agreement and corresponding Service Terms. Licensed Software shall include, if and to the extent applicable and specified in the applicable relevant Service Terms, corresponding online or electronic documentation, associated media and printed materials, including the source code, and example programs. The Qt Company may in the course of its development activities, at its free and absolute discretion and without any obligation to send or publish any notifications to Customer or in general, make changes, additions or deletions in the components and functionalities of the Licensed Software, provided that no such changes, additions or deletions will affect the already released version of the Licensed Software, but only upcoming version(s). Licensed Software is commercial computer software, developed at private expense and offered to the public under standard commercial terms. +3.6. "Professional Services" shall mean The Qt Company's professional-, consulting-, training- and/or project services delivered to Customer under this Agreement and specified in a Purchase Document. +3.7. "Support" shall mean maintenance and support services provided by The Qt Company to assist Customer in using the Licensed Software, as further specified in the Appendix for Support Terms. +3.8. "The Qt Company" shall mean: +(i) in the event Customer is an entity residing in the United States or a legal entity incorporated in or having its headquarters in the United States, The Qt Company Inc., a Delaware corporation with its office at 3031 Tisch Way, 110 Plaza West, San Jose, CA 95128, USA.; or +(ii) in the event Customer is an entity residing outside of the United States or a legal entity incorporated or having its registered office outside of the United States, The Qt Company Oy., a Finnish company with its registered office at Miestentie 7, 02150 Espoo, Finland. + +4. PRICES AND PAYMENT +4.1. The Qt Company agrees to make Services available to Customer subject to the prices set forth in the Appendix for Pricing. In the event that the Appendix for Pricing does not include a price for certain Services, the applicable price shall be the price agreed by the Parties in the respective Purchase Document. +4.2. All prices are exclusive of value added tax or other taxes, levels, or duties. Value added tax as well as other possible public charges imposed by authorities shall be added to the prices. +4.3. All fees under this Agreement are non-cancellable and non-refundable. +4.4. All fees under this Agreement shall be paid by Customer no later than thirty (30) days from the date of the applicable invoice from The Qt Company. +4.5. Unless otherwise agreed or provided in the respective Service Terms or Purchase Document, The Qt Company will invoice fees for: +4.5.1. Licensed Software and Support in advance upon conclusion of the Purchase Document, and +4.5.2. Professional Services monthly in arrears after the Service has been performed. +4.6. A late payment charge of the lower of: (a) one percent (1%) per month; or (b) the highest interest rate stipulated by applicable law, shall be charged on any unpaid balances that remain past due and which have not been disputed by Customer in good faith within thirty (30) days of receipt of invoice from The Qt Company. +4.7. The Qt Company may either (i) invoice Customer based on existing agreement, (ii) request Customer to place a purchase order corresponding to a quote by The Qt Company, or (iii) use Customer's stored Credit Card information to automatically charge the Customer for the relevant Renewal Term. +4.8. Unless and to the extent otherwise agreed in the Appendix for Pricing or in the Purchase Document, The Qt Company shall be entitled to adjust the prices set forth in the Appendix for Pricing by notifying Customer of the change in writing at least sixty (60) days before the effective date of the change. The change shall not affect the current pricing term of Services agreed upon before the effective date of the change. + +5. CONFIDENTIALITY +5.1. The Parties shall keep confidential, and shall not use or disclose to any unauthorized third parties, the existence and content of this Agreement as well as any Confidential Information received from the other Party or otherwise learned in connection with the Agreement or the performance of the Services, without the prior written consent of the other Party. Confidential Information shall mean information that is designated as confidential or that would be reasonably understood to be confidential given the circumstances of disclosure and the nature of the information. The Parties shall not use Confidential Information received from the other Party for any other purposes than the performance of the Agreement or the fulfilment of their rights and obligations hereunder. +5.2. Each Party shall limit access the other Party's Confidential Information only to those of its employees, subcontractors, Contractors, Affiliates or financial or legal advisors who necessarily need access to the Confidential Information for the proper performance of the Party's rights and obligations under the Agreement. Each Party shall ensure that the persons receiving Confidential Information of the other Party are bound by confidentiality obligations not less restrictive than those stipulated herein. +5.3. Each Party shall protect the confidentiality of the other Party's Confidential Information with at least the same degree of security as it exercises to its own confidential information, but no less than a standard of reasonable care. +5.4. The confidentiality obligation stipulated herein shall not be applied to material and information which: +(iii) has become generally available or otherwise public prior to its submission by the other Party; +(iv) becomes generally available or otherwise public due to a reason other than the negligence or omission of the recipient or its personnel or other actions in violation of this Agreement or applicable legislation; +(v) the Party has lawfully received from a third party without any obligation of confidentiality; +(vi) was lawfully in the possession of the receiving Party prior to receipt of the same from the other Party without any obligation of confidentiality related thereto; +(vii) a Party has developed independently without using material or information received from the other Party; or +(viii) a Party must disclose pursuant to law, decree or other order issued by competent regulatory or governmental body or other public authority or a judicial order, in which case the Party shall, to the extent permitted by applicable law, inform the other Party in writing of the disclosure of information prior to such disclosure. +5.5. Each Party shall, upon request of the other Party at any time, including upon termination, cancellation or expiry of the Agreement, promptly destroy or deliver to the other Party any and all the documents, files, copies and material containing Confidential Information of the other Party. Notwithstanding the foregoing, a Party may retain one copy of the Confidential Information in a secure location, if and solely to the extent required to comply with applicable laws or regulations. Any Confidential Information stored in electronic back-up form shall be rendered inaccessible and destroyed in accordance with standard back-up procedures. + +6. INTELLECTUAL PROPERTY RIGHTS +6.1. Unless and to the extent expressly provided in the respective Service Terms, this Agreement carries no assignment or license to the intellectual property rights of either Party and all such rights are and shall remain the exclusive property of the Party to whom such rights are vested under applicable law at the signing of this Agreement or thereafter. +6.2. Where The Qt Company's delivery includes any materials owned by a third party, such third party materials shall be governed in all respects by the applicable license terms of such third-party right holders. The Qt Company shall duly inform the Customer whenever such third party materials are included in the Services and of applicable license terms to be followed by the Customer in using such third party materials. + +7. FEES AND ORDERING +7.1. Services Fees. Services Fees are described in the Purchase Document. +7.2. Ordering Services. +(i) Customer may purchase Services pursuant to agreed pricing terms or, if no specific pricing terms have been agreed upon, at The Qt Company's standard pricing terms applicable at the time of purchase. +(ii) Unless expressly otherwise agreed, any price or other term quoted to Customer shall only be valid for the thirty (30) days from the date such price has been quoted. + +8. LIMITED WARRANTY AND WARRANTY DISCLAIMER +8.1. The Qt Company hereby represents and warrants that: (i) it has the power and authority to grant the rights and licenses granted to Customer under this Agreement; (ii) the Licensed Software will operate materially in accordance with its specifications (as set forth in the applicable product documentation or, where relevant, program description); (iii) Professional Services and Support will be performed in a professional, workmanlike manner pursuant to the Agreement; and (iv) during the ten years prior to the effective date of this Agreement, there have not been any claims alleging that the Licensed Software has infringed any intellectual property rights of a third party and, to the knowledge of The Qt Company as of the effective date of this Agreement, no such infringement exists. These warranties do not apply to issues arising from, or relating to, any third-party materials or Customer's use of the Licensed Software in violation of applicable law or the terms of this Agreement. +8.2. Except to the extent set forth above, the Services are delivered to Customer "as is" and to the maximum extent permitted by applicable law, exclusive of other warranties, whether express, implied, or otherwise. Customer's sole and exclusive remedy and The Qt Company's entire liability for deficiencies or errors in the Services shall be limited, at The Qt Company's option, to correction of the error, replacement of the Services, re-performance of the Service or return of the applicable fees paid for the defective Service for the time period during which Customer was not able to utilize the Service as agreed. + +9. LIMITATION OF LIABILITY +9.1. EXCEPT FOR (I) CASES OF GROSS NEGLIGENCE OR INTENTIONAL MISCONDUCT, (II) A BREACH OR VIOLATION OF THE OTHER PARTY'S INTELLECTUAL PROPERTY RIGHTS, OR (III) WHERE REQUIRED BY APPLICABLE LAW, IN NO EVENT SHALL EITHER PARTY BE LIABLE TO THE OTHER PARTY FOR ANY LOST PROFITS, LOSS OF DATA, LOSS OF BUSINESS OR GOODWILL OR ANY OTHER INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE COST, DAMAGES OR EXPENSE OF ANY KIND, HOWSOEVER ARISING UNDER OR IN CONNECTION WITH THIS AGREEMENT. +9.2. EXCEPT FOR (I) CASES OF GROSS NEGLIGENCE OR INTENTIONAL MISCONDUCT, (II) A BREACH OR VIOLATION OF THE OTHER PARTY'S INTELLECTUAL PROPERTY RIGHTS, AND TO THE EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL EITHER PARTY'S TOTAL AGGREGATE LIABILITY UNDER THIS AGREEMENT EXCEED THE AGGREGATE FEES PAID OR PAYABLE TO THE QT COMPANY BY CUSTOMER FOR THE RESPECTIVE LICENSED SOFTWARE OR SERVICE GIVING RISE TO THE LIABILITY. THE FOREGOING LIMITATION WILL NOT APPLY TO CUSTOMER'S OBLIGATION TO PAY THE APPLICABLE FEES CORRESPONDING TO ITS ACTUAL USE OF LICENSED SOFTWARE OR SERVICES. + +10. TERM AND TERMINATION +10.1. This Agreement shall enter into force upon signing by both Parties and is effective as of the last date of signature. +10.2. This Agreement shall remain in force until further notice and may be terminated without cause by either Party by no less than three (3) months' prior written notice to the other Party. +10.3. Termination of a particular Purchase Document and the Services governed thereunder shall be stipulated under the applicable Service Terms. +10.4. Either Party may terminate this Agreement with immediate effect, if the other Party: +(i) commits a material breach of the terms of this Agreement (including applicable Service Terms) and has not remedied such breach within a reasonable period of time (which shall be no less than thirty (30) days) of the non-breaching Party's written notice specifying the breach, or +(ii) becomes bankrupt, insolvent or goes into liquidation or debt restructuring. +10.5. Termination of this Agreement shall, as such, have no effect on the validity of any Services ordered and agreed prior to the effective date of such termination, and such Services shall continue to remain in force pursuant to applicable Service Terms (including the terms of this Agreement) for the remainder of the duration of the applicable Service validity term. + +11. GOVERNING LAW AND DISPUTE RESOLUTION +11.1. The United Nations Convention on Contracts for the International Sale of Goods will not apply to this Agreement. +11.2. Where this Agreement is concluded with The Qt Company, Inc., a Delaware corporation, the Parties agree that this Section 10.2 will apply. This Agreement will be governed by, and construed in accordance with the laws of the State of California and any controlling United States federal law. Any dispute, controversy or claim arising out of or relating to this contract, including the formation, interpretation, breach or termination thereof, and whether the claims asserted are arbitrable, will be referred to and finally determined by arbitration in accordance with the JAMS International Arbitration Rules. The tribunal will consist of one arbitrator. The place of arbitration will be San Francisco, California, USA. The language to be used in the arbitral proceedings will be English. Judgment upon the award rendered by the arbitrator(s) may be entered in any court having jurisdiction thereof. This Section 10.2 shall not preclude parties from seeking provisional remedies in aid of arbitration from a court of appropriate jurisdiction. Notwithstanding the foregoing, any action by The Qt Company solely to collect license or other fees hereunder may be brought in any court of competent jurisdiction. +11.3. Where this Agreement is concluded with The Qt Company, Oy., a Finnish company, the parties agree that this Section 10.3 will apply. This Agreement shall be construed and interpreted in accordance with the laws of Finland, excluding its choice of law provisions. All disputes arising out of or in connection with this Agreement shall be finally settled in accordance with the laws of Finland, excluding its choice of law provisions. All disputes arising out of or in connection with this Agreement shall be finally settled under the Rules of Arbitration of the International Chamber of Commerce by one or more arbitrators appointed in accordance with the said Rules. The place of arbitration will be Helsinki, Finland. The language to be used in arbitral proceedings will be English. This Section 10.3 shall not preclude parties from seeking provisional remedies in aid of arbitration from a court of appropriate jurisdiction. + +12. MISCELLANOUS +12.1. No Assignment. Customer shall not be entitled to assign or transfer all or any of its rights, benefits and obligations under this Agreement except in case of sale of relevant business or assets or otherwise with prior written consent of The Qt Company, which shall not be unreasonably withheld or delayed. The Qt Company shall be entitled to freely assign or transfer any of its rights, benefits or obligations under this Agreement. +12.2. Surviving Sections. Any terms and conditions that by their nature or otherwise reasonably should survive termination of this Agreement shall so be deemed to survive. +12.3. Entire Agreement. This Agreement, its Appendices and any applicable Purchase Documents constitute the complete agreement between the Parties and supersedes all prior or contemporaneous discussions, representations, contracts (including prior License Agreements and similar prior agreements), and proposals, written or oral, with respect to the subject matters discussed herein. +12.4. Subcontractors. The Qt Company may utilize subcontractors in the performance of Services under this Agreement, provided that The Qt Company remains responsible for the performance of the Services and compliance with this Agreement, as well as ensuring that subcontractors are required to abide by relevant restrictions (e.g., confidentiality) set forth in this Agreement. +12.5. Modifications. No modification of this Agreement shall be effective unless contained in a writing executed by an authorized representative of each Party. No standard terms and conditions or provisions of any Customer purchase order or other ordering form that Customer may use in connection with the acquisition of Services will modify or affect this Agreement, the parties agree that any such terms and conditions are void with no legal effect. +12.6. Affiliate Orders. Customer Affiliates may purchase Services via this Agreement as follows: +(i) any purchases by Customer Affiliates from The Qt Company or its Affiliates will create a contractual relationship directly between the relevant The Qt Company entity and the respective ordering Customer Affiliate; +(ii) the entry into a Purchase Document between The Qt Company and Customer Affiliate creates an agreement between The Qt Company and Customer Affiliate and incorporates all terms and conditions of this Agreement as the governing agreement between The Qt Company and Customer Affiliate ("Accession Agreement"): and +(iii) Customer Affiliate will be deemed "Customer" under the terms of this Agreement and all rights and obligations under such Accession Agreement are vested and borne solely by the ordering Customer Affiliate and the relevant The Qt Company entity as contracting parties under such Accession Agreement. +12.7. Force Majeure. Neither Party shall be liable to the other for any delay or non-performance of its obligations hereunder in the event and to the extent that such delay or non-performance is due to an event of act of God, terrorist attack or other similar unforeseeable catastrophic event that prevents either Party for fulfilling its obligations under this Agreement and which such Party cannot avoid or circumvent ("Force Majeure Event"). If the Force Majeure Event results in a delay or non-performance of a Party for a period of three (3) months or longer, then either Party shall have the right to terminate the relevant Purchase Document and Services thereunder with immediate effect without any liability (except for the obligations of payment arising prior to the Force Majeure Event) towards the other Party. +12.8. Notices. Any notice given by one Party to the other shall be deemed properly given and deemed received if specifically acknowledged by the receiving Party in writing or when successfully delivered to the recipient by hand, fax, or special courier during normal business hours on a business day to the addresses specified for each Party in this Agreement. Each communication and document made or delivered by one Party to the other Party pursuant to this Agreement shall be in the English language. +12.9. Attorney Fees. The prevailing Party in any action to enforce this Agreement shall be entitled to recover its attorney's fees and costs in connection with such action. +12.10. Privacy and Security. The Parties commit to and comply with their respective applicable obligations under the privacy and security terms set forth in the Privacy and Security Appendix and relevant Appendices attached hereto. +12.11. Feedback. Customer agrees that, from time to time, The Qt Company, may request feedback from Customer regarding the Services ("Feedback"). Customer may choose to provide Feedback and agrees that The Qt Company may freely use, copy, disclose, and exploit any Feedback. No Feedback will be considered Customer Confidential Information unless explicitly agreed otherwise between the Parties. +12.12. Export Control. Customer acknowledges that the Services, or portions thereof, may be subject to export control restrictions under the applicable laws of respective countries. Customer shall fully comply with all applicable export license restrictions and requirements, economic sanctions restrictions, as well as with all laws and regulations relating thereto, and shall procure all necessary governmental authorizations, including without limitation, all necessary licenses, approvals, permissions, or consents, where necessary (e.g., for re-exportation of the Redistributables, Applications and/or Devices, each as defined in the relevant Service Terms). +12.13. Severability. If any provision of this Agreement shall be adjudged by any court of competent jurisdiction to be unenforceable or invalid, that provision shall be limited or eliminated to the minimum extent necessary so that this Agreement shall otherwise remain in full force and effect and enforceable. + +13. APPENDICES +13.1. The following appendices form an integral part of this Agreement. In case of a discrepancy between this Agreement and any of its Appendices, this Agreement shall prevail. In case of discrepancies between the Purchase Document(s) and this Agreement or applicable Service Terms, the terms of this Agreement or the applicable Service Terms shall prevail, except in cases where an express deliberate deviation from the terms of this Agreement or applicable Service Terms has been concluded pursuant to Section 2.3 hereof, in which case the Purchase Document shall prevail. +1. Appendix for Qt Development Framework +2. Appendix for Support Terms https://www.qt.io/terms-conditions/support-terms +3. Appendix for Privacy and Security Terms https://www.qt.io/terms-conditions/privacy-and-security + +Appendix for Qt Development Framework +Version 2024-02 + +1. This Appendix for Qt Development Framework is an integral part of the Agreement and specifies the legal terms for the licensing of Licensed Software (as defined below) between The Qt Company and the Customer. Entry into this Appendix governs the use of and supersedes any prior contracts between the Parties (including prior License Agreements and similar prior agreements), with respect to the Licensed Software under this Appendix. + +2. DEFINITIONS +2.1. Capitalized words used in this Appendix shall have the meanings described in the Agreement or as defined below. +2.2. "Add-on Products" shall mean The Qt Company's specific add-on software products which are not licensed as part of The Qt Company's standard Services offerings, but shall be included into the scope of Licensed Software only if so specifically agreed between the Parties. +2.3. "Application" means software products created using the Licensed Software, which include the Redistributables, or part thereof. +2.4. "End Customer" shall mean Customer's customer(s) to whom Customer, directly or indirectly, distributes copies of the Redistributables as integrated or incorporated into Applications or Devices. +2.5. "Data Protection Legislation" shall mean the General Data Protection Regulation (EU 2016/679) (GDPR) and any national implementing laws, regulations and secondary legislation, as may be amended or updated from time to time, as well as any other data protection laws or regulations applicable in the relevant territory. +2.6. "Deployment Platforms" shall mean target operating systems and/or hardware specified in the License Certificate, on which the Redistributables can be distributed pursuant to the terms and conditions of this Appendix. +2.7. "Designated User(s)" shall mean the employee(s) of Customer or Customer's Affiliates acting within the scope of their employment or Customer's Contractors acting within the scope of their services on behalf of Customer. +2.8. "Development License" shall mean the license needed by the Customer for each Designated User to use Licensed Software under the license grant described in Section 5 of this Appendix. Development Licenses are available per respective Licensed Software products; each product having its designated scope and purpose of use. +2.9. "Development Platforms" shall mean the host operating system(s) specified in the License Certificate, on which Licensed Software can be used under the Development License. +2.10. "Devices" shall mean +(i) hardware devices or products that +a. are manufactured and/or distributed by the Customer, its Affiliates, Contractors or End Customer, and +b. incorporate, integrate or link to Applications such that substantial functionality of such unit, when used by an End User, is provided by Application(s) or otherwise depends on the Licensed Software; or +(ii) Applications designed for the hardware devices specified in item (i). +Devices covered by this Appendix shall be specified in the Pricing Appendix or Purchase Document. +2.11. "Distribution License(s)" shall mean a royalty-bearing license required for any kind of sale, trade, exchange, loan, lease, rental or other distribution by or on behalf of Customer to a third party of Redistributables in connection with Devices pursuant to license grant described in Section 5.3 of this Appendix. Distribution Licenses are sold separately for each type of Device respectively and cannot be used for any other type of Devices. +2.12. "Distribution License Packs" shall mean set of prepaid Distribution Licenses for distribution of Redistributables, as defined in The Qt Company's standard price list, quote, Pricing Appendix or in the Purchase Document, as applicable. +2.13. "Evaluation License Term" shall mean a time period specified in the License Certificate for the Customer to use the relevant Licensed Software for evaluation purposes according to Section 5.6 of this Appendix. +2.14. "Intellectual Property Rights" shall mean patents (including utility models), design patents, and designs (whether or not capable of registration), chip topography rights and other like protection, copyrights, trademarks, service marks, trade names, logos or other words or symbols and any other form of statutory protection of any kind and applications for any of the foregoing as well as any trade secrets. +2.15. "License Certificate" shall mean a certificate generated by The Qt Company for each Designated User respectively upon their download of the Licensed Software, which will be available under the respective Designated User's Qt Account at account.qt.io. License Certificates will specify relevant information pertaining to the Licensed Software purchased by Customer and the license to the Licensed Software. +2.16. "License Fee" shall mean the fee charged to Customer for rights granted under this Appendix. +2.17. "Licensed Software" shall mean the specified product(s) of Qt Software which Customer has purchased and which is provided to Customer under the terms of this Appendix (including its Exhibits). Licensed Software shall include corresponding online or electronic documentation, associated media and printed materials, including source code (where applicable), example programs and the documentation. Licensed Software does not include Third Party Software (as defined in Section 6) or Qt Community Edition. The Qt Company may, in the course of its development activities, at its free and absolute discretion and without any obligation to send or publish any notifications to Customer or in general, make changes, additions or deletions in the components and functionalities of the Licensed Software, provided that no such changes, additions or deletions will affect the already released version of the Licensed Software, but only upcoming version(s). +2.18. "License Term" shall mean the agreed validity period of the Development License during which the relevant Licensed Software product can be used pursuant to this Appendix. The agreed License Term, as ordered and paid for by Customer, shall be memorialized in the applicable License Certificate. +2.19. "Customer's Records" shall mean books and records that contain information bearing on Customer's compliance with the Agreement, Customer's use of Qt Community Edition and/or the payments due to The Qt Company under the Agreement, including, but not limited to user information, assembly logs, sales records and distribution records. +2.20. "Modified Software" shall have the meaning as set forth below in Section 4. +2.21. "Qt Software" shall mean the development and design software of The Qt Company, which The Qt Company makes available under commercial and/or open source licenses as either the "Licensed Software" or the "Qt Community Edition". +2.22. "Permitted Software" shall mean third party products that are generally available to the public, which may include parts of Qt Community Edition or be developed using Qt Community Edition. +2.23. "Pre-Release Code" shall have the meaning as set forth in Section 7. +2.24. "Prohibited Combination" shall mean any effort to use, combine, incorporate, link or integrate Licensed Software with any software created with or incorporating Qt Community Edition, or use Licensed Software for creation of any such software. +2.25. "Qt Community Edition" shall mean the open source version of Qt Software available under the terms of the GNU Lesser General Public License, version 2.1 or later ("LGPL") or the GNU General Public License, version 2.0 or later ("GPL"). For clarity, Qt Community Edition shall not be provided, governed or used under this Appendix. +2.26. "Redistributables" shall mean the portions of Licensed Software as set forth in Exhibit 1 hereto that may be distributed pursuant to this Appendix in object code form only, including any relevant documentation. Where relevant, any reference to Licensed Software in this Appendix includes and refers to Redistributables. +2.27. "Renewal Term" shall mean an extension of the previous License Term as agreed between the Parties. +2.28. "Submitted Modified Software" shall have the meaning as set forth in Section 4.2 of this Appendix. +2.29. "Third-Party Software" shall have the meaning set forth in Section 6 of this Appendix. +2.30. "Updates" shall mean a release or version of the Licensed Software containing bug fixes, error corrections and other changes that are generally made available to users of the Licensed Software that have contracted for Support. Updates are generally depicted as a change to the digits following the decimal in the Licensed Software version number. The Qt Company shall make Updates available to Customer under the Support. Updates shall be considered as part of the Licensed Software hereunder. +2.31. "Upgrades" shall mean a release or version of the Licensed Software containing enhancements and new features and are generally depicted as a change to the first digit of the Licensed Software version number. In the event that Upgrades are provided to Customer under this Appendix, they shall be considered as part of the Licensed Software hereunder. + +3. OWNERSHIP +3.1. Ownership of The Qt Company +3.1.1. The Licensed Software is protected by copyright laws and international copyright treaties, as well as other intellectual property laws and treaties. The Licensed Software is licensed, not sold. +3.1.2. All of The Qt Company's Intellectual Property Rights are and shall remain the exclusive property of The Qt Company or its respective licensors . No rights to The Qt Company's Intellectual Property Rights are assigned or granted to Customer under this Appendix, except when and to the extent expressly specified herein. +3.2. Ownership of Customer +3.2.1. All of Customer's Intellectual Property Rights are and shall remain the exclusive property of Customer or its licensors respectively. +3.2.2. Except to the extent set forth in this Appendix, all Intellectual Property Rights to the Modified Software, Applications and Devices (except to Redistributables included therein) shall remain with Customer. + +4. MODIFIED SOFTWARE +4.1. Customer may create bug-fixes, error corrections, patches or modifications to the Licensed Software ("Modified Software"). To the extent that Customer's Modified Software breaks source or binary compatibility or other functionality with the Licensed Software, Customer acknowledges that The Qt Company's ability to provide Support may be prevented or limited and Customer's ability to make use of Updates may be restricted. +4.2. Customer may, at its sole and absolute discretion, choose to submit Modified Software to The Qt Company ("Submitted Modified Software") in connection with Customer's Support request, service request or otherwise. In the event Customer does so, then, Customer hereby grants The Qt Company a sublicensable, assignable, irrevocable, perpetual, worldwide, non-exclusive, royalty-free and fully paid-up license, under all of Customer's Intellectual Property Rights, to reproduce, adapt, translate, modify, and prepare derivative works of, publicly display, publicly perform, sublicense, make available and distribute such Submitted Modified Software as The Qt Company sees fit at its free and absolute discretion. + +5. LICENSES GRANTED +5.1. Development with Licensed Software +5.1.1. Subject to the terms of the Agreement, The Qt Company grants to Customer a worldwide, non-exclusive, non-transferable license, valid for each License Term, to use, modify and copy the Licensed Software by Designated Users on the Development Platforms for the sole purposes of designing, developing, demonstrating and testing Application(s) and/or Devices, and to provide support and other services related to such Applications and Devices to End Customers. Each Application and/or Device can only include, incorporate or integrate contributions by such Designated Users who are duly licensed for the applicable Development Platform(s) and Deployment Platform(s) (i.e have a valid license for the appropriate Licensed Software product and only use one type of Qt Development License per Customer Application and/or Device(s)). +5.1.2. Customer may install copies of the Licensed Software on five (5) computers per Designated User, provided that only Designated Users who have a valid Development License may use the Licensed Software. +5.1.3. Customer may designate another Designated User to replace a then-current Designated User by notifying The Qt Company in writing, where such replacement is due to termination of employment, long-term absence or other permanent reason affecting Designated User's need for Licensed Software. +5.1.4. Upon expiry of the initially agreed License Term, the respective License Term shall be automatically extended by one or more Renewal Term(s), unless and until either Party notifies the other Party in writing, that it does not wish to continue the License Term, such notification to be provided to the other Party no less than thirty (30) days before expiry of the respective License Term. The Qt Company shall, in good time before the due date for the above notification, remind the Customer on the coming Renewal Term. Unless otherwise agreed between the Parties, Renewal Term shall be equal to the length of the previous License Term, but no longer than thirty-six (36) months. +5.1.5. Any such Renewal Term shall be subject to License Fees agreed between the Parties or, if no advance agreement exists, subject to The Qt Company's standard list pricing applicable at the commencement date of any such Renewal Term. +5.2. Distribution of Applications +5.2.1. Subject to the terms of the Agreement, The Qt Company grants to Customer a worldwide, non-exclusive, non-transferable, perpetual, royalty-free and revocable (only for Customer’s material breach of agreement) right and license to: +(i) distribute, by itself or through its Contractors, Redistributables as installed, incorporated or integrated into Applications for execution on the Deployment Platforms; and +(ii) grant perpetual and irrevocable sublicenses to Redistributables, as distributed hereunder, for End Customers solely to the extent necessary in order for the End Customers to use the Applications for their respective intended purposes. +5.2.2. Right to distribute the Redistributables as part of an Application as provided herein is not royalty-bearing but is conditional upon the Application having been created, updated and maintained under a valid and duly paid Development License. +5.3. Distribution of Devices +5.3.1. Subject to the terms of the Agreement, The Qt Company grants to Customer a worldwide, non-exclusive, non-transferable, perpetual, revocable (only for Customer’s material breach of agreement), royalty-bearing right and license to: +(i) distribute, by itself or through one or more tiers of Contractors, Redistributables as installed, incorporated or integrated, or intended to be installed, incorporated or integrated into Devices for execution on the Deployment Platforms; and +(ii) grant perpetual and irrevocable sublicenses to Redistributables, as distributed hereunder, for End Customers solely to the extent necessary in order for the End Customers to use the Devices for their respective intended purposes. +5.3.2. Right to distribute the Devices as provided herein is conditional upon (i) the Devices having been created, updated and maintained under a valid and duly paid Development License, and (ii) Customer having acquired corresponding Distribution Licenses at the time of distribution of any Devices to End Customers. +5.4. Further Requirements +5.4.1. The licenses granted in this Section 5 by The Qt Company to Customer are conditional and subject to Customer's compliance with the following terms: +(i) Customer acknowledges that The Qt Company has separate products for the purpose of Applications and Devices respectively, where development and distribution of Devices is only allowed using the correct designated product. Customer shall ensure and bear the burden of proof that Customer is using a correct product entitling Customer to development and distribution of Devices; +(ii) Customer shall not remove or alter any copyright, trademark or other proprietary rights notice(s) contained in any portion of the Licensed Software; +(iii) Applications must add primary and substantial functionality to Licensed Software so as not to compete with the Licensed Software; +(iv) Applications may not pass on functionality which in any way makes it possible for others to create software with Licensed Software; provided however that Customer may use Licensed Software’s scripting and QML ("Qt Quick") functionality solely in order to enable scripting, themes and styles that augment the functionality and appearance of the Application(s) without adding primary and substantial functionality to the Application(s); +(v) Customer shall not use Licensed Software in any manner or for any purpose that infringes, misappropriates or otherwise violates any Intellectual Property Right or right of any third party, or that violates any applicable law; +(vi) Customer shall not use The Qt Company's or any of its suppliers' names, logos, or trademarks to market Applications, except that Customer may use “Built with Qt” logo to indicate that an Application or Device was developed using Licensed Software; +(vii) Customer shall not distribute, sublicense or disclose source code of Licensed Software to any third party (provided however that Customer may appoint employee(s) of Contractors and Affiliates as Designated Users to use Licensed Software pursuant to this Appendix). +(viii) Customer shall not grant the End Customers a right to: (a) make copies of the Redistributables except when and to the extent required to use the Applications and/or Devices for their intended purpose; (b) modify the Redistributables or create derivative works thereof; (c) decompile, disassemble or otherwise reverse engineer Redistributables; or (d) redistribute any copy or portion of the Redistributables to any third party, except as part of the onward sale of the Application or Device on which the Redistributables are installed; +(ix) Customer shall not, and shall cause that its Affiliates or Contractors shall not, use Licensed Software in any Prohibited Combination, unless Customer has received specific advance written permission from The Qt Company to do so. Absent such written permission, any and all distribution by Customer during the term of the Agreement of a hardware device or product: a) which incorporates or integrates any part of Licensed Software or Qt Community Edition; or b) where substantial functionality is provided by software built with Licensed Software or Qt Community Edition or otherwise depends on Licensed Software or Qt Community Edition, shall be considered to be Device distribution under this Appendix and shall be dependent on Customer’s compliance thereof (including but not limited to the obligation to pay applicable License Fees for such distribution). Notwithstanding the foregoing, Customer is entitled to use and combine Licensed Software with Permitted Software; +(x) Customer shall cause all of its Affiliates, Contractors and End Customer entitled to make use of the licenses granted under this Appendix, to be contractually bound to comply with the relevant terms hereof and not to use the Licensed Software beyond the terms hereof nor for any purposes other than operating within the scope of their services for Customer. Customer shall be responsible for any and all actions and omissions of its Affiliates, Contractors, and End Customers relating to the Licensed Software and use thereof (including but not limited to payment of all applicable License Fees); +(xi) Except when and to the extent explicitly provided in this Section 5, Customer shall not transfer, publish, disclose, display or otherwise make available the Licensed Software; and +(xii) Customer shall not attempt or enlist a third party to conduct or attempt to conduct any of the above. +5.4.2. The above terms shall not be applicable if and solely to the extent they conflict with any mandatory provisions of applicable laws. +5.4.3. Any use of Licensed Software beyond the provisions of this Appendix is strictly prohibited and requires, at a minimum an additional license from The Qt Company (e.g. certain additional rights granted under software development kit “SDK” agreement with regard to limitations of Section 5.4.1 iv, vii or viii). +5.5. Evaluation License +5.5.1. Subject to the terms of this Appendix, The Qt Company grants to Customer a worldwide, non-exclusive, non-transferable license, valid for the Evaluation License Term to use the relevant Licensed Software product solely for Customer’s internal use to evaluate and determine whether the Licensed Software meets Customer's business requirements, specifically excluding any commercial use of the Licensed Software or any derived work thereof. +5.5.2. Upon the expiry of the Evaluation License Term, Customer must either discontinue use of the relevant Licensed Software or acquire a commercial Development License specified herein. + +6. THIRD-PARTY SOFTWARE. The Licensed Software may provide links or access to third party libraries or code (collectively "Third-Party Software") to implement various functions. Third-Party Software does not, however, comprise part of the Licensed Software, but is provided to Customer complimentary and use thereof is discretionary for Customer. Third-Party Software will be listed in the ".../src/3rdparty" source tree delivered with the Licensed Software or documented in the Licensed Software, as such may be amended from time to time. Customer acknowledges that use or distribution of Third-Party Software is in all respects subject to applicable license terms of applicable third-party right holders. + +7. PRE-RELEASE CODE +7.1. The Licensed Software may contain pre-release code and functionality, or sample code marked or otherwise stated with appropriate designation such as "Technology Preview", "Alpha", "Beta", "Experimental", "Sample", "Example" etc. ("Pre-Release Code"). +7.2. Such Pre-Release Code may be provided complimentary for Customer, in order to provide experimental support or information for new platforms or preliminary versions of one or more new functionalities, or for other similar reasons. Pre-Release Code may not be at the level of performance and compatibility of a final, generally available, product offering. Pre-Release Code may not operate correctly, may contain errors and may be substantially modified by The Qt Company prior to a commercial product release, if any. The Qt Company is under no obligation to make Pre-Release Code commercially available, or provide any Support or Updates relating thereto. To the maximum extent permitted by law, the Qt Company assumes no liability whatsoever regarding any Pre-Release Code and any use thereof is exclusively at Customer's own risk and expense. +7.3. Unless Licensed Software specifies different license terms for the respective Pre-Release Code, Customer is entitled to use such pre-release code pursuant to Section 5 of this Appendix, just like other Licensed Software. + +8. SUPPORT. Support is provided according to agreed support level and subject to applicable requirements and restrictions, as specified in the Appendix for Support Terms. + +9. FEES AND ORDERING: DISTRIBUTION LICENSES +9.1. Distribution License Packs +9.1.1. Unless otherwise agreed in writing, Distribution Licenses shall be purchased by way of Distribution License Packs. +9.1.2. Upon due payment of the ordered Distribution License Pack(s), Customer will have an account of Distribution Licenses available for distributing the Redistributables in accordance with this Agreement. +9.2. Each time Customer distributes a copy of Redistributables, one Distribution License is used and Customer's account of available Distribution Licenses is decreased accordingly. +9.3. Customer may distribute copies of the Redistributables so long as Customer has Distribution Licenses remaining on its account. + +10. RECORD-KEEPING AND REPORTING OBLIGATIONS; AUDIT RIGHTS +10.1. Customer's Record-keeping +10.1.1. Customer shall at all times during the term of the Agreement or validity of any of the licenses hereunder, whichever is later, and for a period of two (2) years thereafter, maintain Customer's Records in an accurate and up-to-date form. Customer's Records shall be adequate to reasonably enable The Qt Company to determine Customer's compliance with the provisions of the Agreement. The records shall conform to general good accounting practices. +10.1.2. Customer shall, within thirty (30) days from receiving The Qt Company's request to that effect, deliver to The Qt Company a report based on Customer's Records, such report to contain information, in sufficient detail, on: (i) number and identity of users working with Licensed Software or Qt Community Edition, (ii) copies of Redistributables distributed by Customer during the most recent calendar quarter and/or any other term specified by The Qt Company, and (iii) any other information pertaining to Customer's compliance with the terms of the Agreement (e.g. information on products and/or projects relating to use of Distribution Licenses), as The Qt Company may reasonably require from time to time. +10.2. The Qt Company's Audit Rights +10.2.1. The Qt Company or an independent auditor acting on behalf of The Qt Company may, upon at least thirty (30) days' prior written notice and at The Qt Company expense, audit Customer with respect to Customer's use of the Licensed Software, but not more frequently than once during each six (6) month period. Such audit may be conducted by mail, electronic means or through an in-person visit to Customer's place of business. Any possible in-person audit shall be conducted during regular business hours at Customer's facilities, shall not unreasonably interfere with Customer's business activities and shall be limited in scope to verify Customer's compliance with the terms of the Agreement. The Qt Company or its independent auditor shall be entitled to inspect Customer's Records and conduct necessary interviews of Customer's relevant employees and Contractors. All Customer's Records and use thereof shall be subject to the obligation of confidentiality under the Agreement. +10.2.2. If an audit reveals that Customer is using the Licensed Software beyond scope of the licenses Customer has paid for, Customer shall pay to The Qt Company any amounts owed for such unauthorized use within thirty (30) days from receipt of the corresponding invoice from The Qt Company. +10.2.3. In addition, in the event the audit reveals a material violation of the terms of the Agreement (without limitation, either (i) underpayment of more than 10% of License Fees or 10,000 euros (whichever is more) or (ii) distribution of products, which include or result from Prohibited Combination, shall be deemed a material violation for purposes of this section), then Customer shall pay The Qt Company's reasonable cost of conducting such audit. + +11. TERMINATION +11.1. Termination of Licenses +11.1.1. The Qt Company may terminate Customer's rights to any and all Licensed Software (including access to Support), if Customer: +(i) commits a material breach of the Agreement (including this Appendix) and has not remedied the breach within a reasonable period of time (which shall be no less than 30 days) of The Qt Company's written notice specifying the breach, or +(ii) becomes bankrupt, insolvent or goes into liquidation or debt restructuring. +11.2. Suspension of rights: Instead of termination, The Qt Company reserves the right to suspend or withhold grants of any and all rights to the Licensed Software (including Support), should Customer fail to make payment in timely fashion or otherwise violate or is reasonably suspected of violating its obligations under the Agreement and/or this Appendix, and where such violation or breach is not cured within ten (10) business days following The Qt Company's written notice thereof. +11.3. Parties Rights and Duties upon Termination +11.3.1. Upon expiry or termination of the Development Licenses, Customer shall cease and shall cause all Designated Users (including those of its Affiliates' and Contractors') to cease using the relevant Licensed Software. +11.3.2. Upon such expiry or termination of Development Licenses, Customer shall destroy or return to The Qt Company all copies of the respective Licensed Software and all related materials and will certify the same by Customer's duly authorized officer to The Qt Company upon its request, provided however that Customer may retain and utilize such copies of the Licensed Software to the extent required to provide Customer's continued support to End Customers, for archiving purposes or as is required under applicable law. +11.3.3. Distribution Licenses are perpetual and, therefore, Customer's distribution rights hereunder shall only terminate upon The Qt Company's termination of Distribution Licenses due to Customer's material breach as set forth in Section 11.1.1(i) of this Appendix. In case of such termination by The Qt Company due to Customer's material breach, Customer must cease any distribution of Applications and Devices at the effective date of termination. +11.3.4. Expiry or termination of any of Customer's licenses hereunder for any reason whatsoever shall not: +(i) relieve Customer of its obligation to pay any License Fees accrued or payable to The Qt Company prior to the effective date of termination, and Customer pay to The Qt Company all such fees within 30 days from the effective date of termination of the licenses; +(ii) relieve Customer of its obligation to ensure that Applications and Devices (including those already distributed) remain in compliance with the terms of the Agreement; nor +(iii) affect any rights of End Customer to continue use of Applications and Devices (and therein incorporated Redistributables). +11.4. Extension of Rights under Special Circumstances. In the event that, during the applicable License Term, The Qt Company is declared bankrupt under a final, non-cancellable decision by relevant court of law, and the Agreement is not, at the date of expiry of the Development License(s), assigned to a party who has assumed The Qt Company's position as a legitimate licensor of Licensed Software under the Agreement, then all valid Development Licenses possessed by Customer at such date of expiry, and which Customer has not notified for expiry, shall be extended to be valid in perpetuity under the terms of the Agreement. Any such extension shall not apply to The Qt Company's Support obligations. + +EXHIBIT 1, Licensed Software +At the time of conclusion of this Appendix, the latest available version of Licensed Software includes the software libraries and tools set forth in Exhibit 1 (as provided below), depending on which product(s) Customer has purchased under the relevant Purchase Document. +The modules and tools are specific to each product version respectively and may vary from version to version. Modules and tools included in the latest publicly available version of the respective product at any given time are listed in Exhibit 1 of https://www.qt.io/terms-conditions/qt-dev-framework/exhibit-1. If a new version of Licensed Software does not include a module or tool present in an older version which Customer is entitled to use under a valid license from The Qt Company, then Customer will continue to have such right during the validity of Customer's license to relevant Licensed Software. In the event a new version of the Licensed Software adds modules or tools to any previous version(s), Customer's rights will extend to cover also such additional modules and tools. + +EXHIBIT 2 - Small Business Terms +1. This Exhibit applies to entities that qualify as a Qualified Small Business (defined below) and provides additional terms and conditions applicable to small business pricing and licensing. In the event that Customer is a Qualified Small Business and there is any conflict between the terms of this Exhibit and any other terms of the Agreement, the terms in this Exhibit shall take precedence. + +2. APPLICABILITY FOR SMALL BUSINESS LICENSES. Any small business discounts applied require that Customer (including any Customer Affiliates or group entities) has an annual revenue (including annual capital funding) below 1 Million EUR, or the equivalent thereof, as approved by The Qt Company (each, a "Qualified Small Business"). The annual revenue, including funding, must be evidenced upon request by business records and approved by The Qt Company in its reasonable discretion. + +3. SUPPORT. Support is limited to: (i) Install Support; and (ii) for any other Standard Support issue, five (5) support tickets annually. + +4. LIMITATION ON NUMBER OF SMALL BUSINESS DEVELOPER LICENSES. Qualified Small Business discounts and purchasing structure may be applied to a maximum of three discounted developer licenses (either ADE or DCP) per Qualified Small Business. Any additional licenses purchased will be at The Qt Company list price in effect at the time. + +5. LIMITATION FOR NUMBER OF INSTALLATIONS. Customer may install copies of the Licensed Software on two (2) computers per Designated User, provided that only the Designated Users who have a valid Development License may use the Licensed Software. + +6. CONDITIONAL WAIVER OF DISTRIBUTION LICENSES. For Qualified Small Businesses, the Agreement requirements to purchase Distribution Licenses for Devices shall apply only when Customer ceases to be a Qualified Small Business (e.g., when annual revenue threshholds are bypassed). + +7. ADDITIONAL TERMS FOR RENEWALS. The initial subscription purchase term for Qualified Small Business Licenses is twelve (12) months. Upon expiration of the initial twelve (12) month term and unless terminated in accordance with the Agreement, the Licenses will automatically renew for additional twelve (12) month terms with applicable Qualified Small Business discounts. If Customer ceases to be a Qualified Small Business, renewal pricing shall be at The Qt Company list price in effect at the time of renewal, or as agreed in writing between the parties. + +8. ADDITIONAL AUDIT RIGHTS. In addition to the audit rights set forth in the Agreement, The Qt Company reserves the right to audit Customer financial records in order to determine whether Customer is a Qualified Small Business. diff --git a/.cmake.conf b/.cmake.conf new file mode 100644 index 0000000..814c3fb --- /dev/null +++ b/.cmake.conf @@ -0,0 +1,4 @@ +set(QT_REPO_MODULE_VERSION "6.7.2") +set(QT_REPO_MODULE_PRERELEASE_VERSION_SEGMENT "alpha1") +set(QT_EXTRA_INTERNAL_TARGET_DEFINES "QT_NO_AS_CONST=1") +list(APPEND QT_EXTRA_INTERNAL_TARGET_DEFINES "QT_NO_FOREACH=1") diff --git a/.tag b/.tag new file mode 100644 index 0000000..0e84d95 --- /dev/null +++ b/.tag @@ -0,0 +1 @@ +b42c3e57081283d79dc06f5c230abcea9e54b93d diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..babfc18 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,24 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) + +include(.cmake.conf) +project(QtConnectivity + VERSION "${QT_REPO_MODULE_VERSION}" + DESCRIPTION "Qt Connectivity Libraries" + HOMEPAGE_URL "https://qt.io/" + LANGUAGES CXX C +) + +find_package(Qt6 ${PROJECT_VERSION} CONFIG REQUIRED COMPONENTS BuildInternals Core Network) +find_package(Qt6 ${PROJECT_VERSION} CONFIG OPTIONAL_COMPONENTS + DBus Gui Widgets Quick QuickControls2) +qt_internal_project_setup() + +if(NOT TARGET Qt::Network) + message(NOTICE "Skipping the build as the condition \"TARGET Qt::Network\" is not met.") + return() +endif() + +qt_build_repo() diff --git a/LICENSES/Apache-2.0.txt b/LICENSES/Apache-2.0.txt new file mode 100644 index 0000000..136d900 --- /dev/null +++ b/LICENSES/Apache-2.0.txt @@ -0,0 +1,61 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/LICENSES/BSD-3-Clause.txt b/LICENSES/BSD-3-Clause.txt new file mode 100644 index 0000000..b91bbd8 --- /dev/null +++ b/LICENSES/BSD-3-Clause.txt @@ -0,0 +1,9 @@ +Copyright (c) . + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. 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. + 3. Neither the name of the copyright holder 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 HOLDER 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/LICENSES/GFDL-1.3-no-invariants-only.txt b/LICENSES/GFDL-1.3-no-invariants-only.txt new file mode 100644 index 0000000..857214d --- /dev/null +++ b/LICENSES/GFDL-1.3-no-invariants-only.txt @@ -0,0 +1,451 @@ + + 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 +https://www.gnu.org/licenses/. + +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/LICENSES/GPL-2.0-only.txt b/LICENSES/GPL-2.0-only.txt new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/LICENSES/GPL-2.0-only.txt @@ -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/LICENSES/GPL-3.0-only.txt b/LICENSES/GPL-3.0-only.txt new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/LICENSES/GPL-3.0-only.txt @@ -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/LICENSES/LGPL-3.0-only.txt b/LICENSES/LGPL-3.0-only.txt new file mode 100644 index 0000000..65c5ca8 --- /dev/null +++ b/LICENSES/LGPL-3.0-only.txt @@ -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/LICENSES/LicenseRef-Qt-Commercial.txt b/LICENSES/LicenseRef-Qt-Commercial.txt new file mode 100644 index 0000000..825b1f3 --- /dev/null +++ b/LICENSES/LicenseRef-Qt-Commercial.txt @@ -0,0 +1,8 @@ +Licensees holding valid commercial Qt licenses may use this software in +accordance with the the terms contained in a written agreement between +you and The Qt Company. Alternatively, the terms and conditions that were +accepted by the licensee when buying and/or downloading the +software do apply. + +For the latest licensing terms and conditions, see https://www.qt.io/terms-conditions. +For further information use the contact form at https://www.qt.io/contact-us. diff --git a/LICENSES/Qt-GPL-exception-1.0.txt b/LICENSES/Qt-GPL-exception-1.0.txt new file mode 100644 index 0000000..d0322bf --- /dev/null +++ b/LICENSES/Qt-GPL-exception-1.0.txt @@ -0,0 +1,22 @@ +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. + diff --git a/cmake/FindBlueZ.cmake b/cmake/FindBlueZ.cmake new file mode 100644 index 0000000..b1d3012 --- /dev/null +++ b/cmake/FindBlueZ.cmake @@ -0,0 +1,12 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +set(BlueZ_FOUND 0) + +find_package(PkgConfig QUIET) + +pkg_check_modules(BLUEZ bluez IMPORTED_TARGET) + +if(TARGET PkgConfig::BLUEZ) + set(BlueZ_FOUND 1) +endif() diff --git a/cmake/FindPCSCLITE.cmake b/cmake/FindPCSCLITE.cmake new file mode 100644 index 0000000..2abb626 --- /dev/null +++ b/cmake/FindPCSCLITE.cmake @@ -0,0 +1,21 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +if(WIN32) + add_library(PkgConfig::PCSCLITE INTERFACE IMPORTED) + target_link_libraries(PkgConfig::PCSCLITE INTERFACE winscard) + set(PCSCLITE_FOUND 1) +elseif(MACOS) + qt_internal_find_apple_system_framework(FWPCSC PCSC) + add_library(PkgConfig::PCSCLITE INTERFACE IMPORTED) + target_link_libraries(PkgConfig::PCSCLITE INTERFACE ${FWPCSC}) + set(PCSCLITE_FOUND 1) +else() + find_package(PkgConfig QUIET) + + pkg_check_modules(PCSCLITE libpcsclite IMPORTED_TARGET) +endif() + +if(NOT TARGET PkgConfig::PCSCLITE) + set(PCSCLITE_FOUND 0) +endif() diff --git a/coin/axivion/ci_config_linux.json b/coin/axivion/ci_config_linux.json new file mode 100644 index 0000000..b7ae35f --- /dev/null +++ b/coin/axivion/ci_config_linux.json @@ -0,0 +1,40 @@ +{ + "Project": { + "BuildSystemIntegration": { + "child_order": [ + "GCCSetup", + "CMake", + "LinkLibraries" + ] + }, + "CMake": { + "_active": true, + "_copy_from": "CMakeIntegration", + "build_environment": {}, + "build_options": "-j4", + "generate_options": "--fresh", + "generator": "Ninja" + }, + "GCCSetup": { + "_active": true, + "_copy_from": "Command", + "build_command": "gccsetup --cc gcc --cxx g++ --config ../../../axivion/" + }, + "LinkLibraries": { + "_active": true, + "_copy_from": "AxivionLinker", + "input_files": [ + "build/lib/lib*.so*.ir" + ], + "ir": "build/$(env:TESTED_MODULE_COIN).ir" + } + }, + "_Format": "1.0", + "_Version": "7.6.2", + "_VersionNum": [ + 7, + 6, + 2, + 12725 + ] +} diff --git a/coin/module_config.yaml b/coin/module_config.yaml new file mode 100644 index 0000000..aaf3323 --- /dev/null +++ b/coin/module_config.yaml @@ -0,0 +1,13 @@ +version: 2 +accept_configuration: + condition: property + property: features + not_contains_value: Disable + +instructions: + Build: + - !include "{{qt/qtbase}}/coin_module_build_template_v2.yaml" + + Test: + - !include "{{qt/qtbase}}/coin_module_test_template_v3.yaml" + - !include "{{qt/qtbase}}/coin_module_test_docs.yaml" diff --git a/config.tests/bluez/CMakeLists.txt b/config.tests/bluez/CMakeLists.txt new file mode 100644 index 0000000..975a71f --- /dev/null +++ b/config.tests/bluez/CMakeLists.txt @@ -0,0 +1,34 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(config_test_bluez LANGUAGES C CXX) + +if(DEFINED QT_CONFIG_COMPILE_TEST_CMAKE_SYSTEM_PREFIX_PATH) + set(CMAKE_SYSTEM_PREFIX_PATH "${QT_CONFIG_COMPILE_TEST_CMAKE_SYSTEM_PREFIX_PATH}") +endif() +if(DEFINED QT_CONFIG_COMPILE_TEST_CMAKE_SYSTEM_FRAMEWORK_PATH) + set(CMAKE_SYSTEM_FRAMEWORK_PATH "${QT_CONFIG_COMPILE_TEST_CMAKE_SYSTEM_FRAMEWORK_PATH}") +endif() + +foreach(p ${QT_CONFIG_COMPILE_TEST_PACKAGES}) + find_package(${p}) +endforeach() + +if(QT_CONFIG_COMPILE_TEST_LIBRARIES) + link_libraries(${QT_CONFIG_COMPILE_TEST_LIBRARIES}) +endif() +if(QT_CONFIG_COMPILE_TEST_LIBRARY_TARGETS) + foreach(lib ${QT_CONFIG_COMPILE_TEST_LIBRARY_TARGETS}) + if(TARGET ${lib}) + link_libraries(${lib}) + endif() + endforeach() +endif() + +add_executable(${PROJECT_NAME} + main.cpp +) +target_compile_options(${PROJECT_NAME} PRIVATE + -fpermissive +) diff --git a/config.tests/bluez/main.cpp b/config.tests/bluez/main.cpp new file mode 100644 index 0000000..f9da8ec --- /dev/null +++ b/config.tests/bluez/main.cpp @@ -0,0 +1,19 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: BSD-3-Clause + +#include + +int main() +{ + bdaddr_t anyTmp = {{0, 0, 0, 0, 0, 0}}; + bdaddr_t localTmp = {{0, 0, 0, 0xff, 0xff, 0xff}}; + + bacmp(&anyTmp, &localTmp); + + uint32_t field0 = 1; + uint16_t field1 = 1; + + field0 = htonl(field0); + field1 = htons(field1); + return 0; +} diff --git a/config.tests/bluez_le/CMakeLists.txt b/config.tests/bluez_le/CMakeLists.txt new file mode 100644 index 0000000..87536de --- /dev/null +++ b/config.tests/bluez_le/CMakeLists.txt @@ -0,0 +1,31 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(config_test_bluez_le LANGUAGES C CXX) + +if(DEFINED QT_CONFIG_COMPILE_TEST_CMAKE_SYSTEM_PREFIX_PATH) + set(CMAKE_SYSTEM_PREFIX_PATH "${QT_CONFIG_COMPILE_TEST_CMAKE_SYSTEM_PREFIX_PATH}") +endif() +if(DEFINED QT_CONFIG_COMPILE_TEST_CMAKE_SYSTEM_FRAMEWORK_PATH) + set(CMAKE_SYSTEM_FRAMEWORK_PATH "${QT_CONFIG_COMPILE_TEST_CMAKE_SYSTEM_FRAMEWORK_PATH}") +endif() + +foreach(p ${QT_CONFIG_COMPILE_TEST_PACKAGES}) + find_package(${p}) +endforeach() + +if(QT_CONFIG_COMPILE_TEST_LIBRARIES) + link_libraries(${QT_CONFIG_COMPILE_TEST_LIBRARIES}) +endif() +if(QT_CONFIG_COMPILE_TEST_LIBRARY_TARGETS) + foreach(lib ${QT_CONFIG_COMPILE_TEST_LIBRARY_TARGETS}) + if(TARGET ${lib}) + link_libraries(${lib}) + endif() + endforeach() +endif() + +add_executable(${PROJECT_NAME} + main.cpp +) diff --git a/config.tests/bluez_le/main.cpp b/config.tests/bluez_le/main.cpp new file mode 100644 index 0000000..a180c76 --- /dev/null +++ b/config.tests/bluez_le/main.cpp @@ -0,0 +1,14 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include + +int main() +{ + sockaddr_l2 addr; + memset(&addr, 0, sizeof(addr)); + addr.l2_family = AF_BLUETOOTH; + addr.l2_cid = 4; + addr.l2_bdaddr_type = BDADDR_LE_PUBLIC; +} diff --git a/config.tests/linux_crypto_api/CMakeLists.txt b/config.tests/linux_crypto_api/CMakeLists.txt new file mode 100644 index 0000000..2ee9cca --- /dev/null +++ b/config.tests/linux_crypto_api/CMakeLists.txt @@ -0,0 +1,31 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(config_test_linux_crypto_api LANGUAGES C CXX) + +if(DEFINED QT_CONFIG_COMPILE_TEST_CMAKE_SYSTEM_PREFIX_PATH) + set(CMAKE_SYSTEM_PREFIX_PATH "${QT_CONFIG_COMPILE_TEST_CMAKE_SYSTEM_PREFIX_PATH}") +endif() +if(DEFINED QT_CONFIG_COMPILE_TEST_CMAKE_SYSTEM_FRAMEWORK_PATH) + set(CMAKE_SYSTEM_FRAMEWORK_PATH "${QT_CONFIG_COMPILE_TEST_CMAKE_SYSTEM_FRAMEWORK_PATH}") +endif() + +foreach(p ${QT_CONFIG_COMPILE_TEST_PACKAGES}) + find_package(${p}) +endforeach() + +if(QT_CONFIG_COMPILE_TEST_LIBRARIES) + link_libraries(${QT_CONFIG_COMPILE_TEST_LIBRARIES}) +endif() +if(QT_CONFIG_COMPILE_TEST_LIBRARY_TARGETS) + foreach(lib ${QT_CONFIG_COMPILE_TEST_LIBRARY_TARGETS}) + if(TARGET ${lib}) + link_libraries(${lib}) + endif() + endforeach() +endif() + +add_executable(${PROJECT_NAME} + main.cpp +) diff --git a/config.tests/linux_crypto_api/main.cpp b/config.tests/linux_crypto_api/main.cpp new file mode 100644 index 0000000..deeea05 --- /dev/null +++ b/config.tests/linux_crypto_api/main.cpp @@ -0,0 +1,16 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include +#include +#include + +int main() +{ + sockaddr_alg sa; + sa.salg_family = AF_ALG; + sa.salg_type[0] = 0; + sa.salg_name[0] = 0; + setsockopt(3, 279 /* SOL_ALG */, ALG_SET_KEY, "dummy", 5); +} diff --git a/config.tests/winrt_bt/CMakeLists.txt b/config.tests/winrt_bt/CMakeLists.txt new file mode 100644 index 0000000..2a9034b --- /dev/null +++ b/config.tests/winrt_bt/CMakeLists.txt @@ -0,0 +1,34 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(config_test_winrt LANGUAGES C CXX) + +if(DEFINED QT_CONFIG_COMPILE_TEST_CMAKE_SYSTEM_PREFIX_PATH) + set(CMAKE_SYSTEM_PREFIX_PATH "${QT_CONFIG_COMPILE_TEST_CMAKE_SYSTEM_PREFIX_PATH}") +endif() +if(DEFINED QT_CONFIG_COMPILE_TEST_CMAKE_SYSTEM_FRAMEWORK_PATH) + set(CMAKE_SYSTEM_FRAMEWORK_PATH "${QT_CONFIG_COMPILE_TEST_CMAKE_SYSTEM_FRAMEWORK_PATH}") +endif() + +foreach(p ${QT_CONFIG_COMPILE_TEST_PACKAGES}) + find_package(${p}) +endforeach() + +if(QT_CONFIG_COMPILE_TEST_LIBRARIES) + link_libraries(${QT_CONFIG_COMPILE_TEST_LIBRARIES}) +endif() +if(QT_CONFIG_COMPILE_TEST_LIBRARY_TARGETS) + foreach(lib ${QT_CONFIG_COMPILE_TEST_LIBRARY_TARGETS}) + if(TARGET ${lib}) + link_libraries(${lib}) + endif() + endforeach() +endif() + +add_executable(${PROJECT_NAME} + main.cpp +) +target_link_libraries(${PROJECT_NAME} PUBLIC + runtimeobject +) diff --git a/config.tests/winrt_bt/main.cpp b/config.tests/winrt_bt/main.cpp new file mode 100644 index 0000000..e2e08d2 --- /dev/null +++ b/config.tests/winrt_bt/main.cpp @@ -0,0 +1,22 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include +#include + +#if defined(_WIN32) && defined(__INTEL_COMPILER) +#error "Windows ICC fails to build the WinRT backend (QTBUG-68026)." +#endif + +int main() +{ + Microsoft::WRL::ComPtr deviceInformationStatics; + ABI::Windows::Foundation::GetActivationFactory(Microsoft::WRL::Wrappers::HString::MakeReference + (RuntimeClass_Windows_Devices_Enumeration_DeviceInformation).Get(), &deviceInformationStatics); + + (void)Microsoft::WRL::ComPtr().Get(); + (void)Microsoft::WRL::ComPtr().Get(); + (void)Microsoft::WRL::ComPtr().Get(); + return 0; +} diff --git a/dependencies.yaml b/dependencies.yaml new file mode 100644 index 0000000..0bd5c73 --- /dev/null +++ b/dependencies.yaml @@ -0,0 +1,7 @@ +dependencies: + ../qtbase: + ref: b5fbe0923cfc566036b83c3d968f225b26117efc + required: true + ../qtdeclarative: + ref: 12533cc0bd83a2076efb4af0bc1832b0db9568fc + required: false diff --git a/dist/changes-5.10.0 b/dist/changes-5.10.0 new file mode 100644 index 0000000..68310e3 --- /dev/null +++ b/dist/changes-5.10.0 @@ -0,0 +1,78 @@ +Qt 5.10 introduces many new features and improvements as well as bugfixes +over the 5.9.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.10 series is binary compatible with the 5.9.x series. +Applications compiled for 5.9 will continue to run with 5.10. + +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. + +**************************************************************************** +* Qt 5.10.0 Changes * +**************************************************************************** + +QtBluetooth +----------- + + - Register QLowEnergyCharacteristic and QLowEnergyDescriptor as meta + types. It is therefore necessary to declare them as meta types in the + header files. This commit will cause conflicts with existing meta type + declarations in applications using Qt. Those declarations need to be + removed. + + - Renamed qbluetoothglobal.h to qtbluetoothglobal.h. + + - QBluetoothSocket: + * Added QBluetoothSocket::RemoteHostClosedError. + + - QLowEnergyController: + * Added QLowEnergyController::RemoteHostClosedError. + + - Windows: + * [QTBUG-61566] Enabled UWP backend for desktop Windows versions that + support the API. + +QtNfc +----- + + - Renamed qnfcglobal.h tp qtnfcglobal.h. + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Android +------- + + - Improved handling of "connection reset by remote device" use cases for + QLowEnergyController. + +iOS/macOS +--------- + + - Fixed compilation issues related to macOS 10.13 SDK changes. + +Linux/BlueZ +----------- + + - Improved detection of Bluetooth device type (classic vs. low energy) based + on service uuids being offered by the device. + + - [QTBUG-61554] Enabled default BTLE peripheral services even when + QLowEnergyController is running as central role. + + - [QTBUG-57575] Added option to allow more targeted discovery of Bluetooth + devices based on type. + +WinRT +----- + + - Fixed -no-pch build of QtBluetooth. diff --git a/dist/changes-5.10.1 b/dist/changes-5.10.1 new file mode 100644 index 0000000..3754c07 --- /dev/null +++ b/dist/changes-5.10.1 @@ -0,0 +1,39 @@ +Qt 5.10.1 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.10.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.10 series is binary compatible with the 5.9.x series. +Applications compiled for 5.9 will continue to run with 5.10. + +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. + +This release contains all fixes included in the Qt 5.9.4 release. + +**************************************************************************** +* Qt 5.10.1 Changes * +**************************************************************************** + +QtBluetooth +----------- + + - Fixed missing QML version bump. The QML import statement for QtBluetooth + was still 5.9. + - Added various documentation improvements, e.g. special handling for iOS + use cases. + +QtNfc +----- + + - Fixed missing QML version bump. The QML import statement for QtNfc + was still 5.9. + - Added various improvements to all NFC examples. diff --git a/dist/changes-5.11.0 b/dist/changes-5.11.0 new file mode 100644 index 0000000..227c9a4 --- /dev/null +++ b/dist/changes-5.11.0 @@ -0,0 +1,79 @@ +Qt 5.11 introduces many new features and improvements as well as bugfixes +over the 5.10.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.11 series is binary compatible with the 5.10.x series. +Applications compiled for 5.10 will continue to run with 5.11. + +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. + +**************************************************************************** +* Qt 5.11.0 Changes * +**************************************************************************** + +QtBluetooth +----------- + + - Added default assignment operator for QBluetoothUuid. + + - Added default qRegisterMetaType() calls for QLowEnergyCharacteristic + and QLowEnergyDescriptor. + + - Fixed various clazy warnings throughout the library. + + - [QTBUG-65831] Added QBluetoothSocket::connectToService() overload to + disambiguate corner cases. + + - Fixed minor documentation issues. + + - [QTBUG-67651] Fixed QLowEnergyController::remoteName() and remoteAddress(). + +QtNfc +----- + + - Improved and reviewed most examples and their documentation + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Android +------- + + - [QTBUG-66490] Fixed case of ACCESS_FINE_LOCATION not being recognized as + possible permission besides ACCESS_COARSE_LOCATION for device discovery. + + - Fixed repeated connect()/disconnect() behavior for QLowEnergyController + in peripheral mode. + +iOS/macOS +--------- + + - Dropped 10.9 SDK support + +Linux/BlueZ +----------- + + - [QTBUG-46819] Ported QLowEnergyController central mode to BlueZ's DBus + API. The new implementation is used when BlueZ 5.42+ is detected. Earlier + versions will continue to use the the previous custom GATT stack. The benefit + of this change is improved co-existence with BlueZ which avoids interference + between BlueZ and Qt and permits multiple Qt and platform apps being able to + share BTLE connections. The custom GATT peripheral role implementation is still used on + all BlueZ platforms. + + - [QTBUG-66056] Fixed case of QLowEnergyController not resetting the MTU in between connect()/ + disconnect() cycles. + +WinRT +----- + + - Fixed issues with not properly closing QBluetoothSocket. diff --git a/dist/changes-5.11.1 b/dist/changes-5.11.1 new file mode 100644 index 0000000..b4df5c8 --- /dev/null +++ b/dist/changes-5.11.1 @@ -0,0 +1,54 @@ +Qt 5.11.1 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.11.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.11 series is binary compatible with the 5.10.x series. +Applications compiled for 5.10 will continue to run with 5.11. + +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. + +**************************************************************************** +* Qt 5.11.1 Changes * +**************************************************************************** + +QtBluetooth +----------- + + - [QTBUG-67672] Addressed missing emission of readChannelFinished() in + QBluetoothSocket as required by QIODevice. + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Android +------- + + - [QTBUG-65826] Fixed crash in QLowEnergyController during service discovery. + +iOS/macOS +--------- + + - [QTBUG-68422] Fixed never-ending QLowEnergyController service discovery due + to remote peripheral devices not responding properly to requests. A timeout + was added to catch such cases. + +Linux/BlueZ +----------- + + - [QTBUG-64735] Fixed blocking QBluetoothLocalDevice::requestPairing() call + which should not block. + + - Fixed missing service invalidation when calling + QLowEnergyController::disconnectService(). + diff --git a/dist/changes-5.11.2 b/dist/changes-5.11.2 new file mode 100644 index 0000000..2aee4cd --- /dev/null +++ b/dist/changes-5.11.2 @@ -0,0 +1,58 @@ +Qt 5.11.2 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.11.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.11 series is binary compatible with the 5.10.x series. +Applications compiled for 5.10 will continue to run with 5.11. + +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. + +**************************************************************************** +* Qt 5.11.2 Changes * +**************************************************************************** + +QtBluetooth +----------- + + - Fixed incorrect application of QBluetoothSocket type during + QBluetoothSocket::connectToService(const QBluetoothServiceInfo&, OpenMode). + The function applied the socket type of the QBLuetoothSocket default ctor + and ignored the requested socket type of the given QBluetoothServiceInfo + instance + +QtNfc +----- + + - [QTBUG-67958] Fixed QMetaObject::invokeMethod() warning. + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Android +------- + + - [QTBUG-69700] Fixed incorrect matching of + QBluetoothServiceDiscoveryAgent::uuidFilter() during a service discovery. + +iOS/macOS +--------- + + - [QTBUG-69857] Fixed crash in QBluetoothServiceInfo::unregisterService() on macOS. + + +Linux/BlueZ +----------- + + - [QTBUG-68890] Fixed a crash in QLowEnergyController on BlueZ 5 triggered when + BTLE devices disconnect and reconnect. diff --git a/dist/changes-5.12.0 b/dist/changes-5.12.0 new file mode 100644 index 0000000..761debe --- /dev/null +++ b/dist/changes-5.12.0 @@ -0,0 +1,70 @@ +Qt 5.12 introduces many new features and improvements as well as bugfixes +over the 5.11.x series. For more details, refer to the online documentation +included in this distribution. The documentation is also available online: + +https://doc.qt.io/qt-5/index.html + +The Qt version 5.12 series is binary compatible with the 5.11.x series. +Applications compiled for 5.11 will continue to run with 5.12. + +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. + +**************************************************************************** +* Qt 5.12.0 Changes * +**************************************************************************** + +QtBluetooth +----------- + + - [QTBUG-68026] Excluded ICC build for QtBluetooth. Previously, ICC attempted to build + the WinRT implementation which does not work. In the long term, ICC should build + the Win32 port of QtBluetooth which unfortunately does not exist yet. + + - [QTBUG-68550] Added a DBus based Bluez implementation for QBluetoothSocket. Previously, + raw Bluetooth socket API was used to established the connection. However + this is no longer the recommended BlueZ way and hence the need for this change. + The new implementation is chosen if the BlueZ runtime version is 5.46+. This change + required extensive redesign of the QBluetoothSocket internals affecting all other platforms. + + - [QTBUG-69857] Fixed crash in QBluetoothServiceInfo::unregisterService() on macOS. + + - Added manufacturer data related API to QBluetoothDeviceInfo. This is needed for + Bluetooth Low Energy device scans. + + - [QTBUG-46008] [QTBUG-69747] Added QBluetoothDeviceDiscoveryAgent::deviceUpdated() + signal. The signal permits live updates of changing Bluetooth Low Energy data such + as manufacturer or RSSI information during the discovery. + + - Fixed incorrect QLowEnergyService::state() of local (peripheral) services. + + - Fixed failing Bluetooth config test when using clang due to stricter error + dectection in clang (when compared to gcc). + + - [QTBUG-70222] Fixed incorrect detection of BTLE Battery services in BlueZ 5.48+ + + - [QTBUG-70295] Added implementation to properly handle pin code pairing + (BluetoothDevice.PAIRING_VARIANT_PIN) on Android. So far, only + BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION was supported. + + - [QTBUG-70754] Ensured that repeated calls to QLowEnergyCOntroller::startAdvertising() + updates the to-be-updated info on Linux. + + - [QTBUG-58660] Fixed discovery of unpaired Bluetooth devices on WinRT. + + - [QTBUG-58529] Fixed incorrect BluetoothProfileDescriptorList generation by various + QBluetoothSocket related classes, documentation and examples. + +QtNfc +----- + + - [QTBUG-62169] Added QNearFieldManager::isSupported(). This only works on + Android at the moment. + + - Added QNearFieldManager::AdapterState enum and the related adapterStateChanged() + signal. diff --git a/dist/changes-5.12.1 b/dist/changes-5.12.1 new file mode 100644 index 0000000..418855a --- /dev/null +++ b/dist/changes-5.12.1 @@ -0,0 +1,56 @@ +Qt 5.12.1 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.12.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.12 series is binary compatible with the 5.11.x series. +Applications compiled for 5.11 will continue to run with 5.12. + +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. + +**************************************************************************** +* Qt 5.12.1 Changes * +**************************************************************************** + +QtBluetooth +----------- + + - Added various documentation clarifications. + - Fixed issue when compiling qbluetoothsocket.h header via gcc 4.8 + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Android +------- + + - [QTBUG-46008] Fixed wrong order emitting + QBluetoothDeviceDiscoveryAgent::deviceUpdated() & deviceDiscovered() signals. + +iOS/macOS +--------- + + - [QTBUG-72487] Addressed inability to run several LE service detail discoveries + concurrently. + +Linux/BlueZ +----------- + + - [QTBUG-72742] Added missing dbus registration for an unexpected way of + using QBluetoothSocket. + +WinRT/UWP +--------- + + - [QTBUG-67090] Fixed WinRT port not working with heartrate-game example. + - Added several fixes to unit tests enabling them to be run by Qt CI on WinRT. diff --git a/dist/changes-5.12.2 b/dist/changes-5.12.2 new file mode 100644 index 0000000..9e0f7fa --- /dev/null +++ b/dist/changes-5.12.2 @@ -0,0 +1,61 @@ +Qt 5.12.2 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.12.0 through 5.12.1. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + +https://doc.qt.io/qt-5/index.html + +The Qt version 5.12 series is binary compatible with the 5.11.x series. +Applications compiled for 5.11 will continue to run with 5.12. + +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. + +*************************************************************************** +* Qt 5.12.2 Changes * +*************************************************************************** + +QtBluetooth +----------- + + - Added documentation improvements to QBluetoothServiceDiscoveryAgent. + +QtNfc +----- + + - Fixed exceptions on Android WearOS devices because those devices not + supporting NFC. + +*************************************************************************** +* Platform Specific Changes * +*************************************************************************** + +Android +------- + + - [QTBUG-72681] Fixed wrong reversing of service uuids when calling + QBLuetoothSocket::connectToService(). + + - Fixed a crash when destroying QBluetoothDeviceDisocveryAgent during an + ongoing scan. + + - [QTBUG-73571] Fixed tst_QBluetoothServiceDiscoveryAgent::tst_invalidBtAddress() + which was failing on Android. + +iOS/macOS +--------- + + - [QTBUG-73140] Fixed a crash in QBluetoothDeviceDiscoveryAgent when the user + turns off Bluetooth while a scan is running. + +Linux/BlueZ +----------- + + - [QTBUG-72800] Addressed bug where a discovered custom uuid was not returned + via BluetoothServiceInfo::serviceUuid() but as serviceClassUuids(). diff --git a/dist/changes-5.12.3 b/dist/changes-5.12.3 new file mode 100644 index 0000000..2341dae --- /dev/null +++ b/dist/changes-5.12.3 @@ -0,0 +1,42 @@ +Qt 5.12.3 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.12.0 through 5.12.2. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + +https://doc.qt.io/qt-5/index.html + +The Qt version 5.12 series is binary compatible with the 5.11.x series. +Applications compiled for 5.11 will continue to run with 5.12. + +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. + +**************************************************************************** +* Qt 5.12.3 Changes * +**************************************************************************** + +QtBluetooth +----------- + + - Fixed crash at calling QLowEnergyController::disconnectFromDevice while + not connected. + + - [QTBUG-74513] Fixed missing emission of QBluetoothSocket::bytesWritten() signal on + Bluez v5.46+. + + - Fixed NullPointerException on Android when discovering BTLE services while an + unexpected device connect is triggered. + + - Applied a variety of minor code cleanups. + +QtNfc +----- + + - [QTBUG-74538] Addressed a compile error in qnearfieldtarget_emulator_p.h + when using gcc 4.8. diff --git a/dist/changes-5.12.4 b/dist/changes-5.12.4 new file mode 100644 index 0000000..d751f70 --- /dev/null +++ b/dist/changes-5.12.4 @@ -0,0 +1,39 @@ +Qt 5.12.4 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.12.0 through 5.12.3. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + +https://doc.qt.io/qt-5/index.html + +The Qt version 5.12 series is binary compatible with the 5.11.x series. +Applications compiled for 5.11 will continue to run with 5.12. + +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. + +**************************************************************************** +* Qt 5.12.4 Changes * +**************************************************************************** + +QtBluetooth +----------- + + - Fixed a memory leak in QBluetoothServiceDiscoveryAgent on Android. + + - [QTBUG-75035] Improved likelihood of + QBluetoothSocket::connectToService(QBluetoothServiceInfo,..) succeeding when + QBluetoothServiceInfo::socketProtocol() returns a non-RFCOMM type. Since Android + does not support anything but RFCOMM it always assumes RFCOMM. + + - Fixed reading of descriptor values on WinRT. + + - [QTBUG-75043] Fixed behavior when a peripheral changes its service list at runtime + + - [QTBUG-75278] Fixed socket leak when running QLowEnergyController Peripheral mode + on Linux. diff --git a/dist/changes-5.12.5 b/dist/changes-5.12.5 new file mode 100644 index 0000000..9f0b41b --- /dev/null +++ b/dist/changes-5.12.5 @@ -0,0 +1,38 @@ +Qt 5.12.5 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.12.0 through 5.12.4. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + +https://doc.qt.io/qt-5/index.html + +The Qt version 5.12 series is binary compatible with the 5.11.x series. +Applications compiled for 5.11 will continue to run with 5.12. + +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. + +**************************************************************************** +* Qt 5.12.5 Changes * +**************************************************************************** + +QtBluetooth +----------- + + - [QTBUG-76847] Fixed ambiguous type conversions on Apple platforms. + + - [QTBUG-75089] Removed attempt to delete nullptr on WinRT when calling + QBluetoothDeviceDiscoveryAgent::stop(). + + - [QTBUG-76565] Reverted handling of PAIRING_VARIANT_PIN by + QBluetoothLocalDevice on Android. + + - [QTBUG-62520] Improved documentation covering platform limitations on WinRT. + + - Fixed QLowEnergyAdvertisingData::setManufacturerData() on Android. Previously a wrong + JNI signature prevented setting the data. diff --git a/dist/changes-5.13.0 b/dist/changes-5.13.0 new file mode 100644 index 0000000..921b45a --- /dev/null +++ b/dist/changes-5.13.0 @@ -0,0 +1,59 @@ +Qt 5.13 introduces many new features and improvements as well as bugfixes +over the 5.12.x series. For more details, refer to the online documentation +included in this distribution. The documentation is also available online: + +https://doc.qt.io/qt-5/index.html + +The Qt version 5.13 series is binary compatible with the 5.12.x series. +Applications compiled for 5.12 will continue to run with 5.13. + +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. + +**************************************************************************** +* Qt 5.13.0 Changes * +**************************************************************************** + +QtBluetooth +----------- + + - [QTBUG-58660] Added ability to connect to BLE devices on WinRT without + pairing. + + - [QTBUG-69954] Fixed potential crash due to late callbacks on WinRT. + + - Improved WinRT implementation signficantly. This incorporates a large + number of patches (each improving the stability and general robustness of + the code base). During the process the number of potential asserts was + reduced as well. + + - Deprecated QBluetoothDeviceInfo::DataCompleteness related APIs. + + - Replaced QBluetoothDeviceInfo::LanAccessDevice with QBluetoothDeviceInfo::NetworkDevice. + LanAccessDevice was deprecated. + + - Implemented support for QBluetoothDeviceDiscoveryAgent::deviceUpdated() on Apple and WinRT + platforms. + + - [QTBUG-71943] Implemented RSSI and manufacturer data discovery on WinRT. + + - [QTBUG-74394] Fixed broken QLowEnergyController::disconnectFromDevice() on WinRT. + + - Added a compile fix for g++ 8. + + - [QTBUG-73717] Fixed warnings in QDeclarativeBluetoothDiscoveryModel. + +QtNfc +----- + + - QNearFieldManager: + * adapterStateChanged() now has a fully qualified parameter + QNearFieldManager::AdapterState. This can cause a problem if the + connection/method invocation was done with just AdapterState as the + parameter type, in which case these need to be changed to use + QNearFieldManager::AdapaterState instead. diff --git a/dist/changes-5.13.1 b/dist/changes-5.13.1 new file mode 100644 index 0000000..706bd31 --- /dev/null +++ b/dist/changes-5.13.1 @@ -0,0 +1,36 @@ +Qt 5.13.1 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.13.0. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + +https://doc.qt.io/qt-5/index.html + +The Qt version 5.13 series is binary compatible with the 5.12.x series. +Applications compiled for 5.12 will continue to run with 5.13. + +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. + +**************************************************************************** +* Qt 5.13.1 Changes * +**************************************************************************** + +QtBluetooth +----------- + + - [QTBUG-62520] Improved stability of QBluetoothSocket::connectToService() + on WinRT. + + - [QTBUG-62294] Added implementation for QBluetoothLocalSocket on WinRT. Note + that the platform only supports pairingStatus() related features. + + - Improved stability of QLowEnergyController on WinRT. + + - [QTBUG-75907] Reduced number of asserts in QLowEnergyController on WinRT. + diff --git a/dist/changes-5.13.2 b/dist/changes-5.13.2 new file mode 100644 index 0000000..22c4b3f --- /dev/null +++ b/dist/changes-5.13.2 @@ -0,0 +1,35 @@ +Qt 5.13.2 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.13.0 through 5.13.1. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + +https://doc.qt.io/qt-5/index.html + +The Qt version 5.13 series is binary compatible with the 5.12.x series. +Applications compiled for 5.12 will continue to run with 5.13. + +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. + +**************************************************************************** +* Qt 5.13.2 Changes * +**************************************************************************** + +QtBluetooth +----------- + + - [QTQAINFRA-2139] Fixed QMutex related compile error when using clang on + Windows. + + - [QTBUG-78201] Fixed a case where an existing descriptor was not discovered + during the service discovery due to not being readable. This issue happened + on Android. + + - Fixed a few minor documentation issues. + diff --git a/dist/changes-5.14.0 b/dist/changes-5.14.0 new file mode 100644 index 0000000..68bd528 --- /dev/null +++ b/dist/changes-5.14.0 @@ -0,0 +1,53 @@ +Qt 5.14 introduces many new features and improvements as well as bugfixes +over the 5.13.x series. For more details, refer to the online documentation +included in this distribution. The documentation is also available online: + +https://doc.qt.io/qt-5/index.html + +The Qt version 5.14 series is binary compatible with the 5.13.x series. +Applications compiled for 5.13 will continue to run with 5.14. + +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. + +**************************************************************************** +* Android * +**************************************************************************** + + - [QTBUG-67482] Ported Bluetooth device scanning API to BluetoothLeScanner + API. This API will be used on Android SDK v21+. + + - [QTBUG-69615] Fixed classic device discovery problems on Android. Newer + Android versions (9+) require Location permission for classic device + discovery. + +**************************************************************************** +* QtBluetooth * +**************************************************************************** + + - Added possibility to build win32 backend which also works on Windows 7. + + - Deprecated QBluetoothServiceInfo::DataComplete. + + - Signficant refactoring of the Apple platform Bluetooth code to bring it + closer to all other code lines. Previously the macOS and iOS code was very + distinct which caused duplicated code lines. + + - Proved the examples for HighDPI use cases. + + - Added QLowEnergyController::Authorization enum value. + + - [QTBUG-76615] Added the ability to support multiple manufacturer data + entries per QBluetoothDeviceInfo instance. This is of relevance when dealing + with BluetoothDeviceDiscoveryAgent::deviceUpdated() signals. + + - [QTBUG77390] Reduced likelyhood of blocking the main event loop on Linux when + doing a device scan. + + - [BlueZ] [QTBUG-63019] Added QLowEnergyController::createCentral with + locale device overload. diff --git a/dist/changes-5.14.1 b/dist/changes-5.14.1 new file mode 100644 index 0000000..be79e80 --- /dev/null +++ b/dist/changes-5.14.1 @@ -0,0 +1,25 @@ +Qt 5.14.1 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.14.0. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + +https://doc.qt.io/qt-5/index.html + +The Qt version 5.14 series is binary compatible with the 5.13.x series. +Applications compiled for 5.13 will continue to run with 5.14. + +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. + +**************************************************************************** +* QtBluetooth * +**************************************************************************** + + - BlueZ-DBus: + * Invalidate btle service when it has disappeared diff --git a/dist/changes-5.14.2 b/dist/changes-5.14.2 new file mode 100644 index 0000000..4b0fa8a --- /dev/null +++ b/dist/changes-5.14.2 @@ -0,0 +1,49 @@ +Qt 5.14.2 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.14.0 through 5.14.1. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + +https://doc.qt.io/qt-5/index.html + +The Qt version 5.14 series is binary compatible with the 5.13.x series. +Applications compiled for 5.13 will continue to run with 5.14. + +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. + +**************************************************************************** +* QtBluetooth * +**************************************************************************** + + - Windows: + * [QTBUG-80770] Fixed service state (DiscoveryRequired) when service + detail discovery fails. + * [QTBUG-81827] Avoid possible lock when calling + QBluetoothServer::hasPendingConnections. + - Android: + * Fixed the missing QLowEnergyService::error() signal emission if the + error was detected on the Java side. This probably cut 50% of all + errors out. + * Fixed runtime exception that happened when calling "stopLeScan" when + device's Bluetooth adapter is turned off. + * [QTBUG-81875] Fixed QBluetoothDeviceDiscoveryAgent with Android API 29. + * Fixed race condition where incoming and outgoing Low Energy requests + could overwrite each others payload. + - Linux: + * [QTBUG-81696] Added support for characteristic Write Without Response + requests when using BlueZ 5.50 or later. + +**************************************************************************** +* QtNFC * +**************************************************************************** + + - Android: + * Fixed case when QNearFieldTarget::waitForRequestCompleted() did not stop + early (caused overly long timeout case) despite QNearFieldTarget::sendCommand() + having failed already. diff --git a/dist/changes-5.15.0 b/dist/changes-5.15.0 new file mode 100644 index 0000000..2fa22be --- /dev/null +++ b/dist/changes-5.15.0 @@ -0,0 +1,25 @@ +Qt 5.15 introduces many new features and improvements as well as bugfixes +over the 5.14.x series. For more details, refer to the online documentation +included in this distribution. The documentation is also available online: + +https://doc.qt.io/qt-5/index.html + +The Qt version 5.15 series is binary compatible with the 5.14.x series. +Applications compiled for 5.14 will continue to run with 5.15. + +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. + +**************************************************************************** +* QtBluetooth * +**************************************************************************** + + - On macOS, fixed missing writeNotify notifications in QBluetoothSocket. + + - Fixed several deprecation warnings introduced by changes in other Qt modules. + diff --git a/dist/changes-5.15.1 b/dist/changes-5.15.1 new file mode 100644 index 0000000..332ee9d --- /dev/null +++ b/dist/changes-5.15.1 @@ -0,0 +1,20 @@ +Qt 5.15.1 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.15.0. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + +https://doc.qt.io/qt-5/index.html + +The Qt version 5.15 series is binary compatible with the 5.14.x series. +Applications compiled for 5.14 will continue to run with 5.15. + +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. + + - This release contains only minor code improvements. diff --git a/dist/changes-5.15.2 b/dist/changes-5.15.2 new file mode 100644 index 0000000..904e0ea --- /dev/null +++ b/dist/changes-5.15.2 @@ -0,0 +1,24 @@ +Qt 5.15.2 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.15.1. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + + https://doc.qt.io/qt-5.15/index.html + +The Qt version 5.15 series is binary compatible with the 5.14.x series. +Applications compiled for 5.14 will continue to run with 5.15. + +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. + +**************************************************************************** +* Qt 5.15.2 * +**************************************************************************** + +This release only contains minor changes. diff --git a/dist/changes-5.2.1 b/dist/changes-5.2.1 new file mode 100644 index 0000000..efcf536 --- /dev/null +++ b/dist/changes-5.2.1 @@ -0,0 +1,58 @@ +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 +-------------------- + + - Fixed make install rules for all examples + + - Minor code improvements made such as removal of compiler warnings and + code cleanups. + +**************************************************************************** +* Library * +**************************************************************************** + +QtBluetooth +----------- + + - Fixed cases where device and service discovery classes emitted an error + signal but the human readable error string was not adjusted + + - Marked untranslated error strings for translation + + - [QTBUG-32253] + * Utilized new QLoggingCategory API for warnings and debug messages + +QtNfc +------ + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Blackberry +------- + + - Dangling pointer in QBluetoothServiceDiscoveryAgent fixed + diff --git a/dist/changes-5.3.0 b/dist/changes-5.3.0 new file mode 100644 index 0000000..b5c4dc8 --- /dev/null +++ b/dist/changes-5.3.0 @@ -0,0 +1,153 @@ +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 +-------------------- + +**************************************************************************** +* Library * +**************************************************************************** + +QtBluetooth +----------- + + - Documentation: + * The documentation for the Bluetooth discovery classes has been + improved. + * QBluetoothSocket's local name, port and address property documentation + improved. + * Documentation of all examples improved. + + - General: + * Added a new Object-Push example. + * QML scanner example was optimized for high DPI displays and + error handling was improved. This ensures a better user interface + for Android and BlackBerry devices. + * Replaced tennis example against new QML based PingPong example. + * Test application added. This application enables easier testing + and debugging of the various API features. + + - BluetoothDiscoveryModel (QML): + * Improved error handling of device discovery process. + * Fixed incorrect behavior when changing from device to service discovery + and vice versa. + + - QBluetoothDeviceDiscoveryAgent: + * Added checks and error enum value to avoid incorrect handling of + non-existing local Bluetooth adapter addresses. + + - QBluetoothHostInfo: + * Copy operator added. + + - QBluetoothLocalDevice: + * Added a new API elements to retrieve connected Bluetooth devices + and to receive notifications about connection changes. + + - QBluetoothServiceDiscoveryAgent: + * Fixed the fallback backend's initial state and error values. + * Duplicated code was removed. + * QBluetoothServiceDiscoveryAgent::clear() was improved to avoid + unpredictable class behavior. + + - QBluetoothServer: + * Checks added to avoid calls to listen() while the server socket is + already listening for incoming sockets. + * Fixed inconsistent state() of server object after failed service + registration attempt during listen() call. + * Fixed incorrect parameter type of error() signal. This fixed issues + whereby QObject::connect() could not find the signal. + * Added custom uuid to serial port service SDP data set. This enables + the discovery of such profiles on Android devices. + + - QBluetoothServiceInfo: + * Fixed broken implementation of serviceClassUuids(). + + - QBluetoothSocket: + * Fixed a crash in Bluez part of QBluetoothSocket() which was caused + triggered when calling the sequence connect() - abort() - connect(). + * Fixed missing initialization of the internal socket error state + variable. This caused incorrect QBluetoothSocket::error() right after + class instantiation. + * Synchronized handling of errors across all supported platforms. + + - QBluetoothUuid: + * Fixed wrong value of PnpInformation enum value. + * Added newly defined ServiceClassUuid's defined Bluetooth forum. + + +QtNfc +----- + + - Documentation: + * Added missing documentation to QQmlNdefRecord. + * General documentation fixes add. + + - General: + * Added a new corkboard example displaying the content of NDEF text + records. + * A new NFC share API was added. The API provides sharing of NDEF + messages and arbitrary files via NFC and may potentially use other + communication protocols such as wifi or Bluetooth as part of its + implementation. + + + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Android +------- + + - [QTBUG-33792] QtBluetooth has been ported to Android. + +BlackBerry 10: +-------------- + + - [QTBUG-36626] Fixed a memory leak in QBluetoothServer::listen(). + - Fixed incomplete implementation of QBluetoothServer::close(). + - Fixed wrong pairingStatus() returned by QBluetoothLocalDevice. + - Fixed accidental loss of remote device information in QBluetoothServer. + - Added incomplete implementation of QBluetooth::setMaxPendingConnections(). + - Fixed always failing call to QBluetoothServerInfo::unregisterService(). + - Fixed missing emission of ConnectedState by QBluetoothSocket. + - Fixed implementation of QBluetoothTransferManager::put() when using + together with a QFile. + +Bluez/Linux +----------- + + - The handling of powered-off local Bluetooth adapters was improved. + - Fixed memory leaks in service and device discovery classes. + - Removed dead code from SDP discovery implementation. + - Fixed crash during service discovery. + - Fixed incorrect invocation of QBluetoothDiscoveryAgent where the + remote service address was incorrectly assumed to be the local Bt + adapter address. This prevented the detection of the remote service. + - Removed caching of QBluetoothSocket::localName() and peerName() values. Under + certain circumstances those functions returned wrong values. + - Fixed missing update of internal QBluetoothSocket::state during SDP discovery. + - Removed assertion during service discovery due to unknown SDP attribute. + - Prevented calls to QBluetoothSocket::connectToService() while the socket + is already in the ServiceLoockupState. + - Fixed failing call to QBluetoothServer::listen(QBluetoothAddress) if the passed + address was null. + diff --git a/dist/changes-5.3.1 b/dist/changes-5.3.1 new file mode 100644 index 0000000..1fa1720 --- /dev/null +++ b/dist/changes-5.3.1 @@ -0,0 +1,89 @@ +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 +-------------------- + + - [QTBUG-38140] Changed btchat example to use full service discovery to + increase chance of finding remote services. Some platforms such as Android + may not be able to find remote services via a minimal service discovery. + + +**************************************************************************** +* Library * +**************************************************************************** + +QtBluetooth +----------- + + - QML BluetoothDiscoveryModel: + * Fixed inconsistent behavior whereby the QML model never reset its + content while the underlying QBluetoothServiceDiscoveryAgent instance + did reset. This caused the QML model to show an incomplete list of remote + Bluetooth services during its second run. + + - QDebug helper for QBluetoothUuid became aware of QT_NO_DEBUG_STREAM + define. + + - QBluetoothSocket: + * Fixed duplicate emission of unconnected state in the reconnection + case. + + - Fixed crash when calling listen() on the QML BluetoothService type. + + - Added some documentation improvements. + + - Added "classname" entry to all qmldir files enabling QML + plug-ins when doing static builds (on iOS). + + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +BlackBerry +---------- + + - Converted BlackBerry backend to new Bluetooth C API which was introduced + by OS version 10.2.1 or later. + +Linux +----- + + - Fixed accidental double up of remote services entries by + QBluetoothServiceDiscoveryAgent due to missing duplication check. + + - QBluetoothSocket: + * Fixed internal read buffer corruption during timeouts. + * Fixed a crash on reconnect. + + - [QTBUG-38402] Fixed incorrect detection of connected devices and their + changes by QBluetoothLocalDevice + + - Implemented handling of xml tag by QBluetoothServiceInfo. This tag is + used by Bluez to indicate the SDP entries for DocumentationUrl, + ClientExecutableUrl and IconUrl. So far these entries where being ignored. + + - [QTBUG-38399] Ensured correct handling of removed Bluetooth dongles by + already instantiated QBluetoothLocalDevice objects. + diff --git a/dist/changes-5.3.2 b/dist/changes-5.3.2 new file mode 100644 index 0000000..e700e85 --- /dev/null +++ b/dist/changes-5.3.2 @@ -0,0 +1,49 @@ +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. + +**************************************************************************** +* General * +**************************************************************************** + +QtBluetooth +----------- + + - Removed dead code from the library. + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Android +------- + + - [QTBUG-39815] Removed calls to Android's BluetoothSocket.isConnected(). + It does not work reliably on all devices and prevented those devices from + successfully establishing an RFCOMM socket connection. + + - [QTBUG-40172] Increased robustness of QBluetoothSocket::connectToService() + by providing a fallback implementation using private Android APIs which + increase the chance of successful connects on some devices. + +Linux +----- + + - Removed undesirable system header includes from the Bluez code base. + - Fixed incomplete SDP entries when using L2CP sockets and avoided + crash on client side when incomplete SDP entry is encountered. diff --git a/dist/changes-5.4.0 b/dist/changes-5.4.0 new file mode 100644 index 0000000..7880982 --- /dev/null +++ b/dist/changes-5.4.0 @@ -0,0 +1,99 @@ +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 * +**************************************************************************** + +QtBluetooth +----------- + + - Bluetooth Low Energy Support added: + * Connect/disconnect to peripherals supported. + * Services on Peripheral can be discovered and interacted with. + * BlueZ on Linux is the only currently supported platform. + Minimal requirement are a Linux kernel v 3.5+ and BlueZ version 4.101+. + More platforms will be added by future Qt releases. + * The feature/API remains in Tech Preview stage throughout the Qt 5.4 + release. Some API elements may still change in future releases. + + - Fixed documentation throughout all classes. + + - General: + * Bluetooth Low Energy scanner example has been added. + * Heart Listener Bluetooth Low Energy Heart Belt example has been added. + + - QBluetoothAddress: + * QDebug streaming operator added. + + - QBluetoothDeviceInfo: + * QBluetooth::CoreConfiguration enum added. + * CoreConfiguration attribute added. + + - QBluetoothServiceDiscoveryAgent: + * Fixed cases where Bluez doesn't provide service names for given + Bluetooth service class uuid. + + - QBLuetoothSocket: + * [QTBUG-32704] Fixed behavior of isReadable()/isOpen()/isWritable(). + So far, these functions returned wrong values. + + - QBluetoothTransferReply: + * QBluetoothTransferReply::error() signal added. + * QBluetoothTransferReply::SessionError value added to TransferError enum. + * QBluetoothTransferReply::TransferError enum declared as as meta type. + * Fixed a memory leak on Bluez and QNX. + * Fixed segmentation fault if passed QIODevice was 0. + + - QBluetoothUuid: + * Added QBluetoothUuid::protocolToString(QBluetoothUuid::ProtocolUuid) + which returns a human-readable string for the given protocol uuid. + * Various Bluetooth Low Energy related API elements added. This includes + two new constructors, the DescriptorType and CharacteristicType enum, + various values for ServiceClassUuid enum and helper functions to + handle the extended range of new enums. + +QtNfc +----- + + - General: + * Fixed reference error bug in NFC poster example + + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Android +------- + + - Fixed broken QBluetoothServer::isListening(). It returned false right + after a successful call to listen(). + +Bluez/Linux +----------- + + - API ported to Bluez 5.x. + + - Fixed license issue. + + - QBluetoothDeviceDiscoveryAgent: + * Add support to enable detection of Bluetooth Low Energy devices. + + - QBluetoothSocket: + * Fixed case where port L2CP port number was not converted to little-endian. + This bug affected big-endian platforms. diff --git a/dist/changes-5.4.1 b/dist/changes-5.4.1 new file mode 100644 index 0000000..5a4a5db --- /dev/null +++ b/dist/changes-5.4.1 @@ -0,0 +1,38 @@ +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 * +**************************************************************************** + +QtBluetooth +----------- + + - General: + * Extended documentation with regards to Bluetooth Low Energy. The + affected classes were QLowEnergyController and QLowEnergyService. + * LowEnergyScanner and chat examples improved. + + - QBluetoothServer: + * [QTBUG-43806] Fixed SDP registration of PublicBrowseGroup in BlueZ 5.x. + + - QLowEnergyController: + * Fixed blocking of ATT command processing due to a reconnect to the target + device. + diff --git a/dist/changes-5.4.2 b/dist/changes-5.4.2 new file mode 100644 index 0000000..3ac1079 --- /dev/null +++ b/dist/changes-5.4.2 @@ -0,0 +1,50 @@ +Qt 5.4.2 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with 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 * +**************************************************************************** + +QtBluetooth +----------- + + - [QTBUG-43757] Enabled Pairing request ability on Android v15-18. Previously + this only worked on v 19 or later. + - [QTBUG-44164] Fixed leaking of local references in QBluetoothSocket on Android. + - Fixed memory leak in QBluetoothLocalDevice on Bluez 4.x platforms. + - Fixed SDP scanning on Bluez 5.x platforms. + - [QTBUG-44452] Fixed QBluetoothServer error code when encountering EADDRINUSE + on Bluez 4.x and 5.x platforms. + - Improved QBluetoothServiceInfo documentation. + - [QTBUG-44792] Fixed QBluetoothSocket error handling on Android when calling + BluetoothDevice.getServiceChannel() + - [QTBUG-44915] Fixed handling of GATT server requests on Bluez platforms. + GATT Server requests are answered with "Request no supported" as required by the Bluetooth specification. + - [QTBUG-45066] Fixed crash in QBluetoothLocalDevice ctor on some Android devices + due to a platform exception in BluetoothAdapter.getDefaultAdapter(). + - [QTBUG-44930] Fixed crash in QBluetoothServiceDiscoveryAgent on Bluez 5.x platforms + when using single device discovery. Single device discovery is used during + QBluetoothSocket::connectToService(). + - [QTBUG-44930] Fixed crash when closing QBluetoothSocket during a pending + connection attempt on Android. + - Forced QBluetoothSocket to close when its dtor is called on Android. + - Removed assertion if encryption change is received which was not requested + by the current QLowEnergyController instance on Bluez platforms. + - Fixed crash due to dangling pointer during closure of QBluetoothSocket on Android. + diff --git a/dist/changes-5.5.0 b/dist/changes-5.5.0 new file mode 100644 index 0000000..9ddd8e3 --- /dev/null +++ b/dist/changes-5.5.0 @@ -0,0 +1,105 @@ +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 * +**************************************************************************** + +QtBluetooth +----------- + + - Ported Classic Bluetooth components and classes to OS X. A similar port + to iOS is not possible due to missing platform support. + - Ported Low Energy components to iOS, OS X and Android + - Improved QBluetoothTransferManager documentation + - Improved QLowEnergyService documentation + - Added missing detailsChanged() signal emissions in BluetoothService QML type + + - QBluetoothDeviceDiscoveryAgent: + * Extended QBluetoothDeviceDiscoveryAgent documentation around Bluetooth + Low Energy device discovery + * Added QBluetoothDeviceDiscoveryAgent::UnsupportedPlatformError flag + + - QBluetoothDeviceInfo: + * Added QBluetoothDeviceInfo(QBluetoothUuid,QString,quint32) ctor + * Fixed incorrect initialization of QBluetoothDeviceInfo::coreConfiguration() + in the class ctor. By default, it is set to + QBluetoothDeviceInfo::UnknownCoreConfiguration. + * Added Q_DECLARE_OPERATORS_FOR_FLAGS macro for CoreConfiguration + and ServiceClasses enums + + - QBluetoothHostInfo: + * Added Q_DECLARE_METATYPE + * Added comparison operators + + - QLowEnergyController: + * QLowEnergyController::ConnectionError enum value added. + * Added QLowEnergyController(QBluetoothDeviceInfo) ctor. This ctor is the + preferred ctor. + + - QLowEnergyService: + * Add capability to initiate reading of characteristics and descriptors. Previously + the variable was only updated during the initial service discovery or when + a value notification was received. + * Added guard to prevent writing of service before service discovery + was complete. + * Force write of characteristics and descriptors even when they are marked as + read-only. This permits workarounds where the device's meta data reports + wrong values. + * Improved class documentation + * Added remoteName() member function + + - QBluetoothUuid: + * Extended QBluetoothUuid::ServiceClassUuid enum to incorporate latest + BLuetooth Low Energy service type standards/definitions + * Extended QBluetoothUuid::CharacteristicType to incorporate latest + Bluetooth Low Energy characteritistic standards/definitions + * Extended QBluetoothUuid::DescriptorType to incorporate latest + Bluetooth Low Energy descriptor standards/definitions + + - Examples: + * Fixed several lowenergyscanner example bugs + +QtNfc +----- + + - Ported module to Linux using Neard v0.14+ + - Improved QNdefNfcSmartPosterRecord documentation + - Extended QML NearField type with polling property, tagFound() and tagRemoved signals + - Added QNdefNfcSmartPosterRecord::operator=() operator + + - Examples: + * Fixed several bugs in corkboard example + * Fixed hanging ndefeditor example when receiving invalid NFC requests + * Fixed loading of images in poster example + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Android +------- + + - Added support for Bluetooth Low Energy in Qt Bluetooth + - Avoided duplicated notifications for same device during Bluetooth device + discovery + +Linux/Bluez +----------- + +- Improved Bluez version detection. The previous check didn't handle these + "no Bluez available" case. diff --git a/dist/changes-5.5.1 b/dist/changes-5.5.1 new file mode 100644 index 0000000..e377026 --- /dev/null +++ b/dist/changes-5.5.1 @@ -0,0 +1,43 @@ +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 * +**************************************************************************** + +QtBluetooth +----------- + + - Fixed several minor documentation issues. + + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Linux/BlueZ +----------- + + - QLowEnergyCharacteristic + * Fixed reading of PropertyTypes which caused some bits to be set due to + missing initialization. + + - [QTBUG-47028] Fixed endless loop in QLowEnergyService::discoverDetails(). + + - Minor performance improvements when processing ATT_OP_READ_BY_TYPE_REQUESTS. diff --git a/dist/changes-5.6.0 b/dist/changes-5.6.0 new file mode 100644 index 0000000..3d34719 --- /dev/null +++ b/dist/changes-5.6.0 @@ -0,0 +1,89 @@ +Qt 5.6 introduces 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 * +**************************************************************************** + +QtBluetooth +----------- + + - [QTBUG-46377] Added QBluetoothSocket::(set)preferredSecurityFlag(). + - Q_DECLARE_METATYPE declarations added for various Q_ENUMS + - Fixed crash in btscanner example + - Added several documentation fixes + - Fixed wrong emission of CharacteristicWriteError where CharacteristicReadError + should have been emitted + - Fixed wrong emission of DescriptorWriteError where DescriptorReadError + should have been emitted + - Fixed wrong endianness handling in heartlistener example + +QtNfc +----- + + - API has been ported to Android + - Significantly improved implementation and documentation of QML NdefFilter + API + - Added general documentation improvements + - Fixed memory leak due to missing QQmlNdefRecord destructor + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Android +------- + + - Increased robustness of Bluetooth Low Energy Service detail discovery + - [QTBUG-49367] Fixed missing jar file creation due to wrong build dependencies + - [QTBUG-50125] Fixed missing invalidation of QLowEnergyService details on + disconnect from device + - [QTBUG-50345] Fixed QBluetoothSocket::bytesAvailable() + +Linux/Bluez +----------- + + - [MER#1231] Enforce proper checking of error codes during device discovery + when using Bluez 4.x + - [MER#1225] Adjusted QBluetoothSocket::peerName() to comply with Jolla security + restrictions + - [MER1230] Enforced pairing of StartDiscovery() and StopDiscovery() during device + discovery on Bluez 4 + - Fixed memory leak in Bluez 4 code path of QBluetoothServiceDiscoveryAgent + - [QTBUG-48481] Fixed crash during device discovery due to null pointer access on + Bluez 5 + - [QTBUG-49650] Forcing usage of unbuffered L2CAP sockets for GATT protocol + - [QTBUG-49402] Sanitized handling of app names when registering internal agents + The app name is used to name the dbus path and not every permissible app name + character is a permissible dbus path character + - Removed assert in QLowEnergyController which could be caused by malicious device + +QNX/BlackBerry +-------------- + + - Removed support for this platform from QtNfc + - Removed support for this platform from QtBluetooth + +iOS +--- + + - [QTBUG-48518] Fixed compile and crash bugs when using iOS 9.x + - [QTBUG-48713] Enabled support for Bluetooth system alert dialog + - Fixed threading related timer issues + - [QTBUG-49476] Moved Low Energy code base to non-main dispatch queue + - [QTBUG-50125] Fixed missing invalidation of QLowEnergyService details on + disconnect from device diff --git a/dist/changes-5.6.1 b/dist/changes-5.6.1 new file mode 100644 index 0000000..6535ae4 --- /dev/null +++ b/dist/changes-5.6.1 @@ -0,0 +1,60 @@ +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 * +**************************************************************************** + +QtBluetooth +----------- + + - Fixed various documentation issues. + - Improved QBluetoothServiceInfo QDebug operator. + +QtNfc +----- + + - [QTBUG-51860] Fixed crash related to incorrect QML import statement + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Android +------- + + - [QTBUG-52530] Added ACCESS_COURSE_LOCATION permission to QtBluetooth. + Android 6.0+ requires this type of permission for device discovery. + - [QTBUG-52154] Fixed Annotated URL example on Android. This Qt Nfc example + was not working due to missing Ndef message handler registration. The registration + is still not implemented but the example does not require it to properly work. + +iOS/OS X +-------- + + - [QTBUG-52324] Fixed details discovery of included/secondary BTLE services + on iOS and OS X + +Linux/Bluez +----------- + + - [QTBUG-47593] Improved QBluetoothSocket's service discovery on Bluez 5. This + happened if the targeted serial service did not advertise a custom uuid and a minimal + service discovery was used to identify the serial port service. In such cases + QBluetoothSocket never found the remote service. diff --git a/dist/changes-5.6.2 b/dist/changes-5.6.2 new file mode 100644 index 0000000..004aee3 --- /dev/null +++ b/dist/changes-5.6.2 @@ -0,0 +1,73 @@ +Qt 5.6.2 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.6.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/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 * +**************************************************************************** + +QtBluetooth +----------- + + - Done minor code cleanups. + - Added various general documentation improvements. + - Improved the documentation for QBluetoothDeviceInfo::minorDeviceClass(). + - [QTBUG-55073] Improved handling of calls to QBluetoothSocket::connectToService() + while an UnknownProtocol identifier was set as socket type. + +QtNfc +----- + + - [QTBUG-53616] Fixed NFC poster example and improved its documentation + - Worked around a clang bug where clang failed to export a default destructor. + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Android +------- + + - [QTBUG-53012] Increased BTLE scan timeout to 25s to increase chance of finding + remote devices. Qt 5.8 introduces a proper API for the problem. + - Fixed a problem which triggered BTLE searches on Android devices + without BTLE support. + - Fixed a problem where device discovery did not detect a devices major + and minor device class identifier. + - Fixed newDevice signal spamming in QBluetoothDeviceDiscoveryAgent. + This happened when SDP and BTLE scan revealed the same device with + different names. + +iOS/OS X +--------- + + - Fixed potential linker error on iOS. + - Added some minor code cleanups. + +Linux/Bluez +----------- + + - [QTBUG-51307] Fixed internal state problem in QBluetoothDeviceDiscoveryAgent + and QML BluetoothModel type. + - [QTBUG-53041] Fixed SDP scans on devices which do not support PUBLIC_BROWSE_GROUP + scans. + - [QTBUG-53715] Fixed premature device discovery abortion when triggering + start() - stop() - start() in quick order. + - [QTBUG-54055] Fixed build of QtBluetooth with BlueZ version which does not support + BTLE. + diff --git a/dist/changes-5.6.3 b/dist/changes-5.6.3 new file mode 100644 index 0000000..8dcd6b6 --- /dev/null +++ b/dist/changes-5.6.3 @@ -0,0 +1,47 @@ +Qt 5.6.3 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 * +**************************************************************************** + +QtNfc +----- + + - Android: + * [QTBUG-55297] Addressed an ODR violation in QLlcpServer + + +QtBluetooth +----------- + + - [QTBUG-56294] Fixed misleading error message in QBluetoothSocket. + + - Android: + * [QTBUG-45066] Fixed crash in QBluetoothDeviceDiscoveryAgent ctor due to + Java exception on some Android devices such as the HTC 10. + + - BlueZ: + * Made sdpscanner compilable with non C++11 compiler. + + - iOS/macOS: + * Replaced deprecated CBCentralManagerState enum and related values with + CBManagerState. This change was introduced by iOS 10. + * Fixed build on MacOSX10.12 SDK. Missing includes were added that allow + to build the module with 10.12 SDK and Xcode 8. diff --git a/dist/changes-5.7.0 b/dist/changes-5.7.0 new file mode 100644 index 0000000..1beb80a --- /dev/null +++ b/dist/changes-5.7.0 @@ -0,0 +1,56 @@ +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 * +**************************************************************************** + +QtBluetooth +----------- + + - Added API for Bluetooth Low Energy Peripheral support. This new API is + a Technology Preview and currently only supported on BlueZ. + - [QTBUG-52428] Added QLowEnergyConnectionParameters class to enable + adjustment of BTLE connection parameters + - Added operator!= for QBluetoothUuid + - Added Bluetooth Low Energy signed write support on Linux/BlueZ and Android + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +iOS/tvOS +-------- + + - Added support for QtBluetooth on tvOS. diff --git a/dist/changes-5.7.1 b/dist/changes-5.7.1 new file mode 100644 index 0000000..e04fa83 --- /dev/null +++ b/dist/changes-5.7.1 @@ -0,0 +1,79 @@ +Qt 5.7.1 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.7.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.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 * +**************************************************************************** + +QtBluetooth +----------- + - Improved heartlistener example when handling BTLE notifications. + - Improved the documentation for QBluetoothDeviceInfo::minorDeviceClass(). + - [QTBUG-55073] Improved handling of calls to QBluetoothSocket::connectToService() + while an UnknownProtocol identifier was set as socket type. + - [QTBUG-56294] Fixed misleading error messages in QBLuetoothSocket Dummy + implementation. + +QtNfc +----- + + - [QTBUG-53616] Fixed NFC poster example and improved its documentation + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Android +------- + + - Fixed a problem which triggered BTLE searches on Android devices + without BTLE support. + - Added workaround for clang default destructor export bug. + - Ensured that JNI_OnLoad is not called more than once. THis is a workaround forward + https://code.google.com/p/android/issues/detail?id=215069. + - Fixed QtBluetooth working when using Android services. + - Fixed QtNfc handling when using Android services. + - Fixed Nfc corkboard example due to incomplete Manifest file. + - Fixed a problem where device discovery did not detect a devices major + and minor device class identifier. + - Fixed newDevice signal spamming in QBluetoothDeviceDiscoveryAgent. + This happened when SDP and BTLE scan revealed the same device with + different names. + +iOS/macOS +--------- + + - Fixed potential linker error on iOS. + - Added some minor code cleanups. + - Added support for iOS 10 and macOS 10.12 SDKs. + +Linux/Bluez +----------- + + - [QTBUG-51307] Fixed internal state problem in QBluetoothDeviceDiscoveryAgent + and QML BluetoothModel type. + - [QTBUG-53041] Fixed SDP scans on devices which do not support PUBLIC_BROWSE_GROUP + scans. + - [QTBUG-53715] Fixed premature device discovery abortion when triggering + start() - stop() - start() in quick order. + - [QTBUG-53683] Fixed build on Linux using clang/trunk + - [QTBUG-54055] Fixed build of QtBluetooth with BlueZ version which does not support + BTLE. + - [QTBUG-54475] Improved failure handling in QBluetoothSocket when ::write() fails. + - [QTBUG-54475] Highlighted incomplete handling of BTLE packet writes. diff --git a/dist/changes-5.8.0 b/dist/changes-5.8.0 new file mode 100644 index 0000000..4e013c1 --- /dev/null +++ b/dist/changes-5.8.0 @@ -0,0 +1,76 @@ +Qt 5.8 introduces many new features and improvements as well as bugfixes +over the 5.7.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.8 series is binary compatible with the 5.7.x series. +Applications compiled for 5.7 will continue to run with 5.8. + +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 * +**************************************************************************** + +QtBluetooth +----------- + + - Added Bluetooth Low Energy peripheral role support for iOS/macOS. + - Added WinRT support for QBluetoothDeviceDiscoveryAgent and Bluetooth Low + Energy central role. + - [QTBUG-53012] Added API to set the timeout of Bluetooth Low Energy device + discoveries. + - Fixed minor documentation issues. + - [QTBUG-46253] Added API to select the device discovery mode utilized by + QBluetoothDeviceDiscoveryAgent (btle vs classic vs combined). + - [QTBUG-46377] Added preferredSecurityGlags() and setPreferredSecurityFlags() + methods to QBluetoothSocket. + - Adjusted QtBluetooth to the changes required by the Qt Lite build system. + +QtNfc +----- + + - [QTBUG-55297] Fixed ODR violation in QLlcpServer on Android. + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Android +------- + + - [QTBUG-56625] Parsed list of advertised services found in LE scan + record and pass them to API client via QBluetoothDeviceInfo::serviceUuids() + - [QTBUG-55035] Added support for new runtime permission check when running Bluetooth + applications on Android 7.x. The Bluetooth stack requires Location permissions + when running a device discovery. + - [QTBUG-52692] Redesigned/Simplified Android central role implementation and prevented + blocking of service discovery in case the peripheral does not behave as per standard. + - [QTBUG-56625] Improved Low Energy device discovery by evaluating scan records and + feeding their content into QBluetoothDeviceInfo instances. + - [QTBUG-45066] Fixed crash in QBluetoothDeviceDiscoveryAgent ctor due to Java exception. + +iOS/macOS +-------- + + - Removed iOS v 6.x support from the code base + - [QTBUG-56898] Fixed a crash when writing GATT attributes. + - Adjusted code base to latest macOS and iOS releases. + - [QTBUG-53331] Forced error signal when calling + QBluetoothLocalDevice::requestPairing(). + - [QTBUG-52690] Added QLowEnergyController::remoteDeviceUuid() to expose the iOS/macOS + specific device UUID. Those two platforms do not expose Bluetooth addresses to + application developers. + +Linux/Bluez +----------- + + - Fixed build of sdpscanner due to incorrect build order + diff --git a/dist/changes-5.9.0 b/dist/changes-5.9.0 new file mode 100644 index 0000000..2c8e162 --- /dev/null +++ b/dist/changes-5.9.0 @@ -0,0 +1,89 @@ +Qt 5.9 introduces many new features and improvements as well as bugfixes +over the 5.8.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.9 series is binary compatible with the 5.8.x series. +Applications compiled for 5.8 will continue to run with 5.9. + +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 * +**************************************************************************** + +QtBluetooth +----------- + + - Added various improvements to the existing Bluetooth examples. + - Added various documentation improvements. + - Added new heartrate-game example replacing the old heartlistener example. + +QtNfc +----- + + - Introduced QNearFieldTarget::maxCommandLength() to make it possible to + check the maximum supported length for commands. + - Introduced QNearFieldTarget::(set)keepConnection() permitting control over + the connection behavior. If this flag is set the NFC device does not disconnect + automatically after reading an NFC message. QNearFieldTarget::disconnect() + was added to permit manual separation of the connection. This feature is currently + only implemented on Android. + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Android +------- + + - Added support for QNearFieldTarget::sendCommand(). + - Fixed crash due to references leak in QBluetoothDeviceDiscoveryAgent on Android. + - Added more detailed GATT error reporting. + - [QTBUG-58085] Fixed unnecessarily dangerous right request for ACCESS_COURSE_LOCATION + during BTLE scanning on Android platforms below version 23. + - Prevented nil exception if reading of a descriptor failed during discovery. + - [QTBUG-58056] Fixed not reported characteristic if system failed to read its value + during the service discovery. + - [QTBUG-53483] Added support for BTLE peripheral on Android. + - [QTBUG-56078] Improved likelyhood that BluetoothGatt.connectGatt() succeeds. This addresses + the GATT_ERROR 133 (0x85) problem on Android v23+ devices. There is no fix available + on older Android versions. + - [QTBUG-57646] Fixed problems when using QtNfc when running as a service. + - [QTBUG-59343] Fixed crash on restart of NFC applications. + - [QTBUG-59455] Fixed detection of all NFC tags even non-NDEF tags. + - [QTBUG-59917] Added workaround for BLUETOOTH_PRIVILEGED security exception when + attempting to read a BTLE HID service. + +iOS/macOS +--------- + + - Fixed missing behavior whereby QLowEnergyController::disconnectFromDevice() + did not stop advertisement. + - [QTBUG-58080] Changed priority of advertised BTLE device name. Qt prefers the + device name as set by the advertisement data over the GAP name. + +Linux/BlueZ +----------- + + - [QTBUG-52692] Prevented stalling of Linux central BTLE implementation. + - Fixed continued advertisement of peripheral data once + QLowEnergyController::disconnectFromDevice() was called. Public documentation + was added to publically state the behavior. + - [QTBUG-57417] Fixed duplicated QBluetoothLocalAdapter:deviceConnected() and + deviceDisconnected() signal emissions if the local device has several Bluetooth adapter. + - [QTBUG-59392] Ensured that pairing passkey and pincode are truly random. + - [QTBUG-59754] Ensured that QLowEnergyController::connected() is emitted on peripheral. + Previously the signal was never emitted. + +WinRT +----- + + - [QTBUG-37779] Added support for Classic Bluetooth on WinRT. diff --git a/dist/changes-5.9.1 b/dist/changes-5.9.1 new file mode 100644 index 0000000..d8ae779 --- /dev/null +++ b/dist/changes-5.9.1 @@ -0,0 +1,67 @@ +Qt 5.9.1 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.9.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.9 series is binary compatible with the 5.8.x series. +Applications compiled for 5.8 will continue to run with 5.9. + +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 * +**************************************************************************** + +QtBluetooth +----------- + + - Fixed several compiler warnings through the code base adopting new compilers + such as GCC 7. + - Added better documentation of GPL license usage via sdpscanner on BLueZ. + The GPL license usage is limited to separate process and does not taint + QtBluetooth users. + - Added limitation to do classic device discovery only inside + QBLuetoothServiceDiscoveryAgent. Prior to this change + QBLuetoothServiceDiscoveryAgent always performed a search for Low Energy + devices too. This is not necessary and reduces the time for SDP + discoveries. + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Android +------- + + - [QTBUG-61392] Added workaround for swapped uuids obtained when doing SDP + discovery on Android 6.0.1 or later systems. + - Removed workaround for QBluetoothSocket that uses the private + BluetoothDevice.getServiceChannel() API from Android 6.0+ platforms. + The private API was removed in Android 6.0. + - [QTBUG-61321] Added code handler to catch BluetoothGatt.GATT_FAILURE. + - Fixed an issue where a QBLuetoothServiceDiscoveryAgent run would fail + to find any service because the last device for which the service discovery + was done failed. + +Linux/Bluez +----------- + + - [QTBUG-58941] Fixed failure to re-advertise peripheral after + QLowEnergyController disconnect and restart. + - [QTBUG-55150] Fixed handling of concurrent BTLE connections via QtBluetooth + and for example BlueZ tools like bluetoothctl. There can only be one connection + at a given time. Under the new behavior the current process closes every + BTLE connection not managed by itself. + - Fixed buffer overrun when handling GATT Blob read requests. + - [QTBUG-46776] Added code to detect whether a found Bluetooth address is random + or public. The standard BlueZ DBus interface does not expose this flag. + This requires CAP_NET_ADMIN permissions though. diff --git a/dist/changes-5.9.2 b/dist/changes-5.9.2 new file mode 100644 index 0000000..e1f70f7 --- /dev/null +++ b/dist/changes-5.9.2 @@ -0,0 +1,75 @@ +Qt 5.9.2 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.9.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.9 series is binary compatible with the 5.8.x series. +Applications compiled for 5.8 will continue to run with 5.9. + +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 * +**************************************************************************** + +QtBluetooth +----------- + + - Fixed several documentation issues in QML chat example. + - Improved QML BluetoothSocket type documentation. + - Fixed QML chat example not handling all socket states leading to wrong + state reports. + - [QTBUG-61542] Added workaround for QTBUG-61392 to QML chat example. + - [QTBUG-61392] Added Android platform bug workaround to all Bluetooth examples + requiring the workaround. + - Added various improvements to pingpong example. + - [QTBUG-57847] Ensured that QBluetoothDeviceDiscoveryAgent::deviceDiscovered() + is continuously emitted when the Low Energy search timeout is set to 0. + - [QTBUG-60131] Fixed never ending recursion in QBluetoothDeviceDiscoveryAgent::stop(). + +QtNfc +----- + + - [QTBUG-60268] Fixed QNdefNfcActRecord::action for platforms with unsigned chat + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Android +------- + + - [QTBUG-58190] & [QTBUG-60830] Fixed concurrency bug in QBluetoothSocket::canReadLine(). + - Addressed case whereby QBluetoothSocket::bytesWritten() was emitted even if + the write failed. + - [QTBUG-61755] Added ability to negotiate the MTU when communicating with + other BTLE devices. + - Fixed dead lock during QLowEnergyController's service discovery when the last + to be discovered characteristic or descriptor is read only. + +Linux/Bluez +----------- + + - [QTBUG-61554] Added the means to define GAP/GATT services for central roles. + +macOS +----- + + - [QTBUG-62658] Enabled macOS 10.13 in QtBluetooth. + +Windows UWP +----------- + + - Fixed several crashes when using QBluetoothSocket. + - Fixed crash in QBluetoothServer::nextPendingConnection(). + - Fixed missing QBluetoothDeviceDiscoveryAgent::finished() signal when the + device scan only targets classic device search. diff --git a/dist/changes-5.9.3 b/dist/changes-5.9.3 new file mode 100644 index 0000000..ea702da --- /dev/null +++ b/dist/changes-5.9.3 @@ -0,0 +1,37 @@ +Qt 5.9.3 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.9.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.9 series is binary compatible with the 5.8.x series. +Applications compiled for 5.8 will continue to run with 5.9. + +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. + +**************************************************************************** +* Qt 5.9.3 Changes * +**************************************************************************** + +QtBluetooth +----------- + + - Updated FDL and BSD license headers throughout the module + - [QTBUG-63630] Added warning about incorrect thread/runloop usage on Apple + platforms. The IOBluetooth framework used by QtBluetooth requires CFRunLoops + - [QTBUG-63210] Fixed build using -no-pch on Windows + +QtNfc +----- + + - Updated FDL and BSD license headers throughout the module + - [QTBUG-62858] Fixed writing of NDefMessages on Android + diff --git a/dist/changes-5.9.4 b/dist/changes-5.9.4 new file mode 100644 index 0000000..746c43d --- /dev/null +++ b/dist/changes-5.9.4 @@ -0,0 +1,31 @@ +Qt 5.9.4 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.9.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.9 series is binary compatible with the 5.8.x series. +Applications compiled for 5.8 will continue to run with 5.9. + +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. + +**************************************************************************** +* Qt 5.9.4 Changes * +**************************************************************************** + +QtBLuetooth +----------- + + - [QTBUG-64669] Fixed hanging service discovery state when remote device + does not respond to ATT read requests. + - [QTBUG-64597] Fixed compilation of heartrate server example with disabled + gui module. + - Added minor improvements to Windows UWP builds. diff --git a/dist/changes-5.9.5 b/dist/changes-5.9.5 new file mode 100644 index 0000000..8a69c52 --- /dev/null +++ b/dist/changes-5.9.5 @@ -0,0 +1,29 @@ +Qt 5.9.5 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.9.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.9 series is binary compatible with the 5.8.x series. +Applications compiled for 5.9 will continue to run with 5.9. + +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. + +**************************************************************************** +* Qt 5.9.5 Changes * +**************************************************************************** + +QtBluetooth +----------- + + - [QTBUG-65801] Fixed never ending QBLuetoothDeviceDiscoveryAhgent::start(ClassMethod) + on WinRT/UWP. + - Fixed internal cleanup issue in QBluetoothSocket on WinRT/UWP. diff --git a/dist/changes-5.9.6 b/dist/changes-5.9.6 new file mode 100644 index 0000000..f0179a5 --- /dev/null +++ b/dist/changes-5.9.6 @@ -0,0 +1,24 @@ +Qt 5.9.6 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.9.0 through 5.9.5. + +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.9 series is binary compatible with the 5.8.x series. +Applications compiled for 5.8 will continue to run with 5.9. + +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. + +**************************************************************************** +* Qt 5.9.6 Changes * +**************************************************************************** + + - This release contains only minor code improvements. diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 0000000..d009126 --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +qt_examples_build_begin(EXTERNAL_BUILD) + +if(TARGET Qt6::Bluetooth) + add_subdirectory(bluetooth) +endif() +if(TARGET Qt6::Nfc) + add_subdirectory(nfc) +endif() + +qt_examples_build_end() diff --git a/examples/bluetooth/CMakeLists.txt b/examples/bluetooth/CMakeLists.txt new file mode 100644 index 0000000..8ea6028 --- /dev/null +++ b/examples/bluetooth/CMakeLists.txt @@ -0,0 +1,11 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +qt_internal_add_example(heartrate-server) +if(TARGET Qt6::Widgets) + qt_internal_add_example(btchat) +endif() +if(TARGET Qt6::Quick) + qt_internal_add_example(lowenergyscanner) + qt_internal_add_example(heartrate-game) +endif() diff --git a/examples/bluetooth/bluetooth.pro b/examples/bluetooth/bluetooth.pro new file mode 100644 index 0000000..7b2484d --- /dev/null +++ b/examples/bluetooth/bluetooth.pro @@ -0,0 +1,10 @@ +TEMPLATE = subdirs + +SUBDIRS += heartrate-server + +qtHaveModule(widgets) { + SUBDIRS += btchat +} + +qtHaveModule(quick): SUBDIRS += lowenergyscanner \ + heartrate-game diff --git a/examples/bluetooth/btchat/CMakeLists.txt b/examples/bluetooth/btchat/CMakeLists.txt new file mode 100644 index 0000000..667dc19 --- /dev/null +++ b/examples/bluetooth/btchat/CMakeLists.txt @@ -0,0 +1,66 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(btchat LANGUAGES CXX) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/bluetooth/btchat") + +find_package(Qt6 REQUIRED COMPONENTS Bluetooth Core Widgets) + +qt_standard_project_setup() + +qt_add_executable(btchat + chat.cpp chat.h chat.ui + chatclient.cpp chatclient.h + chatserver.cpp chatserver.h + main.cpp + remoteselector.cpp remoteselector.h remoteselector.ui +) + +set(icon_files) +foreach(icon IN ITEMS bluetooth bluetooth_dark send send_dark) + foreach(scale IN ITEMS "" "@2" "@3" "@4") + list(APPEND icon_files "icons/btchat/24x24${scale}/${icon}.png") + endforeach() +endforeach() + +qt_add_resources(btchat "theme" FILES + ${icon_files} + icons/btchat/index.theme +) + +set_target_properties(btchat PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(btchat PRIVATE + Qt6::Bluetooth + Qt6::Core + Qt6::Widgets +) + +if (APPLE) + # Using absolute path for shared plist files is a Ninja bug workaround + get_filename_component(SHARED_PLIST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../shared ABSOLUTE) + if (IOS) + set_target_properties(btchat PROPERTIES + MACOSX_BUNDLE_INFO_PLIST "${SHARED_PLIST_DIR}/Info.cmake.ios.plist" + ) + else() + set_target_properties(btchat PROPERTIES + MACOSX_BUNDLE_INFO_PLIST "${SHARED_PLIST_DIR}/Info.cmake.macos.plist" + ) + endif() +endif() + +install(TARGETS btchat + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/bluetooth/btchat/btchat.pro b/examples/bluetooth/btchat/btchat.pro new file mode 100644 index 0000000..0d7b5f7 --- /dev/null +++ b/examples/bluetooth/btchat/btchat.pro @@ -0,0 +1,51 @@ +TEMPLATE = app +TARGET = btchat + +QT = core bluetooth widgets +requires(qtConfig(listwidget)) + +SOURCES = \ + main.cpp \ + chat.cpp \ + remoteselector.cpp \ + chatserver.cpp \ + chatclient.cpp + +HEADERS = \ + chat.h \ + remoteselector.h \ + chatserver.h \ + chatclient.h + +FORMS = \ + chat.ui \ + remoteselector.ui + +theme_resources.files = \ + icons/btchat/24x24/bluetooth.png \ + icons/btchat/24x24/bluetooth_dark.png \ + icons/btchat/24x24/send.png \ + icons/btchat/24x24/send_dark.png \ + icons/btchat/24x24@2/bluetooth.png \ + icons/btchat/24x24@2/bluetooth_dark.png \ + icons/btchat/24x24@2/send.png \ + icons/btchat/24x24@2/send_dark.png \ + icons/btchat/24x24@3/bluetooth.png \ + icons/btchat/24x24@3/bluetooth_dark.png \ + icons/btchat/24x24@3/send.png \ + icons/btchat/24x24@3/send_dark.png \ + icons/btchat/24x24@4/bluetooth.png \ + icons/btchat/24x24@4/bluetooth_dark.png \ + icons/btchat/24x24@4/send.png \ + icons/btchat/24x24@4/send_dark.png \ + icons/btchat/index.theme + +theme_resources.prefix = / + +RESOURCES += theme_resources + +ios: QMAKE_INFO_PLIST = ../shared/Info.qmake.ios.plist +macos: QMAKE_INFO_PLIST = ../shared/Info.qmake.macos.plist + +target.path = $$[QT_INSTALL_EXAMPLES]/bluetooth/btchat +INSTALLS += target diff --git a/examples/bluetooth/btchat/chat.cpp b/examples/bluetooth/btchat/chat.cpp new file mode 100644 index 0000000..bf79490 --- /dev/null +++ b/examples/bluetooth/btchat/chat.cpp @@ -0,0 +1,260 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "chat.h" +#include "chatclient.h" +#include "chatserver.h" +#include "remoteselector.h" +#include "ui_chat.h" + +#include + +#include +#include +#include + +#include +#include + +#if QT_CONFIG(permissions) +#include +#include + +#include +#endif + +using namespace Qt::StringLiterals; + +static constexpr auto serviceUuid = "e8e10f95-1a70-4b27-9ccf-02010264e9c8"_L1; +#ifdef Q_OS_ANDROID +static constexpr auto reverseUuid = "c8e96402-0102-cf9c-274b-701a950fe1e8"_L1; +#endif + +Chat::Chat(QWidget *parent) + : QDialog(parent), ui(new Ui::Chat) +{ + //! [Construct UI] + ui->setupUi(this); + + connect(ui->connectButton, &QPushButton::clicked, this, &Chat::connectClicked); + connect(ui->sendButton, &QPushButton::clicked, this, &Chat::sendClicked); + //! [Construct UI] + ui->connectButton->setFocus(); + + QStyleHints *styleHints = qGuiApp->styleHints(); + updateIcons(styleHints->colorScheme()); + connect(styleHints, &QStyleHints::colorSchemeChanged, this, &Chat::updateIcons); + + initBluetooth(); +} + +Chat::~Chat() +{ + qDeleteAll(clients); + delete ui; +} + +void Chat::initBluetooth() +{ +#if QT_CONFIG(permissions) + QBluetoothPermission permission{}; + switch (qApp->checkPermission(permission)) { + case Qt::PermissionStatus::Undetermined: + qApp->requestPermission(permission, this, &Chat::initBluetooth); + return; + case Qt::PermissionStatus::Denied: + QMessageBox::warning(this, tr("Missing permissions"), + tr("Permissions are needed to use Bluetooth. " + "Please grant the permissions to this " + "application in the system settings.")); + qApp->quit(); + return; + case Qt::PermissionStatus::Granted: + break; // proceed to initialization + } +#endif // QT_CONFIG(permissions) + + localAdapters = QBluetoothLocalDevice::allDevices(); + if (localAdapters.size() < 2) { + ui->localAdapterBox->setVisible(false); + } else { + //we ignore more than two adapters + ui->localAdapterBox->setVisible(true); + ui->firstAdapter->setText(tr("Default (%1)", "%1 = Bluetooth address"). + arg(localAdapters.at(0).address().toString())); + ui->secondAdapter->setText(localAdapters.at(1).address().toString()); + ui->firstAdapter->setChecked(true); + connect(ui->firstAdapter, &QRadioButton::clicked, this, &Chat::newAdapterSelected); + connect(ui->secondAdapter, &QRadioButton::clicked, this, &Chat::newAdapterSelected); + } + + // make discoverable + if (!localAdapters.isEmpty()) { + QBluetoothLocalDevice adapter(localAdapters.at(0).address()); + adapter.setHostMode(QBluetoothLocalDevice::HostDiscoverable); + } else { + qWarning("Local adapter is not found! The application might work incorrectly."); + } + + //! [Create Chat Server] + server = new ChatServer(this); + connect(server, QOverload::of(&ChatServer::clientConnected), + this, &Chat::clientConnected); + connect(server, QOverload::of(&ChatServer::clientDisconnected), + this, QOverload::of(&Chat::clientDisconnected)); + connect(server, &ChatServer::messageReceived, + this, &Chat::showMessage); + connect(this, &Chat::sendMessage, server, &ChatServer::sendMessage); + server->startServer(); + //! [Create Chat Server] + + //! [Get local device name] + localName = QBluetoothLocalDevice().name(); + //! [Get local device name] +} + +void Chat::updateIcons(Qt::ColorScheme scheme) +{ + const QString bluetoothIconName = (scheme == Qt::ColorScheme::Dark) ? u"bluetooth_dark"_s + : u"bluetooth"_s; + const QString sendIconName = (scheme == Qt::ColorScheme::Dark) ? u"send_dark"_s : u"send"_s; + ui->sendButton->setIcon(QIcon::fromTheme(sendIconName)); + ui->connectButton->setIcon(QIcon::fromTheme(bluetoothIconName)); +} + +//! [clientConnected clientDisconnected] +void Chat::clientConnected(const QString &name) +{ + ui->chat->insertPlainText(QString::fromLatin1("%1 has joined chat.\n").arg(name)); +} + +void Chat::clientDisconnected(const QString &name) +{ + ui->chat->insertPlainText(QString::fromLatin1("%1 has left.\n").arg(name)); +} +//! [clientConnected clientDisconnected] + +//! [connected] +void Chat::connected(const QString &name) +{ + ui->chat->insertPlainText(QString::fromLatin1("Joined chat with %1.\n").arg(name)); +} +//! [connected] + +void Chat::newAdapterSelected() +{ + const int newAdapterIndex = adapterFromUserSelection(); + if (currentAdapterIndex != newAdapterIndex) { + server->stopServer(); + currentAdapterIndex = newAdapterIndex; + const QBluetoothHostInfo info = localAdapters.at(currentAdapterIndex); + QBluetoothLocalDevice adapter(info.address()); + adapter.setHostMode(QBluetoothLocalDevice::HostDiscoverable); + server->startServer(info.address()); + localName = info.name(); + } +} + +int Chat::adapterFromUserSelection() const +{ + int result = 0; + QBluetoothAddress newAdapter = localAdapters.at(0).address(); + + if (ui->secondAdapter->isChecked()) { + newAdapter = localAdapters.at(1).address(); + result = 1; + } + return result; +} + +void Chat::reactOnSocketError(const QString &error) +{ + ui->chat->insertPlainText(QString::fromLatin1("%1\n").arg(error)); +} + +//! [clientDisconnected] +void Chat::clientDisconnected() +{ + ChatClient *client = qobject_cast(sender()); + if (client) { + clients.removeOne(client); + client->deleteLater(); + } +} +//! [clientDisconnected] + +//! [Connect to remote service] +void Chat::connectClicked() +{ + ui->connectButton->setEnabled(false); + + // scan for services + const QBluetoothAddress adapter = localAdapters.isEmpty() ? + QBluetoothAddress() : + localAdapters.at(currentAdapterIndex).address(); + + RemoteSelector remoteSelector(adapter); +#ifdef Q_OS_ANDROID + // QTBUG-61392 + Q_UNUSED(serviceUuid); + remoteSelector.startDiscovery(QBluetoothUuid(reverseUuid)); +#else + remoteSelector.startDiscovery(QBluetoothUuid(serviceUuid)); +#endif + if (remoteSelector.exec() == QDialog::Accepted) { + QBluetoothServiceInfo service = remoteSelector.service(); + + qDebug() << "Connecting to service" << service.serviceName() + << "on" << service.device().name(); + + // Create client + ChatClient *client = new ChatClient(this); + + connect(client, &ChatClient::messageReceived, + this, &Chat::showMessage); + connect(client, &ChatClient::disconnected, + this, QOverload<>::of(&Chat::clientDisconnected)); + connect(client, QOverload::of(&ChatClient::connected), + this, &Chat::connected); + connect(client, &ChatClient::socketErrorOccurred, + this, &Chat::reactOnSocketError); + connect(this, &Chat::sendMessage, client, &ChatClient::sendMessage); + client->startClient(service); + + clients.append(client); + } + + ui->connectButton->setEnabled(true); +} +//! [Connect to remote service] + +//! [sendClicked] +void Chat::sendClicked() +{ + ui->sendButton->setEnabled(false); + ui->sendText->setEnabled(false); + + showMessage(localName, ui->sendText->text()); + emit sendMessage(ui->sendText->text()); + + ui->sendText->clear(); + + ui->sendText->setEnabled(true); + ui->sendButton->setEnabled(true); +#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) + // avoid keyboard automatically popping up again on mobile devices + ui->sendButton->setFocus(); +#else + ui->sendText->setFocus(); +#endif +} +//! [sendClicked] + +//! [showMessage] +void Chat::showMessage(const QString &sender, const QString &message) +{ + ui->chat->moveCursor(QTextCursor::End); + ui->chat->insertPlainText(QString::fromLatin1("%1: %2\n").arg(sender, message)); + ui->chat->ensureCursorVisible(); +} +//! [showMessage] diff --git a/examples/bluetooth/btchat/chat.h b/examples/bluetooth/btchat/chat.h new file mode 100644 index 0000000..ca5318c --- /dev/null +++ b/examples/bluetooth/btchat/chat.h @@ -0,0 +1,58 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include + +#include + +QT_BEGIN_NAMESPACE +namespace Ui { + class Chat; +} +QT_END_NAMESPACE + +class ChatServer; +class ChatClient; + +//! [declaration] +class Chat : public QDialog +{ + Q_OBJECT + +public: + explicit Chat(QWidget *parent = nullptr); + ~Chat(); + +signals: + void sendMessage(const QString &message); + +private slots: + void connectClicked(); + void sendClicked(); + + void showMessage(const QString &sender, const QString &message); + + void clientConnected(const QString &name); + void clientDisconnected(const QString &name); + void clientDisconnected(); + void connected(const QString &name); + void reactOnSocketError(const QString &error); + + void newAdapterSelected(); + + void initBluetooth(); + + void updateIcons(Qt::ColorScheme scheme); + +private: + int adapterFromUserSelection() const; + int currentAdapterIndex = 0; + Ui::Chat *ui; + + ChatServer *server = nullptr; + QList clients; + QList localAdapters; + + QString localName; +}; +//! [declaration] diff --git a/examples/bluetooth/btchat/chat.ui b/examples/bluetooth/btchat/chat.ui new file mode 100644 index 0000000..bea3d2e --- /dev/null +++ b/examples/bluetooth/btchat/chat.ui @@ -0,0 +1,115 @@ + + + Chat + + + + 0 + 0 + 400 + 300 + + + + Bluetooth Chat + + + + + + Local Bluetooth Adapter + + + false + + + + + + Default + + + + + + + + + + + + + + + + + Qt::NoFocus + + + + + + + + + Enter message + + + + + + + + + + true + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Connect + + + false + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + diff --git a/examples/bluetooth/btchat/chatclient.cpp b/examples/bluetooth/btchat/chatclient.cpp new file mode 100644 index 0000000..18e100a --- /dev/null +++ b/examples/bluetooth/btchat/chatclient.cpp @@ -0,0 +1,89 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "chatclient.h" + +#include +#include + +#include + +using namespace Qt::StringLiterals; + +ChatClient::ChatClient(QObject *parent) + : QObject(parent) +{ +} + +ChatClient::~ChatClient() +{ + stopClient(); +} + +//! [startClient] +void ChatClient::startClient(const QBluetoothServiceInfo &remoteService) +{ + if (socket) + return; + + // Connect to service + socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol); + qDebug() << "Create socket"; + socket->connectToService(remoteService); + qDebug() << "ConnectToService done"; + + connect(socket, &QBluetoothSocket::readyRead, this, &ChatClient::readSocket); + connect(socket, &QBluetoothSocket::connected, this, QOverload<>::of(&ChatClient::connected)); + connect(socket, &QBluetoothSocket::disconnected, this, &ChatClient::disconnected); + connect(socket, &QBluetoothSocket::errorOccurred, this, &ChatClient::onSocketErrorOccurred); +} +//! [startClient] + +//! [stopClient] +void ChatClient::stopClient() +{ + delete socket; + socket = nullptr; +} +//! [stopClient] + +//! [readSocket] +void ChatClient::readSocket() +{ + if (!socket) + return; + + while (socket->canReadLine()) { + QByteArray line = socket->readLine().trimmed(); + emit messageReceived(socket->peerName(), + QString::fromUtf8(line.constData(), line.length())); + } +} +//! [readSocket] + +//! [sendMessage] +void ChatClient::sendMessage(const QString &message) +{ + QByteArray text = message.toUtf8() + '\n'; + socket->write(text); +} +//! [sendMessage] + +void ChatClient::onSocketErrorOccurred(QBluetoothSocket::SocketError error) +{ + if (error == QBluetoothSocket::SocketError::NoSocketError) + return; + + QMetaEnum metaEnum = QMetaEnum::fromType(); + QString errorString = socket->peerName() + ' '_L1 + + metaEnum.valueToKey(static_cast(error)) + " occurred"_L1; + + emit socketErrorOccurred(errorString); +} + +//! [connected] +void ChatClient::connected() +{ + emit connected(socket->peerName()); +} +//! [connected] diff --git a/examples/bluetooth/btchat/chatclient.h b/examples/bluetooth/btchat/chatclient.h new file mode 100644 index 0000000..da75bf5 --- /dev/null +++ b/examples/bluetooth/btchat/chatclient.h @@ -0,0 +1,44 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef CHATCLIENT_H +#define CHATCLIENT_H + +#include + +#include + +QT_FORWARD_DECLARE_CLASS(QBluetoothServiceInfo) + +//! [declaration] +class ChatClient : public QObject +{ + Q_OBJECT + +public: + explicit ChatClient(QObject *parent = nullptr); + ~ChatClient(); + + void startClient(const QBluetoothServiceInfo &remoteService); + void stopClient(); + +public slots: + void sendMessage(const QString &message); + +signals: + void messageReceived(const QString &sender, const QString &message); + void connected(const QString &name); + void disconnected(); + void socketErrorOccurred(const QString &errorString); + +private slots: + void readSocket(); + void connected(); + void onSocketErrorOccurred(QBluetoothSocket::SocketError); + +private: + QBluetoothSocket *socket = nullptr; +}; +//! [declaration] + +#endif // CHATCLIENT_H diff --git a/examples/bluetooth/btchat/chatserver.cpp b/examples/bluetooth/btchat/chatserver.cpp new file mode 100644 index 0000000..addbc1a --- /dev/null +++ b/examples/bluetooth/btchat/chatserver.cpp @@ -0,0 +1,164 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "chatserver.h" + +#include +#include + +using namespace Qt::StringLiterals; + +//! [Service UUID] +static constexpr auto serviceUuid = "e8e10f95-1a70-4b27-9ccf-02010264e9c8"_L1; +//! [Service UUID] + +ChatServer::ChatServer(QObject *parent) + : QObject(parent) +{ +} + +ChatServer::~ChatServer() +{ + stopServer(); +} + +void ChatServer::startServer(const QBluetoothAddress& localAdapter) +{ + if (rfcommServer) + return; + + //! [Create the server] + rfcommServer = new QBluetoothServer(QBluetoothServiceInfo::RfcommProtocol, this); + connect(rfcommServer, &QBluetoothServer::newConnection, + this, QOverload<>::of(&ChatServer::clientConnected)); + bool result = rfcommServer->listen(localAdapter); + if (!result) { + qWarning() << "Cannot bind chat server to" << localAdapter.toString(); + return; + } + //! [Create the server] + + //serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceRecordHandle, (uint)0x00010010); + + QBluetoothServiceInfo::Sequence profileSequence; + QBluetoothServiceInfo::Sequence classId; + classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ServiceClassUuid::SerialPort)); + classId << QVariant::fromValue(quint16(0x100)); + profileSequence.append(QVariant::fromValue(classId)); + serviceInfo.setAttribute(QBluetoothServiceInfo::BluetoothProfileDescriptorList, + profileSequence); + + classId.clear(); + classId << QVariant::fromValue(QBluetoothUuid(serviceUuid)); + classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ServiceClassUuid::SerialPort)); + + serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classId); + + //! [Service name, description and provider] + serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceName, tr("Bt Chat Server")); + serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceDescription, + tr("Example bluetooth chat server")); + serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceProvider, tr("qt-project.org")); + //! [Service name, description and provider] + + //! [Service UUID set] + serviceInfo.setServiceUuid(QBluetoothUuid(serviceUuid)); + //! [Service UUID set] + + //! [Service Discoverability] + const auto groupUuid = QBluetoothUuid(QBluetoothUuid::ServiceClassUuid::PublicBrowseGroup); + QBluetoothServiceInfo::Sequence publicBrowse; + publicBrowse << QVariant::fromValue(groupUuid); + serviceInfo.setAttribute(QBluetoothServiceInfo::BrowseGroupList, publicBrowse); + //! [Service Discoverability] + + //! [Protocol descriptor list] + QBluetoothServiceInfo::Sequence protocolDescriptorList; + QBluetoothServiceInfo::Sequence protocol; + protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ProtocolUuid::L2cap)); + protocolDescriptorList.append(QVariant::fromValue(protocol)); + protocol.clear(); + protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ProtocolUuid::Rfcomm)) + << QVariant::fromValue(quint8(rfcommServer->serverPort())); + protocolDescriptorList.append(QVariant::fromValue(protocol)); + serviceInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, + protocolDescriptorList); + //! [Protocol descriptor list] + + //! [Register service] + serviceInfo.registerService(localAdapter); + //! [Register service] +} + +//! [stopServer] +void ChatServer::stopServer() +{ + // Unregister service + serviceInfo.unregisterService(); + + // Close sockets + qDeleteAll(clientSockets); + clientNames.clear(); + + // Close server + delete rfcommServer; + rfcommServer = nullptr; +} +//! [stopServer] + +//! [sendMessage] +void ChatServer::sendMessage(const QString &message) +{ + QByteArray text = message.toUtf8() + '\n'; + + for (QBluetoothSocket *socket : std::as_const(clientSockets)) + socket->write(text); +} +//! [sendMessage] + +//! [clientConnected] +void ChatServer::clientConnected() +{ + QBluetoothSocket *socket = rfcommServer->nextPendingConnection(); + if (!socket) + return; + + connect(socket, &QBluetoothSocket::readyRead, this, &ChatServer::readSocket); + connect(socket, &QBluetoothSocket::disconnected, + this, QOverload<>::of(&ChatServer::clientDisconnected)); + clientSockets.append(socket); + clientNames[socket] = socket->peerName(); + emit clientConnected(socket->peerName()); +} +//! [clientConnected] + +//! [clientDisconnected] +void ChatServer::clientDisconnected() +{ + QBluetoothSocket *socket = qobject_cast(sender()); + if (!socket) + return; + + emit clientDisconnected(clientNames[socket]); + + clientSockets.removeOne(socket); + clientNames.remove(socket); + + socket->deleteLater(); +} +//! [clientDisconnected] + +//! [readSocket] +void ChatServer::readSocket() +{ + QBluetoothSocket *socket = qobject_cast(sender()); + if (!socket) + return; + + while (socket->canReadLine()) { + QByteArray line = socket->readLine().trimmed(); + emit messageReceived(clientNames[socket], + QString::fromUtf8(line.constData(), line.length())); + } +} +//! [readSocket] diff --git a/examples/bluetooth/btchat/chatserver.h b/examples/bluetooth/btchat/chatserver.h new file mode 100644 index 0000000..ab60cad --- /dev/null +++ b/examples/bluetooth/btchat/chatserver.h @@ -0,0 +1,48 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef CHATSERVER_H +#define CHATSERVER_H + +#include + +#include +#include + +QT_FORWARD_DECLARE_CLASS(QBluetoothServer) +QT_FORWARD_DECLARE_CLASS(QBluetoothSocket) + +//! [declaration] +class ChatServer : public QObject +{ + Q_OBJECT + +public: + explicit ChatServer(QObject *parent = nullptr); + ~ChatServer(); + + void startServer(const QBluetoothAddress &localAdapter = QBluetoothAddress()); + void stopServer(); + +public slots: + void sendMessage(const QString &message); + +signals: + void messageReceived(const QString &sender, const QString &message); + void clientConnected(const QString &name); + void clientDisconnected(const QString &name); + +private slots: + void clientConnected(); + void clientDisconnected(); + void readSocket(); + +private: + QBluetoothServer *rfcommServer = nullptr; + QBluetoothServiceInfo serviceInfo; + QList clientSockets; + QMap clientNames; +}; +//! [declaration] + +#endif // CHATSERVER_H diff --git a/examples/bluetooth/btchat/doc/images/btchat-example.png b/examples/bluetooth/btchat/doc/images/btchat-example.png new file mode 100644 index 0000000..acfadf5 Binary files /dev/null and b/examples/bluetooth/btchat/doc/images/btchat-example.png differ diff --git a/examples/bluetooth/btchat/doc/src/btchat.qdoc b/examples/bluetooth/btchat/doc/src/btchat.qdoc new file mode 100644 index 0000000..5ad1150 --- /dev/null +++ b/examples/bluetooth/btchat/doc/src/btchat.qdoc @@ -0,0 +1,213 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \example btchat + \title Bluetooth Chat + \examplecategory {Connectivity} + \brief Shows communication through Bluetooth using RFCOMM protocol. + + The Bluetooth Chat example shows how to use the \l{Qt Bluetooth} API to communicate + with another application on a remote device using Bluetooth RFCOMM protocol. + + \image btchat-example.png + + The Bluetooth Chat example implements a simple chat program between multiple parties. The + application always acts as both a server and a client eliminating the need to determine who + should connect to whom. + + \include examples-run.qdocinc + + \section1 Chat Server + + The chat server is implemented by the \c ChatServer class. + The \c ChatServer class is declared as: + + \snippet btchat/chatserver.h declaration + + The first thing the chat server needs to do is create an instance of + QBluetoothServer to listen for incoming Bluetooth connections. The + \c {clientConnected()} slot will be called whenever a new connection is + created. + + \snippet btchat/chatserver.cpp Create the server + + The chat server is only useful if others know that it is there. To enable other devices to + discover it, a record describing the service needs to be published in the system's SDP (Service + Discovery Protocol) database. The QBluetoothServiceInfo class encapsulates a service record. + + We will publish a service record that contains some textual descriptions of the services, a + UUID that uniquely identifies the service, the discoverability attribute, and connection + parameters. + + The textual description of the service is stored in the \c {ServiceName}, + \c {ServiceDescription}, and \c {ServiceProvider} attributes. + + \snippet btchat/chatserver.cpp Service name, description and provider + + Bluetooth uses UUIDs as unique identifiers. The chat service uses a randomly generated + UUID. + + \snippet btchat/chatserver.cpp Service UUID + \snippet btchat/chatserver.cpp Service UUID set + + A Bluetooth service is only discoverable if it is in the + \l {QBluetoothUuid::}{PublicBrowseGroup}. + + \snippet btchat/chatserver.cpp Service Discoverability + + The \c ProtocolDescriptorList attribute is used to publish the connection parameters that the + remote device requires to connect to our service. Here we specify that the \c Rfcomm protocol + is used and set the port number to the port that our \c rfcommServer instance is listening to. + + \snippet btchat/chatserver.cpp Protocol descriptor list + + Finally, we register the service record with the system. + + \snippet btchat/chatserver.cpp Register service + + As mentioned earlier, incoming connections are handled in the + \c {clientConnected()} slot where pending connections are connected to the + \l {QBluetoothSocket::}{readyRead()} and + \l {QBluetoothSocket::}{disconnected()} signals. The signals notify others + that a new client has connected. + + \snippet btchat/chatserver.cpp clientConnected + + The \c {readSocket()} slot is called whenever data is ready to be read from + a client socket. The slot reads individual lines from the socket, converts + them from UTF-8, and emits the \c {messageReceived()} signal. + + \snippet btchat/chatserver.cpp readSocket + + The \c {clientDisconnected()} slot is called whenever a client disconnects + from the service. The slot emits a signal to notify others that a client + has disconnected, and deletes the socket. + + \snippet btchat/chatserver.cpp clientDisconnected + + The \c {sendMessage()} slot is used to send a message to all connected clients. The message is + converted into UTF-8 and appended with a newline before being sent to all clients. + + \snippet btchat/chatserver.cpp sendMessage + + When the chat server is stopped, the service record is removed from the + system SDP database, all connected client sockets are deleted, and the + \c rfcommServer instance is deleted. + + \snippet btchat/chatserver.cpp stopServer + + \section1 Service Discovery + + Before connecting to the server, the client needs to scan the nearby + devices and search for the device that is advertising the chat service. + This is done by the \c RemoteSelector class. + + To start service lookup, the \c RemoteSelector creates an instance of + \l QBluetoothServiceDiscoveryAgent and connects to its signals. + + \snippet btchat/remoteselector.cpp createDiscoveryAgent + + An UUID filter is set, so that the service discovery only shows the devices + that advertise the needed service. After that a + \l {QBluetoothServiceDiscoveryAgent::}{FullDiscovery} is started: + + \snippet btchat/remoteselector.cpp startDiscovery + + When a matching service is discovered, a + \l {QBluetoothServiceDiscoveryAgent::}{serviceDiscovered()} signal is + emitted with an instance of \l QBluetoothServiceInfo as a parameter. This + service info is used to extract the device name and the service name, + and add a new entry to the list of discovered remote devices: + + \snippet btchat/remoteselector.cpp serviceDiscovered + + Later the user can select one of the devices from the list and try to + connect to it. + + \section1 Chat Client + + The chat client is implemented by the \c ChatClient class. + The \c ChatClient class is declared as: + + \snippet btchat/chatclient.h declaration + + The client creates a new QBluetoothSocket and connects to the remote + service described by the \c remoteService parameter. Slots are connected + to the socket's \l {QBluetoothSocket::}{readyRead()}, + \l {QBluetoothSocket::}{connected()}, and + \l {QBluetoothSocket::}{disconnected()} signals. + + \snippet btchat/chatclient.cpp startClient + + On successful socket connection we emit a signal to notify other users. + + \snippet btchat/chatclient.cpp connected + + Similarly to the chat server, the \c readSocket() slot is called when data + is available from the socket. Lines are read individually and converted + from UTF-8. The \c {messageReceived()} signal is emitted. + + \snippet btchat/chatclient.cpp readSocket + + The \c {sendMessage()} slot is used to send a message to the remote device. + The message is converted to UTF-8 and a newline is appended. + + \snippet btchat/chatclient.cpp sendMessage + + To disconnect from the remote chat service, the QBluetoothSocket instance is deleted. + + \snippet btchat/chatclient.cpp stopClient + + \section1 Chat Dialog + + The main window of this example is the chat dialog, implemented in the + \c Chat class. This class displays a chat session between a single + \c ChatServer and zero or more \c {ChatClient}s. The \c Chat class is + declared as: + + \snippet btchat/chat.h declaration + + First we construct the user interface + + \snippet btchat/chat.cpp Construct UI + + We create an instance of the \c ChatServer and respond to its + \c {clientConnected()}, \c {clientDiconnected()}, and + \c {messageReceived()} signals. + + \snippet btchat/chat.cpp Create Chat Server + + In response to the \c {clientConnected()} and \c {clientDisconnected()} + signals of the \c ChatServer, we display the typical "X has joined chat." + and "Y has left." messages in the chat session. + + \snippet btchat/chat.cpp clientConnected clientDisconnected + + Incoming messages from clients connected to the \c ChatServer are handled + in the \c {showMessage()} slot. The message text tagged with the remote + device name is displayed in the chat session. + + \snippet btchat/chat.cpp showMessage + + In response to the connect button being clicked, the application starts service discovery and + presents a list of discovered chat services on remote devices. A \c ChatClient for the service + is selected by the user. + + \snippet btchat/chat.cpp Connect to remote service + + In reponse to the \c {connected()} signals from \c ChatClient, we display + the "Joined chat with X." message in the chat session. + + \snippet btchat/chat.cpp connected + + Messages are sent to all remote devices via the \c ChatServer and + \c ChatClient instances by emitting the \c {sendMessage()} signal. + + \snippet btchat/chat.cpp sendClicked + + We need to clean up \c ChatClient instances when the remote device forces + a disconnect. + + \snippet btchat/chat.cpp clientDisconnected +*/ diff --git a/examples/bluetooth/btchat/icons/btchat/24x24/bluetooth.png b/examples/bluetooth/btchat/icons/btchat/24x24/bluetooth.png new file mode 100644 index 0000000..832dd04 Binary files /dev/null and b/examples/bluetooth/btchat/icons/btchat/24x24/bluetooth.png differ diff --git a/examples/bluetooth/btchat/icons/btchat/24x24/bluetooth_dark.png b/examples/bluetooth/btchat/icons/btchat/24x24/bluetooth_dark.png new file mode 100644 index 0000000..48b772d Binary files /dev/null and b/examples/bluetooth/btchat/icons/btchat/24x24/bluetooth_dark.png differ diff --git a/examples/bluetooth/btchat/icons/btchat/24x24/send.png b/examples/bluetooth/btchat/icons/btchat/24x24/send.png new file mode 100644 index 0000000..dfce248 Binary files /dev/null and b/examples/bluetooth/btchat/icons/btchat/24x24/send.png differ diff --git a/examples/bluetooth/btchat/icons/btchat/24x24/send_dark.png b/examples/bluetooth/btchat/icons/btchat/24x24/send_dark.png new file mode 100644 index 0000000..66e78da Binary files /dev/null and b/examples/bluetooth/btchat/icons/btchat/24x24/send_dark.png differ diff --git a/examples/bluetooth/btchat/icons/btchat/24x24@2/bluetooth.png b/examples/bluetooth/btchat/icons/btchat/24x24@2/bluetooth.png new file mode 100644 index 0000000..12bbb81 Binary files /dev/null and b/examples/bluetooth/btchat/icons/btchat/24x24@2/bluetooth.png differ diff --git a/examples/bluetooth/btchat/icons/btchat/24x24@2/bluetooth_dark.png b/examples/bluetooth/btchat/icons/btchat/24x24@2/bluetooth_dark.png new file mode 100644 index 0000000..f3456e6 Binary files /dev/null and b/examples/bluetooth/btchat/icons/btchat/24x24@2/bluetooth_dark.png differ diff --git a/examples/bluetooth/btchat/icons/btchat/24x24@2/send.png b/examples/bluetooth/btchat/icons/btchat/24x24@2/send.png new file mode 100644 index 0000000..8c4d5d0 Binary files /dev/null and b/examples/bluetooth/btchat/icons/btchat/24x24@2/send.png differ diff --git a/examples/bluetooth/btchat/icons/btchat/24x24@2/send_dark.png b/examples/bluetooth/btchat/icons/btchat/24x24@2/send_dark.png new file mode 100644 index 0000000..03b597c Binary files /dev/null and b/examples/bluetooth/btchat/icons/btchat/24x24@2/send_dark.png differ diff --git a/examples/bluetooth/btchat/icons/btchat/24x24@3/bluetooth.png b/examples/bluetooth/btchat/icons/btchat/24x24@3/bluetooth.png new file mode 100644 index 0000000..235b91a Binary files /dev/null and b/examples/bluetooth/btchat/icons/btchat/24x24@3/bluetooth.png differ diff --git a/examples/bluetooth/btchat/icons/btchat/24x24@3/bluetooth_dark.png b/examples/bluetooth/btchat/icons/btchat/24x24@3/bluetooth_dark.png new file mode 100644 index 0000000..c64aa4a Binary files /dev/null and b/examples/bluetooth/btchat/icons/btchat/24x24@3/bluetooth_dark.png differ diff --git a/examples/bluetooth/btchat/icons/btchat/24x24@3/send.png b/examples/bluetooth/btchat/icons/btchat/24x24@3/send.png new file mode 100644 index 0000000..3d15b19 Binary files /dev/null and b/examples/bluetooth/btchat/icons/btchat/24x24@3/send.png differ diff --git a/examples/bluetooth/btchat/icons/btchat/24x24@3/send_dark.png b/examples/bluetooth/btchat/icons/btchat/24x24@3/send_dark.png new file mode 100644 index 0000000..7f1a9f4 Binary files /dev/null and b/examples/bluetooth/btchat/icons/btchat/24x24@3/send_dark.png differ diff --git a/examples/bluetooth/btchat/icons/btchat/24x24@4/bluetooth.png b/examples/bluetooth/btchat/icons/btchat/24x24@4/bluetooth.png new file mode 100644 index 0000000..bad3e2e Binary files /dev/null and b/examples/bluetooth/btchat/icons/btchat/24x24@4/bluetooth.png differ diff --git a/examples/bluetooth/btchat/icons/btchat/24x24@4/bluetooth_dark.png b/examples/bluetooth/btchat/icons/btchat/24x24@4/bluetooth_dark.png new file mode 100644 index 0000000..01f420b Binary files /dev/null and b/examples/bluetooth/btchat/icons/btchat/24x24@4/bluetooth_dark.png differ diff --git a/examples/bluetooth/btchat/icons/btchat/24x24@4/send.png b/examples/bluetooth/btchat/icons/btchat/24x24@4/send.png new file mode 100644 index 0000000..c931f7a Binary files /dev/null and b/examples/bluetooth/btchat/icons/btchat/24x24@4/send.png differ diff --git a/examples/bluetooth/btchat/icons/btchat/24x24@4/send_dark.png b/examples/bluetooth/btchat/icons/btchat/24x24@4/send_dark.png new file mode 100644 index 0000000..8b80120 Binary files /dev/null and b/examples/bluetooth/btchat/icons/btchat/24x24@4/send_dark.png differ diff --git a/examples/bluetooth/btchat/icons/btchat/index.theme b/examples/bluetooth/btchat/icons/btchat/index.theme new file mode 100644 index 0000000..3209f84 --- /dev/null +++ b/examples/bluetooth/btchat/icons/btchat/index.theme @@ -0,0 +1,22 @@ +[Icon Theme] +Name=btchat +Directories=24x24,24x24@2,24x24@3,24x24@4 + +[24x24] +Size=24 +Type=Fixed + +[24x24@2] +Size=24 +Scale=2 +Type=Fixed + +[24x24@3] +Size=24 +Scale=3 +Type=Fixed + +[24x24@4] +Size=24 +Scale=4 +Type=Fixed diff --git a/examples/bluetooth/btchat/main.cpp b/examples/bluetooth/btchat/main.cpp new file mode 100644 index 0000000..1da4f9f --- /dev/null +++ b/examples/bluetooth/btchat/main.cpp @@ -0,0 +1,32 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "chat.h" + +#include + +#include + +using namespace Qt::StringLiterals; + +int main(int argc, char *argv[]) +{ + // QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true")); + QApplication app(argc, argv); + + QIcon::setThemeName(u"btchat"_s); + + Chat d; + QObject::connect(&d, &Chat::accepted, &app, &QApplication::quit); + +#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) + d.showMaximized(); +#else + d.show(); +#endif + + app.exec(); + + return 0; +} + diff --git a/examples/bluetooth/btchat/remoteselector.cpp b/examples/bluetooth/btchat/remoteselector.cpp new file mode 100644 index 0000000..dc501c8 --- /dev/null +++ b/examples/bluetooth/btchat/remoteselector.cpp @@ -0,0 +1,155 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "remoteselector.h" +#include "ui_remoteselector.h" + +#include +#include +#include +#include + +#include +#include + +#include + +using namespace Qt::StringLiterals; + +RemoteSelector::RemoteSelector(const QBluetoothAddress &localAdapter, QWidget *parent) + : QDialog(parent), ui(new Ui::RemoteSelector) +{ + ui->setupUi(this); +#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) + setWindowState(Qt::WindowMaximized); +#endif + + QStyleHints *styleHints = qGuiApp->styleHints(); + updateIcon(styleHints->colorScheme()); + connect(styleHints, &QStyleHints::colorSchemeChanged, this, &RemoteSelector::updateIcon); + +//! [createDiscoveryAgent] + m_discoveryAgent = new QBluetoothServiceDiscoveryAgent(localAdapter); + + connect(m_discoveryAgent, &QBluetoothServiceDiscoveryAgent::serviceDiscovered, + this, &RemoteSelector::serviceDiscovered); + connect(m_discoveryAgent, &QBluetoothServiceDiscoveryAgent::finished, + this, &RemoteSelector::discoveryFinished); + connect(m_discoveryAgent, &QBluetoothServiceDiscoveryAgent::canceled, + this, &RemoteSelector::discoveryFinished); +//! [createDiscoveryAgent] +} + +RemoteSelector::~RemoteSelector() +{ + delete ui; + delete m_discoveryAgent; +} + +void RemoteSelector::startDiscovery(const QBluetoothUuid &uuid) +{ + ui->status->setText(tr("Scanning...")); + if (m_discoveryAgent->isActive()) + m_discoveryAgent->stop(); + + ui->remoteDevices->clear(); + +//! [startDiscovery] + m_discoveryAgent->setUuidFilter(uuid); + m_discoveryAgent->start(QBluetoothServiceDiscoveryAgent::FullDiscovery); +//! [startDiscovery] +} + +void RemoteSelector::stopDiscovery() +{ + if (m_discoveryAgent){ + m_discoveryAgent->stop(); + } +} + +QBluetoothServiceInfo RemoteSelector::service() const +{ + return m_service; +} + +void RemoteSelector::serviceDiscovered(const QBluetoothServiceInfo &serviceInfo) +{ +#if 0 + qDebug() << "Discovered service on" + << serviceInfo.device().name() << serviceInfo.device().address().toString(); + qDebug() << "\tService name:" << serviceInfo.serviceName(); + qDebug() << "\tDescription:" + << serviceInfo.attribute(QBluetoothServiceInfo::ServiceDescription).toString(); + qDebug() << "\tProvider:" + << serviceInfo.attribute(QBluetoothServiceInfo::ServiceProvider).toString(); + qDebug() << "\tL2CAP protocol service multiplexer:" + << serviceInfo.protocolServiceMultiplexer(); + qDebug() << "\tRFCOMM server channel:" << serviceInfo.serverChannel(); +#endif + const QBluetoothAddress address = serviceInfo.device().address(); + for (const QBluetoothServiceInfo &info : std::as_const(m_discoveredServices)) { + if (info.device().address() == address) + return; + } + +//! [serviceDiscovered] + QString remoteName; + if (serviceInfo.device().name().isEmpty()) + remoteName = address.toString(); + else + remoteName = serviceInfo.device().name(); + + QListWidgetItem *item = + new QListWidgetItem(QString::fromLatin1("%1 %2").arg(remoteName, + serviceInfo.serviceName())); + + m_discoveredServices.insert(item, serviceInfo); + ui->remoteDevices->addItem(item); +//! [serviceDiscovered] +} + +void RemoteSelector::discoveryFinished() +{ + ui->status->setText(tr("Select the chat service to connect to.")); +} + +void RemoteSelector::updateIcon(Qt::ColorScheme scheme) +{ + const QString bluetoothIconName = (scheme == Qt::ColorScheme::Dark) ? u"bluetooth_dark"_s + : u"bluetooth"_s; + const QIcon bluetoothIcon = QIcon::fromTheme(bluetoothIconName); + ui->iconLabel->setPixmap(bluetoothIcon.pixmap(24, 24, QIcon::Normal, QIcon::On)); +} + +void RemoteSelector::on_remoteDevices_itemActivated(QListWidgetItem *item) +{ + m_service = m_discoveredServices.value(item); + if (m_discoveryAgent->isActive()) + m_discoveryAgent->stop(); + + accept(); +} + +void RemoteSelector::on_remoteDevices_itemClicked(QListWidgetItem *) +{ + ui->connectButton->setEnabled(true); + ui->connectButton->setFocus(); +} + +void RemoteSelector::on_connectButton_clicked() +{ + auto items = ui->remoteDevices->selectedItems(); + if (items.size()) { + QListWidgetItem *item = items[0]; + m_service = m_discoveredServices.value(item); + if (m_discoveryAgent->isActive()) + m_discoveryAgent->stop(); + + accept(); + } +} + +void RemoteSelector::on_cancelButton_clicked() +{ + reject(); +} diff --git a/examples/bluetooth/btchat/remoteselector.h b/examples/bluetooth/btchat/remoteselector.h new file mode 100644 index 0000000..c6fc665 --- /dev/null +++ b/examples/bluetooth/btchat/remoteselector.h @@ -0,0 +1,52 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef REMOTESELECTOR_H +#define REMOTESELECTOR_H + +#include + +#include + +QT_BEGIN_NAMESPACE + +class QBluetoothAddress; +class QBluetoothServiceDiscoveryAgent; +class QBluetoothUuid; +class QListWidgetItem; + +namespace Ui { + class RemoteSelector; +} +QT_END_NAMESPACE + +class RemoteSelector : public QDialog +{ + Q_OBJECT + +public: + explicit RemoteSelector(const QBluetoothAddress &localAdapter, QWidget *parent = nullptr); + ~RemoteSelector(); + + void startDiscovery(const QBluetoothUuid &uuid); + void stopDiscovery(); + QBluetoothServiceInfo service() const; + +private: + Ui::RemoteSelector *ui; + + QBluetoothServiceDiscoveryAgent *m_discoveryAgent; + QBluetoothServiceInfo m_service; + QMap m_discoveredServices; + +private slots: + void serviceDiscovered(const QBluetoothServiceInfo &serviceInfo); + void discoveryFinished(); + void updateIcon(Qt::ColorScheme scheme); + void on_remoteDevices_itemActivated(QListWidgetItem *item); + void on_remoteDevices_itemClicked(QListWidgetItem *item); + void on_cancelButton_clicked(); + void on_connectButton_clicked(); +}; + +#endif // REMOTESELECTOR_H diff --git a/examples/bluetooth/btchat/remoteselector.ui b/examples/bluetooth/btchat/remoteselector.ui new file mode 100644 index 0000000..853f610 --- /dev/null +++ b/examples/bluetooth/btchat/remoteselector.ui @@ -0,0 +1,75 @@ + + + RemoteSelector + + + + 0 + 0 + 400 + 300 + + + + Available chat services + + + + + + + + + Qt::AlignCenter + + + + + + + Scanning... + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Cancel + + + + + + + false + + + Connect + + + + + + + + + + diff --git a/examples/bluetooth/heartrate-game/App.qml b/examples/bluetooth/heartrate-game/App.qml new file mode 100644 index 0000000..db6aa71 --- /dev/null +++ b/examples/bluetooth/heartrate-game/App.qml @@ -0,0 +1,99 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Layouts +import HeartRateGame + +Item { + id: app + + required property ConnectionHandler connectionHandler + required property DeviceFinder deviceFinder + required property DeviceHandler deviceHandler + + anchors.fill: parent + opacity: 0.0 + + Behavior on opacity { + NumberAnimation { + duration: 500 + } + } + + property int __currentIndex: 0 + + TitleBar { + id: titleBar + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + currentIndex: app.__currentIndex + + onTitleClicked: (index) => { + if (index < app.__currentIndex) + app.__currentIndex = index + } + } + + StackLayout { + id: pageStack + anchors.left: parent.left + anchors.right: parent.right + anchors.top: titleBar.bottom + anchors.bottom: parent.bottom + currentIndex: app.__currentIndex + + Connect { + connectionHandler: app.connectionHandler + deviceFinder: app.deviceFinder + deviceHandler: app.deviceHandler + + onShowMeasurePage: app.__currentIndex = 1 + } + Measure { + id: measurePage + deviceHandler: app.deviceHandler + + onShowStatsPage: app.__currentIndex = 2 + } + Stats { + deviceHandler: app.deviceHandler + } + + onCurrentIndexChanged: { + if (currentIndex === 0) + measurePage.close() + } + } + + BluetoothAlarmDialog { + id: btAlarmDialog + anchors.fill: parent + visible: !app.connectionHandler.alive || permissionError + permissionError: !app.connectionHandler.hasPermission + } + + Keys.onReleased: (event) => { + switch (event.key) { + case Qt.Key_Escape: + case Qt.Key_Back: + { + if (app.__currentIndex > 0) { + app.__currentIndex = app.__currentIndex - 1 + event.accepted = true + } else { + Qt.quit() + } + break + } + default: + break + } + } + + Component.onCompleted: { + forceActiveFocus() + app.opacity = 1.0 + } +} diff --git a/examples/bluetooth/heartrate-game/BluetoothAlarmDialog.qml b/examples/bluetooth/heartrate-game/BluetoothAlarmDialog.qml new file mode 100644 index 0000000..5cc8f39 --- /dev/null +++ b/examples/bluetooth/heartrate-game/BluetoothAlarmDialog.qml @@ -0,0 +1,80 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick + +Item { + id: root + + property bool permissionError: false + + anchors.fill: parent + + Rectangle { + anchors.fill: parent + color: "black" + opacity: 0.9 + } + + MouseArea { + id: eventEater + } + + Rectangle { + id: dialogFrame + + anchors.centerIn: parent + width: parent.width * 0.8 + height: parent.height * 0.6 + border.color: "#454545" + color: GameSettings.backgroundColor + radius: width * 0.05 + + Item { + id: dialogContainer + anchors.fill: parent + anchors.margins: parent.width*0.05 + + Image { + id: offOnImage + anchors.left: quitButton.left + anchors.right: quitButton.right + anchors.top: parent.top + height: GameSettings.heightForWidth(width, sourceSize) + source: "images/bt_off_to_on.png" + } + + Text { + anchors.left: parent.left + anchors.right: parent.right + anchors.top: offOnImage.bottom + anchors.bottom: quitButton.top + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + wrapMode: Text.WordWrap + font.pixelSize: GameSettings.smallFontSize + color: GameSettings.textColor + text: root.permissionError + ? qsTr("Bluetooth permissions are not granted. Please grant the permissions in the system settings.") + : qsTr("This application cannot be used without Bluetooth. Please switch Bluetooth ON to continue.") + } + + GameButton { + id: quitButton + anchors.bottom: parent.bottom + anchors.horizontalCenter: parent.horizontalCenter + width: dialogContainer.width * 0.6 + height: GameSettings.buttonHeight + onClicked: Qt.quit() + + Text { + anchors.centerIn: parent + color: GameSettings.textColor + font.pixelSize: GameSettings.microFontSize + text: qsTr("QUIT") + } + } + } + } +} + diff --git a/examples/bluetooth/heartrate-game/BottomLine.qml b/examples/bluetooth/heartrate-game/BottomLine.qml new file mode 100644 index 0000000..80fdaa8 --- /dev/null +++ b/examples/bluetooth/heartrate-game/BottomLine.qml @@ -0,0 +1,11 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick + +Rectangle { + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: parent.bottom + width: parent.width + height: parent.height * 0.05 +} diff --git a/examples/bluetooth/heartrate-game/CMakeLists.txt b/examples/bluetooth/heartrate-game/CMakeLists.txt new file mode 100644 index 0000000..7677bcb --- /dev/null +++ b/examples/bluetooth/heartrate-game/CMakeLists.txt @@ -0,0 +1,91 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(heartrate-game LANGUAGES CXX) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/bluetooth/heartrate-game") + +find_package(Qt6 REQUIRED COMPONENTS Bluetooth Core Gui Qml Quick) + +qt_standard_project_setup(REQUIRES 6.5) + +qt_add_executable(heartrate-game + heartrate-global.h + main.cpp +) + +set_target_properties(heartrate-game PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(heartrate-game PRIVATE + Qt6::Bluetooth + Qt6::Core + Qt6::Gui + Qt6::Qml + Qt6::Quick +) + +set_source_files_properties(GameSettings.qml PROPERTIES + QT_QML_SINGLETON_TYPE TRUE +) + +qt_add_qml_module(heartrate-game + URI HeartRateGame + VERSION 1.0 + SOURCES + bluetoothbaseclass.cpp bluetoothbaseclass.h + connectionhandler.cpp connectionhandler.h + devicefinder.cpp devicefinder.h + devicehandler.cpp devicehandler.h + deviceinfo.cpp deviceinfo.h + QML_FILES + App.qml + BluetoothAlarmDialog.qml + BottomLine.qml + Connect.qml + GameButton.qml + GamePage.qml + GameSettings.qml + Measure.qml + SplashScreen.qml + Stats.qml + StatsLabel.qml + TitleBar.qml + Main.qml + RESOURCES + images/alert.svg + images/bluetooth.svg + images/bt_off_to_on.png + images/clock.svg + images/heart.png + images/logo.png + images/progress.svg + images/search.svg +) + +if (APPLE) + # Using absolute path for shared plist files is a Ninja bug workaround + get_filename_component(SHARED_PLIST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../shared ABSOLUTE) + if (IOS) + set_target_properties(heartrate-game PROPERTIES + MACOSX_BUNDLE_INFO_PLIST "${SHARED_PLIST_DIR}/Info.cmake.ios.plist" + ) + else() + set_target_properties(heartrate-game PROPERTIES + MACOSX_BUNDLE_INFO_PLIST "${SHARED_PLIST_DIR}/Info.cmake.macos.plist" + ) + endif() +endif() + +install(TARGETS heartrate-game + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/bluetooth/heartrate-game/Connect.qml b/examples/bluetooth/heartrate-game/Connect.qml new file mode 100644 index 0000000..ed5fb63 --- /dev/null +++ b/examples/bluetooth/heartrate-game/Connect.qml @@ -0,0 +1,155 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +pragma ComponentBehavior: Bound +import QtQuick +import HeartRateGame + +GamePage { + id: connectPage + + required property ConnectionHandler connectionHandler + required property DeviceFinder deviceFinder + required property DeviceHandler deviceHandler + + signal showMeasurePage + + errorMessage: deviceFinder.error + infoMessage: deviceFinder.info + iconType: deviceFinder.icon + + Text { + id: viewCaption + anchors { + top: parent.top + topMargin: GameSettings.fieldMargin + connectPage.messageHeight + horizontalCenter: parent.horizontalCenter + } + width: parent.width - GameSettings.fieldMargin * 2 + height: GameSettings.fieldHeight + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + color: GameSettings.textColor + font.pixelSize: GameSettings.smallFontSize + text: qsTr("Found Devices") + } + + Rectangle { + id: viewContainer + anchors.top: viewCaption.bottom + // only BlueZ platform has address type selection + anchors.bottom: connectPage.connectionHandler.requiresAddressType ? addressTypeButton.top + : searchButton.top + anchors.bottomMargin: GameSettings.fieldMargin + anchors.horizontalCenter: parent.horizontalCenter + width: parent.width - GameSettings.fieldMargin * 2 + color: GameSettings.viewColor + radius: GameSettings.buttonRadius + + ListView { + id: devices + anchors.fill: parent + model: connectPage.deviceFinder.devices + clip: true + + delegate: Rectangle { + id: box + + required property int index + required property var modelData + + height: GameSettings.fieldHeight * 1.2 + width: devices.width + color: index % 2 === 0 ? GameSettings.delegate1Color : GameSettings.delegate2Color + + MouseArea { + anchors.fill: parent + onClicked: { + connectPage.deviceFinder.connectToService(box.modelData.deviceAddress) + connectPage.showMeasurePage() + } + } + + Text { + id: device + font.pixelSize: GameSettings.microFontSize + text: box.modelData.deviceName + anchors.top: parent.top + anchors.topMargin: parent.height * 0.15 + anchors.leftMargin: parent.height * 0.15 + anchors.left: parent.left + color: GameSettings.textColor + } + + Text { + id: deviceAddress + font.pixelSize: GameSettings.microFontSize + text: box.modelData.deviceAddress + anchors.bottom: parent.bottom + anchors.bottomMargin: parent.height * 0.15 + anchors.rightMargin: parent.height * 0.15 + anchors.right: parent.right + color: Qt.darker(GameSettings.textColor) + } + } + } + } + + GameButton { + id: addressTypeButton + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: searchButton.top + anchors.bottomMargin: GameSettings.fieldMargin * 0.5 + width: viewContainer.width + height: GameSettings.fieldHeight + visible: connectPage.connectionHandler.requiresAddressType // only required on BlueZ + state: "public" + onClicked: state === "public" ? state = "random" : state = "public" + + states: [ + State { + name: "public" + PropertyChanges { + addressTypeText.text: qsTr("PUBLIC ADDRESS") + } + PropertyChanges { + connectPage.deviceHandler.addressType: DeviceHandler.PublicAddress + } + }, + State { + name: "random" + PropertyChanges { + addressTypeText.text: qsTr("RANDOM ADDRESS") + } + PropertyChanges { + connectPage.deviceHandler.addressType: DeviceHandler.RandomAddress + } + } + ] + + Text { + id: addressTypeText + anchors.centerIn: parent + font.pixelSize: GameSettings.microFontSize + color: GameSettings.textDarkColor + } + } + + GameButton { + id: searchButton + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: parent.bottom + anchors.bottomMargin: GameSettings.fieldMargin + width: viewContainer.width + height: GameSettings.fieldHeight + enabled: !connectPage.deviceFinder.scanning + onClicked: connectPage.deviceFinder.startSearch() + + Text { + anchors.centerIn: parent + font.pixelSize: GameSettings.microFontSize + text: qsTr("START SEARCH") + color: GameSettings.textDarkColor + } + } +} diff --git a/examples/bluetooth/heartrate-game/GameButton.qml b/examples/bluetooth/heartrate-game/GameButton.qml new file mode 100644 index 0000000..8e87601 --- /dev/null +++ b/examples/bluetooth/heartrate-game/GameButton.qml @@ -0,0 +1,39 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick + +Rectangle { + id: button + color: baseColor + onEnabledChanged: checkColor() + radius: GameSettings.buttonRadius + + property color baseColor: GameSettings.buttonColor + property color pressedColor: GameSettings.buttonPressedColor + property color disabledColor: GameSettings.disabledButtonColor + + signal clicked + + function checkColor() { + if (!button.enabled) { + button.color = disabledColor + } else { + if (mouseArea.containsPress) + button.color = pressedColor + else + button.color = baseColor + } + } + + MouseArea { + id: mouseArea + anchors.fill: parent + onPressed: button.checkColor() + onReleased: button.checkColor() + onClicked: { + button.checkColor() + button.clicked() + } + } +} diff --git a/examples/bluetooth/heartrate-game/GamePage.qml b/examples/bluetooth/heartrate-game/GamePage.qml new file mode 100644 index 0000000..ff81e9c --- /dev/null +++ b/examples/bluetooth/heartrate-game/GamePage.qml @@ -0,0 +1,77 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import HeartRateGame + +Item { + id: page + + property string errorMessage: "" + property string infoMessage: "" + property real messageHeight: msg.height + property bool hasError: errorMessage != "" + property bool hasInfo: infoMessage != "" + property int iconType: BluetoothBaseClass.IconNone + + function iconTypeToName(icon: int) : string { + switch (icon) { + case BluetoothBaseClass.IconNone: return "" + case BluetoothBaseClass.IconBluetooth: return "images/bluetooth.svg" + case BluetoothBaseClass.IconError: return "images/alert.svg" + case BluetoothBaseClass.IconProgress: return "images/progress.svg" + case BluetoothBaseClass.IconSearch: return "images/search.svg" + } + } + + Rectangle { + id: msg + anchors { + top: parent.top + left: parent.left + right: parent.right + topMargin: GameSettings.fieldMargin * 0.5 + leftMargin: GameSettings.fieldMargin + rightMargin: GameSettings.fieldMargin + } + height: GameSettings.fieldHeight + radius: GameSettings.buttonRadius + color: page.hasError ? GameSettings.errorColor : "transparent" + visible: page.hasError || page.hasInfo + border { + width: 1 + color: page.hasError ? GameSettings.errorColor : GameSettings.infoColor + } + + Image { + id: icon + readonly property int imgSize: GameSettings.fieldHeight * 0.5 + anchors { + left: parent.left + leftMargin: GameSettings.fieldMargin * 0.5 + verticalCenter: parent.verticalCenter + } + visible: source.toString() !== "" + source: page.iconTypeToName(page.iconType) + sourceSize.width: imgSize + sourceSize.height: imgSize + fillMode: Image.PreserveAspectFit + } + + Text { + id: error + anchors { + fill: parent + leftMargin: GameSettings.fieldMargin + icon.width + rightMargin: GameSettings.fieldMargin + icon.width + } + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + minimumPixelSize: 5 + font.pixelSize: GameSettings.microFontSize + fontSizeMode: Text.Fit + color: page.hasError ? GameSettings.textColor : GameSettings.infoColor + text: page.hasError ? page.errorMessage : page.infoMessage + } + } +} diff --git a/examples/bluetooth/heartrate-game/GameSettings.qml b/examples/bluetooth/heartrate-game/GameSettings.qml new file mode 100644 index 0000000..4032787 --- /dev/null +++ b/examples/bluetooth/heartrate-game/GameSettings.qml @@ -0,0 +1,61 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +pragma Singleton +import QtQuick + +QtObject { + property int wHeight + property int wWidth + + // Colors + readonly property color lightGreenColor: "#80ebb6" + readonly property color backgroundColor: "#2c3038" + readonly property color buttonColor: "#2cde85" + readonly property color buttonPressedColor: lightGreenColor + readonly property color disabledButtonColor: "#808080" + readonly property color viewColor: "#262626" + readonly property color delegate1Color: "#262626" + readonly property color delegate2Color: "#404040" + readonly property color textColor: "#ffffff" + readonly property color textDarkColor: "#0d0d0d" + readonly property color textInfoColor: lightGreenColor + readonly property color sliderColor: "#00414a" + readonly property color sliderBorderColor: lightGreenColor + readonly property color sliderTextColor: lightGreenColor + readonly property color errorColor: "#ba3f62" + readonly property color infoColor: lightGreenColor + readonly property color titleColor: "#202227" + readonly property color selectedTitleColor: "#19545c" + readonly property color hoverTitleColor: Qt.rgba(selectedTitleColor.r, + selectedTitleColor.g, + selectedTitleColor.b, + 0.25) + readonly property color bottomLineColor: "#e6e6e6" + readonly property color heartRateColor: "#f80067" + + // All the fonts are given for the window of certain size. + // Resizing the window changes all the fonts accordingly + readonly property int defaultSize: 500 + readonly property real fontScaleFactor: Math.min(wWidth, wHeight) / defaultSize + + // Font sizes + readonly property real microFontSize: 16 * fontScaleFactor + readonly property real tinyFontSize: 20 * fontScaleFactor + readonly property real smallFontSize: 24 * fontScaleFactor + readonly property real mediumFontSize: 32 * fontScaleFactor + readonly property real bigFontSize: 36 * fontScaleFactor + readonly property real largeFontSize: 54 * fontScaleFactor + readonly property real hugeFontSize: 128 * fontScaleFactor + + // Some other values + property real fieldHeight: wHeight * 0.08 + property real fieldMargin: fieldHeight * 0.5 + property real buttonHeight: wHeight * 0.08 + property real buttonRadius: buttonHeight * 0.1 + + // Some help functions + function heightForWidth(w, ss) { + return w / ss.width * ss.height + } +} diff --git a/examples/bluetooth/heartrate-game/Main.qml b/examples/bluetooth/heartrate-game/Main.qml new file mode 100644 index 0000000..e26f9b0 --- /dev/null +++ b/examples/bluetooth/heartrate-game/Main.qml @@ -0,0 +1,71 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +pragma ComponentBehavior: Bound +import QtQuick +import QtQuick.Window +import HeartRateGame + +Window { + id: wroot + visible: true + width: 720 * .7 + height: 1240 * .7 + title: qsTr("HeartRateGame") + color: GameSettings.backgroundColor + + required property ConnectionHandler connectionHandler + required property DeviceFinder deviceFinder + required property DeviceHandler deviceHandler + + Component.onCompleted: { + GameSettings.wWidth = Qt.binding(function () { + return width + }) + GameSettings.wHeight = Qt.binding(function () { + return height + }) + } + + Loader { + id: splashLoader + anchors.fill: parent + asynchronous: false + visible: true + + sourceComponent: SplashScreen { + appIsReady: appLoader.status === Loader.Ready + onReadyChanged: { + if (ready) { + appLoader.visible = true + splashLoader.visible = false + splashLoader.active = false + } + } + } + + onStatusChanged: { + if (status === Loader.Ready) + appLoader.active = true + } + } + + Loader { + id: appLoader + anchors.fill: parent + active: false + asynchronous: true + visible: false + + sourceComponent: App { + connectionHandler: wroot.connectionHandler + deviceFinder: wroot.deviceFinder + deviceHandler: wroot.deviceHandler + } + + onStatusChanged: { + if (status === Loader.Error) + Qt.quit() + } + } +} diff --git a/examples/bluetooth/heartrate-game/Measure.qml b/examples/bluetooth/heartrate-game/Measure.qml new file mode 100644 index 0000000..04ebeb0 --- /dev/null +++ b/examples/bluetooth/heartrate-game/Measure.qml @@ -0,0 +1,325 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import HeartRateGame + +GamePage { + id: measurePage + + required property DeviceHandler deviceHandler + + errorMessage: deviceHandler.error + infoMessage: deviceHandler.info + iconType: deviceHandler.icon + + property real __timeCounter: 0 + property real __maxTimeCount: 60 + + readonly property string relaxText: qsTr("Relax!") + readonly property string startText: qsTr("When you are ready,\npress Start.") + readonly property string instructionText: qsTr("You have %1s time to increase heart\nrate as much as possible.").arg(__maxTimeCount) + readonly property string goodLuckText: qsTr("Good luck!") + + signal showStatsPage + + function close() { + deviceHandler.stopMeasurement() + deviceHandler.disconnectService() + } + + function start() { + if (!deviceHandler.measuring) { + __timeCounter = 0 + deviceHandler.startMeasurement() + } + } + + function stop() { + if (deviceHandler.measuring) + deviceHandler.stopMeasurement() + + measurePage.showStatsPage() + } + + Timer { + id: measureTimer + interval: 1000 + running: measurePage.deviceHandler.measuring + repeat: true + onTriggered: { + measurePage.__timeCounter++ + if (measurePage.__timeCounter >= measurePage.__maxTimeCount) + measurePage.stop() + } + } + + Column { + anchors.centerIn: parent + spacing: GameSettings.fieldHeight * 0.5 + + Rectangle { + id: circle + + readonly property bool hintVisible: !measurePage.deviceHandler.measuring + readonly property real innerSpacing: Math.min(width * 0.05, 25) + + anchors.horizontalCenter: parent.horizontalCenter + width: Math.min(measurePage.width, measurePage.height - GameSettings.fieldHeight * 4) + - 2 * GameSettings.fieldMargin + height: width + radius: width * 0.5 + color: GameSettings.viewColor + + Text { + id: relaxTextBox + anchors { + bottom: startTextBox.top + bottomMargin: parent.innerSpacing + horizontalCenter: parent.horizontalCenter + } + width: parent.width * 0.6 + height: parent.height * 0.1 + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + text: measurePage.relaxText + visible: circle.hintVisible + color: GameSettings.textColor + fontSizeMode: Text.Fit + font.pixelSize: GameSettings.smallFontSize + font.bold: true + } + + Text { + id: startTextBox + anchors { + bottom: heart.top + bottomMargin: parent.innerSpacing + horizontalCenter: parent.horizontalCenter + } + width: parent.width * 0.8 + height: parent.height * 0.15 + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + text: measurePage.startText + visible: circle.hintVisible + color: GameSettings.textColor + fontSizeMode: Text.Fit + font.pixelSize: GameSettings.tinyFontSize + } + + Text { + id: measureTextBox + anchors { + bottom: heart.top + horizontalCenter: parent.horizontalCenter + } + width: parent.width * 0.7 + height: parent.height * 0.35 + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + text: measurePage.deviceHandler.hr + visible: measurePage.deviceHandler.measuring + color: GameSettings.heartRateColor + fontSizeMode: Text.Fit + font.pixelSize: GameSettings.hugeFontSize + font.bold: true + } + + Image { + id: heart + anchors.centerIn: circle + width: parent.width * 0.2 + height: width + fillMode: Image.PreserveAspectFit + source: "images/heart.png" + smooth: true + antialiasing: true + + SequentialAnimation { + id: heartAnim + running: measurePage.deviceHandler.measuring + loops: Animation.Infinite + alwaysRunToEnd: true + PropertyAnimation { + target: heart + property: "scale" + to: 1.4 + duration: 500 + easing.type: Easing.InQuad + } + PropertyAnimation { + target: heart + property: "scale" + to: 1.0 + duration: 500 + easing.type: Easing.OutQuad + } + } + } + + Text { + id: instructionTextBox + anchors { + top: heart.bottom + topMargin: parent.innerSpacing + horizontalCenter: parent.horizontalCenter + } + width: parent.width * 0.8 + height: parent.height * 0.15 + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + text: measurePage.instructionText + visible: circle.hintVisible + color: GameSettings.textColor + fontSizeMode: Text.Fit + font.pixelSize: GameSettings.tinyFontSize + } + + Text { + id: goodLuckBox + anchors { + top: instructionTextBox.bottom + topMargin: parent.innerSpacing + horizontalCenter: parent.horizontalCenter + } + width: parent.width * 0.6 + height: parent.height * 0.1 + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + text: measurePage.goodLuckText + visible: circle.hintVisible + color: GameSettings.textColor + fontSizeMode: Text.Fit + font.pixelSize: GameSettings.smallFontSize + font.bold: true + } + + Item { + id: minMaxContainer + anchors.horizontalCenter: parent.horizontalCenter + width: parent.width * 0.7 + height: parent.height * 0.15 + anchors.bottom: parent.bottom + anchors.bottomMargin: parent.height * 0.16 + visible: measurePage.deviceHandler.measuring + + Text { + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter + width: parent.width * 0.35 + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + text: measurePage.deviceHandler.minHR + color: GameSettings.textColor + fontSizeMode: Text.Fit + font.pixelSize: GameSettings.largeFontSize + + Text { + anchors.left: parent.left + anchors.bottom: parent.top + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + width: parent.width + fontSizeMode: Text.Fit + font.pixelSize: GameSettings.mediumFontSize + color: parent.color + text: "MIN" + } + } + + Text { + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + horizontalAlignment: Text.AlignRight + verticalAlignment: Text.AlignVCenter + width: parent.width * 0.35 + text: measurePage.deviceHandler.maxHR + color: GameSettings.textColor + fontSizeMode: Text.Fit + font.pixelSize: GameSettings.largeFontSize + + Text { + anchors.right: parent.right + anchors.bottom: parent.top + horizontalAlignment: Text.AlignRight + verticalAlignment: Text.AlignVCenter + width: parent.width + fontSizeMode: Text.Fit + font.pixelSize: GameSettings.mediumFontSize + color: parent.color + text: "MAX" + } + } + } + } + + Rectangle { + id: timeSlider + color: GameSettings.viewColor + anchors.horizontalCenter: parent.horizontalCenter + width: circle.width + height: GameSettings.fieldHeight + radius: GameSettings.buttonRadius + border { + width: 1 + color: GameSettings.sliderBorderColor + } + + Rectangle { + anchors { + top: parent.top + topMargin: parent.border.width + left: parent.left + leftMargin: parent.border.width + } + height: parent.height - 2 * parent.border.width + width: Math.min(1.0, measurePage.__timeCounter / measurePage.__maxTimeCount) + * (parent.width - 2 * parent.border.width) + radius: parent.radius + color: GameSettings.sliderColor + } + + Image { + readonly property int imgSize: GameSettings.fieldHeight * 0.5 + anchors { + verticalCenter: parent.verticalCenter + left: parent.left + leftMargin: GameSettings.fieldMargin * 0.5 + } + source: "images/clock.svg" + sourceSize.width: imgSize + sourceSize.height: imgSize + fillMode: Image.PreserveAspectFit + } + + Text { + anchors.centerIn: parent + color: GameSettings.sliderTextColor + text: (measurePage.__maxTimeCount - measurePage.__timeCounter).toFixed(0) + " s" + font.pixelSize: GameSettings.smallFontSize + } + } + } + + GameButton { + id: startButton + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: parent.bottom + anchors.bottomMargin: GameSettings.fieldMargin + width: circle.width + height: GameSettings.fieldHeight + enabled: measurePage.deviceHandler.alive && !measurePage.deviceHandler.measuring + && measurePage.errorMessage === "" + radius: GameSettings.buttonRadius + + onClicked: measurePage.start() + + Text { + anchors.centerIn: parent + font.pixelSize: GameSettings.microFontSize + text: qsTr("START") + color: GameSettings.textDarkColor + } + } +} diff --git a/examples/bluetooth/heartrate-game/README.md b/examples/bluetooth/heartrate-game/README.md new file mode 100644 index 0000000..fd7c6fd --- /dev/null +++ b/examples/bluetooth/heartrate-game/README.md @@ -0,0 +1,7 @@ +# HeartRateGame # + +Demonstrates how to check a Bluetooth-connection, discover LE-devices, connect +to devices, discover services and finally connect to a heartrate-service. +The purpose of the game is increase the heartrate so much as possible in 60s. +Relax before starting the game. Don't be too nervous, it increases the heartrate! + diff --git a/examples/bluetooth/heartrate-game/SplashScreen.qml b/examples/bluetooth/heartrate-game/SplashScreen.qml new file mode 100644 index 0000000..918319d --- /dev/null +++ b/examples/bluetooth/heartrate-game/SplashScreen.qml @@ -0,0 +1,30 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import HeartRateGame + +Item { + id: root + + property bool appIsReady: false + property bool splashIsReady: false + property bool ready: appIsReady && splashIsReady + + anchors.fill: parent + + Image { + anchors.centerIn: parent + width: Math.min(parent.height, parent.width) * 0.6 + height: GameSettings.heightForWidth(width, sourceSize) + source: "images/logo.png" + } + + Timer { + id: splashTimer + interval: 1000 + onTriggered: root.splashIsReady = true + } + + Component.onCompleted: splashTimer.start() +} diff --git a/examples/bluetooth/heartrate-game/Stats.qml b/examples/bluetooth/heartrate-game/Stats.qml new file mode 100644 index 0000000..87487c9 --- /dev/null +++ b/examples/bluetooth/heartrate-game/Stats.qml @@ -0,0 +1,80 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import HeartRateGame + +GamePage { + id: statsPage + + required property DeviceHandler deviceHandler + + Column { + anchors.centerIn: parent + width: parent.width + + Rectangle { + id: resultRect + anchors.horizontalCenter: parent.horizontalCenter + width: height + height: statsPage.height / 2 - GameSettings.fieldHeight + radius: height / 2 + color: GameSettings.viewColor + + Column { + anchors.centerIn: parent + + Text { + id: resultCaption + anchors.horizontalCenter: parent.horizontalCenter + width: resultRect.width * 0.8 + height: resultRect.height * 0.15 + horizontalAlignment: Text.AlignHCenter + fontSizeMode: Text.Fit + font.pixelSize: GameSettings.bigFontSize + color: GameSettings.textColor + text: qsTr("RESULT") + } + + Text { + id: resultValue + anchors.horizontalCenter: parent.horizontalCenter + width: resultRect.width * 0.8 + height: resultRect.height * 0.4 + horizontalAlignment: Text.AlignHCenter + fontSizeMode: Text.Fit + font.pixelSize: GameSettings.hugeFontSize + font.bold: true + color: GameSettings.heartRateColor + text: (statsPage.deviceHandler.maxHR - statsPage.deviceHandler.minHR).toFixed(0) + } + } + } + + + Item { + height: GameSettings.fieldHeight + width: 1 + } + + StatsLabel { + title: qsTr("MIN") + value: statsPage.deviceHandler.minHR.toFixed(0) + } + + StatsLabel { + title: qsTr("MAX") + value: statsPage.deviceHandler.maxHR.toFixed(0) + } + + StatsLabel { + title: qsTr("AVG") + value: statsPage.deviceHandler.average.toFixed(1) + } + + StatsLabel { + title: qsTr("CALORIES") + value: statsPage.deviceHandler.calories.toFixed(3) + } + } +} diff --git a/examples/bluetooth/heartrate-game/StatsLabel.qml b/examples/bluetooth/heartrate-game/StatsLabel.qml new file mode 100644 index 0000000..0ea4249 --- /dev/null +++ b/examples/bluetooth/heartrate-game/StatsLabel.qml @@ -0,0 +1,34 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick + +Item { + height: GameSettings.fieldHeight + width: parent.width + + property alias title: leftText.text + property alias value: rightText.text + + Text { + id: leftText + anchors.left: parent.left + height: parent.height + width: parent.width * 0.45 + horizontalAlignment: Text.AlignRight + verticalAlignment: Text.AlignVCenter + font.pixelSize: GameSettings.mediumFontSize + color: GameSettings.textColor + } + + Text { + id: rightText + anchors.right: parent.right + height: parent.height + width: parent.width * 0.45 + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + font.pixelSize: GameSettings.mediumFontSize + color: GameSettings.textColor + } +} diff --git a/examples/bluetooth/heartrate-game/TitleBar.qml b/examples/bluetooth/heartrate-game/TitleBar.qml new file mode 100644 index 0000000..ccec760 --- /dev/null +++ b/examples/bluetooth/heartrate-game/TitleBar.qml @@ -0,0 +1,63 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +pragma ComponentBehavior: Bound +import QtQuick + +Rectangle { + id: titleBar + + property var __titles: ["CONNECT", "MEASURE", "STATS"] + property int currentIndex: 0 + + signal titleClicked(int index) + + height: GameSettings.fieldHeight + color: GameSettings.titleColor + + Rectangle { + anchors.bottom: parent.bottom + width: parent.width / 3 + height: parent.height + x: titleBar.currentIndex * width + color: GameSettings.selectedTitleColor + + BottomLine { + color: GameSettings.bottomLineColor + } + + Behavior on x { + NumberAnimation { + duration: 200 + } + } + } + + Repeater { + model: 3 + Rectangle { + id: caption + required property int index + property bool hoveredOrPressed: mouseArea.pressed || mouseArea.containsMouse + width: titleBar.width / 3 + height: titleBar.height + x: index * width + color: (titleBar.currentIndex !== index) && hoveredOrPressed + ? GameSettings.hoverTitleColor : "transparent" + Text { + anchors.fill: parent + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + text: titleBar.__titles[caption.index] + font.pixelSize: GameSettings.microFontSize + color: GameSettings.textColor + } + MouseArea { + id: mouseArea + anchors.fill: parent + hoverEnabled: true + onClicked: titleBar.titleClicked(caption.index) + } + } + } +} diff --git a/examples/bluetooth/heartrate-game/bluetoothbaseclass.cpp b/examples/bluetooth/heartrate-game/bluetoothbaseclass.cpp new file mode 100644 index 0000000..4c60b18 --- /dev/null +++ b/examples/bluetooth/heartrate-game/bluetoothbaseclass.cpp @@ -0,0 +1,54 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "bluetoothbaseclass.h" + +BluetoothBaseClass::BluetoothBaseClass(QObject *parent) : QObject(parent) +{ +} + +QString BluetoothBaseClass::error() const +{ + return m_error; +} + +QString BluetoothBaseClass::info() const +{ + return m_info; +} + +void BluetoothBaseClass::setError(const QString &error) +{ + if (m_error != error) { + m_error = error; + emit errorChanged(); + } +} + +void BluetoothBaseClass::setInfo(const QString &info) +{ + if (m_info != info) { + m_info = info; + emit infoChanged(); + } +} + +BluetoothBaseClass::IconType BluetoothBaseClass::icon() const +{ + return m_icon; +} + +void BluetoothBaseClass::setIcon(IconType icon) +{ + if (m_icon != icon) { + m_icon = icon; + emit iconChanged(); + } +} + +void BluetoothBaseClass::clearMessages() +{ + setInfo(""); + setError(""); + setIcon(IconNone); +} diff --git a/examples/bluetooth/heartrate-game/bluetoothbaseclass.h b/examples/bluetooth/heartrate-game/bluetoothbaseclass.h new file mode 100644 index 0000000..fba014f --- /dev/null +++ b/examples/bluetooth/heartrate-game/bluetoothbaseclass.h @@ -0,0 +1,56 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef BLUETOOTHBASECLASS_H +#define BLUETOOTHBASECLASS_H + +#include + +#include + +class BluetoothBaseClass : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QString error READ error WRITE setError NOTIFY errorChanged) + Q_PROPERTY(QString info READ info WRITE setInfo NOTIFY infoChanged) + Q_PROPERTY(IconType icon READ icon WRITE setIcon NOTIFY iconChanged) + + QML_ELEMENT + QML_UNCREATABLE("BluetoothBaseClass is not intended to be created directly") + +public: + enum IconType : int { + IconNone, + IconBluetooth, + IconError, + IconProgress, + IconSearch + }; + Q_ENUM(IconType) + + explicit BluetoothBaseClass(QObject *parent = nullptr); + + QString error() const; + void setError(const QString& error); + + QString info() const; + void setInfo(const QString& info); + + IconType icon() const; + void setIcon(IconType icon); + + void clearMessages(); + +signals: + void errorChanged(); + void infoChanged(); + void iconChanged(); + +private: + QString m_error; + QString m_info; + IconType m_icon = IconNone; +}; + +#endif // BLUETOOTHBASECLASS_H diff --git a/examples/bluetooth/heartrate-game/connectionhandler.cpp b/examples/bluetooth/heartrate-game/connectionhandler.cpp new file mode 100644 index 0000000..87e6462 --- /dev/null +++ b/examples/bluetooth/heartrate-game/connectionhandler.cpp @@ -0,0 +1,84 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "connectionhandler.h" +#include "heartrate-global.h" + +#include + +#include + +#if QT_CONFIG(permissions) +#include +#include +#endif + +ConnectionHandler::ConnectionHandler(QObject *parent) : QObject(parent) +{ + initLocalDevice(); +} + +bool ConnectionHandler::alive() const +{ + +#ifdef QT_PLATFORM_UIKIT + return true; + +#else + if (simulator) + return true; + return m_localDevice && m_localDevice->isValid() + && m_localDevice->hostMode() != QBluetoothLocalDevice::HostPoweredOff; +#endif +} + +bool ConnectionHandler::hasPermission() const +{ + return m_hasPermission; +} + +bool ConnectionHandler::requiresAddressType() const +{ +#if QT_CONFIG(bluez) + return true; +#else + return false; +#endif +} + +QString ConnectionHandler::name() const +{ + return m_localDevice ? m_localDevice->name() : QString(); +} + +QString ConnectionHandler::address() const +{ + return m_localDevice ? m_localDevice->address().toString() : QString(); +} + +void ConnectionHandler::hostModeChanged(QBluetoothLocalDevice::HostMode /*mode*/) +{ + emit deviceChanged(); +} + +void ConnectionHandler::initLocalDevice() +{ +#if QT_CONFIG(permissions) + QBluetoothPermission permission{}; + permission.setCommunicationModes(QBluetoothPermission::Access); + switch (qApp->checkPermission(permission)) { + case Qt::PermissionStatus::Undetermined: + qApp->requestPermission(permission, this, &ConnectionHandler::initLocalDevice); + return; + case Qt::PermissionStatus::Denied: + return; + case Qt::PermissionStatus::Granted: + break; // proceed to initialization + } +#endif + m_localDevice = new QBluetoothLocalDevice(this); + connect(m_localDevice, &QBluetoothLocalDevice::hostModeStateChanged, + this, &ConnectionHandler::hostModeChanged); + m_hasPermission = true; + emit deviceChanged(); +} diff --git a/examples/bluetooth/heartrate-game/connectionhandler.h b/examples/bluetooth/heartrate-game/connectionhandler.h new file mode 100644 index 0000000..e51fcbe --- /dev/null +++ b/examples/bluetooth/heartrate-game/connectionhandler.h @@ -0,0 +1,45 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef CONNECTIONHANDLER_H +#define CONNECTIONHANDLER_H + +#include + +#include + +#include + +class ConnectionHandler : public QObject +{ + Q_OBJECT + + Q_PROPERTY(bool alive READ alive NOTIFY deviceChanged) + Q_PROPERTY(bool hasPermission READ hasPermission NOTIFY deviceChanged) + Q_PROPERTY(QString name READ name NOTIFY deviceChanged) + Q_PROPERTY(QString address READ address NOTIFY deviceChanged) + Q_PROPERTY(bool requiresAddressType READ requiresAddressType CONSTANT) + + QML_ELEMENT +public: + explicit ConnectionHandler(QObject *parent = nullptr); + + bool alive() const; + bool hasPermission() const; + bool requiresAddressType() const; + QString name() const; + QString address() const; + +signals: + void deviceChanged(); + +private slots: + void hostModeChanged(QBluetoothLocalDevice::HostMode mode); + void initLocalDevice(); + +private: + QBluetoothLocalDevice *m_localDevice = nullptr; + bool m_hasPermission = false; +}; + +#endif // CONNECTIONHANDLER_H diff --git a/examples/bluetooth/heartrate-game/devicefinder.cpp b/examples/bluetooth/heartrate-game/devicefinder.cpp new file mode 100644 index 0000000..eaa70ca --- /dev/null +++ b/examples/bluetooth/heartrate-game/devicefinder.cpp @@ -0,0 +1,184 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "devicefinder.h" +#include "devicehandler.h" +#include "deviceinfo.h" +#include "heartrate-global.h" + +#include + +#if QT_CONFIG(permissions) +#include +#include +#endif + +DeviceFinder::DeviceFinder(DeviceHandler *handler, QObject *parent): + BluetoothBaseClass(parent), + m_deviceHandler(handler) +{ + //! [devicediscovery-1] + m_deviceDiscoveryAgent = new QBluetoothDeviceDiscoveryAgent(this); + m_deviceDiscoveryAgent->setLowEnergyDiscoveryTimeout(15000); + + connect(m_deviceDiscoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, + this, &DeviceFinder::addDevice); + connect(m_deviceDiscoveryAgent, &QBluetoothDeviceDiscoveryAgent::errorOccurred, + this, &DeviceFinder::scanError); + + connect(m_deviceDiscoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, + this, &DeviceFinder::scanFinished); + connect(m_deviceDiscoveryAgent, &QBluetoothDeviceDiscoveryAgent::canceled, + this, &DeviceFinder::scanFinished); + //! [devicediscovery-1] + + + if (simulator) { + m_demoTimer.setSingleShot(true); + m_demoTimer.setInterval(2000); + connect(&m_demoTimer, &QTimer::timeout, this, &DeviceFinder::scanFinished); + } + + resetMessages(); +} + +DeviceFinder::~DeviceFinder() +{ + qDeleteAll(m_devices); + m_devices.clear(); +} + +void DeviceFinder::startSearch() +{ +#if QT_CONFIG(permissions) + //! [permissions] + QBluetoothPermission permission{}; + permission.setCommunicationModes(QBluetoothPermission::Access); + switch (qApp->checkPermission(permission)) { + case Qt::PermissionStatus::Undetermined: + qApp->requestPermission(permission, this, &DeviceFinder::startSearch); + return; + case Qt::PermissionStatus::Denied: + setError(tr("Bluetooth permissions not granted!")); + setIcon(IconError); + return; + case Qt::PermissionStatus::Granted: + break; // proceed to search + } + //! [permissions] +#endif // QT_CONFIG(permissions) + clearMessages(); + m_deviceHandler->setDevice(nullptr); + qDeleteAll(m_devices); + m_devices.clear(); + + emit devicesChanged(); + + if (simulator) { + m_demoTimer.start(); + } else { + //! [devicediscovery-2] + m_deviceDiscoveryAgent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod); + //! [devicediscovery-2] + } + + emit scanningChanged(); + setInfo(tr("Scanning for devices...")); + setIcon(IconProgress); +} + +//! [devicediscovery-3] +void DeviceFinder::addDevice(const QBluetoothDeviceInfo &device) +{ + // If device is LowEnergy-device, add it to the list + if (device.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration) { + auto devInfo = new DeviceInfo(device); + auto it = std::find_if(m_devices.begin(), m_devices.end(), + [devInfo](DeviceInfo *dev) { + return devInfo->getAddress() == dev->getAddress(); + }); + if (it == m_devices.end()) { + m_devices.append(devInfo); + } else { + auto oldDev = *it; + *it = devInfo; + delete oldDev; + } + setInfo(tr("Low Energy device found. Scanning more...")); + setIcon(IconProgress); +//! [devicediscovery-3] + emit devicesChanged(); +//! [devicediscovery-4] + } + //... +} +//! [devicediscovery-4] + +void DeviceFinder::scanError(QBluetoothDeviceDiscoveryAgent::Error error) +{ + if (error == QBluetoothDeviceDiscoveryAgent::PoweredOffError) + setError(tr("The Bluetooth adaptor is powered off.")); + else if (error == QBluetoothDeviceDiscoveryAgent::InputOutputError) + setError(tr("Writing or reading from the device resulted in an error.")); + else + setError(tr("An unknown error has occurred.")); + setIcon(IconError); +} + +void DeviceFinder::scanFinished() +{ + if (simulator) { + // Only for testing + for (int i = 0; i < 4; i++) + m_devices.append(new DeviceInfo(QBluetoothDeviceInfo())); + } + + if (m_devices.isEmpty()) { + setError(tr("No Low Energy devices found.")); + setIcon(IconError); + } else { + setInfo(tr("Scanning done.")); + setIcon(IconBluetooth); + } + + emit scanningChanged(); + emit devicesChanged(); +} + +void DeviceFinder::resetMessages() +{ + setError(""); + setInfo(tr("Start search to find devices")); + setIcon(IconSearch); +} + +void DeviceFinder::connectToService(const QString &address) +{ + m_deviceDiscoveryAgent->stop(); + + DeviceInfo *currentDevice = nullptr; + for (QObject *entry : std::as_const(m_devices)) { + auto device = qobject_cast(entry); + if (device && device->getAddress() == address) { + currentDevice = device; + break; + } + } + + if (currentDevice) + m_deviceHandler->setDevice(currentDevice); + + resetMessages(); +} + +bool DeviceFinder::scanning() const +{ + if (simulator) + return m_demoTimer.isActive(); + return m_deviceDiscoveryAgent->isActive(); +} + +QVariant DeviceFinder::devices() +{ + return QVariant::fromValue(m_devices); +} diff --git a/examples/bluetooth/heartrate-game/devicefinder.h b/examples/bluetooth/heartrate-game/devicefinder.h new file mode 100644 index 0000000..703ef2c --- /dev/null +++ b/examples/bluetooth/heartrate-game/devicefinder.h @@ -0,0 +1,63 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef DEVICEFINDER_H +#define DEVICEFINDER_H + +#include "bluetoothbaseclass.h" + +#include + +#include +#include + +#include + +QT_BEGIN_NAMESPACE +class QBluetoothDeviceInfo; +QT_END_NAMESPACE + +class DeviceInfo; +class DeviceHandler; + +class DeviceFinder: public BluetoothBaseClass +{ + Q_OBJECT + + Q_PROPERTY(bool scanning READ scanning NOTIFY scanningChanged) + Q_PROPERTY(QVariant devices READ devices NOTIFY devicesChanged) + + QML_ELEMENT + QML_UNCREATABLE("This class is not intended to be created directly") + +public: + DeviceFinder(DeviceHandler *handler, QObject *parent = nullptr); + ~DeviceFinder(); + + bool scanning() const; + QVariant devices(); + +public slots: + void startSearch(); + void connectToService(const QString &address); + +private slots: + void addDevice(const QBluetoothDeviceInfo &device); + void scanError(QBluetoothDeviceDiscoveryAgent::Error error); + void scanFinished(); + +signals: + void scanningChanged(); + void devicesChanged(); + +private: + void resetMessages(); + + DeviceHandler *m_deviceHandler; + QBluetoothDeviceDiscoveryAgent *m_deviceDiscoveryAgent; + QList m_devices; + + QTimer m_demoTimer; +}; + +#endif // DEVICEFINDER_H diff --git a/examples/bluetooth/heartrate-game/devicehandler.cpp b/examples/bluetooth/heartrate-game/devicehandler.cpp new file mode 100644 index 0000000..c264d77 --- /dev/null +++ b/examples/bluetooth/heartrate-game/devicehandler.cpp @@ -0,0 +1,320 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "devicehandler.h" +#include "deviceinfo.h" +#include "heartrate-global.h" + +#include +#include + +DeviceHandler::DeviceHandler(QObject *parent) : + BluetoothBaseClass(parent) +{ + if (simulator) { + m_demoTimer.setSingleShot(false); + m_demoTimer.setInterval(2000); + connect(&m_demoTimer, &QTimer::timeout, this, &DeviceHandler::updateDemoHR); + m_demoTimer.start(); + updateDemoHR(); + } +} + +void DeviceHandler::setAddressType(AddressType type) +{ + switch (type) { + case DeviceHandler::AddressType::PublicAddress: + m_addressType = QLowEnergyController::PublicAddress; + break; + case DeviceHandler::AddressType::RandomAddress: + m_addressType = QLowEnergyController::RandomAddress; + break; + } +} + +DeviceHandler::AddressType DeviceHandler::addressType() const +{ + if (m_addressType == QLowEnergyController::RandomAddress) + return DeviceHandler::AddressType::RandomAddress; + + return DeviceHandler::AddressType::PublicAddress; +} + +void DeviceHandler::setDevice(DeviceInfo *device) +{ + clearMessages(); + m_currentDevice = device; + + if (simulator) { + setInfo(tr("Demo device connected.")); + setIcon(IconBluetooth); + return; + } + + // Disconnect and delete old connection + if (m_control) { + m_control->disconnectFromDevice(); + delete m_control; + m_control = nullptr; + } + + // Create new controller and connect it if device available + if (m_currentDevice) { + + // Make connections + //! [Connect-Signals-1] + m_control = QLowEnergyController::createCentral(m_currentDevice->getDevice(), this); + //! [Connect-Signals-1] + m_control->setRemoteAddressType(m_addressType); + //! [Connect-Signals-2] + connect(m_control, &QLowEnergyController::serviceDiscovered, + this, &DeviceHandler::serviceDiscovered); + connect(m_control, &QLowEnergyController::discoveryFinished, + this, &DeviceHandler::serviceScanDone); + + connect(m_control, &QLowEnergyController::errorOccurred, this, + [this](QLowEnergyController::Error error) { + Q_UNUSED(error); + setError("Cannot connect to remote device."); + setIcon(IconError); + }); + connect(m_control, &QLowEnergyController::connected, this, [this]() { + setInfo("Controller connected. Search services..."); + setIcon(IconProgress); + m_control->discoverServices(); + }); + connect(m_control, &QLowEnergyController::disconnected, this, [this]() { + setError("LowEnergy controller disconnected"); + setIcon(IconError); + }); + + // Connect + m_control->connectToDevice(); + //! [Connect-Signals-2] + } +} + +void DeviceHandler::startMeasurement() +{ + if (alive()) { + m_start = QDateTime::currentDateTime(); + m_min = 0; + m_max = 0; + m_avg = 0; + m_sum = 0; + m_calories = 0; + m_measuring = true; + m_measurements.clear(); + emit measuringChanged(); + } +} + +void DeviceHandler::stopMeasurement() +{ + m_measuring = false; + emit measuringChanged(); +} + +//! [Filter HeartRate service 1] +void DeviceHandler::serviceDiscovered(const QBluetoothUuid &gatt) +{ + if (gatt == QBluetoothUuid(QBluetoothUuid::ServiceClassUuid::HeartRate)) { + setInfo("Heart Rate service discovered. Waiting for service scan to be done..."); + setIcon(IconProgress); + m_foundHeartRateService = true; + } +} +//! [Filter HeartRate service 1] + +void DeviceHandler::serviceScanDone() +{ + setInfo("Service scan done."); + setIcon(IconBluetooth); + + // Delete old service if available + if (m_service) { + delete m_service; + m_service = nullptr; + } + +//! [Filter HeartRate service 2] + // If heartRateService found, create new service + if (m_foundHeartRateService) + m_service = m_control->createServiceObject(QBluetoothUuid(QBluetoothUuid::ServiceClassUuid::HeartRate), this); + + if (m_service) { + connect(m_service, &QLowEnergyService::stateChanged, this, &DeviceHandler::serviceStateChanged); + connect(m_service, &QLowEnergyService::characteristicChanged, this, &DeviceHandler::updateHeartRateValue); + connect(m_service, &QLowEnergyService::descriptorWritten, this, &DeviceHandler::confirmedDescriptorWrite); + m_service->discoverDetails(); + } else { + setError("Heart Rate Service not found."); + setIcon(IconError); + } +//! [Filter HeartRate service 2] +} + +// Service functions +//! [Find HRM characteristic] +void DeviceHandler::serviceStateChanged(QLowEnergyService::ServiceState s) +{ + switch (s) { + case QLowEnergyService::RemoteServiceDiscovering: + setInfo(tr("Discovering services...")); + setIcon(IconProgress); + break; + case QLowEnergyService::RemoteServiceDiscovered: + { + setInfo(tr("Service discovered.")); + setIcon(IconBluetooth); + + const QLowEnergyCharacteristic hrChar = + m_service->characteristic(QBluetoothUuid(QBluetoothUuid::CharacteristicType::HeartRateMeasurement)); + if (!hrChar.isValid()) { + setError("HR Data not found."); + setIcon(IconError); + break; + } + + m_notificationDesc = hrChar.descriptor(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration); + if (m_notificationDesc.isValid()) + m_service->writeDescriptor(m_notificationDesc, QByteArray::fromHex("0100")); + + break; + } + default: + //nothing for now + break; + } + + emit aliveChanged(); +} +//! [Find HRM characteristic] + +//! [Reading value] +void DeviceHandler::updateHeartRateValue(const QLowEnergyCharacteristic &c, const QByteArray &value) +{ + // ignore any other characteristic change -> shouldn't really happen though + if (c.uuid() != QBluetoothUuid(QBluetoothUuid::CharacteristicType::HeartRateMeasurement)) + return; + + auto data = reinterpret_cast(value.constData()); + quint8 flags = *data; + + //Heart Rate + int hrvalue = 0; + if (flags & 0x1) // HR 16 bit? otherwise 8 bit + hrvalue = static_cast(qFromLittleEndian(data[1])); + else + hrvalue = static_cast(data[1]); + + addMeasurement(hrvalue); +} +//! [Reading value] + +void DeviceHandler::updateDemoHR() +{ + int randomValue = 0; + if (m_currentValue < 30) // Initial value + randomValue = 55 + QRandomGenerator::global()->bounded(30); + else if (!m_measuring) // Value when relax + randomValue = qBound(55, m_currentValue - 2 + QRandomGenerator::global()->bounded(5), 75); + else // Measuring + randomValue = m_currentValue + QRandomGenerator::global()->bounded(10) - 2; + + addMeasurement(randomValue); +} + +void DeviceHandler::confirmedDescriptorWrite(const QLowEnergyDescriptor &d, const QByteArray &value) +{ + if (d.isValid() && d == m_notificationDesc && value == QByteArray::fromHex("0000")) { + //disabled notifications -> assume disconnect intent + m_control->disconnectFromDevice(); + delete m_service; + m_service = nullptr; + } +} + +void DeviceHandler::disconnectService() +{ + m_foundHeartRateService = false; + + //disable notifications + if (m_notificationDesc.isValid() && m_service + && m_notificationDesc.value() == QByteArray::fromHex("0100")) { + m_service->writeDescriptor(m_notificationDesc, QByteArray::fromHex("0000")); + } else { + if (m_control) + m_control->disconnectFromDevice(); + + delete m_service; + m_service = nullptr; + } +} + +bool DeviceHandler::measuring() const +{ + return m_measuring; +} + +bool DeviceHandler::alive() const +{ + if (simulator) + return true; + + if (m_service) + return m_service->state() == QLowEnergyService::RemoteServiceDiscovered; + + return false; +} + +int DeviceHandler::hr() const +{ + return m_currentValue; +} + +int DeviceHandler::time() const +{ + return m_start.secsTo(m_stop); +} + +int DeviceHandler::maxHR() const +{ + return m_max; +} + +int DeviceHandler::minHR() const +{ + return m_min; +} + +float DeviceHandler::average() const +{ + return m_avg; +} + +float DeviceHandler::calories() const +{ + return m_calories; +} + +void DeviceHandler::addMeasurement(int value) +{ + m_currentValue = value; + + // If measuring and value is appropriate + if (m_measuring && value > 30 && value < 250) { + + m_stop = QDateTime::currentDateTime(); + m_measurements << value; + + m_min = m_min == 0 ? value : qMin(value, m_min); + m_max = qMax(value, m_max); + m_sum += value; + m_avg = (double)m_sum / m_measurements.size(); + m_calories = ((-55.0969 + (0.6309 * m_avg) + (0.1988 * 94) + (0.2017 * 24)) / 4.184) + * 60 * time() / 3600; + } + + emit statsChanged(); +} diff --git a/examples/bluetooth/heartrate-game/devicehandler.h b/examples/bluetooth/heartrate-game/devicehandler.h new file mode 100644 index 0000000..a010d39 --- /dev/null +++ b/examples/bluetooth/heartrate-game/devicehandler.h @@ -0,0 +1,107 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef DEVICEHANDLER_H +#define DEVICEHANDLER_H + +#include "bluetoothbaseclass.h" + +#include +#include + +#include +#include +#include + +#include + +class DeviceInfo; + +class DeviceHandler : public BluetoothBaseClass +{ + Q_OBJECT + + Q_PROPERTY(bool measuring READ measuring NOTIFY measuringChanged) + Q_PROPERTY(bool alive READ alive NOTIFY aliveChanged) + Q_PROPERTY(int hr READ hr NOTIFY statsChanged) + Q_PROPERTY(int maxHR READ maxHR NOTIFY statsChanged) + Q_PROPERTY(int minHR READ minHR NOTIFY statsChanged) + Q_PROPERTY(float average READ average NOTIFY statsChanged) + Q_PROPERTY(int time READ time NOTIFY statsChanged) + Q_PROPERTY(float calories READ calories NOTIFY statsChanged) + Q_PROPERTY(AddressType addressType READ addressType WRITE setAddressType) + + QML_ELEMENT + +public: + enum class AddressType { + PublicAddress, + RandomAddress + }; + Q_ENUM(AddressType) + + DeviceHandler(QObject *parent = nullptr); + + void setDevice(DeviceInfo *device); + void setAddressType(AddressType type); + AddressType addressType() const; + + bool measuring() const; + bool alive() const; + + // Statistics + int hr() const; + int time() const; + float average() const; + int maxHR() const; + int minHR() const; + float calories() const; + +signals: + void measuringChanged(); + void aliveChanged(); + void statsChanged(); + +public slots: + void startMeasurement(); + void stopMeasurement(); + void disconnectService(); + +private: + //QLowEnergyController + void serviceDiscovered(const QBluetoothUuid &); + void serviceScanDone(); + + //QLowEnergyService + void serviceStateChanged(QLowEnergyService::ServiceState s); + void updateHeartRateValue(const QLowEnergyCharacteristic &c, + const QByteArray &value); + void confirmedDescriptorWrite(const QLowEnergyDescriptor &d, + const QByteArray &value); + + void updateDemoHR(); + +private: + void addMeasurement(int value); + + QLowEnergyController *m_control = nullptr; + QLowEnergyService *m_service = nullptr; + QLowEnergyDescriptor m_notificationDesc; + DeviceInfo *m_currentDevice = nullptr; + + bool m_foundHeartRateService = false; + bool m_measuring = false; + int m_currentValue = 0, m_min = 0, m_max = 0, m_sum = 0; + float m_avg = 0, m_calories = 0; + + // Statistics + QDateTime m_start; + QDateTime m_stop; + + QList m_measurements; + QLowEnergyController::RemoteAddressType m_addressType = QLowEnergyController::PublicAddress; + + QTimer m_demoTimer; +}; + +#endif // DEVICEHANDLER_H diff --git a/examples/bluetooth/heartrate-game/deviceinfo.cpp b/examples/bluetooth/heartrate-game/deviceinfo.cpp new file mode 100644 index 0000000..9bfff54 --- /dev/null +++ b/examples/bluetooth/heartrate-game/deviceinfo.cpp @@ -0,0 +1,45 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "deviceinfo.h" +#include "heartrate-global.h" + +#include +#include + +using namespace Qt::StringLiterals; + +DeviceInfo::DeviceInfo(const QBluetoothDeviceInfo &info): + m_device(info) +{ +} + +QBluetoothDeviceInfo DeviceInfo::getDevice() const +{ + return m_device; +} + +QString DeviceInfo::getName() const +{ + if (simulator) + return u"Demo BT Device"_s; + return m_device.name(); +} + +QString DeviceInfo::getAddress() const +{ + if (simulator) + return u"00:11:22:33:44:55"_s; +#ifdef Q_OS_DARWIN + // workaround for Core Bluetooth: + return m_device.deviceUuid().toString(); +#else + return m_device.address().toString(); +#endif +} + +void DeviceInfo::setDevice(const QBluetoothDeviceInfo &device) +{ + m_device = device; + emit deviceChanged(); +} diff --git a/examples/bluetooth/heartrate-game/deviceinfo.h b/examples/bluetooth/heartrate-game/deviceinfo.h new file mode 100644 index 0000000..19dd7af --- /dev/null +++ b/examples/bluetooth/heartrate-game/deviceinfo.h @@ -0,0 +1,34 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef DEVICEINFO_H +#define DEVICEINFO_H + +#include + +#include +#include + +class DeviceInfo: public QObject +{ + Q_OBJECT + + Q_PROPERTY(QString deviceName READ getName NOTIFY deviceChanged) + Q_PROPERTY(QString deviceAddress READ getAddress NOTIFY deviceChanged) + +public: + DeviceInfo(const QBluetoothDeviceInfo &device); + + void setDevice(const QBluetoothDeviceInfo &device); + QString getName() const; + QString getAddress() const; + QBluetoothDeviceInfo getDevice() const; + +signals: + void deviceChanged(); + +private: + QBluetoothDeviceInfo m_device; +}; + +#endif // DEVICEINFO_H diff --git a/examples/bluetooth/heartrate-game/doc/images/heartgame-result.webp b/examples/bluetooth/heartrate-game/doc/images/heartgame-result.webp new file mode 100644 index 0000000..58815ac Binary files /dev/null and b/examples/bluetooth/heartrate-game/doc/images/heartgame-result.webp differ diff --git a/examples/bluetooth/heartrate-game/doc/images/heartgame-running.webp b/examples/bluetooth/heartrate-game/doc/images/heartgame-running.webp new file mode 100644 index 0000000..1de7af6 Binary files /dev/null and b/examples/bluetooth/heartrate-game/doc/images/heartgame-running.webp differ diff --git a/examples/bluetooth/heartrate-game/doc/images/heartgame-search.webp b/examples/bluetooth/heartrate-game/doc/images/heartgame-search.webp new file mode 100644 index 0000000..727486d Binary files /dev/null and b/examples/bluetooth/heartrate-game/doc/images/heartgame-search.webp differ diff --git a/examples/bluetooth/heartrate-game/doc/images/heartgame-start.webp b/examples/bluetooth/heartrate-game/doc/images/heartgame-start.webp new file mode 100644 index 0000000..9a49e4a Binary files /dev/null and b/examples/bluetooth/heartrate-game/doc/images/heartgame-start.webp differ diff --git a/examples/bluetooth/heartrate-game/doc/src/heartrate-game.qdoc b/examples/bluetooth/heartrate-game/doc/src/heartrate-game.qdoc new file mode 100644 index 0000000..891ffc6 --- /dev/null +++ b/examples/bluetooth/heartrate-game/doc/src/heartrate-game.qdoc @@ -0,0 +1,77 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \example heartrate-game + \title Bluetooth Low Energy Heart Rate Game + \examplecategory {Connectivity} + \meta tags {bluetooth, ble, quick} + \brief A game demonstrating the interaction with a Bluetooth Low Energy Heart Rate + device/service. + + The Bluetooth Low Energy Heart Rate Game shows how to develop a Bluetooth Low Energy + application using the \l{QtBluetooth}{Qt Bluetooth API}. The application covers the scanning for + Bluetooth Low Energy devices, connecting to a Heart Rate service on the device, writing + characteristics and descriptors, and receiving updates from the device once the heart rate + has changed. + + \image heartgame-start.webp + + The example introduces the following Qt classes: + + \list + \li \l QLowEnergyController + \li \l QLowEnergyService + \li \l QLowEnergyCharacteristic + \li \l QLowEnergyDescriptor + \endlist + + A Bluetooth Low Energy device with a Heart Rate + service is required for this application to work. An alternative might be a programmable + Bluetooth Low Energy device which might simulate the service. You can also use the + \l {heartrate-server} {Heart Rate server} example for that purpose. + If no such device is available, a demo mode is available which creates and displays + random values. This demo mode is enabled by passing \c{--simulator} on the + command line. + + The goal of the game is to increase the measured heart rate as much as possible. + + A detailed explanation of the APIs used in this example is given in the + \l {Using Qt Bluetooth Low Energy API} section of the \l{Qt Bluetooth} module + documentation. + + The \l {lowenergyscanner}{Bluetooth Low Energy Scanner} example might be more suitable + if a heart rate device is not available. The scanner example works with any type of Bluetooth + Low Energy peripheral device. + + \include examples-run.qdocinc + + \section1 Checking Bluetooth Permissions + + Before the application can start using Bluetooth, we have to check that + appropriate permissions were granted: + + \snippet heartrate-game/devicefinder.cpp permissions + + + \section1 Visual Tour + + The application searches for all Bluetooth Low Energy peripheral devices in the vicinity. + It is assumed that the remote devices advertise their presence. The found devices are + presented in a list. Note that all found Bluetooth Low Energy devices are listed even + if they do not offer a Heart Rate service. + + \image heartgame-search.webp + + After the user has selected a target device, the example connects to its Heart Rate service + if one is available. It automatically enables notification updates for the Heart Rate value + and presents the current value on the screen. + + \image heartgame-running.webp + + Once the monitoring process is finished, a small summary of the received + values is presented. + + \image heartgame-result.webp + +*/ diff --git a/examples/bluetooth/heartrate-game/heartrate-game.pro b/examples/bluetooth/heartrate-game/heartrate-game.pro new file mode 100644 index 0000000..7cd5dcc --- /dev/null +++ b/examples/bluetooth/heartrate-game/heartrate-game.pro @@ -0,0 +1,57 @@ +TEMPLATE = app +TARGET = heartrate-game + +QT += qml quick bluetooth + +CONFIG += qmltypes +QML_IMPORT_NAME = HeartRateGame +QML_IMPORT_MAJOR_VERSION = 1 + +HEADERS += \ + connectionhandler.h \ + deviceinfo.h \ + devicefinder.h \ + devicehandler.h \ + bluetoothbaseclass.h \ + heartrate-global.h + +SOURCES += main.cpp \ + connectionhandler.cpp \ + deviceinfo.cpp \ + devicefinder.cpp \ + devicehandler.cpp \ + bluetoothbaseclass.cpp + +qml_resources.files = \ + qmldir \ + App.qml \ + BluetoothAlarmDialog.qml \ + BottomLine.qml \ + Connect.qml \ + GameButton.qml \ + GamePage.qml \ + GameSettings.qml \ + Measure.qml \ + SplashScreen.qml \ + Stats.qml \ + StatsLabel.qml \ + TitleBar.qml \ + Main.qml \ + images/alert.svg \ + images/bluetooth.svg \ + images/bt_off_to_on.png \ + images/clock.svg \ + images/heart.png \ + images/logo.png \ + images/progress.svg \ + images/search.svg + +qml_resources.prefix = /qt/qml/HeartRateGame + +RESOURCES = qml_resources + +ios: QMAKE_INFO_PLIST = ../shared/Info.qmake.ios.plist +macos: QMAKE_INFO_PLIST = ../shared/Info.qmake.macos.plist + +target.path = $$[QT_INSTALL_EXAMPLES]/bluetooth/heartrate-game +INSTALLS += target diff --git a/examples/bluetooth/heartrate-game/heartrate-global.h b/examples/bluetooth/heartrate-game/heartrate-global.h new file mode 100644 index 0000000..a967e64 --- /dev/null +++ b/examples/bluetooth/heartrate-game/heartrate-global.h @@ -0,0 +1,9 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef HEARTRATEGLOBAL_H +#define HEARTRATEGLOBAL_H + +extern bool simulator; + +#endif // HEARTRATEGLOBAL_H diff --git a/examples/bluetooth/heartrate-game/images/alert.svg b/examples/bluetooth/heartrate-game/images/alert.svg new file mode 100644 index 0000000..c48c10e --- /dev/null +++ b/examples/bluetooth/heartrate-game/images/alert.svg @@ -0,0 +1,4 @@ + + + + diff --git a/examples/bluetooth/heartrate-game/images/bluetooth.svg b/examples/bluetooth/heartrate-game/images/bluetooth.svg new file mode 100644 index 0000000..6d01b28 --- /dev/null +++ b/examples/bluetooth/heartrate-game/images/bluetooth.svg @@ -0,0 +1,3 @@ + + + diff --git a/examples/bluetooth/heartrate-game/images/bt_off_to_on.png b/examples/bluetooth/heartrate-game/images/bt_off_to_on.png new file mode 100644 index 0000000..5ea1f3f Binary files /dev/null and b/examples/bluetooth/heartrate-game/images/bt_off_to_on.png differ diff --git a/examples/bluetooth/heartrate-game/images/clock.svg b/examples/bluetooth/heartrate-game/images/clock.svg new file mode 100644 index 0000000..655996b --- /dev/null +++ b/examples/bluetooth/heartrate-game/images/clock.svg @@ -0,0 +1,4 @@ + + + + diff --git a/examples/bluetooth/heartrate-game/images/heart.png b/examples/bluetooth/heartrate-game/images/heart.png new file mode 100644 index 0000000..4ba0f82 Binary files /dev/null and b/examples/bluetooth/heartrate-game/images/heart.png differ diff --git a/examples/bluetooth/heartrate-game/images/logo.png b/examples/bluetooth/heartrate-game/images/logo.png new file mode 100644 index 0000000..ea0af7e Binary files /dev/null and b/examples/bluetooth/heartrate-game/images/logo.png differ diff --git a/examples/bluetooth/heartrate-game/images/progress.svg b/examples/bluetooth/heartrate-game/images/progress.svg new file mode 100644 index 0000000..449fe5e --- /dev/null +++ b/examples/bluetooth/heartrate-game/images/progress.svg @@ -0,0 +1,4 @@ + + + + diff --git a/examples/bluetooth/heartrate-game/images/search.svg b/examples/bluetooth/heartrate-game/images/search.svg new file mode 100644 index 0000000..9af5fe4 --- /dev/null +++ b/examples/bluetooth/heartrate-game/images/search.svg @@ -0,0 +1,4 @@ + + + + diff --git a/examples/bluetooth/heartrate-game/main.cpp b/examples/bluetooth/heartrate-game/main.cpp new file mode 100644 index 0000000..4719211 --- /dev/null +++ b/examples/bluetooth/heartrate-game/main.cpp @@ -0,0 +1,56 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "connectionhandler.h" +#include "devicefinder.h" +#include "devicehandler.h" +#include "heartrate-global.h" + +#include +#include +#include + +#include + +#include + +using namespace Qt::StringLiterals; + +bool simulator = false; + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + + QCommandLineParser parser; + parser.setApplicationDescription(u"Bluetooth Low Energy Heart Rate Game"_s); + parser.addHelpOption(); + parser.addVersionOption(); + QCommandLineOption simulatorOption(u"simulator"_s, u"Simulator"_s); + parser.addOption(simulatorOption); + + QCommandLineOption verboseOption(u"verbose"_s, u"Verbose mode"_s); + parser.addOption(verboseOption); + parser.process(app); + + if (parser.isSet(verboseOption)) + QLoggingCategory::setFilterRules(u"qt.bluetooth* = true"_s); + simulator = parser.isSet(simulatorOption); + + ConnectionHandler connectionHandler; + DeviceHandler deviceHandler; + DeviceFinder deviceFinder(&deviceHandler); + + QQmlApplicationEngine engine; + engine.setInitialProperties({ + {u"connectionHandler"_s, QVariant::fromValue(&connectionHandler)}, + {u"deviceFinder"_s, QVariant::fromValue(&deviceFinder)}, + {u"deviceHandler"_s, QVariant::fromValue(&deviceHandler)} + }); + + QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed, &app, + []() { QCoreApplication::exit(1); }, Qt::QueuedConnection); + engine.loadFromModule("HeartRateGame", "Main"); + + return app.exec(); +} diff --git a/examples/bluetooth/heartrate-game/qmldir b/examples/bluetooth/heartrate-game/qmldir new file mode 100644 index 0000000..161e6ba --- /dev/null +++ b/examples/bluetooth/heartrate-game/qmldir @@ -0,0 +1,15 @@ +module HeartRateGame +prefer :/qt/qml/HeartRateGame/ +App 1.0 App.qml +BluetoothAlarmDialog 1.0 BluetoothAlarmDialog.qml +BottomLine 1.0 BottomLine.qml +Connect 1.0 Connect.qml +GameButton 1.0 GameButton.qml +GamePage 1.0 GamePage.qml +singleton GameSettings 1.0 GameSettings.qml +Measure 1.0 Measure.qml +SplashScreen 1.0 SplashScreen.qml +Stats 1.0 Stats.qml +StatsLabel 1.0 StatsLabel.qml +TitleBar 1.0 TitleBar.qml +Main 1.0 Main.qml diff --git a/examples/bluetooth/heartrate-server/CMakeLists.txt b/examples/bluetooth/heartrate-server/CMakeLists.txt new file mode 100644 index 0000000..505e967 --- /dev/null +++ b/examples/bluetooth/heartrate-server/CMakeLists.txt @@ -0,0 +1,58 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(heartrate-server LANGUAGES CXX) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/bluetooth/heartrate-server") + +find_package(Qt6 REQUIRED COMPONENTS Bluetooth Core) + +qt_standard_project_setup() + +if(ANDROID OR APPLE) + find_package(Qt6 REQUIRED COMPONENTS Gui) +endif() + +qt_add_executable(heartrate-server + main.cpp +) + +set_target_properties(heartrate-server PROPERTIES + MACOSX_BUNDLE TRUE +) + +target_link_libraries(heartrate-server PRIVATE + Qt6::Bluetooth + Qt6::Core +) + +if(ANDROID OR APPLE) + target_link_libraries(heartrate-server PRIVATE + Qt6::Gui + ) +endif() + +if (APPLE) + # Using absolute path for shared plist files is a Ninja bug workaround + get_filename_component(SHARED_PLIST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../shared ABSOLUTE) + if (IOS) + set_target_properties(heartrate-server PROPERTIES + MACOSX_BUNDLE_INFO_PLIST "${SHARED_PLIST_DIR}/Info.cmake.ios.plist" + ) + else() + set_target_properties(heartrate-server PROPERTIES + MACOSX_BUNDLE_INFO_PLIST "${SHARED_PLIST_DIR}/Info.cmake.macos.plist" + ) + endif() +endif() + +install(TARGETS heartrate-server + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/bluetooth/heartrate-server/doc/src/heartrate-server.qdoc b/examples/bluetooth/heartrate-server/doc/src/heartrate-server.qdoc new file mode 100644 index 0000000..30725ae --- /dev/null +++ b/examples/bluetooth/heartrate-server/doc/src/heartrate-server.qdoc @@ -0,0 +1,111 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \example heartrate-server + \title Bluetooth Low Energy Heart Rate Server + \examplecategory {Connectivity} + \meta tags {bluetooth, ble} + + \brief An example demonstrating how to set up and advertise a GATT service. The example + demonstrates the use of the \l{Qt Bluetooth} Low Energy classes related to peripheral (slave) + functionality. + + The Bluetooth Low Energy Heart Rate Server is a command-line application that shows how to + develop a Bluetooth GATT server using the \l{QtBluetooth}{Qt Bluetooth API}. + The application covers setting up a service, advertising it and notifying clients about changes + to characteristic values. + + The example makes use of the following Qt classes: + + \list + \li \l QLowEnergyAdvertisingData + \li \l QLowEnergyAdvertisingParameters + \li \l QLowEnergyServiceData + \li \l QLowEnergyCharacteristicData + \li \l QLowEnergyDescriptorData + \li \l QLowEnergyController + \li \l QLowEnergyService + + \endlist + + The example implements a server application, which means it has no graphical user interface. + To visualize what it is doing, you can use the \l {heartrate-game}{Heart Rate Game} + example, which is basically the client-side counterpart to this application. + + \section1 Checking Bluetooth Permission + Before the application can create a service and start advertising, we have to check + if the application has a permission to use Bluetooth. + \snippet heartrate-server/main.cpp Check Bluetooth Permission + + \section1 Request Bluetooth Permission + If the Bluetooth authorization status is undetermined, we have to request a permission + to use Bluetooth. + \snippet heartrate-server/main.cpp Request Bluetooth Permission + + \section1 Setting up Advertising Data and Parameters + + Two classes are used to configure the advertising process: + \list + \li \l QLowEnergyAdvertisingData specifies which information is to be + broadcasted + \li \l QLowEnergyAdvertisingParameters is used for specific aspects such + as setting the advertising interval or controlling which devices are + allowed to connect. + \endlist + + In our example, we simply use the default parameters. + + The information contained in the \l QLowEnergyAdvertisingData will be visible to other devices + that are currently scanning. They can use it to decide whether they want to establish a connection + or not. In our example, we include the type of service we offer, a name that adequately + describes our device to humans, and the transmit power level of the device. The latter is + often useful to potential clients, because they can tell how far away our device is by + comparing the received signal strength to the advertised one. + \note Space for the advertising data is very limited (only 31 bytes in total), so + variable-length data such as the device name should be kept as short as possible. + \snippet heartrate-server/main.cpp Advertising Data + + \section1 Setting up Service Data + Next we configure the kind of service we want to offer. We use the + \l {QBluetoothUuid::ServiceClassUuid}{Heart Rate} service as defined in the + Bluetooth specification in its minimal form, that is, consisting only of the + \l {QBluetoothUuid::CharacteristicType}{Heart Rate Measurement} characteristic. + This characteristic must support the \l {QLowEnergyCharacteristic::}{Notify} + property (and no others), and it needs to have a \l {QBluetoothUuid::DescriptorType} + {Client Characteristic Configuration} descriptor, which enables clients to + register to get notified about changes to characteristic values. We set the + initial heart rate value to zero, as it cannot be read anyway (the only way + the client can get the value is via notifications). + \snippet heartrate-server/main.cpp Service Data + + \section1 Advertising and Listening for Incoming Connections + Now that all the data has been set up, we can start advertising. First we create a + \l QLowEnergyController object in the + \l {QLowEnergyController::PeripheralRole} {peripheral role} and use it to create a (dynamic) + \l QLowEnergyService object from our (static) \l QLowEnergyServiceData. + Then we call \l QLowEnergyController::startAdvertising(). + Note that we hand in our \l QLowEnergyAdvertisingData twice: The first argument + acts as the actual advertising data, the second one as the scan response data. They could + transport different information, but here we don't have a need for that. We also pass + a default-constructed instance of \l QLowEnergyAdvertisingParameters, because the default + advertising parameters are fine for us. If a client is interested in the advertised service, + it can now establish a connection to our device. When that happens, the device stops advertising + and the \l QLowEnergyController::connected() signal is emitted. + \note When a client disconnects, advertising does not resume automatically. If you want that + to happen, you need to connect to the \l QLowEnergyController::disconnected() signal + and call \l QLowEnergyController::startAdvertising() in the respective slot. + \snippet heartrate-server/main.cpp Start Advertising + + \section1 Providing the Heartrate + So far, so good. But how does a client actually get at the heart rate? This happens by + regularly updating the value of the respective characteristic in the \l QLowEnergyService + object that we received from the \l QLowEnergyController in the code snippet above. + The source of the heart rate would normally be some kind of sensor, but in our example, + we just make up values that we let oscillate between 60 and 100. The most important part in the + following code snippet is the call to \l QLowEnergyService::writeCharacteristic. If + a client is currently connected and has enabled notifications by writing to the aforementioned + \c {Client Characteristic Configuration}, it will get notified about the new value. + \snippet heartrate-server/main.cpp Provide Heartbeat +*/ + diff --git a/examples/bluetooth/heartrate-server/heartrate-server.pro b/examples/bluetooth/heartrate-server/heartrate-server.pro new file mode 100644 index 0000000..56869fd --- /dev/null +++ b/examples/bluetooth/heartrate-server/heartrate-server.pro @@ -0,0 +1,15 @@ +TEMPLATE = app +TARGET = heartrate-server + +QT = core bluetooth +android|darwin: QT += gui + +CONFIG += console + +SOURCES += main.cpp + +ios: QMAKE_INFO_PLIST = ../shared/Info.qmake.ios.plist +macos: QMAKE_INFO_PLIST = ../shared/Info.qmake.macos.plist + +target.path = $$[QT_INSTALL_EXAMPLES]/bluetooth/heartrate-server +INSTALLS += target diff --git a/examples/bluetooth/heartrate-server/main.cpp b/examples/bluetooth/heartrate-server/main.cpp new file mode 100644 index 0000000..90b4461 --- /dev/null +++ b/examples/bluetooth/heartrate-server/main.cpp @@ -0,0 +1,144 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#if defined(Q_OS_ANDROID) || defined(Q_OS_DARWIN) +#include +#else +#include +#endif + +#include +#include +#include + +#if QT_CONFIG(permissions) +#include +#endif + +#include + +int main(int argc, char *argv[]) +{ + // QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true")); +#if defined(Q_OS_ANDROID) || defined(Q_OS_DARWIN) + QGuiApplication app(argc, argv); +#else + QCoreApplication app(argc, argv); +#endif + +#if QT_CONFIG(permissions) + //! [Check Bluetooth Permission] + auto permissionStatus = app.checkPermission(QBluetoothPermission{}); + //! [Check Bluetooth Permission] + + //! [Request Bluetooth Permission] + if (permissionStatus == Qt::PermissionStatus::Undetermined) { + qInfo("Requesting Bluetooth permission ..."); + app.requestPermission(QBluetoothPermission{}, [&permissionStatus](const QPermission &permission){ + qApp->exit(); + permissionStatus = permission.status(); + }); + // Now, wait for permission request to resolve. + app.exec(); + } + //! [Request Bluetooth Permission] + + if (permissionStatus == Qt::PermissionStatus::Denied) { + // Either explicitly denied by a user, or Bluetooth is off. + qWarning("This application cannot use Bluetooth, the permission was denied"); + return -1; + } + +#endif + //! [Advertising Data] + QLowEnergyAdvertisingData advertisingData; + advertisingData.setDiscoverability(QLowEnergyAdvertisingData::DiscoverabilityGeneral); + advertisingData.setIncludePowerLevel(true); + advertisingData.setLocalName("HeartRateServer"); + advertisingData.setServices(QList() << QBluetoothUuid::ServiceClassUuid::HeartRate); + //! [Advertising Data] + + //! [Service Data] + QLowEnergyCharacteristicData charData; + charData.setUuid(QBluetoothUuid::CharacteristicType::HeartRateMeasurement); + charData.setValue(QByteArray(2, 0)); + charData.setProperties(QLowEnergyCharacteristic::Notify); + const QLowEnergyDescriptorData clientConfig(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration, + QByteArray(2, 0)); + charData.addDescriptor(clientConfig); + + QLowEnergyServiceData serviceData; + serviceData.setType(QLowEnergyServiceData::ServiceTypePrimary); + serviceData.setUuid(QBluetoothUuid::ServiceClassUuid::HeartRate); + serviceData.addCharacteristic(charData); + //! [Service Data] + + //! [Start Advertising] + bool errorOccurred = false; + const std::unique_ptr leController(QLowEnergyController::createPeripheral()); + auto errorHandler = [&leController, &errorOccurred](QLowEnergyController::Error errorCode) { + qWarning().noquote().nospace() << errorCode << " occurred: " + << leController->errorString(); + if (errorCode != QLowEnergyController::RemoteHostClosedError) { + qWarning("Heartrate-server quitting due to the error."); + errorOccurred = true; + QCoreApplication::quit(); + } + }; + QObject::connect(leController.get(), &QLowEnergyController::errorOccurred, errorHandler); + + std::unique_ptr service(leController->addService(serviceData)); + leController->startAdvertising(QLowEnergyAdvertisingParameters(), advertisingData, + advertisingData); + if (errorOccurred) + return -1; + //! [Start Advertising] + + //! [Provide Heartbeat] + QTimer heartbeatTimer; + quint8 currentHeartRate = 60; + enum ValueChange { ValueUp, ValueDown } valueChange = ValueUp; + const auto heartbeatProvider = [&service, ¤tHeartRate, &valueChange]() { + QByteArray value; + value.append(char(0)); // Flags that specify the format of the value. + value.append(char(currentHeartRate)); // Actual value. + QLowEnergyCharacteristic characteristic + = service->characteristic(QBluetoothUuid::CharacteristicType::HeartRateMeasurement); + Q_ASSERT(characteristic.isValid()); + service->writeCharacteristic(characteristic, value); // Potentially causes notification. + if (currentHeartRate == 60) + valueChange = ValueUp; + else if (currentHeartRate == 100) + valueChange = ValueDown; + if (valueChange == ValueUp) + ++currentHeartRate; + else + --currentHeartRate; + }; + QObject::connect(&heartbeatTimer, &QTimer::timeout, heartbeatProvider); + heartbeatTimer.start(1000); + //! [Provide Heartbeat] + + auto reconnect = [&leController, advertisingData, &service, serviceData]() { + service.reset(leController->addService(serviceData)); + if (service) { + leController->startAdvertising(QLowEnergyAdvertisingParameters(), + advertisingData, advertisingData); + } + }; + QObject::connect(leController.get(), &QLowEnergyController::disconnected, reconnect); + + const int retval = QCoreApplication::exec(); + return errorOccurred ? -1 : retval; +} diff --git a/examples/bluetooth/lowenergyscanner/CMakeLists.txt b/examples/bluetooth/lowenergyscanner/CMakeLists.txt new file mode 100644 index 0000000..bb7d8fa --- /dev/null +++ b/examples/bluetooth/lowenergyscanner/CMakeLists.txt @@ -0,0 +1,72 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(lowenergyscanner LANGUAGES CXX) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/bluetooth/lowenergyscanner") + +find_package(Qt6 REQUIRED COMPONENTS Bluetooth Core Gui Quick) + +qt_standard_project_setup(REQUIRES 6.5) + +qt_add_executable(lowenergyscanner + main.cpp +) + +set_target_properties(lowenergyscanner PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(lowenergyscanner PUBLIC + Qt6::Bluetooth + Qt6::Core + Qt6::Gui + Qt6::Quick +) + +if (APPLE) + # Using absolute path for shared plist files is a Ninja bug workaround + get_filename_component(SHARED_PLIST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../shared ABSOLUTE) + if (IOS) + set_target_properties(lowenergyscanner PROPERTIES + MACOSX_BUNDLE_INFO_PLIST "${SHARED_PLIST_DIR}/Info.cmake.ios.plist" + ) + else() + set_target_properties(lowenergyscanner PROPERTIES + MACOSX_BUNDLE_INFO_PLIST "${SHARED_PLIST_DIR}/Info.cmake.macos.plist" + ) + endif() +endif() + +qt_add_qml_module(lowenergyscanner + URI Scanner + VERSION 1.0 + SOURCES + characteristicinfo.cpp characteristicinfo.h + device.cpp device.h + deviceinfo.cpp deviceinfo.h + serviceinfo.cpp serviceinfo.h + QML_FILES + Characteristics.qml + Devices.qml + Dialog.qml + Header.qml + Label.qml + Main.qml + Menu.qml + Services.qml + RESOURCES + assets/busy_dark.png +) + +install(TARGETS lowenergyscanner + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/bluetooth/lowenergyscanner/Characteristics.qml b/examples/bluetooth/lowenergyscanner/Characteristics.qml new file mode 100644 index 0000000..5d140bd --- /dev/null +++ b/examples/bluetooth/lowenergyscanner/Characteristics.qml @@ -0,0 +1,121 @@ +// Copyright (C) 2013 BlackBerry Limited. All rights reserved. +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +pragma ComponentBehavior: Bound +import QtQuick + +Rectangle { + id: characteristicsPage + + signal showServices + signal showDevices + + width: 300 + height: 600 + + Header { + id: header + anchors.top: parent.top + headerText: "Characteristics list" + } + + Dialog { + id: info + anchors.centerIn: parent + visible: true + dialogText: "Scanning for characteristics..." + } + + Connections { + target: Device + function onCharacteristicsUpdated() { + menu.menuText = "Back" + if (characteristicview.count === 0) { + info.dialogText = "No characteristic found" + info.busyImage = false + } else { + info.visible = false + info.busyImage = true + } + } + + function onDisconnected() { + characteristicsPage.showDevices() + } + } + + ListView { + id: characteristicview + width: parent.width + clip: true + + anchors.top: header.bottom + anchors.bottom: menu.top + model: Device.characteristicList + + delegate: Rectangle { + required property var modelData + id: box + height: 300 + width: characteristicview.width + color: "lightsteelblue" + border.width: 2 + border.color: "black" + radius: 5 + + Label { + id: characteristicName + textContent: box.modelData.characteristicName + anchors.top: parent.top + anchors.topMargin: 5 + } + + Label { + id: characteristicUuid + font.pointSize: characteristicName.font.pointSize * 0.7 + textContent: box.modelData.characteristicUuid + anchors.top: characteristicName.bottom + anchors.topMargin: 5 + } + + Label { + id: characteristicValue + font.pointSize: characteristicName.font.pointSize * 0.7 + textContent: ("Value: " + box.modelData.characteristicValue) + anchors.bottom: characteristicHandle.top + horizontalAlignment: Text.AlignHCenter + anchors.topMargin: 5 + } + + Label { + id: characteristicHandle + font.pointSize: characteristicName.font.pointSize * 0.7 + textContent: ("Handlers: " + box.modelData.characteristicHandle) + anchors.bottom: characteristicPermission.top + anchors.topMargin: 5 + } + + Label { + id: characteristicPermission + font.pointSize: characteristicName.font.pointSize * 0.7 + textContent: box.modelData.characteristicPermission + anchors.bottom: parent.bottom + anchors.topMargin: 5 + anchors.bottomMargin: 5 + } + } + } + + Menu { + id: menu + anchors.bottom: parent.bottom + menuWidth: parent.width + menuText: Device.update + menuHeight: (parent.height / 6) + onButtonClick: { + characteristicsPage.showServices() + Device.update = "Back" + } + } +} diff --git a/examples/bluetooth/lowenergyscanner/Devices.qml b/examples/bluetooth/lowenergyscanner/Devices.qml new file mode 100644 index 0000000..b41c259 --- /dev/null +++ b/examples/bluetooth/lowenergyscanner/Devices.qml @@ -0,0 +1,144 @@ +// Copyright (C) 2013 BlackBerry Limited. All rights reserved. +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +pragma ComponentBehavior: Bound +import QtCore +import QtQuick + +Rectangle { + id: devicesPage + + property bool deviceState: Device.state + signal showServices + + width: 300 + height: 600 + + function toggleDiscovery() { + if (!Device.state) { + Device.startDeviceDiscovery() + // if startDeviceDiscovery() failed Device.state is not set + if (Device.state) { + info.dialogText = "Searching..." + info.visible = true + } + } else { + Device.stopDeviceDiscovery() + } + } + + onDeviceStateChanged: { + if (!Device.state) + info.visible = false + } + + Header { + id: header + anchors.top: parent.top + headerText: { + if (Device.state) + return "Discovering" + + if (Device.devicesList.length > 0) + return "Select a device" + + return "Start Discovery" + } + } + + Dialog { + id: info + anchors.centerIn: parent + visible: false + } + + ListView { + id: theListView + width: parent.width + clip: true + + anchors.top: header.bottom + anchors.bottom: connectToggle.top + model: Device.devicesList + + delegate: Rectangle { + required property var modelData + id: box + height: 100 + width: theListView.width + color: "lightsteelblue" + border.width: 2 + border.color: "black" + radius: 5 + + MouseArea { + anchors.fill: parent + onClicked: { + Device.scanServices(box.modelData.deviceAddress) + showServices() + } + } + + Label { + id: deviceName + textContent: box.modelData.deviceName + anchors.top: parent.top + anchors.topMargin: 5 + } + + Label { + id: deviceAddress + textContent: box.modelData.deviceAddress + font.pointSize: deviceName.font.pointSize * 0.7 + anchors.bottom: box.bottom + anchors.bottomMargin: 5 + } + } + } + + Menu { + id: connectToggle + + menuWidth: parent.width + anchors.bottom: menu.top + menuText: { + visible = Device.devicesList.length > 0 + if (Device.useRandomAddress) + return "Address type: Random" + else + return "Address type: Public" + } + + onButtonClick: Device.useRandomAddress = !Device.useRandomAddress + } + + //! [permission-object] + BluetoothPermission { + id: permission + communicationModes: BluetoothPermission.Access + onStatusChanged: { + if (permission.status === Qt.PermissionStatus.Denied) + Device.update = "Bluetooth permission required" + else if (permission.status === Qt.PermissionStatus.Granted) + devicesPage.toggleDiscovery() + } + } + //! [permission-object] + + Menu { + id: menu + anchors.bottom: parent.bottom + menuWidth: parent.width + menuHeight: (parent.height / 6) + menuText: Device.update + //! [permission-request] + onButtonClick: { + if (permission.status === Qt.PermissionStatus.Undetermined) + permission.request() + else if (permission.status === Qt.PermissionStatus.Granted) + devicesPage.toggleDiscovery() + } + //! [permission-request] + } +} diff --git a/examples/bluetooth/lowenergyscanner/Dialog.qml b/examples/bluetooth/lowenergyscanner/Dialog.qml new file mode 100644 index 0000000..75e8264 --- /dev/null +++ b/examples/bluetooth/lowenergyscanner/Dialog.qml @@ -0,0 +1,48 @@ +// Copyright (C) 2013 BlackBerry Limited. All rights reserved. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick + +Rectangle { + id: dialog + width: parent.width / 3 * 2 + height: dialogTextId.height + background.height + 20 + z: 50 + property string dialogText: "" + property bool busyImage: true + border.width: 1 + border.color: "#363636" + radius: 10 + + Text { + id: dialogTextId + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: parent.top + anchors.topMargin: 10 + + elide: Text.ElideMiddle + text: dialog.dialogText + color: "#363636" + wrapMode: Text.Wrap + } + + Image { + id: background + + width: 20 + height: 20 + anchors.top: dialogTextId.bottom + anchors.horizontalCenter: dialogTextId.horizontalCenter + visible: parent.busyImage + source: "assets/busy_dark.png" + fillMode: Image.PreserveAspectFit + NumberAnimation on rotation { + duration: 3000 + from: 0 + to: 360 + loops: Animation.Infinite + } + } +} diff --git a/examples/bluetooth/lowenergyscanner/Header.qml b/examples/bluetooth/lowenergyscanner/Header.qml new file mode 100644 index 0000000..c95385d --- /dev/null +++ b/examples/bluetooth/lowenergyscanner/Header.qml @@ -0,0 +1,25 @@ +// Copyright (C) 2013 BlackBerry Limited. All rights reserved. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick + +Rectangle { + id: header + width: parent.width + height: 70 + border.width: 1 + border.color: "#363636" + radius: 5 + property string headerText: "" + + Text { + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + anchors.fill: parent + text: header.headerText + font.bold: true + font.pointSize: 20 + elide: Text.ElideMiddle + color: "#363636" + } +} diff --git a/examples/bluetooth/lowenergyscanner/Label.qml b/examples/bluetooth/lowenergyscanner/Label.qml new file mode 100644 index 0000000..e311567 --- /dev/null +++ b/examples/bluetooth/lowenergyscanner/Label.qml @@ -0,0 +1,16 @@ +// Copyright (C) 2013 BlackBerry Limited. All rights reserved. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick + +Text { + property string textContent: "" + font.pointSize: 20 + anchors.horizontalCenter: parent.horizontalCenter + color: "#363636" + horizontalAlignment: Text.AlignHCenter + elide: Text.ElideMiddle + width: parent.width + wrapMode: Text.Wrap + text: textContent +} diff --git a/examples/bluetooth/lowenergyscanner/Main.qml b/examples/bluetooth/lowenergyscanner/Main.qml new file mode 100644 index 0000000..88600ba --- /dev/null +++ b/examples/bluetooth/lowenergyscanner/Main.qml @@ -0,0 +1,31 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Layouts + +Window { + id: main + + width: 300 + height: 600 + visible: true + + StackLayout { + id: pagesLayout + anchors.fill: parent + currentIndex: 0 + + Devices { + onShowServices: pagesLayout.currentIndex = 1 + } + Services { + onShowDevices: pagesLayout.currentIndex = 0 + onShowCharacteristics: pagesLayout.currentIndex = 2 + } + Characteristics { + onShowDevices: pagesLayout.currentIndex = 0 + onShowServices: pagesLayout.currentIndex = 1 + } + } +} diff --git a/examples/bluetooth/lowenergyscanner/Menu.qml b/examples/bluetooth/lowenergyscanner/Menu.qml new file mode 100644 index 0000000..ef69c89 --- /dev/null +++ b/examples/bluetooth/lowenergyscanner/Menu.qml @@ -0,0 +1,55 @@ +// Copyright (C) 2013 BlackBerry Limited. All rights reserved. +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick + +Rectangle { + id: menu + + property real menuWidth: 100 + property real menuHeight: 50 + property string menuText: "Search" + signal buttonClick + + height: menuHeight + width: menuWidth + + Rectangle { + id: search + width: parent.width + height: parent.height + anchors.centerIn: parent + color: "#363636" + border.width: 1 + border.color: "#E3E3E3" + radius: 5 + Text { + id: searchText + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + anchors.fill: parent + text: menu.menuText + elide: Text.ElideMiddle + color: "#E3E3E3" + wrapMode: Text.WordWrap + } + + MouseArea { + anchors.fill: parent + onPressed: { + search.width = search.width - 7 + search.height = search.height - 5 + } + + onReleased: { + search.width = search.width + 7 + search.height = search.height + 5 + } + + onClicked: { + menu.buttonClick() + } + } + } +} diff --git a/examples/bluetooth/lowenergyscanner/Services.qml b/examples/bluetooth/lowenergyscanner/Services.qml new file mode 100644 index 0000000..4d7fee3 --- /dev/null +++ b/examples/bluetooth/lowenergyscanner/Services.qml @@ -0,0 +1,115 @@ +// Copyright (C) 2013 BlackBerry Limited. All rights reserved. +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +pragma ComponentBehavior: Bound +import QtQuick + +Rectangle { + id: servicesPage + + signal showCharacteristics + signal showDevices + + width: 300 + height: 600 + + Component.onCompleted: { + // Loading this page may take longer than QLEController + // stopping with an error, go back and readjust this view + // based on controller errors + if (Device.controllerError) { + info.visible = false + menu.menuText = Device.update + } + } + + Header { + id: header + anchors.top: parent.top + headerText: "Services list" + } + + Dialog { + id: info + anchors.centerIn: parent + visible: true + dialogText: "Scanning for services..." + } + + Connections { + target: Device + function onServicesUpdated() { + if (servicesview.count === 0) + info.dialogText = "No services found" + else + info.visible = false + } + + function onDisconnected() { + servicesPage.showDevices() + } + } + + ListView { + id: servicesview + width: parent.width + anchors.top: header.bottom + anchors.bottom: menu.top + model: Device.servicesList + clip: true + + delegate: Rectangle { + required property var modelData + id: box + height: 100 + color: "lightsteelblue" + border.width: 2 + border.color: "black" + radius: 5 + width: servicesview.width + + MouseArea { + anchors.fill: parent + onClicked: { + Device.connectToService(box.modelData.serviceUuid) + servicesPage.showCharacteristics() + } + } + + Label { + id: serviceName + textContent: box.modelData.serviceName + anchors.top: parent.top + anchors.topMargin: 5 + } + + Label { + textContent: box.modelData.serviceType + font.pointSize: serviceName.font.pointSize * 0.5 + anchors.top: serviceName.bottom + } + + Label { + id: serviceUuid + font.pointSize: serviceName.font.pointSize * 0.5 + textContent: box.modelData.serviceUuid + anchors.bottom: box.bottom + anchors.bottomMargin: 5 + } + } + } + + Menu { + id: menu + anchors.bottom: parent.bottom + menuWidth: parent.width + menuText: Device.update + menuHeight: (parent.height / 6) + onButtonClick: { + Device.disconnectFromDevice() + servicesPage.showDevices() + Device.update = "Search" + } + } +} diff --git a/examples/bluetooth/lowenergyscanner/assets/busy_dark.png b/examples/bluetooth/lowenergyscanner/assets/busy_dark.png new file mode 100644 index 0000000..3a10595 Binary files /dev/null and b/examples/bluetooth/lowenergyscanner/assets/busy_dark.png differ diff --git a/examples/bluetooth/lowenergyscanner/characteristicinfo.cpp b/examples/bluetooth/lowenergyscanner/characteristicinfo.cpp new file mode 100644 index 0000000..59df54c --- /dev/null +++ b/examples/bluetooth/lowenergyscanner/characteristicinfo.cpp @@ -0,0 +1,106 @@ +// Copyright (C) 2013 BlackBerry Limited. All rights reserved. +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "characteristicinfo.h" + +#include + +#include + +using namespace Qt::StringLiterals; + +CharacteristicInfo::CharacteristicInfo(const QLowEnergyCharacteristic &characteristic): + m_characteristic(characteristic) +{ +} + +void CharacteristicInfo::setCharacteristic(const QLowEnergyCharacteristic &characteristic) +{ + m_characteristic = characteristic; + emit characteristicChanged(); +} + +QString CharacteristicInfo::getName() const +{ + //! [les-get-descriptors] + QString name = m_characteristic.name(); + if (!name.isEmpty()) + return name; + + // find descriptor with CharacteristicUserDescription + const QList descriptors = m_characteristic.descriptors(); + for (const QLowEnergyDescriptor &descriptor : descriptors) { + if (descriptor.type() == QBluetoothUuid::DescriptorType::CharacteristicUserDescription) { + name = descriptor.value(); + break; + } + } + //! [les-get-descriptors] + + if (name.isEmpty()) + name = u"Unknown"_s; + + return name; +} + +QString CharacteristicInfo::getUuid() const +{ + const QBluetoothUuid uuid = m_characteristic.uuid(); + bool success = false; + quint16 result16 = uuid.toUInt16(&success); + if (success) + return u"0x"_s + QString::number(result16, 16); + + quint32 result32 = uuid.toUInt32(&success); + if (success) + return u"0x"_s + QString::number(result32, 16); + + return uuid.toString().remove('{'_L1).remove('}'_L1); +} + +QString CharacteristicInfo::getValue() const +{ + // Show raw string first and hex value below + QByteArray a = m_characteristic.value(); + QString result; + if (a.isEmpty()) { + result = u""_s; + return result; + } + + result = a; + result += '\n'_L1; + result += a.toHex(); + + return result; +} + +QString CharacteristicInfo::getPermission() const +{ + QString properties = u"( "_s; + uint permission = m_characteristic.properties(); + if (permission & QLowEnergyCharacteristic::Read) + properties += u" Read"_s; + if (permission & QLowEnergyCharacteristic::Write) + properties += u" Write"_s; + if (permission & QLowEnergyCharacteristic::Notify) + properties += u" Notify"_s; + if (permission & QLowEnergyCharacteristic::Indicate) + properties += u" Indicate"_s; + if (permission & QLowEnergyCharacteristic::ExtendedProperty) + properties += u" ExtendedProperty"_s; + if (permission & QLowEnergyCharacteristic::Broadcasting) + properties += u" Broadcast"_s; + if (permission & QLowEnergyCharacteristic::WriteNoResponse) + properties += u" WriteNoResp"_s; + if (permission & QLowEnergyCharacteristic::WriteSigned) + properties += u" WriteSigned"_s; + properties += u" )"_s; + return properties; +} + +QLowEnergyCharacteristic CharacteristicInfo::getCharacteristic() const +{ + return m_characteristic; +} diff --git a/examples/bluetooth/lowenergyscanner/characteristicinfo.h b/examples/bluetooth/lowenergyscanner/characteristicinfo.h new file mode 100644 index 0000000..a39ce82 --- /dev/null +++ b/examples/bluetooth/lowenergyscanner/characteristicinfo.h @@ -0,0 +1,42 @@ +// Copyright (C) 2013 BlackBerry Limited. All rights reserved. +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef CHARACTERISTICINFO_H +#define CHARACTERISTICINFO_H + +#include + +#include +#include + +#include + +class CharacteristicInfo: public QObject +{ + Q_OBJECT + Q_PROPERTY(QString characteristicName READ getName NOTIFY characteristicChanged) + Q_PROPERTY(QString characteristicUuid READ getUuid NOTIFY characteristicChanged) + Q_PROPERTY(QString characteristicValue READ getValue NOTIFY characteristicChanged) + Q_PROPERTY(QString characteristicPermission READ getPermission NOTIFY characteristicChanged) + + QML_ANONYMOUS + +public: + CharacteristicInfo() = default; + CharacteristicInfo(const QLowEnergyCharacteristic &characteristic); + void setCharacteristic(const QLowEnergyCharacteristic &characteristic); + QString getName() const; + QString getUuid() const; + QString getValue() const; + QString getPermission() const; + QLowEnergyCharacteristic getCharacteristic() const; + +Q_SIGNALS: + void characteristicChanged(); + +private: + QLowEnergyCharacteristic m_characteristic; +}; + +#endif // CHARACTERISTICINFO_H diff --git a/examples/bluetooth/lowenergyscanner/device.cpp b/examples/bluetooth/lowenergyscanner/device.cpp new file mode 100644 index 0000000..87c2d9c --- /dev/null +++ b/examples/bluetooth/lowenergyscanner/device.cpp @@ -0,0 +1,353 @@ +// Copyright (C) 2013 BlackBerry Limited. All rights reserved. +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "device.h" + +#include +#include + +#include +#include +#include + +#if QT_CONFIG(permissions) +#include + +#include +#endif + +using namespace Qt::StringLiterals; + +Device::Device() +{ + //! [les-devicediscovery-1] + discoveryAgent = new QBluetoothDeviceDiscoveryAgent(this); + discoveryAgent->setLowEnergyDiscoveryTimeout(25000); + connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, + this, &Device::addDevice); + connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::errorOccurred, + this, &Device::deviceScanError); + connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, + this, &Device::deviceScanFinished); + connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::canceled, + this, &Device::deviceScanFinished); + //! [les-devicediscovery-1] + + setUpdate(u"Search"_s); +} + +Device::~Device() +{ + qDeleteAll(devices); + qDeleteAll(m_services); + qDeleteAll(m_characteristics); + devices.clear(); + m_services.clear(); + m_characteristics.clear(); +} + +void Device::startDeviceDiscovery() +{ + qDeleteAll(devices); + devices.clear(); + emit devicesUpdated(); + + //! [les-devicediscovery-2] + discoveryAgent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod); + //! [les-devicediscovery-2] + + if (discoveryAgent->isActive()) { + setUpdate(u"Stop"_s); + m_deviceScanState = true; + Q_EMIT stateChanged(); + } +} + +void Device::stopDeviceDiscovery() +{ + if (discoveryAgent->isActive()) + discoveryAgent->stop(); +} + +//! [les-devicediscovery-3] +void Device::addDevice(const QBluetoothDeviceInfo &info) +{ + if (info.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration) { + auto devInfo = new DeviceInfo(info); + auto it = std::find_if(devices.begin(), devices.end(), + [devInfo](DeviceInfo *dev) { + return devInfo->getAddress() == dev->getAddress(); + }); + if (it == devices.end()) { + devices.append(devInfo); + } else { + auto oldDev = *it; + *it = devInfo; + delete oldDev; + } + emit devicesUpdated(); + } +} +//! [les-devicediscovery-3] + +void Device::deviceScanFinished() +{ + m_deviceScanState = false; + emit stateChanged(); + if (devices.isEmpty()) + setUpdate(u"No Low Energy devices found..."_s); + else + setUpdate(u"Done! Scan Again!"_s); +} + +QVariant Device::getDevices() +{ + return QVariant::fromValue(devices); +} + +QVariant Device::getServices() +{ + return QVariant::fromValue(m_services); +} + +QVariant Device::getCharacteristics() +{ + return QVariant::fromValue(m_characteristics); +} + +QString Device::getUpdate() +{ + return m_message; +} + +void Device::scanServices(const QString &address) +{ + // We need the current device for service discovery. + + for (auto d: std::as_const(devices)) { + if (auto device = qobject_cast(d)) { + if (device->getAddress() == address) { + currentDevice.setDevice(device->getDevice()); + break; + } + } + } + + if (!currentDevice.getDevice().isValid()) { + qWarning() << "Not a valid device"; + return; + } + + qDeleteAll(m_characteristics); + m_characteristics.clear(); + emit characteristicsUpdated(); + qDeleteAll(m_services); + m_services.clear(); + emit servicesUpdated(); + + setUpdate(u"Back\n(Connecting to device...)"_s); + + if (controller && m_previousAddress != currentDevice.getAddress()) { + controller->disconnectFromDevice(); + delete controller; + controller = nullptr; + } + + //! [les-controller-1] + if (!controller) { + // Connecting signals and slots for connecting to LE services. + controller = QLowEnergyController::createCentral(currentDevice.getDevice(), this); + connect(controller, &QLowEnergyController::connected, + this, &Device::deviceConnected); + connect(controller, &QLowEnergyController::errorOccurred, this, &Device::errorReceived); + connect(controller, &QLowEnergyController::disconnected, + this, &Device::deviceDisconnected); + connect(controller, &QLowEnergyController::serviceDiscovered, + this, &Device::addLowEnergyService); + connect(controller, &QLowEnergyController::discoveryFinished, + this, &Device::serviceScanDone); + } + + if (isRandomAddress()) + controller->setRemoteAddressType(QLowEnergyController::RandomAddress); + else + controller->setRemoteAddressType(QLowEnergyController::PublicAddress); + controller->connectToDevice(); + //! [les-controller-1] + + m_previousAddress = currentDevice.getAddress(); +} + +void Device::addLowEnergyService(const QBluetoothUuid &serviceUuid) +{ + //! [les-service-1] + QLowEnergyService *service = controller->createServiceObject(serviceUuid); + if (!service) { + qWarning() << "Cannot create service for uuid"; + return; + } + //! [les-service-1] + auto serv = new ServiceInfo(service); + m_services.append(serv); + + emit servicesUpdated(); +} +//! [les-service-1] + +void Device::serviceScanDone() +{ + setUpdate(u"Back\n(Service scan done!)"_s); + // force UI in case we didn't find anything + if (m_services.isEmpty()) + emit servicesUpdated(); +} + +void Device::connectToService(const QString &uuid) +{ + QLowEnergyService *service = nullptr; + for (auto s: std::as_const(m_services)) { + auto serviceInfo = qobject_cast(s); + if (!serviceInfo) + continue; + + if (serviceInfo->getUuid() == uuid) { + service = serviceInfo->service(); + break; + } + } + + if (!service) + return; + + qDeleteAll(m_characteristics); + m_characteristics.clear(); + emit characteristicsUpdated(); + + if (service->state() == QLowEnergyService::RemoteService) { + //! [les-service-3] + connect(service, &QLowEnergyService::stateChanged, + this, &Device::serviceDetailsDiscovered); + service->discoverDetails(); + setUpdate(u"Back\n(Discovering details...)"_s); + //! [les-service-3] + return; + } + + //discovery already done + const QList chars = service->characteristics(); + for (const QLowEnergyCharacteristic &ch : chars) { + auto cInfo = new CharacteristicInfo(ch); + m_characteristics.append(cInfo); + } + + QTimer::singleShot(0, this, &Device::characteristicsUpdated); +} + +void Device::deviceConnected() +{ + setUpdate(u"Back\n(Discovering services...)"_s); + connected = true; + //! [les-service-2] + controller->discoverServices(); + //! [les-service-2] +} + +void Device::errorReceived(QLowEnergyController::Error /*error*/) +{ + qWarning() << "Error: " << controller->errorString(); + setUpdate(u"Back\n(%1)"_s.arg(controller->errorString())); +} + +void Device::setUpdate(const QString &message) +{ + m_message = message; + emit updateChanged(); +} + +void Device::disconnectFromDevice() +{ + // UI always expects disconnect() signal when calling this signal + // TODO what is really needed is to extend state() to a multi value + // and thus allowing UI to keep track of controller progress in addition to + // device scan progress + + if (controller->state() != QLowEnergyController::UnconnectedState) + controller->disconnectFromDevice(); + else + deviceDisconnected(); +} + +void Device::deviceDisconnected() +{ + qWarning() << "Disconnect from device"; + emit disconnected(); +} + +void Device::serviceDetailsDiscovered(QLowEnergyService::ServiceState newState) +{ + if (newState != QLowEnergyService::RemoteServiceDiscovered) { + // do not hang in "Scanning for characteristics" mode forever + // in case the service discovery failed + // We have to queue the signal up to give UI time to even enter + // the above mode + if (newState != QLowEnergyService::RemoteServiceDiscovering) { + QMetaObject::invokeMethod(this, "characteristicsUpdated", + Qt::QueuedConnection); + } + return; + } + + auto service = qobject_cast(sender()); + if (!service) + return; + + + + //! [les-chars] + const QList chars = service->characteristics(); + for (const QLowEnergyCharacteristic &ch : chars) { + auto cInfo = new CharacteristicInfo(ch); + m_characteristics.append(cInfo); + } + //! [les-chars] + + emit characteristicsUpdated(); +} + +void Device::deviceScanError(QBluetoothDeviceDiscoveryAgent::Error error) +{ + if (error == QBluetoothDeviceDiscoveryAgent::PoweredOffError) { + setUpdate(u"The Bluetooth adaptor is powered off, power it on before doing discovery."_s); + } else if (error == QBluetoothDeviceDiscoveryAgent::InputOutputError) { + setUpdate(u"Writing or reading from the device resulted in an error."_s); + } else { + static QMetaEnum qme = discoveryAgent->metaObject()->enumerator( + discoveryAgent->metaObject()->indexOfEnumerator("Error")); + setUpdate(u"Error: "_s + QLatin1StringView(qme.valueToKey(error))); + } + + m_deviceScanState = false; + emit stateChanged(); +} + +bool Device::state() +{ + return m_deviceScanState; +} + +bool Device::hasControllerError() const +{ + return (controller && controller->error() != QLowEnergyController::NoError); +} + +bool Device::isRandomAddress() const +{ + return randomAddress; +} + +void Device::setRandomAddress(bool newValue) +{ + randomAddress = newValue; + emit randomAddressChanged(); +} diff --git a/examples/bluetooth/lowenergyscanner/device.h b/examples/bluetooth/lowenergyscanner/device.h new file mode 100644 index 0000000..4a7e7f8 --- /dev/null +++ b/examples/bluetooth/lowenergyscanner/device.h @@ -0,0 +1,102 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef DEVICE_H +#define DEVICE_H + +#include "characteristicinfo.h" +#include "deviceinfo.h" +#include "serviceinfo.h" + +#include +#include +#include + +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE +class QBluetoothDeviceInfo; +class QBluetoothUuid; +QT_END_NAMESPACE + +class Device: public QObject +{ + Q_OBJECT + Q_PROPERTY(QVariant devicesList READ getDevices NOTIFY devicesUpdated) + Q_PROPERTY(QVariant servicesList READ getServices NOTIFY servicesUpdated) + Q_PROPERTY(QVariant characteristicList READ getCharacteristics NOTIFY characteristicsUpdated) + Q_PROPERTY(QString update READ getUpdate WRITE setUpdate NOTIFY updateChanged) + Q_PROPERTY(bool useRandomAddress READ isRandomAddress WRITE setRandomAddress + NOTIFY randomAddressChanged) + Q_PROPERTY(bool state READ state NOTIFY stateChanged) + Q_PROPERTY(bool controllerError READ hasControllerError) + + QML_ELEMENT + QML_SINGLETON + +public: + Device(); + ~Device(); + QVariant getDevices(); + QVariant getServices(); + QVariant getCharacteristics(); + QString getUpdate(); + bool state(); + bool hasControllerError() const; + + bool isRandomAddress() const; + void setRandomAddress(bool newValue); + +public slots: + void startDeviceDiscovery(); + void stopDeviceDiscovery(); + void scanServices(const QString &address); + + void connectToService(const QString &uuid); + void disconnectFromDevice(); + +private slots: + // QBluetoothDeviceDiscoveryAgent related + void addDevice(const QBluetoothDeviceInfo&); + void deviceScanFinished(); + void deviceScanError(QBluetoothDeviceDiscoveryAgent::Error); + + // QLowEnergyController realted + void addLowEnergyService(const QBluetoothUuid &uuid); + void deviceConnected(); + void errorReceived(QLowEnergyController::Error); + void serviceScanDone(); + void deviceDisconnected(); + + // QLowEnergyService related + void serviceDetailsDiscovered(QLowEnergyService::ServiceState newState); + +Q_SIGNALS: + void devicesUpdated(); + void servicesUpdated(); + void characteristicsUpdated(); + void updateChanged(); + void stateChanged(); + void disconnected(); + void randomAddressChanged(); + +private: + void setUpdate(const QString &message); + QBluetoothDeviceDiscoveryAgent *discoveryAgent; + DeviceInfo currentDevice; + QList devices; + QList m_services; + QList m_characteristics; + QString m_previousAddress; + QString m_message; + bool connected = false; + QLowEnergyController *controller = nullptr; + bool m_deviceScanState = false; + bool randomAddress = false; +}; + +#endif // DEVICE_H diff --git a/examples/bluetooth/lowenergyscanner/deviceinfo.cpp b/examples/bluetooth/lowenergyscanner/deviceinfo.cpp new file mode 100644 index 0000000..66300a2 --- /dev/null +++ b/examples/bluetooth/lowenergyscanner/deviceinfo.cpp @@ -0,0 +1,43 @@ +// Copyright (C) 2013 BlackBerry Limited. All rights reserved. +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "deviceinfo.h" + +#ifdef Q_OS_DARWIN +# include +#else +# include +#endif + +DeviceInfo::DeviceInfo(const QBluetoothDeviceInfo &d) +{ + device = d; +} + +QString DeviceInfo::getAddress() const +{ +#ifdef Q_OS_DARWIN + // On OS X and iOS we do not have addresses, + // only unique UUIDs generated by Core Bluetooth. + return device.deviceUuid().toString(); +#else + return device.address().toString(); +#endif +} + +QString DeviceInfo::getName() const +{ + return device.name(); +} + +QBluetoothDeviceInfo DeviceInfo::getDevice() +{ + return device; +} + +void DeviceInfo::setDevice(const QBluetoothDeviceInfo &dev) +{ + device = QBluetoothDeviceInfo(dev); + Q_EMIT deviceChanged(); +} diff --git a/examples/bluetooth/lowenergyscanner/deviceinfo.h b/examples/bluetooth/lowenergyscanner/deviceinfo.h new file mode 100644 index 0000000..7a0c735 --- /dev/null +++ b/examples/bluetooth/lowenergyscanner/deviceinfo.h @@ -0,0 +1,38 @@ +// Copyright (C) 2013 BlackBerry Limited. All rights reserved. +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef DEVICEINFO_H +#define DEVICEINFO_H + +#include + +#include +#include + +#include + +class DeviceInfo: public QObject +{ + Q_OBJECT + Q_PROPERTY(QString deviceName READ getName NOTIFY deviceChanged) + Q_PROPERTY(QString deviceAddress READ getAddress NOTIFY deviceChanged) + + QML_ANONYMOUS + +public: + DeviceInfo() = default; + DeviceInfo(const QBluetoothDeviceInfo &d); + QString getAddress() const; + QString getName() const; + QBluetoothDeviceInfo getDevice(); + void setDevice(const QBluetoothDeviceInfo &dev); + +Q_SIGNALS: + void deviceChanged(); + +private: + QBluetoothDeviceInfo device; +}; + +#endif // DEVICEINFO_H diff --git a/examples/bluetooth/lowenergyscanner/doc/images/lowenergyscanner-chars.png b/examples/bluetooth/lowenergyscanner/doc/images/lowenergyscanner-chars.png new file mode 100644 index 0000000..ff6d9e3 Binary files /dev/null and b/examples/bluetooth/lowenergyscanner/doc/images/lowenergyscanner-chars.png differ diff --git a/examples/bluetooth/lowenergyscanner/doc/images/lowenergyscanner-devices.png b/examples/bluetooth/lowenergyscanner/doc/images/lowenergyscanner-devices.png new file mode 100644 index 0000000..49a1c46 Binary files /dev/null and b/examples/bluetooth/lowenergyscanner/doc/images/lowenergyscanner-devices.png differ diff --git a/examples/bluetooth/lowenergyscanner/doc/images/lowenergyscanner-services.png b/examples/bluetooth/lowenergyscanner/doc/images/lowenergyscanner-services.png new file mode 100644 index 0000000..5420c25 Binary files /dev/null and b/examples/bluetooth/lowenergyscanner/doc/images/lowenergyscanner-services.png differ diff --git a/examples/bluetooth/lowenergyscanner/doc/src/lowenergyscanner.qdoc b/examples/bluetooth/lowenergyscanner/doc/src/lowenergyscanner.qdoc new file mode 100644 index 0000000..da44fcc --- /dev/null +++ b/examples/bluetooth/lowenergyscanner/doc/src/lowenergyscanner.qdoc @@ -0,0 +1,137 @@ +// Copyright (C) 2013 BlackBerry Limited all rights reserved +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \example lowenergyscanner + \title Bluetooth Low Energy Scanner + \examplecategory {Connectivity} + \meta tags {bluetooth, ble} + \brief An application designed to browse the content of Bluetooth Low + Energy peripheral devices. The example demonstrates the use of all \l{Qt Bluetooth} + Low Energy classes. + + The Bluetooth Low Energy Scanner Example shows how to develop Bluetooth + Low Energy applications using the \l{QtBluetooth}{Qt Bluetooth API}. The application covers + scanning for Low Energy devices, scanning their services and reading + the service characteristics and descriptors. + + \image lowenergyscanner-services.png + + The example introduces the following Qt classes: + + \list + \li \l QLowEnergyController + \li \l QLowEnergyService + \li \l QLowEnergyCharacteristic + \li \l QLowEnergyDescriptor + \endlist + + The example can be used with any arbitrary Bluetooth Low Energy peripheral + device. It creates a snapshot of all services, characteristics and descriptors + and presents them to the user. Therefore the application provides an easy way of + browsing the content offered by a peripheral device. + + \include examples-run.qdocinc + + \section1 Requesting Permission to use Bluetooth + + On certain platforms, it is required to explicitly grant permissions for + using Bluetooth. The example uses \c BluetoothPermission QML object to + check and request the permissions, if required: + + \snippet lowenergyscanner/Devices.qml permission-object + + The permission request dialog is triggered when the user tries to start + the device discovery, and the permission status is \c {Undetermined}: + + \snippet lowenergyscanner/Devices.qml permission-request + + The device discovery starts if the permission is granted by the user. + Otherwise the application is non-functional. + + \section1 Scanning for Devices + + The first step is to find all peripheral devices. The devices can be found using + the \l QBluetoothDeviceDiscoveryAgent class. The discovery process is started using + \l {QBluetoothDeviceDiscoveryAgent::start()}{start()}. Each new device is advertised via + the \l {QBluetoothDeviceDiscoveryAgent::deviceDiscovered()}{deviceDiscovered()} signal: + + \snippet lowenergyscanner/device.cpp les-devicediscovery-1 + \snippet lowenergyscanner/device.cpp les-devicediscovery-2 + + The below \c addDevice() slot is triggered as a reaction to the discovery of a new + device. It filters all found devices which + have the \l QBluetoothDeviceInfo::LowEnergyCoreConfiguration flag and adds them to a + list which is shown to the user. + The \l {QBluetoothDeviceDiscoveryAgent::}{deviceDiscovered()} signal may be + emitted multiple times for the same device as more details are discovered. + Here we match these device discoveries so that the user only sees the + individual devices: + + \snippet lowenergyscanner/device.cpp les-devicediscovery-3 + + The list of devices may look like in the image below. \note It is a prerequisite + that the remote devices actively advertise their presence. + + \image lowenergyscanner-devices.png + + \section1 Connecting to Services + + After the user has selected a device from the list the application connects to the + device and scans all services. The \l QLowEnergyController class is used to connect + to the device. The \l {QLowEnergyController::connectToDevice()} function triggers the + connection process which lasts until the \l {QLowEnergyController::connected()} signal + is received or an error has occurred: + + \snippet lowenergyscanner/device.cpp les-controller-1 + + The slot triggered by the \l {QLowEnergyController::connected()}{connected()} + signal immediately calls \l {QLowEnergyController::discoverServices()} to start the service + discovery on the connected peripheral device. + + \snippet lowenergyscanner/device.cpp les-service-2 + + The resulting list is presented to the user.The image below displays the results when the SensorTag + device is selected. The view lists the names of the services, whether they are + primary or secondary services and the UUID which determines the service type. + + \image lowenergyscanner-services.png + + As soon as the service is chosen the related \l QLowEnergyService instance is created to + permit interaction with it: + + \snippet lowenergyscanner/device.cpp les-service-1 + + The service object provides the required signals and functions to discover the service details, + read and write characteristics and descriptors, as well as receive data change notifications. + Change notifications can be triggered as a result of writing a value or due to an on-device + update potentially triggered by the internal logic. + During the initial detail search the service's \l {QLowEnergyService::state()}{state()} transitions + from \l {QLowEnergyService::RemoteService}{RemoteService} to + \l {QLowEnergyService::RemoteServiceDiscovering}{RemoteServiceDiscovering} and eventually ends with + \l {QLowEnergyService::RemoteServiceDiscovered}{RemoteServiceDiscovered}: + + \snippet lowenergyscanner/device.cpp les-service-3 + + \section1 Reading Service Data + + Upon selection of a service the service details are shown. Each characteristic + is listed together with its name, UUID, value, handle and properties. + + \image lowenergyscanner-chars.png + + It is possible to retrieve the service's characteristics via + \l QLowEnergyService::characteristics() and in turn, each descriptor can be obtained + via \l QLowEnergyCharacteristic::descriptors(). + + \snippet lowenergyscanner/device.cpp les-chars + + Although the example application does not display descriptors it uses descriptors to + get the name of an individual characteristic if its name cannot be discerned based on its + UUID. The second way to obtain the name is the existence of a descriptor of the type + \l {QBluetoothUuid::DescriptorType::CharacteristicUserDescription}. The code below demonstrates how this + may be achieved: + + \snippet lowenergyscanner/characteristicinfo.cpp les-get-descriptors +*/ diff --git a/examples/bluetooth/lowenergyscanner/lowenergyscanner.pro b/examples/bluetooth/lowenergyscanner/lowenergyscanner.pro new file mode 100644 index 0000000..1e798a5 --- /dev/null +++ b/examples/bluetooth/lowenergyscanner/lowenergyscanner.pro @@ -0,0 +1,45 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +TEMPLATE = app +TARGET = lowenergyscanner + +QT += quick bluetooth + +CONFIG += qmltypes +QML_IMPORT_NAME = Scanner +QML_IMPORT_MAJOR_VERSION = 1 + +SOURCES += main.cpp \ + device.cpp \ + deviceinfo.cpp \ + serviceinfo.cpp \ + characteristicinfo.cpp + +HEADERS += \ + device.h \ + deviceinfo.h \ + serviceinfo.h \ + characteristicinfo.h + +qml_resources.files = \ + qmldir \ + Characteristics.qml \ + Devices.qml \ + Dialog.qml \ + Header.qml \ + Label.qml \ + Main.qml \ + Menu.qml \ + Services.qml \ + assets/busy_dark.png + +qml_resources.prefix = /qt/qml/Scanner + +RESOURCES = qml_resources + +ios: QMAKE_INFO_PLIST = ../shared/Info.qmake.ios.plist +macos: QMAKE_INFO_PLIST = ../shared/Info.qmake.macos.plist + +target.path = $$[QT_INSTALL_EXAMPLES]/bluetooth/lowenergyscanner +INSTALLS += target diff --git a/examples/bluetooth/lowenergyscanner/main.cpp b/examples/bluetooth/lowenergyscanner/main.cpp new file mode 100644 index 0000000..16ff118 --- /dev/null +++ b/examples/bluetooth/lowenergyscanner/main.cpp @@ -0,0 +1,24 @@ +// Copyright (C) 2013 BlackBerry Limited. All rights reserved. +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "device.h" + +#include + +#include + +#include + +int main(int argc, char *argv[]) +{ + // QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true")); + QGuiApplication app(argc, argv); + + QQmlApplicationEngine engine; + QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed, &app, + []() { QCoreApplication::exit(1); }, Qt::QueuedConnection); + engine.loadFromModule("Scanner", "Main"); + + return app.exec(); +} diff --git a/examples/bluetooth/lowenergyscanner/qmldir b/examples/bluetooth/lowenergyscanner/qmldir new file mode 100644 index 0000000..c2f4d14 --- /dev/null +++ b/examples/bluetooth/lowenergyscanner/qmldir @@ -0,0 +1,11 @@ +module Scanner +prefer :/qt/qml/Scanner/ +Characteristics 1.0 Characteristics.qml +Devices 1.0 Devices.qml +Dialog 1.0 Dialog.qml +Header 1.0 Header.qml +Label 1.0 Label.qml +Main 1.0 Main.qml +Menu 1.0 Menu.qml +Services 1.0 Services.qml + diff --git a/examples/bluetooth/lowenergyscanner/serviceinfo.cpp b/examples/bluetooth/lowenergyscanner/serviceinfo.cpp new file mode 100644 index 0000000..d9c81a5 --- /dev/null +++ b/examples/bluetooth/lowenergyscanner/serviceinfo.cpp @@ -0,0 +1,66 @@ +// Copyright (C) 2013 BlackBerry Limited. All rights reserved. +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "serviceinfo.h" + +#include +#include + +using namespace Qt::StringLiterals; + +ServiceInfo::ServiceInfo(QLowEnergyService *service): + m_service(service) +{ + m_service->setParent(this); +} + +QLowEnergyService *ServiceInfo::service() const +{ + return m_service; +} + +QString ServiceInfo::getName() const +{ + if (!m_service) + return QString(); + + return m_service->serviceName(); +} + +QString ServiceInfo::getType() const +{ + if (!m_service) + return QString(); + + QString result; + if (m_service->type() & QLowEnergyService::PrimaryService) + result += u"primary"_s; + else + result += u"secondary"_s; + + if (m_service->type() & QLowEnergyService::IncludedService) + result += u" included"_s; + + result.prepend('<'_L1).append('>'_L1); + + return result; +} + +QString ServiceInfo::getUuid() const +{ + if (!m_service) + return QString(); + + const QBluetoothUuid uuid = m_service->serviceUuid(); + bool success = false; + quint16 result16 = uuid.toUInt16(&success); + if (success) + return u"0x"_s + QString::number(result16, 16); + + quint32 result32 = uuid.toUInt32(&success); + if (success) + return u"0x"_s + QString::number(result32, 16); + + return uuid.toString().remove('{'_L1).remove('}'_L1); +} diff --git a/examples/bluetooth/lowenergyscanner/serviceinfo.h b/examples/bluetooth/lowenergyscanner/serviceinfo.h new file mode 100644 index 0000000..f4347d4 --- /dev/null +++ b/examples/bluetooth/lowenergyscanner/serviceinfo.h @@ -0,0 +1,40 @@ +// Copyright (C) 2013 BlackBerry Limited. All rights reserved. +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef SERVICEINFO_H +#define SERVICEINFO_H + +#include + +#include + +QT_BEGIN_NAMESPACE +class QLowEnergyService; +QT_END_NAMESPACE + +class ServiceInfo: public QObject +{ + Q_OBJECT + Q_PROPERTY(QString serviceName READ getName NOTIFY serviceChanged) + Q_PROPERTY(QString serviceUuid READ getUuid NOTIFY serviceChanged) + Q_PROPERTY(QString serviceType READ getType NOTIFY serviceChanged) + + QML_ANONYMOUS + +public: + ServiceInfo() = default; + ServiceInfo(QLowEnergyService *service); + QLowEnergyService *service() const; + QString getUuid() const; + QString getName() const; + QString getType() const; + +Q_SIGNALS: + void serviceChanged(); + +private: + QLowEnergyService *m_service = nullptr; +}; + +#endif // SERVICEINFO_H diff --git a/examples/bluetooth/shared/Info.cmake.ios.plist b/examples/bluetooth/shared/Info.cmake.ios.plist new file mode 100644 index 0000000..be5a2ba --- /dev/null +++ b/examples/bluetooth/shared/Info.cmake.ios.plist @@ -0,0 +1,39 @@ + + + + + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleIdentifier + ${MACOSX_BUNDLE_GUI_IDENTIFIER} + CFBundleExecutable + ${MACOSX_BUNDLE_EXECUTABLE_NAME} + CFBundleVersion + 0.0.1 + CFBundleShortVersionString + 0.0.1 + CFBundleGetInfoString + + NSHumanReadableCopyright + + CFBundleIconFile + ${MACOSX_BUNDLE_ICON_FILE} + CFBundleDevelopmentRegion + English + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + NSBluetoothAlwaysUsageDescription + Qt BT Example wants to access your Bluetooth adapter + + diff --git a/examples/bluetooth/shared/Info.cmake.macos.plist b/examples/bluetooth/shared/Info.cmake.macos.plist new file mode 100644 index 0000000..77c8db1 --- /dev/null +++ b/examples/bluetooth/shared/Info.cmake.macos.plist @@ -0,0 +1,24 @@ + + + + + CFBundleExecutable + ${MACOSX_BUNDLE_EXECUTABLE_NAME} + CFBundleIconFile + ${MACOSX_BUNDLE_ICON_FILE} + CFBundleIdentifier + ${MACOSX_BUNDLE_GUI_IDENTIFIER} + CFBundlePackageType + APPL + CFBundleSignature + ???? + LSMinimumSystemVersion + ${CMAKE_OSX_DEPLOYMENT_TARGET} + NSPrincipalClass + NSApplication + NSBluetoothAlwaysUsageDescription + Qt BT Example wants to access your Bluetooth adapter + NSSupportsAutomaticGraphicsSwitching + + + diff --git a/examples/bluetooth/shared/Info.qmake.ios.plist b/examples/bluetooth/shared/Info.qmake.ios.plist new file mode 100644 index 0000000..1a3885b --- /dev/null +++ b/examples/bluetooth/shared/Info.qmake.ios.plist @@ -0,0 +1,39 @@ + + + + + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleVersion + 0.0.1 + CFBundleShortVersionString + 0.0.1 + CFBundleGetInfoString + + NSHumanReadableCopyright + + CFBundleIconFile + + CFBundleDevelopmentRegion + English + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + NSBluetoothAlwaysUsageDescription + Qt BT Example wants to access your Bluetooth adapter + + diff --git a/examples/bluetooth/shared/Info.qmake.macos.plist b/examples/bluetooth/shared/Info.qmake.macos.plist new file mode 100644 index 0000000..80b3630 --- /dev/null +++ b/examples/bluetooth/shared/Info.qmake.macos.plist @@ -0,0 +1,24 @@ + + + + + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundlePackageType + APPL + CFBundleSignature + ???? + LSMinimumSystemVersion + ${MACOSX_DEPLOYMENT_TARGET} + NSPrincipalClass + NSApplication + NSBluetoothAlwaysUsageDescription + Qt BT Example wants to access your Bluetooth adapter + NSSupportsAutomaticGraphicsSwitching + + + diff --git a/examples/examples.pro b/examples/examples.pro new file mode 100644 index 0000000..f5e9225 --- /dev/null +++ b/examples/examples.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs + +qtHaveModule(bluetooth): SUBDIRS += bluetooth +qtHaveModule(nfc): SUBDIRS += nfc diff --git a/examples/nfc/CMakeLists.txt b/examples/nfc/CMakeLists.txt new file mode 100644 index 0000000..96cd611 --- /dev/null +++ b/examples/nfc/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +if(TARGET Qt6::Widgets) + qt_internal_add_example(annotatedurl) +endif() +if(TARGET Qt6::QuickControls2) + qt_internal_add_example(ndefeditor) +endif() diff --git a/examples/nfc/annotatedurl/CMakeLists.txt b/examples/nfc/annotatedurl/CMakeLists.txt new file mode 100644 index 0000000..a51a205 --- /dev/null +++ b/examples/nfc/annotatedurl/CMakeLists.txt @@ -0,0 +1,55 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(annotatedurl LANGUAGES CXX) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/nfc/annotatedurl") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Nfc Widgets) + +qt_standard_project_setup() + +qt_add_executable(annotatedurl + MANUAL_FINALIZATION + annotatedurl.cpp annotatedurl.h + main.cpp + mainwindow.cpp mainwindow.h +) + +set_target_properties(annotatedurl PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +if(IOS) + set_target_properties(annotatedurl PROPERTIES + MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist" + ) +endif() + +target_link_libraries(annotatedurl PRIVATE + Qt6::Core + Qt6::Gui + Qt6::Nfc + Qt6::Widgets +) + +if(ANDROID) + set_property(TARGET annotatedurl + APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR + ${CMAKE_CURRENT_SOURCE_DIR}/android + ) +endif() + +qt_finalize_target(annotatedurl) + +install(TARGETS annotatedurl + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/nfc/annotatedurl/Info.plist b/examples/nfc/annotatedurl/Info.plist new file mode 100644 index 0000000..7813167 --- /dev/null +++ b/examples/nfc/annotatedurl/Info.plist @@ -0,0 +1,41 @@ + + + + + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + ${ASSETCATALOG_COMPILER_APPICON_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + ${QMAKE_SHORT_VERSION} + CFBundleSignature + ${QMAKE_PKGINFO_TYPEINFO} + CFBundleVersion + ${QMAKE_FULL_VERSION} + LSRequiresIPhoneOS + + MinimumOSVersion + ${IPHONEOS_DEPLOYMENT_TARGET} + NFCReaderUsageDescription + Qt's annotatedurl wants to access your NFC hardware + UILaunchStoryboardName + LaunchScreen + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/nfc/annotatedurl/android/AndroidManifest.xml b/examples/nfc/annotatedurl/android/AndroidManifest.xml new file mode 100644 index 0000000..3378612 --- /dev/null +++ b/examples/nfc/annotatedurl/android/AndroidManifest.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/nfc/annotatedurl/annotatedurl.cpp b/examples/nfc/annotatedurl/annotatedurl.cpp new file mode 100644 index 0000000..33d5109 --- /dev/null +++ b/examples/nfc/annotatedurl/annotatedurl.cpp @@ -0,0 +1,157 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +#include "annotatedurl.h" + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +AnnotatedUrl::AnnotatedUrl(QObject *parent) + : QObject(parent), + manager(new QNearFieldManager(this)) +{ + connect(manager, &QNearFieldManager::targetDetected, + this, &AnnotatedUrl::targetDetected); + connect(manager, &QNearFieldManager::targetLost, + this, &AnnotatedUrl::targetLost); + connect(manager, &QNearFieldManager::adapterStateChanged, + this, &AnnotatedUrl::handleAdapterStateChange); + +//! [populateFilter] + messageFilter.setOrderMatch(false); + messageFilter.appendRecord(1, 100); + messageFilter.appendRecord(1, 1); + messageFilter.appendRecord(QNdefRecord::Mime, "", 0, 1); +//! [populateFilter] +} + +AnnotatedUrl::~AnnotatedUrl() +{ + +} + +void AnnotatedUrl::startDetection() +{ + if (!manager->isEnabled()) { + qWarning() << "NFC not enabled"; + emit nfcStateChanged(false); + return; + } + + if (manager->startTargetDetection(QNearFieldTarget::NdefAccess)) + emit nfcStateChanged(true); +} + +void AnnotatedUrl::targetDetected(QNearFieldTarget *target) +{ + if (!target) + return; + + connect(target, &QNearFieldTarget::ndefMessageRead, + this, &AnnotatedUrl::handlePolledNdefMessage); + connect(target, &QNearFieldTarget::error, this, + [this]() { emit tagError("Tag read error"); }); + target->readNdefMessages(); +} + +void AnnotatedUrl::targetLost(QNearFieldTarget *target) +{ + if (target) + target->deleteLater(); +} + +void AnnotatedUrl::handlePolledNdefMessage(QNdefMessage message) +{ + QNearFieldTarget *target = qobject_cast(sender()); + handleMessage(message, target); +} + +//! [handleAdapterState] +void AnnotatedUrl::handleAdapterStateChange(QNearFieldManager::AdapterState state) +{ + if (state == QNearFieldManager::AdapterState::Online) { + startDetection(); + } else if (state == QNearFieldManager::AdapterState::Offline) { + manager->stopTargetDetection(); + emit nfcStateChanged(false); + } +} +//! [handleAdapterState] + +//! [handleMessage 1] +void AnnotatedUrl::handleMessage(const QNdefMessage &message, QNearFieldTarget *target) +{ +//! [handleMessage 1] + Q_UNUSED(target); + +//! [handleMessage 2] + if (!messageFilter.match(message)) { + emit tagError("Invalid message format"); + return; + } +//! [handleMessage 2] + + enum { + MatchedNone, + MatchedFirst, + MatchedEnglish, + MatchedLanguage, + MatchedLanguageAndCountry + } bestMatch = MatchedNone; + + QLocale defaultLocale; + + QString title; + QUrl url; + QPixmap pixmap; + +//! [handleMessage 3] + for (const QNdefRecord &record : message) { + if (record.isRecordType()) { + QNdefNfcTextRecord textRecord(record); + + title = textRecord.text(); + QLocale locale(textRecord.locale()); +//! [handleMessage 3] + // already found best match + if (bestMatch == MatchedLanguageAndCountry) { + // do nothing + } else if (bestMatch <= MatchedLanguage && locale == defaultLocale) { + bestMatch = MatchedLanguageAndCountry; + } else if (bestMatch <= MatchedEnglish && + locale.language() == defaultLocale.language()) { + bestMatch = MatchedLanguage; + } else if (bestMatch <= MatchedFirst && locale.language() == QLocale::English) { + bestMatch = MatchedEnglish; + } else if (bestMatch == MatchedNone) { + bestMatch = MatchedFirst; + } +//! [handleMessage 4] + } else if (record.isRecordType()) { + QNdefNfcUriRecord uriRecord(record); + + url = uriRecord.uri(); + } else if (record.typeNameFormat() == QNdefRecord::Mime && + record.type().startsWith("image/")) { + pixmap = QPixmap::fromImage(QImage::fromData(record.payload())); + } +//! [handleMessage 4] +//! [handleMessage 5] + } + + emit annotatedUrl(url, title, pixmap); +} +//! [handleMessage 5] diff --git a/examples/nfc/annotatedurl/annotatedurl.h b/examples/nfc/annotatedurl/annotatedurl.h new file mode 100644 index 0000000..95404e5 --- /dev/null +++ b/examples/nfc/annotatedurl/annotatedurl.h @@ -0,0 +1,46 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef ANNOTATEDURL_H +#define ANNOTATEDURL_H + +#include +#include +#include + +#include + +QT_FORWARD_DECLARE_CLASS(QNearFieldTarget) +QT_FORWARD_DECLARE_CLASS(QPixmap) +QT_FORWARD_DECLARE_CLASS(QUrl) + +//! [0] +class AnnotatedUrl : public QObject +{ + Q_OBJECT + +public: + explicit AnnotatedUrl(QObject *parent = 0); + ~AnnotatedUrl(); + + void startDetection(); + +signals: + void annotatedUrl(const QUrl &url, const QString &title, const QPixmap &pixmap); + void nfcStateChanged(bool enabled); + void tagError(const QString &error); + +public slots: + void targetDetected(QNearFieldTarget *target); + void targetLost(QNearFieldTarget *target); + void handleMessage(const QNdefMessage &message, QNearFieldTarget *target); + void handlePolledNdefMessage(QNdefMessage message); + void handleAdapterStateChange(QNearFieldManager::AdapterState state); + +private: + QNearFieldManager *manager; + QNdefFilter messageFilter; +}; +//! [0] + +#endif // ANNOTATEDURL_H diff --git a/examples/nfc/annotatedurl/annotatedurl.pro b/examples/nfc/annotatedurl/annotatedurl.pro new file mode 100644 index 0000000..a9ecf76 --- /dev/null +++ b/examples/nfc/annotatedurl/annotatedurl.pro @@ -0,0 +1,24 @@ +QT += nfc widgets + +CONFIG += strict_flags + +TARGET = annotatedurl + +SOURCES += main.cpp \ + mainwindow.cpp \ + annotatedurl.cpp + +HEADERS += mainwindow.h \ + annotatedurl.h + +ios: QMAKE_INFO_PLIST = Info.plist + +android { + ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android + + DISTFILES += \ + android/AndroidManifest.xml +} + +target.path = $$[QT_INSTALL_EXAMPLES]/nfc/annotatedurl +INSTALLS += target diff --git a/examples/nfc/annotatedurl/doc/images/annotatedurl.png b/examples/nfc/annotatedurl/doc/images/annotatedurl.png new file mode 100644 index 0000000..39f2c66 Binary files /dev/null and b/examples/nfc/annotatedurl/doc/images/annotatedurl.png differ diff --git a/examples/nfc/annotatedurl/doc/images/annotatedurl2.png b/examples/nfc/annotatedurl/doc/images/annotatedurl2.png new file mode 100644 index 0000000..bb6208e Binary files /dev/null and b/examples/nfc/annotatedurl/doc/images/annotatedurl2.png differ diff --git a/examples/nfc/annotatedurl/doc/images/annotatedurl3.png b/examples/nfc/annotatedurl/doc/images/annotatedurl3.png new file mode 100644 index 0000000..363b768 Binary files /dev/null and b/examples/nfc/annotatedurl/doc/images/annotatedurl3.png differ diff --git a/examples/nfc/annotatedurl/doc/src/annotatedurl.qdoc b/examples/nfc/annotatedurl/doc/src/annotatedurl.qdoc new file mode 100644 index 0000000..b76c349 --- /dev/null +++ b/examples/nfc/annotatedurl/doc/src/annotatedurl.qdoc @@ -0,0 +1,132 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! +\example annotatedurl +\title Annotated URL +\examplecategory {Connectivity} +\meta tags {nfc, ndef, widgets} +\brief Reads formatted NFC Data Exchange Format (NDEF) messages. + +The Annotated URL example uses \l{Qt NFC} to display the contents of specifically +formatted NFC Data Exchange Format (NDEF) messages read from an NFC +Tag. The NDEF message should contain a URI record, an optional \c +image/* MIME record, and one or more localized Text records. + +This is the initial state of the example: +\image annotatedurl.png + +If a tag is touched, its NDEF content will be shown. Here is the UI +for a tag that contains a text record and URI record: + +\image annotatedurl2.png + +When the screen is tapped, the URL will be opened in the browser. + +\section1 AnnotatedUrl Class Definition + +The \c AnnotatedUrl class wraps \l QNearFieldManager, the class providing +the NFC Tag detection functionality. NDEF messages are read by +\l QNearFieldManager and forwarded to a handler contained in the +\c AnnotatedUrl class. After parsing the NDEF message the class emits +the \c annotatedUrl() signal. The UI reacts to the signal displaying +the contents of the NDEF message. + +\snippet annotatedurl/annotatedurl.h 0 + +\note The \c startDetection() method is used to defer the actual tag detection +until all the connections between the UI and NFC-related logic are established. +This is important when the application is automatically started once an NFC tag +is touched. Such usecase is currently supported on Android. + +\snippet annotatedurl/main.cpp 0 + +\section1 Message Filtering + +As it is mentioned above, the application supports the NDEF messages of a +specific format. A correct message should contain the following fields: + +\list + \li \e {At least one} NDEF Text record, which will be used as a header. + \li \e {Exactly one} NDEF URI record. + \li \e {An optional} MIME record with an icon. +\endlist + +The order of the records is not strictly specified. + +An instance of \l QNdefFilter is used to validate the NDEF message. The filter +is populated as follows: + +\snippet annotatedurl/annotatedurl.cpp populateFilter + +If the incoming message does not match the filter, an error message is shown: + +\image annotatedurl3.png + +\note The \l {ndefeditor}{NDEF Editor} example application can be used to create +the tags with correct or incorrect message structure. + +\section1 AnnotatedUrl Handler Implementation + +NFC messages read by the \l QNearFieldManager are forwarded to +\c {AnnotatedUrl::handleMessage}. + +\snippet annotatedurl/annotatedurl.cpp handleMessage 1 + +At first the messages are validated using the \l QNdefFilter::match() method: + +\snippet annotatedurl/annotatedurl.cpp handleMessage 2 + +If the messages have the correct format, the parsing continues. + +Because NFC messages are composed of several NDEF records, looping +through all of the records allows the extraction of the 3 parameters +to be displayed in the UI: the Uri, the Title and the Pixmap: + +\snippet annotatedurl/annotatedurl.cpp handleMessage 3 +\snippet annotatedurl/annotatedurl.cpp handleMessage 4 + +Finally after having extracted the parameters of the NFC message the +corresponding signal is emitted so that the UI can handle it. + +\snippet annotatedurl/annotatedurl.cpp handleMessage 5 + +\section1 Adapter State Handling + +On Android the adapter state changes can be detected by connecting to the +\l QNearFieldManager::adapterStateChanged() signal. This allows stopping the +detection when the NFC adapter is disabled, and restarting it when the adapter +is enabled again. This approach is implemented in the +\c {AnnotatedUrl::handleAdapterStateChange} slot. + +\snippet annotatedurl/annotatedurl.cpp handleAdapterState + +\section1 Automatic Application Startup + +Android supports automatic application startup when the NDEF tag is touched. +See \l {Qt NFC on Android} for the required changes to the Android manifest +file. + +Introduction of a custom AndroidManifest.xml requires special steps on the +build system side. + +\section2 Building with qmake + +When using qmake, the following needs to be added to the \c {.pro} file: + +\quotefromfile annotatedurl/annotatedurl.pro +\skipto android { +\printuntil } + +\section2 Building with CMake + +When using CMake, the following needs to be added to the \c CMakeLists.txt: + +\quotefromfile annotatedurl/CMakeLists.txt +\skipto if(ANDROID) +\printuntil endif() + +\include examples-run.qdocinc + +\sa {Qt NFC} +*/ diff --git a/examples/nfc/annotatedurl/main.cpp b/examples/nfc/annotatedurl/main.cpp new file mode 100644 index 0000000..352a959 --- /dev/null +++ b/examples/nfc/annotatedurl/main.cpp @@ -0,0 +1,32 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "annotatedurl.h" +#include "mainwindow.h" + +#include +#include +#include + +#include + +//! [0] +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow mainWindow; + AnnotatedUrl annotatedUrl; + + QObject::connect(&annotatedUrl, &AnnotatedUrl::annotatedUrl, + &mainWindow, &MainWindow::displayAnnotatedUrl); + QObject::connect(&annotatedUrl, &AnnotatedUrl::nfcStateChanged, + &mainWindow, &MainWindow::nfcStateChanged); + QObject::connect(&annotatedUrl, &AnnotatedUrl::tagError, + &mainWindow, &MainWindow::showTagError); + + annotatedUrl.startDetection(); + mainWindow.show(); + + return a.exec(); +} +//! [0] diff --git a/examples/nfc/annotatedurl/mainwindow.cpp b/examples/nfc/annotatedurl/mainwindow.cpp new file mode 100644 index 0000000..7b41836 --- /dev/null +++ b/examples/nfc/annotatedurl/mainwindow.cpp @@ -0,0 +1,117 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "mainwindow.h" + +#include + +#include +#include + +#include +#include + +MainWindow::MainWindow(QWidget *parent) + : QWidget(parent), + m_titleLabel(new QLabel(this)), + m_infoLabel(new QLabel(tr("Enable NFC"), this)), + m_uriLabel(new QLabel(this)), + m_landscapeIconLabel(new QLabel(this)), + m_portraitIconLabel(new QLabel(this)) +{ + m_titleLabel->setAlignment(Qt::AlignCenter); + m_infoLabel->setAlignment(Qt::AlignCenter); + m_uriLabel->setAlignment(Qt::AlignCenter); + m_landscapeIconLabel->setAlignment(Qt::AlignCenter); + m_portraitIconLabel->setAlignment(Qt::AlignCenter); + + QFont f = m_titleLabel->font(); + f.setBold(true); + m_titleLabel->setFont(f); + + QVBoxLayout *verticalLayout = new QVBoxLayout; + verticalLayout->addWidget(m_titleLabel); + verticalLayout->addWidget(m_infoLabel); + verticalLayout->addWidget(m_portraitIconLabel); + verticalLayout->addWidget(m_uriLabel); + + QHBoxLayout *horizontalLayout = new QHBoxLayout; + horizontalLayout->addWidget(m_landscapeIconLabel); + horizontalLayout->addLayout(verticalLayout); + horizontalLayout->setSpacing(0); + + setLayout(horizontalLayout); + + handleScreenChange(); +} + +MainWindow::~MainWindow() +{ +} + +void MainWindow::displayAnnotatedUrl(const QUrl &url, const QString &title, const QPixmap &pixmap) +{ + m_infoLabel->setHidden(true); + + m_uriLabel->setText(url.toString()); + m_titleLabel->setText(title); + + m_pixmap = pixmap; + updateWidgetLayout(m_screen->orientation()); +} + +void MainWindow::nfcStateChanged(bool enabled) +{ + const QString text = enabled ? "Touch a tag" : "Enable NFC"; + m_infoLabel->setText(text); +} + +void MainWindow::showTagError(const QString &message) +{ + m_uriLabel->clear(); + m_titleLabel->clear(); + m_pixmap = QPixmap(); + m_landscapeIconLabel->setVisible(false); + m_portraitIconLabel->setVisible(false); + + m_infoLabel->setHidden(false); + m_infoLabel->setText(message); +} + +void MainWindow::mouseReleaseEvent(QMouseEvent * /*event*/) +{ + QDesktopServices::openUrl(QUrl(m_uriLabel->text())); +} + +void MainWindow::moveEvent(QMoveEvent * /*event*/) +{ + if (screen() != m_screen) + handleScreenChange(); +} + +void MainWindow::updateWidgetLayout(Qt::ScreenOrientation orientation) +{ + m_landscapeIconLabel->setVisible(false); + m_portraitIconLabel->setVisible(false); + if (!m_pixmap.isNull()) { + const bool landscapeMode = (orientation == Qt::LandscapeOrientation) + || (orientation == Qt::InvertedLandscapeOrientation); + QLabel *imageLabel = landscapeMode ? m_landscapeIconLabel : m_portraitIconLabel; + imageLabel->setVisible(true); + if (m_pixmap.width() > imageLabel->width() || m_pixmap.height() > imageLabel->height()) + imageLabel->setPixmap(m_pixmap.scaled(imageLabel->size(), Qt::KeepAspectRatio)); + else + imageLabel->setPixmap(m_pixmap); + } +} + +void MainWindow::handleScreenChange() +{ + if (m_screen) + disconnect(m_screen, &QScreen::orientationChanged, this, &MainWindow::updateWidgetLayout); + + m_screen = screen(); + connect(m_screen, &QScreen::orientationChanged, this, &MainWindow::updateWidgetLayout); + + updateWidgetLayout(m_screen->orientation()); +} diff --git a/examples/nfc/annotatedurl/mainwindow.h b/examples/nfc/annotatedurl/mainwindow.h new file mode 100644 index 0000000..059c703 --- /dev/null +++ b/examples/nfc/annotatedurl/mainwindow.h @@ -0,0 +1,49 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include + +#include + +QT_FORWARD_DECLARE_CLASS(QMouseEvent) +QT_FORWARD_DECLARE_CLASS(QUrl) +QT_FORWARD_DECLARE_CLASS(QString) +QT_FORWARD_DECLARE_CLASS(QLabel) +QT_FORWARD_DECLARE_CLASS(QScreen) + +class MainWindow : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); + +public slots: + void displayAnnotatedUrl(const QUrl &url, const QString &title, const QPixmap &pixmap); + void nfcStateChanged(bool enabled); + void showTagError(const QString &message); + +protected: + void mouseReleaseEvent(QMouseEvent *event) override; + void moveEvent(QMoveEvent *event) override; + +private slots: + void updateWidgetLayout(Qt::ScreenOrientation orientation); + +private: + void handleScreenChange(); + + QLabel *m_titleLabel; + QLabel *m_infoLabel; + QLabel *m_uriLabel; + QLabel *m_landscapeIconLabel; + QLabel *m_portraitIconLabel; + QScreen *m_screen = nullptr; + QPixmap m_pixmap; +}; + +#endif // MAINWINDOW_H diff --git a/examples/nfc/ndefeditor/CMakeLists.txt b/examples/nfc/ndefeditor/CMakeLists.txt new file mode 100644 index 0000000..2e295c2 --- /dev/null +++ b/examples/nfc/ndefeditor/CMakeLists.txt @@ -0,0 +1,69 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(ndefeditor LANGUAGES CXX) + +set(CMAKE_AUTOMOC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/nfc/ndefeditor") + +find_package(Qt6 REQUIRED COMPONENTS Core Nfc Quick QuickControls2) + +qt_standard_project_setup(REQUIRES 6.5) + +qt_add_executable(ndefeditor + main.cpp +) + +set(icon_files) +foreach(icon IN ITEMS add arrow_back file_download file_upload link text_snippet) + foreach(scale IN ITEMS "" "@2" "@3" "@4") + list(APPEND icon_files "icons/ndefeditor/20x20${scale}/${icon}.png") + endforeach() +endforeach() + +qt_add_resources(ndefeditor "theme" FILES + ${icon_files} + icons/ndefeditor/index.theme +) + +qt_add_qml_module(ndefeditor + URI NdefEditor + VERSION 1.0 + QML_FILES + Main.qml + MainWindow.qml + NdefRecordDelegate.qml + SOURCES + nfcmanager.h nfcmanager.cpp + nfctarget.h nfctarget.cpp + ndefmessagemodel.h ndefmessagemodel.cpp +) + +set_target_properties(ndefeditor PROPERTIES + MACOSX_BUNDLE TRUE + WIN32_EXECUTABLE TRUE +) + +if(IOS) + set_target_properties(ndefeditor PROPERTIES + MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.cmake.plist" + ) +endif() + +target_link_libraries(ndefeditor PRIVATE + Qt6::Core + Qt6::Nfc + Qt6::Quick +) + +install(TARGETS ndefeditor + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/nfc/ndefeditor/Info.cmake.plist b/examples/nfc/ndefeditor/Info.cmake.plist new file mode 100644 index 0000000..ee87b3b --- /dev/null +++ b/examples/nfc/ndefeditor/Info.cmake.plist @@ -0,0 +1,54 @@ + + + + + CFBundleInfoDictionaryVersion + 6.0 + + CFBundlePackageType + APPL + + CFBundleName + ${MACOSX_BUNDLE_BUNDLE_NAME} + + CFBundleDisplayName + NDEF Editor + + CFBundleIdentifier + ${MACOSX_BUNDLE_GUI_IDENTIFIER} + + CFBundleExecutable + ${MACOSX_BUNDLE_EXECUTABLE_NAME} + + CFBundleVersion + ${MACOSX_BUNDLE_BUNDLE_VERSION} + + CFBundleShortVersionString + ${MACOSX_BUNDLE_SHORT_VERSION_STRING} + + CFBundleIconFile + ${MACOSX_BUNDLE_ICON_FILE} + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleAllowMixedLocalizations + + + LSRequiresIPhoneOS + + + NFCReaderUsageDescription + Qt's ndefeditor wants to access your NFC hardware + + UILaunchStoryboardName + LaunchScreen + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/nfc/ndefeditor/Info.qmake.plist b/examples/nfc/ndefeditor/Info.qmake.plist new file mode 100644 index 0000000..079533e --- /dev/null +++ b/examples/nfc/ndefeditor/Info.qmake.plist @@ -0,0 +1,49 @@ + + + + + CFBundleInfoDictionaryVersion + 6.0 + + CFBundlePackageType + APPL + + CFBundleName + ${PRODUCT_NAME} + + CFBundleDisplayName + NDEF Editor + + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + + CFBundleExecutable + ${EXECUTABLE_NAME} + + CFBundleVersion + ${QMAKE_FULL_VERSION} + + CFBundleShortVersionString + ${QMAKE_SHORT_VERSION} + + CFBundleIconFile + ${ASSETCATALOG_COMPILER_APPICON_NAME} + + LSRequiresIPhoneOS + + + NFCReaderUsageDescription + Qt's ndefeditor wants to access your NFC hardware + + UILaunchStoryboardName + LaunchScreen + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/nfc/ndefeditor/Main.qml b/examples/nfc/ndefeditor/Main.qml new file mode 100644 index 0000000..c5435e2 --- /dev/null +++ b/examples/nfc/ndefeditor/Main.qml @@ -0,0 +1,9 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +MainWindow { + width: 480 + height: 640 + visible: true + title: qsTr("NDEF Editor") +} diff --git a/examples/nfc/ndefeditor/MainWindow.qml b/examples/nfc/ndefeditor/MainWindow.qml new file mode 100644 index 0000000..d32540f --- /dev/null +++ b/examples/nfc/ndefeditor/MainWindow.qml @@ -0,0 +1,384 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +pragma ComponentBehavior: Bound +import QtQuick +import QtQuick.Controls +import QtQuick.Dialogs +import QtQuick.Layouts + +import NdefEditor + +ApplicationWindow { + id: window + + enum TargetDetectedAction { + NoAction, + ReadMessage, + WriteMessage + } + + StackView { + id: stack + initialItem: mainView + anchors.fill: parent + } + + property int targetDetectedAction: MainWindow.NoAction + + Component { + id: mainView + + ColumnLayout { + ToolBar { + Layout.fillWidth: true + + RowLayout { + anchors.fill: parent + Label { + text: qsTr("NDEF Editor") + elide: Label.ElideRight + horizontalAlignment: Qt.AlignHCenter + verticalAlignment: Qt.AlignVCenter + Layout.fillWidth: true + } + } + } + + Pane { + id: writeTab + Layout.fillWidth: true + Layout.fillHeight: true + + Flickable { + anchors.fill: parent + contentHeight: contentItem.childrenRect.height + + ColumnLayout { + width: parent.width + + ItemDelegate { + icon.name: "file_download" + text: qsTr("Read Tag") + Layout.fillWidth: true + + onClicked: window.readTag() + } + + ItemDelegate { + icon.name: "file_upload" + text: qsTr("Write to Tag") + Layout.fillWidth: true + + onClicked: window.writeTag() + } + + ItemDelegate { + icon.name: "add" + text: qsTr("Add a Record") + Layout.fillWidth: true + + onClicked: addRecordMenu.open() + + Menu { + id: addRecordMenu + title: qsTr("Add record") + + MenuItem { + icon.name: "text_snippet" + text: qsTr("Text record") + onTriggered: stack.push(textRecordDialog) + } + MenuItem { + icon.name: "link" + text: qsTr("URI record") + onTriggered: stack.push(uriRecordDialog) + } + } + } + + Item { + implicitHeight: 20 + } + + Label { + text: qsTr( + "Use buttons above to read an NFC tag or add records manually.\n\n" + + "Once added, swipe to the right to access options for each record.") + wrapMode: Text.Wrap + visible: messages.count === 0 + Layout.fillWidth: true + } + + Repeater { + id: messages + model: messageModel + + delegate: NdefRecordDelegate { + Layout.fillWidth: true + + onDeleteClicked: messageModel.removeRow(index) + + onClicked: { + if (recordType === NdefMessageModel.TextRecord) { + stack.push(textRecordDialog, { + text: recordText, + modelIndex: index + }) + } else if (recordType === NdefMessageModel.UriRecord) { + stack.push(uriRecordDialog, { + uri: recordText, + modelIndex: index + }) + } + } + } + } + } + } + } + } + } + + NdefMessageModel { + id: messageModel + } + + NfcManager { + id: nfcManager + onTargetDetected: (target) => { window.handleTargetDetected(target) } + } + + Connections { + id: targetConnections + target: null + + function onNdefMessageRead(message) { + messageModel.message = message + } + + function onRequestCompleted() { + communicationOverlay.close() + window.targetDetectedAction = MainWindow.NoAction + releaseTarget() + } + + function onError(code) { + communicationOverlay.close() + errorNotification.errorMessage = window.describeError(code) + errorNotification.open() + window.targetDetectedAction = MainWindow.NoAction + releaseTarget() + } + + function releaseTarget() { + target?.destroy() + } + } + + function handleTargetDetected(target: NfcTarget) { + targetConnections.releaseTarget() + + let ok = true + + if (targetDetectedAction === MainWindow.ReadMessage) { + targetConnections.target = target + communicationOverlay.message = qsTr("Target detected. Reading messages...") + errorNotification.errorMessage = qsTr("NDEF read error") + ok = target.readNdefMessages() + } else if (targetDetectedAction === MainWindow.WriteMessage) { + targetConnections.target = target + communicationOverlay.message = qsTr("Target detected. Writing the message...") + errorNotification.errorMessage = qsTr("NDEF write error") + ok = target.writeNdefMessage(messageModel.message) + } else { + target.destroy() + return + } + + if (!ok) { + communicationOverlay.close() + errorNotification.open() + targetConnections.releaseTarget() + } + } + + function readTag() { + window.targetDetectedAction = MainWindow.ReadMessage + nfcManager.startTargetDetection() + communicationOverlay.title = qsTr("Read Tag") + communicationOverlay.message = qsTr("Approach an NFC tag.") + communicationOverlay.open() + } + + function writeTag() { + window.targetDetectedAction = MainWindow.WriteMessage + nfcManager.startTargetDetection() + communicationOverlay.title = qsTr("Write to Tag") + communicationOverlay.message = qsTr("Approach an NFC tag.") + communicationOverlay.open() + } + + function describeError(error) { + switch (error) { + case 2: return qsTr("Usupported feature") + case 3: return qsTr("Target out of range") + case 4: return qsTr("No response") + case 5: return qsTr("Checksum mismatch") + case 6: return qsTr("Invalid parameters") + case 7: return qsTr("Connection error") + case 8: return qsTr("NDEF read error") + case 9: return qsTr("NDEF write error") + case 10: return qsTr("Command error") + case 11: return qsTr("Timeout") + } + + return qsTr("Unknown error") + } + + Dialog { + id: communicationOverlay + + property alias message: messageLabel.text + + anchors.centerIn: Overlay.overlay + + modal: true + standardButtons: Dialog.Cancel + + ColumnLayout { + Label { + id: messageLabel + } + + BusyIndicator { + Layout.fillWidth: true + } + } + + onClosed: nfcManager.stopTargetDetection() + } + + MessageDialog { + property alias errorMessage: errorNotification.text + + id: errorNotification + + buttons: MessageDialog.Close + title: qsTr("Error") + + onButtonClicked: errorNotification.close() + } + + Component { + id: uriRecordDialog + + ColumnLayout { + property alias uri: uriEditor.text + property int modelIndex: -1 + + ToolBar { + Layout.fillWidth: true + + RowLayout { + anchors.fill: parent + ToolButton { + icon.name: "arrow_back" + onClicked: stack.pop() + } + Label { + text: qsTr("URI Record") + elide: Label.ElideRight + horizontalAlignment: Qt.AlignHCenter + verticalAlignment: Qt.AlignVCenter + Layout.fillWidth: true + } + ToolButton { + text: qsTr("Save") + onClicked: { + if (modelIndex < 0) { + messageModel.addUriRecord(uri) + } else { + messageModel.setTextData(modelIndex, uri) + } + stack.pop() + } + } + } + } + + Pane { + Layout.fillWidth: true + Layout.fillHeight: true + + ColumnLayout { + anchors.fill: parent + + TextField { + id: uriEditor + Layout.fillWidth: true + placeholderText: qsTr("https://qt.io") + inputMethodHints: Qt.ImhUrlCharactersOnly + } + Item { + Layout.fillHeight: true + } + } + } + } + } + + Component { + id: textRecordDialog + + ColumnLayout { + property alias text: textEditor.text + property int modelIndex: -1 + + ToolBar { + Layout.fillWidth: true + + RowLayout { + anchors.fill: parent + ToolButton { + icon.name: "arrow_back" + onClicked: stack.pop() + } + Label { + text: qsTr("Text Record") + elide: Label.ElideRight + horizontalAlignment: Qt.AlignHCenter + verticalAlignment: Qt.AlignVCenter + Layout.fillWidth: true + } + ToolButton { + text: qsTr("Save") + onClicked: { + if (modelIndex < 0) { + messageModel.addTextRecord(textEditor.text) + } else { + messageModel.setTextData(modelIndex, textEditor.text) + } + stack.pop() + } + } + } + } + + Pane { + Layout.fillWidth: true + Layout.fillHeight: true + + ScrollView { + anchors.fill: parent + + TextArea { + id: textEditor + placeholderText: qsTr("Enter some text...") + Layout.fillWidth: true + } + } + } + } + } +} diff --git a/examples/nfc/ndefeditor/NdefRecordDelegate.qml b/examples/nfc/ndefeditor/NdefRecordDelegate.qml new file mode 100644 index 0000000..f01aff0 --- /dev/null +++ b/examples/nfc/ndefeditor/NdefRecordDelegate.qml @@ -0,0 +1,50 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +pragma ComponentBehavior: Bound +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +import NdefEditor + +SwipeDelegate { + required property int index + required property int recordType + required property string recordText + + id: delegate + + contentItem: ColumnLayout { + Label { + text: qsTr("Record %L1 - %2").arg(delegate.index + 1).arg( + delegate.describeRecordType(delegate.recordType)) + font.bold: true + } + + Label { + text: delegate.recordText + elide: Text.ElideRight + maximumLineCount: 1 + Layout.fillWidth: true + } + } + + swipe.left: Button { + text: qsTr("Delete") + padding: 12 + height: delegate.height + anchors.left: delegate.left + SwipeDelegate.onClicked: delegate.deleteClicked() + } + + function describeRecordType(type) { + switch (type) { + case NdefMessageModel.TextRecord: return qsTr("Text") + case NdefMessageModel.UriRecord: return qsTr("URI") + default: return qsTr("Other") + } + } + + signal deleteClicked() +} diff --git a/examples/nfc/ndefeditor/doc/images/ndefeditor.png b/examples/nfc/ndefeditor/doc/images/ndefeditor.png new file mode 100644 index 0000000..2be32f6 Binary files /dev/null and b/examples/nfc/ndefeditor/doc/images/ndefeditor.png differ diff --git a/examples/nfc/ndefeditor/doc/src/ndefeditor.qdoc b/examples/nfc/ndefeditor/doc/src/ndefeditor.qdoc new file mode 100644 index 0000000..0c7a084 --- /dev/null +++ b/examples/nfc/ndefeditor/doc/src/ndefeditor.qdoc @@ -0,0 +1,25 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! +\example ndefeditor +\title NDEF Editor +\examplecategory {Connectivity} +\meta tags {nfc, ndef} +\brief Reads and writes NFC Data Exchange Format (NDEF) messages to NFC Forum Tags. + +The NDEF Editor example uses \l{Qt NFC} to read and write NFC Data Exchange Format +(NDEF) messages to NFC Forum Tags. NDEF messages can be composed by +adding text and URI records. Records can be deleted by swiping them to the left. + +Press \b {Write to Tag} to write the records to an NFC tag. + +Press \b {Read Tag} to read the contents of an NFC tag. A successful read of an +NFC tag replaces the manually added records with the NDEF message from the tag. +If the read operation was cancelled or failed, the NDEF message remains +unchanged. + +\image ndefeditor.png + +\sa {Qt NFC} +*/ diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20/add.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20/add.png new file mode 100644 index 0000000..49659bf Binary files /dev/null and b/examples/nfc/ndefeditor/icons/ndefeditor/20x20/add.png differ diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20/arrow_back.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20/arrow_back.png new file mode 100644 index 0000000..8d39f67 Binary files /dev/null and b/examples/nfc/ndefeditor/icons/ndefeditor/20x20/arrow_back.png differ diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20/file_download.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20/file_download.png new file mode 100644 index 0000000..405a67b Binary files /dev/null and b/examples/nfc/ndefeditor/icons/ndefeditor/20x20/file_download.png differ diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20/file_upload.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20/file_upload.png new file mode 100644 index 0000000..7a13c50 Binary files /dev/null and b/examples/nfc/ndefeditor/icons/ndefeditor/20x20/file_upload.png differ diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20/link.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20/link.png new file mode 100644 index 0000000..6d66338 Binary files /dev/null and b/examples/nfc/ndefeditor/icons/ndefeditor/20x20/link.png differ diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20/text_snippet.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20/text_snippet.png new file mode 100644 index 0000000..bada433 Binary files /dev/null and b/examples/nfc/ndefeditor/icons/ndefeditor/20x20/text_snippet.png differ diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/add.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/add.png new file mode 100644 index 0000000..8114d61 Binary files /dev/null and b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/add.png differ diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/arrow_back.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/arrow_back.png new file mode 100644 index 0000000..843444e Binary files /dev/null and b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/arrow_back.png differ diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/file_download.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/file_download.png new file mode 100644 index 0000000..d848b21 Binary files /dev/null and b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/file_download.png differ diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/file_upload.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/file_upload.png new file mode 100644 index 0000000..2236430 Binary files /dev/null and b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/file_upload.png differ diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/link.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/link.png new file mode 100644 index 0000000..0567312 Binary files /dev/null and b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/link.png differ diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/text_snippet.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/text_snippet.png new file mode 100644 index 0000000..96ab459 Binary files /dev/null and b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/text_snippet.png differ diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/add.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/add.png new file mode 100644 index 0000000..c55d414 Binary files /dev/null and b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/add.png differ diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/arrow_back.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/arrow_back.png new file mode 100644 index 0000000..bb620d6 Binary files /dev/null and b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/arrow_back.png differ diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/file_download.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/file_download.png new file mode 100644 index 0000000..db8e7b1 Binary files /dev/null and b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/file_download.png differ diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/file_upload.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/file_upload.png new file mode 100644 index 0000000..1b24028 Binary files /dev/null and b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/file_upload.png differ diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/link.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/link.png new file mode 100644 index 0000000..e0569cb Binary files /dev/null and b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/link.png differ diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/text_snippet.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/text_snippet.png new file mode 100644 index 0000000..9dc6683 Binary files /dev/null and b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/text_snippet.png differ diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/add.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/add.png new file mode 100644 index 0000000..4813a26 Binary files /dev/null and b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/add.png differ diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/arrow_back.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/arrow_back.png new file mode 100644 index 0000000..54354dd Binary files /dev/null and b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/arrow_back.png differ diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/file_download.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/file_download.png new file mode 100644 index 0000000..20148b9 Binary files /dev/null and b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/file_download.png differ diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/file_upload.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/file_upload.png new file mode 100644 index 0000000..22a98cc Binary files /dev/null and b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/file_upload.png differ diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/link.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/link.png new file mode 100644 index 0000000..f8bedee Binary files /dev/null and b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/link.png differ diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/text_snippet.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/text_snippet.png new file mode 100644 index 0000000..74a5f7f Binary files /dev/null and b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/text_snippet.png differ diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/index.theme b/examples/nfc/ndefeditor/icons/ndefeditor/index.theme new file mode 100644 index 0000000..756b123 --- /dev/null +++ b/examples/nfc/ndefeditor/icons/ndefeditor/index.theme @@ -0,0 +1,22 @@ +[Icon Theme] +Name=ndefeditor +Directories=20x20,20x20@2,20x20@3,20x20@4 + +[20x20] +Size=20 +Type=Fixed + +[20x20@2] +Size=20 +Scale=2 +Type=Fixed + +[20x20@3] +Size=20 +Scale=3 +Type=Fixed + +[20x20@4] +Size=20 +Scale=4 +Type=Fixed diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/qt_attribution.json b/examples/nfc/ndefeditor/icons/ndefeditor/qt_attribution.json new file mode 100644 index 0000000..b9ee69b --- /dev/null +++ b/examples/nfc/ndefeditor/icons/ndefeditor/qt_attribution.json @@ -0,0 +1,14 @@ +{ + "Id": "ndefeditor", + "Name": "Selected Material Icons", + "QDocModule": "qtnfc", + "QtUsage": "Used in NDEF Editor example for Qt NFC.", + "QtParts": [ + "examples" + ], + "Files": "20x20 20x20@2 20x20@3 20x20@4", + "Homepage": "https://fonts.google.com/icons", + "License": "Apache License Version 2.0", + "LicenseId": "Apache-2.0", + "Copyright": "Copyright 2018 Google, Inc. All Rights Reserved." +} diff --git a/examples/nfc/ndefeditor/main.cpp b/examples/nfc/ndefeditor/main.cpp new file mode 100644 index 0000000..a9e5218 --- /dev/null +++ b/examples/nfc/ndefeditor/main.cpp @@ -0,0 +1,22 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include +#include +#include + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + + QIcon::setThemeName("ndefeditor"); + + QQmlApplicationEngine engine; + + QObject::connect( + &engine, &QQmlApplicationEngine::objectCreationFailed, &app, + []() { QCoreApplication::exit(1); }, Qt::QueuedConnection); + engine.loadFromModule("NdefEditor", "Main"); + + return app.exec(); +} diff --git a/examples/nfc/ndefeditor/ndefeditor.pro b/examples/nfc/ndefeditor/ndefeditor.pro new file mode 100644 index 0000000..f6c270d --- /dev/null +++ b/examples/nfc/ndefeditor/ndefeditor.pro @@ -0,0 +1,66 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +QT += nfc quick quickcontrols2 + +CONFIG += qmltypes +QML_IMPORT_NAME = NdefEditor +QML_IMPORT_MAJOR_VERSION = 1 + +TARGET = ndefeditor +TEMPLATE = app + +SOURCES += \ + main.cpp \ + nfcmanager.cpp \ + nfctarget.cpp \ + ndefmessagemodel.cpp + +HEADERS += \ + nfcmanager.h \ + nfctarget.h \ + ndefmessagemodel.h + +qml_resources.files = \ + qmldir \ + Main.qml \ + MainWindow.qml \ + NdefRecordDelegate.qml + +qml_resources.prefix = /qt/qml/NdefEditor + +theme_resources.files = \ + icons/ndefeditor/20x20@2/add.png \ + icons/ndefeditor/20x20@2/arrow_back.png \ + icons/ndefeditor/20x20@2/file_download.png \ + icons/ndefeditor/20x20@2/file_upload.png \ + icons/ndefeditor/20x20@2/link.png \ + icons/ndefeditor/20x20@2/text_snippet.png \ + icons/ndefeditor/20x20@3/add.png \ + icons/ndefeditor/20x20@3/arrow_back.png \ + icons/ndefeditor/20x20@3/file_download.png \ + icons/ndefeditor/20x20@3/file_upload.png \ + icons/ndefeditor/20x20@3/link.png \ + icons/ndefeditor/20x20@3/text_snippet.png \ + icons/ndefeditor/20x20@4/add.png \ + icons/ndefeditor/20x20@4/arrow_back.png \ + icons/ndefeditor/20x20@4/file_download.png \ + icons/ndefeditor/20x20@4/file_upload.png \ + icons/ndefeditor/20x20@4/link.png \ + icons/ndefeditor/20x20@4/text_snippet.png \ + icons/ndefeditor/20x20/add.png \ + icons/ndefeditor/20x20/arrow_back.png \ + icons/ndefeditor/20x20/file_download.png \ + icons/ndefeditor/20x20/file_upload.png \ + icons/ndefeditor/20x20/link.png \ + icons/ndefeditor/20x20/text_snippet.png \ + icons/ndefeditor/index.theme + +theme_resources.prefix = / + +RESOURCES += qml_resources theme_resources + +ios: QMAKE_INFO_PLIST = Info.qmake.plist + +target.path = $$[QT_INSTALL_EXAMPLES]/nfc/ndefeditor +INSTALLS += target diff --git a/examples/nfc/ndefeditor/ndefmessagemodel.cpp b/examples/nfc/ndefeditor/ndefmessagemodel.cpp new file mode 100644 index 0000000..177d21d --- /dev/null +++ b/examples/nfc/ndefeditor/ndefmessagemodel.cpp @@ -0,0 +1,156 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "ndefmessagemodel.h" + +#include +#include + +NdefMessageModel::NdefMessageModel(QObject *parent) : QAbstractListModel(parent) { } + +int NdefMessageModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) + return 0; + + return m_message.size(); +} + +static NdefMessageModel::RecordType getRecordType(const QNdefRecord &record) +{ + if (record.isRecordType()) { + return NdefMessageModel::TextRecord; + } else if (record.isRecordType()) { + return NdefMessageModel::UriRecord; + } + return NdefMessageModel::OtherRecord; +} + +static QString getText(const QNdefRecord &record) +{ + if (record.isRecordType()) { + QNdefNfcTextRecord r(record); + return r.text(); + } else if (record.isRecordType()) { + QNdefNfcUriRecord r(record); + return r.uri().toString(); + } + return record.payload().toHex(':'); +} + +QVariant NdefMessageModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return {}; + + if (index.row() < 0 || index.row() >= m_message.size()) + return {}; + + const auto &record = m_message.at(index.row()); + + switch (role) { + case RecordTypeRole: + return getRecordType(record); + case RecordTextRole: + return getText(record); + default: + return {}; + } +} + +QHash NdefMessageModel::roleNames() const +{ + QHash names; + names[RecordTypeRole] = "recordType"; + names[RecordTextRole] = "recordText"; + return names; +} + +bool NdefMessageModel::removeRows(int row, int count, const QModelIndex &parent) +{ + if (parent.isValid()) + return false; + if (row < 0 || count <= 0) + return false; + if (row >= m_message.size() || (m_message.size() - row) < count) + return false; + + beginRemoveRows(parent, row, row + count - 1); + m_message.remove(row, count); + endRemoveRows(); + Q_EMIT messageChanged(); + + return true; +} + +QNdefMessage NdefMessageModel::message() const +{ + return m_message; +} + +void NdefMessageModel::setMessage(const QNdefMessage &newMessage) +{ + if (m_message == newMessage) + return; + + beginResetModel(); + m_message = newMessage; + endResetModel(); + + Q_EMIT messageChanged(); +} + +void NdefMessageModel::clearMessage() +{ + if (m_message.isEmpty()) + return; + removeRows(0, m_message.size(), {}); +} + +void NdefMessageModel::addTextRecord(const QString &text) +{ + QNdefNfcTextRecord record; + record.setText(text); + + const auto newRow = m_message.size(); + beginInsertRows({}, newRow, newRow); + m_message.append(std::move(record)); + endInsertRows(); + Q_EMIT messageChanged(); +} + +void NdefMessageModel::addUriRecord(const QString &uri) +{ + QNdefNfcUriRecord record; + record.setUri(QUrl(uri)); + + const auto newRow = m_message.size(); + beginInsertRows({}, newRow, newRow); + m_message.append(std::move(record)); + endInsertRows(); + Q_EMIT messageChanged(); +} + +void NdefMessageModel::setTextData(int row, const QString &text) +{ + if (row < 0 || row >= m_message.size()) + return; + + const auto &record = m_message.at(row); + + if (record.isRecordType()) { + QNdefNfcTextRecord r(record); + r.setText(text); + m_message[row] = r; + } else if (record.isRecordType()) { + QNdefNfcUriRecord r(record); + r.setUri(text); + m_message[row] = r; + } else { + return; + } + + const auto idx = index(row); + Q_EMIT dataChanged(idx, idx, { RecordTextRole }); + Q_EMIT messageChanged(); +} diff --git a/examples/nfc/ndefeditor/ndefmessagemodel.h b/examples/nfc/ndefeditor/ndefmessagemodel.h new file mode 100644 index 0000000..5f9ddf2 --- /dev/null +++ b/examples/nfc/ndefeditor/ndefmessagemodel.h @@ -0,0 +1,53 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef NDEFMESSAGEMODEL_H +#define NDEFMESSAGEMODEL_H + +#include + +#include +#include + +class NdefMessageModel : public QAbstractListModel +{ + Q_OBJECT + QML_ELEMENT + Q_PROPERTY(QNdefMessage message READ message WRITE setMessage NOTIFY messageChanged) + +public: + explicit NdefMessageModel(QObject *parent = nullptr); + + enum Role { + RecordTypeRole, + RecordTextRole, + }; + + enum RecordType { + OtherRecord, + TextRecord, + UriRecord, + }; + Q_ENUM(RecordType) + + int rowCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex &index, int role) const override; + QHash roleNames() const override; + bool removeRows(int row, int count, const QModelIndex &parent) override; + + QNdefMessage message() const; + void setMessage(const QNdefMessage &newMessage); + + Q_INVOKABLE void clearMessage(); + Q_INVOKABLE void addTextRecord(const QString &text); + Q_INVOKABLE void addUriRecord(const QString &uri); + Q_INVOKABLE void setTextData(int row, const QString &text); + +Q_SIGNALS: + void messageChanged(); + +private: + QNdefMessage m_message; +}; + +#endif // NDEFMESSAGEMODEL_H diff --git a/examples/nfc/ndefeditor/nfcmanager.cpp b/examples/nfc/ndefeditor/nfcmanager.cpp new file mode 100644 index 0000000..bc09b89 --- /dev/null +++ b/examples/nfc/ndefeditor/nfcmanager.cpp @@ -0,0 +1,29 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "nfcmanager.h" + +#include + +#include "nfctarget.h" + +NfcManager::NfcManager(QObject *parent) : QObject(parent) +{ + m_manager = new QNearFieldManager(this); + + connect(m_manager, &QNearFieldManager::targetDetected, this, [this](QNearFieldTarget *target) { + auto jsTarget = new NfcTarget(target); + QJSEngine::setObjectOwnership(jsTarget, QJSEngine::JavaScriptOwnership); + Q_EMIT targetDetected(jsTarget); + }); +} + +void NfcManager::startTargetDetection() +{ + m_manager->startTargetDetection(QNearFieldTarget::NdefAccess); +} + +void NfcManager::stopTargetDetection() +{ + m_manager->stopTargetDetection(); +} diff --git a/examples/nfc/ndefeditor/nfcmanager.h b/examples/nfc/ndefeditor/nfcmanager.h new file mode 100644 index 0000000..b30f6f3 --- /dev/null +++ b/examples/nfc/ndefeditor/nfcmanager.h @@ -0,0 +1,33 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef NFCMANAGER_H +#define NFCMANAGER_H + +#include + +#include + +#include "nfctarget.h" + +QT_FORWARD_DECLARE_CLASS(QNearFieldManager); + +class NfcManager : public QObject +{ + Q_OBJECT + QML_ELEMENT + +public: + explicit NfcManager(QObject *parent = nullptr); + + Q_INVOKABLE void startTargetDetection(); + Q_INVOKABLE void stopTargetDetection(); + +Q_SIGNALS: + void targetDetected(NfcTarget *target); + +private: + QNearFieldManager *m_manager; +}; + +#endif // NFCMANAGER_H diff --git a/examples/nfc/ndefeditor/nfctarget.cpp b/examples/nfc/ndefeditor/nfctarget.cpp new file mode 100644 index 0000000..68b26df --- /dev/null +++ b/examples/nfc/ndefeditor/nfctarget.cpp @@ -0,0 +1,31 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "nfctarget.h" + +NfcTarget::NfcTarget(QNearFieldTarget *target, QObject *parent) : QObject(parent), m_target(target) +{ + target->setParent(this); + + connect(target, &QNearFieldTarget::ndefMessageRead, this, &NfcTarget::ndefMessageRead); + connect(target, &QNearFieldTarget::requestCompleted, this, &NfcTarget::requestCompleted); + connect(target, &QNearFieldTarget::error, this, &NfcTarget::error); +} + +bool NfcTarget::readNdefMessages() +{ + if (m_target.isNull()) + return false; + + auto req = m_target->readNdefMessages(); + return req.isValid(); +} + +bool NfcTarget::writeNdefMessage(const QNdefMessage &message) +{ + if (m_target.isNull()) + return false; + + auto req = m_target->writeNdefMessages({ message }); + return req.isValid(); +} diff --git a/examples/nfc/ndefeditor/nfctarget.h b/examples/nfc/ndefeditor/nfctarget.h new file mode 100644 index 0000000..fbe3183 --- /dev/null +++ b/examples/nfc/ndefeditor/nfctarget.h @@ -0,0 +1,35 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef NFCTARGET_H +#define NFCTARGET_H + +#include + +#include +#include +#include +#include + +class NfcTarget : public QObject +{ + Q_OBJECT + QML_ELEMENT + QML_UNCREATABLE("Created by NfcManager") + +public: + explicit NfcTarget(QNearFieldTarget *target, QObject *parent = nullptr); + + Q_INVOKABLE bool readNdefMessages(); + Q_INVOKABLE bool writeNdefMessage(const QNdefMessage &message); + +Q_SIGNALS: + void ndefMessageRead(const QNdefMessage &message); + void requestCompleted(); + void error(QNearFieldTarget::Error error); + +private: + QPointer m_target; +}; + +#endif // NFCTARGET_H diff --git a/examples/nfc/ndefeditor/qmldir b/examples/nfc/ndefeditor/qmldir new file mode 100644 index 0000000..0a77d79 --- /dev/null +++ b/examples/nfc/ndefeditor/qmldir @@ -0,0 +1,5 @@ +module NdefEditor +prefer :/qt/qml/NdefEditor/ +Main 1.0 Main.qml +MainWindow 1.0 MainWindow.qml +NdefRecordDelegate 1.0 NdefRecordDelegate.qml diff --git a/examples/nfc/nfc.pro b/examples/nfc/nfc.pro new file mode 100644 index 0000000..49d5452 --- /dev/null +++ b/examples/nfc/nfc.pro @@ -0,0 +1,7 @@ +TEMPLATE = subdirs +qtHaveModule(widgets) { + SUBDIRS += annotatedurl +} +qtHaveModule(quickcontrols2) { + SUBDIRS += ndefeditor +} diff --git a/licenseRule.json b/licenseRule.json new file mode 100644 index 0000000..7a96fb2 --- /dev/null +++ b/licenseRule.json @@ -0,0 +1,94 @@ +[ + { + "comment" : ["file_pattern_ending: strings matched against the end of a file name.", + "location keys: regular expression matched against the beginning of", + "the file path (relative to the git submodule root).", + "spdx: list of SPDX-License-Expression's allowed in the matching files.", + "-------------------------------------------------------", + "Files with the following endings are Build System licensed,", + "unless they are examples", + "Files with other endings can also be build system files" + ], + "file_pattern_ending" : ["CMakeLists.txt", ".cmake", ".pro", ".pri", ".prf", + "configure", "configure.bat", "cmake.in", "plist.in", "CMakeLists.txt.in"], + "location" : { + "" : { + "comment" : "Default", + "file type" : "build system", + "spdx" : ["BSD-3-Clause"] + }, + "(.*)(examples/|snippets/)" : { + "comment" : "Example takes precedent", + "file type" : "examples and snippets", + "spdx" : ["LicenseRef-Qt-Commercial OR BSD-3-Clause"] + } + } + }, + { + "comments" : ["Files with the following endings are Tool licensed,", + "unless they are examples.", + "Files with other endings can also be tool files."], + "file_pattern_ending" : [".sh", ".py", ".pl", ".bat", ".ps1"], + "location" :{ + "" : { + "comment" : "Default", + "file type" : "tools and utils", + "spdx" : ["LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0"] + }, + "(.*)(examples/|snippets/)" : { + "comment" : "Example takes precedent", + "file type" : "examples and snippets", + "spdx" : ["LicenseRef-Qt-Commercial OR BSD-3-Clause"] + } + } + }, + { + "comment" : "Files with the following endings are Documentation licensed.", + "file_pattern_ending" : [".qdoc", ".qdocinc" , ".qdocconf", ".txt", "README", "qt_attribution.json"], + "location" :{ + "" : { + "comment" : "", + "file type" : "documentation", + "spdx" : ["LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only"] + } + } + }, + { + "comment" : ["All other files", + "The licensing is defined only by the file location in the Qt module repository.", + "NO key for this case!", + "This needs to be the last entry of the file."], + "location" : { + "" : { + "comment" : "Default", + "file type" : "module and plugin", + "spdx" : ["LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only"] + }, + "src/" : { + "comment" : "Default", + "file type" : "module and plugin", + "spdx" : ["LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only"] + }, + "src/tools/" : { + "comment" : "Default", + "file type" : "tools and utils", + "spdx" : ["LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0"] + }, + "tests/" : { + "comment" : "Default", + "file type" : "test", + "spdx" : ["LicenseRef-Qt-Commercial OR GPL-3.0-only"] + }, + "(.*)(examples/|snippets/)" : { + "comment" : "Default", + "file type" : "examples and snippets", + "spdx" : ["LicenseRef-Qt-Commercial OR BSD-3-Clause"] + }, + "config\\.tests/" : { + "comment" : "Default", + "file type" : "build system", + "spdx" : ["BSD-3-Clause"] + } + } + } +] diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..e23f22d --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +add_subdirectory(bluetooth) +add_subdirectory(nfc) +if(ANDROID) + add_subdirectory(android) +endif() + +if(QT_FEATURE_bluez) + add_subdirectory(tools/sdpscanner) +endif() diff --git a/src/android/CMakeLists.txt b/src/android/CMakeLists.txt new file mode 100644 index 0000000..a8b6127 --- /dev/null +++ b/src/android/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +if(TARGET Qt::Bluetooth) + add_subdirectory(bluetooth) +endif() +if(TARGET Qt::Nfc) + add_subdirectory(nfc) +endif() diff --git a/src/android/bluetooth/AndroidManifest.xml b/src/android/bluetooth/AndroidManifest.xml new file mode 100644 index 0000000..2735529 --- /dev/null +++ b/src/android/bluetooth/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/src/android/bluetooth/CMakeLists.txt b/src/android/bluetooth/CMakeLists.txt new file mode 100644 index 0000000..f869257 --- /dev/null +++ b/src/android/bluetooth/CMakeLists.txt @@ -0,0 +1,27 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +set(java_sources + src/org/qtproject/qt/android/bluetooth/QtBluetoothBroadcastReceiver.java + src/org/qtproject/qt/android/bluetooth/QtBluetoothInputStreamThread.java + src/org/qtproject/qt/android/bluetooth/QtBluetoothLE.java + src/org/qtproject/qt/android/bluetooth/QtBluetoothLEServer.java + src/org/qtproject/qt/android/bluetooth/QtBluetoothSocketServer.java + src/org/qtproject/qt/android/bluetooth/QtBluetoothGattCharacteristic.java + src/org/qtproject/qt/android/bluetooth/QtBluetoothGattDescriptor.java +) + +qt_internal_add_jar(Qt${QtConnectivity_VERSION_MAJOR}AndroidBluetooth + INCLUDE_JARS ${QT_ANDROID_JAR} + SOURCES ${java_sources} + OUTPUT_DIR "${QT_BUILD_DIR}/jar" +) + +qt_path_join(destination ${INSTALL_DATADIR} "jar") + +install_jar(Qt${QtConnectivity_VERSION_MAJOR}AndroidBluetooth + DESTINATION ${destination} + COMPONENT Devel +) + +add_dependencies(Bluetooth Qt${QtConnectivity_VERSION_MAJOR}AndroidBluetooth) diff --git a/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothBroadcastReceiver.java b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothBroadcastReceiver.java new file mode 100644 index 0000000..6c74c3e --- /dev/null +++ b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothBroadcastReceiver.java @@ -0,0 +1,187 @@ +// Copyright (C) 2016 Lauri Laanmets (Proekspert AS) +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +package org.qtproject.qt.android.bluetooth; + +import android.app.Activity; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothProfile; +import android.bluetooth.BluetoothManager; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.util.Log; + +import java.lang.reflect.Method; +import java.util.HashSet; +import java.util.List; + +public class QtBluetoothBroadcastReceiver extends BroadcastReceiver +{ + /* Pointer to the Qt object that "owns" the Java object */ + @SuppressWarnings("WeakerAccess") + long qtObject = 0; + @SuppressWarnings("WeakerAccess") + static Context qtContext = null; + + // These are opaque tokens that could be used to match the completed action + private static final int TURN_BT_ENABLED = 3330; + private static final int TURN_BT_DISCOVERABLE = 3331; + private static final int TURN_BT_DISABLED = 3332; + + // The 'Disable' action identifier is hidden in the public APIs so we define it here + public static final String ACTION_REQUEST_DISABLE = + "android.bluetooth.adapter.action.REQUEST_DISABLE"; + + private static final String TAG = "QtBluetoothBroadcastReceiver"; + + public void onReceive(Context context, Intent intent) + { + synchronized (qtContext) { + if (qtObject == 0) + return; + + jniOnReceive(qtObject, context, intent); + } + } + + public void unregisterReceiver() + { + synchronized (qtContext) { + qtObject = 0; + try { + qtContext.unregisterReceiver(this); + } catch (Exception ex) { + Log.d(TAG, "Trying to unregister a BroadcastReceiver which is not yet registered"); + } + } + } + + public native void jniOnReceive(long qtObject, Context context, Intent intent); + + static public void setContext(Context context) + { + qtContext = context; + } + + static public boolean setDisabled() + { + if (!(qtContext instanceof android.app.Activity)) { + Log.w(TAG, "Bluetooth cannot be disabled from a service."); + return false; + } + // The 'disable' is hidden in the public API and as such + // there are no availability guarantees; may throw an "ActivityNotFoundException" + Intent intent = new Intent(ACTION_REQUEST_DISABLE); + + try { + ((Activity)qtContext).startActivityForResult(intent, TURN_BT_DISABLED); + } catch (Exception ex) { + Log.w(TAG, "setDisabled() failed to initiate Bluetooth disablement"); + ex.printStackTrace(); + return false; + } + return true; + } + + static public boolean setDiscoverable() + { + if (!(qtContext instanceof android.app.Activity)) { + Log.w(TAG, "Discovery mode cannot be enabled from a service."); + return false; + } + + Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); + intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300); + try { + ((Activity)qtContext).startActivityForResult(intent, TURN_BT_DISCOVERABLE); + } catch (Exception ex) { + Log.w(TAG, "setDiscoverable() failed to initiate Bluetooth discoverability change"); + ex.printStackTrace(); + return false; + } + return true; + } + + static public boolean setEnabled() + { + if (!(qtContext instanceof android.app.Activity)) { + Log.w(TAG, "Bluetooth cannot be enabled from a service."); + return false; + } + + Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); + try { + ((Activity)qtContext).startActivityForResult(intent, TURN_BT_ENABLED); + } catch (Exception ex) { + Log.w(TAG, "setEnabled() failed to initiate Bluetooth enablement"); + ex.printStackTrace(); + return false; + } + return true; + } + + static public boolean setPairingMode(String address, boolean isPairing) + { + BluetoothManager manager = + (BluetoothManager)qtContext.getSystemService(Context.BLUETOOTH_SERVICE); + if (manager == null) + return false; + + BluetoothAdapter adapter = manager.getAdapter(); + if (adapter == null) + return false; + + // Uses reflection as the removeBond() is not part of public API + try { + BluetoothDevice device = adapter.getRemoteDevice(address); + String methodName = "createBond"; + if (!isPairing) + methodName = "removeBond"; + + Method m = device.getClass() + .getMethod(methodName, (Class[]) null); + m.invoke(device, (Object[]) null); + } catch (Exception ex) { + ex.printStackTrace(); + return false; + } + + return true; + } + + /* + * Returns a list of remote devices confirmed to be connected. + * + * This list is not complete as it only detects GATT/BtLE related connections. + * Unfortunately there is no API that provides the complete list. + * + */ + static public String[] getConnectedDevices() + { + BluetoothManager bluetoothManager = + (BluetoothManager) qtContext.getSystemService(Context.BLUETOOTH_SERVICE); + + if (bluetoothManager == null) { + Log.w(TAG, "Failed to retrieve connected devices"); + return new String[0]; + } + + List gattConnections = + bluetoothManager.getConnectedDevices(BluetoothProfile.GATT); + List gattServerConnections = + bluetoothManager.getConnectedDevices(BluetoothProfile.GATT_SERVER); + + // Process found remote connections but avoid duplications + HashSet set = new HashSet(); + for (Object gattConnection : gattConnections) + set.add(gattConnection.toString()); + + for (Object gattServerConnection : gattServerConnections) + set.add(gattServerConnection.toString()); + + return set.toArray(new String[set.size()]); + } +} diff --git a/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothGattCharacteristic.java b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothGattCharacteristic.java new file mode 100644 index 0000000..375aebb --- /dev/null +++ b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothGattCharacteristic.java @@ -0,0 +1,44 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +package org.qtproject.qt.android.bluetooth; + +import android.bluetooth.BluetoothGattCharacteristic; +import android.os.Build; + +import java.util.UUID; + +public class QtBluetoothGattCharacteristic extends BluetoothGattCharacteristic { + public QtBluetoothGattCharacteristic(UUID uuid, int properties, int permissions, + int minimumValueLength, int maximumValueLength) { + super(uuid, properties, permissions); + minValueLength = minimumValueLength; + maxValueLength = maximumValueLength; + } + public int minValueLength; + public int maxValueLength; + // Starting from API 33 Android Bluetooth deprecates characteristic local value caching by + // deprecating the getValue() and setValue() accessors. For peripheral role we store the value + // locally in the characteristic as a convenience - looking up the value on the C++ side would + // be somewhat complicated. This should be safe as all accesses to this class are synchronized. + // For clarity: For API levels below 33 we still need to use the setValue() of the base class + // because Android internally uses getValue() with APIs below 33. + public boolean setLocalValue(byte[] value) { + if (Build.VERSION.SDK_INT >= 33) { + m_localValue = value; + return true; + } else { + return setValue(value); + } + } + + public byte[] getLocalValue() + { + if (Build.VERSION.SDK_INT >= 33) + return m_localValue; + else + return getValue(); + } + + private byte[] m_localValue = null; +} diff --git a/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothGattDescriptor.java b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothGattDescriptor.java new file mode 100644 index 0000000..10194ea --- /dev/null +++ b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothGattDescriptor.java @@ -0,0 +1,39 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +package org.qtproject.qt.android.bluetooth; + +import android.bluetooth.BluetoothGattDescriptor; +import android.os.Build; + +import java.util.UUID; + +public class QtBluetoothGattDescriptor extends BluetoothGattDescriptor { + public QtBluetoothGattDescriptor(UUID uuid, int permissions) { + super(uuid, permissions); + } + // Starting from API 33 Android Bluetooth deprecates descriptor local value caching by + // deprecating the getValue() and setValue() accessors. For peripheral role we store the value + // locally in the descriptor as a convenience - looking up the value on the C++ side would + // be somewhat complicated. This should be safe as all accesses to this class are synchronized. + // For clarity: For API levels below 33 we still need to use the setValue() of the base class + // because Android internally uses getValue() with APIs below 33. + public boolean setLocalValue(byte[] value) { + if (Build.VERSION.SDK_INT >= 33) { + m_localValue = value; + return true; + } else { + return setValue(value); + } + } + + public byte[] getLocalValue() + { + if (Build.VERSION.SDK_INT >= 33) + return m_localValue; + else + return getValue(); + } + + private byte[] m_localValue = null; +} diff --git a/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothInputStreamThread.java b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothInputStreamThread.java new file mode 100644 index 0000000..0fd6f29 --- /dev/null +++ b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothInputStreamThread.java @@ -0,0 +1,68 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +package org.qtproject.qt.android.bluetooth; + +import java.io.InputStream; +import java.io.IOException; +import android.util.Log; + +@SuppressWarnings("WeakerAccess") +public class QtBluetoothInputStreamThread extends Thread +{ + /* Pointer to the Qt object that "owns" the Java object */ + @SuppressWarnings("CanBeFinal") + long qtObject = 0; + @SuppressWarnings("CanBeFinal") + public boolean logEnabled = false; + private static final String TAG = "QtBluetooth"; + private InputStream m_inputStream = null; + + //error codes + public static final int QT_MISSING_INPUT_STREAM = 0; + public static final int QT_READ_FAILED = 1; + public static final int QT_THREAD_INTERRUPTED = 2; + + public QtBluetoothInputStreamThread() + { + setName("QtBtInputStreamThread"); + } + + public void setInputStream(InputStream stream) + { + m_inputStream = stream; + } + + public void run() + { + if (m_inputStream == null) { + errorOccurred(qtObject, QT_MISSING_INPUT_STREAM); + return; + } + + byte[] buffer = new byte[1000]; + int bytesRead; + + try { + while (!isInterrupted()) { + //this blocks until we see incoming data + //or close() on related BluetoothSocket is called + bytesRead = m_inputStream.read(buffer); + readyData(qtObject, buffer, bytesRead); + } + + errorOccurred(qtObject, QT_THREAD_INTERRUPTED); + } catch (IOException ex) { + if (logEnabled) + Log.d(TAG, "InputStream.read() failed:" + ex.toString()); + ex.printStackTrace(); + errorOccurred(qtObject, QT_READ_FAILED); + } + + if (logEnabled) + Log.d(TAG, "Leaving input stream thread"); + } + + public static native void errorOccurred(long qtObject, int errorCode); + public static native void readyData(long qtObject, byte[] buffer, int bufferLength); +} diff --git a/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLE.java b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLE.java new file mode 100644 index 0000000..0e612ad --- /dev/null +++ b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLE.java @@ -0,0 +1,1837 @@ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +package org.qtproject.qt.android.bluetooth; + +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattCallback; +import android.bluetooth.BluetoothGattCharacteristic; +import android.bluetooth.BluetoothGattDescriptor; +import android.bluetooth.BluetoothGattService; +import android.bluetooth.BluetoothProfile; +import android.bluetooth.BluetoothManager; +import android.bluetooth.le.BluetoothLeScanner; +import android.bluetooth.le.ScanCallback; +import android.bluetooth.le.ScanFilter; +import android.bluetooth.le.ScanResult; +import android.bluetooth.le.ScanSettings; +import android.bluetooth.BluetoothStatusCodes; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Build; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Looper; +import android.util.Log; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.util.concurrent.atomic.AtomicInteger; + +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.LinkedList; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.UUID; + + +public class QtBluetoothLE { + private static final String TAG = "QtBluetoothGatt"; + private BluetoothAdapter mBluetoothAdapter = null; + private boolean mLeScanRunning = false; + + private BluetoothGatt mBluetoothGatt = null; + private HandlerThread mHandlerThread = null; + private Handler mHandler = null; + private Constructor mCharacteristicConstructor = null; + private String mRemoteGattAddress; + private final UUID clientCharacteristicUuid = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"); + private final int MAX_MTU = 512; + private final int DEFAULT_MTU = 23; + private int mSupportedMtu = -1; + + /* + * The atomic synchronizes the timeoutRunnable thread and the response thread for the pending + * I/O job. Whichever thread comes first will pass the atomic gate. The other thread is + * cut short. + */ + // handle values above zero are for regular handle specific read/write requests + // handle values below zero are reserved for handle-independent requests + private int HANDLE_FOR_RESET = -1; + private int HANDLE_FOR_MTU_EXCHANGE = -2; + private int HANDLE_FOR_RSSI_READ = -3; + private AtomicInteger handleForTimeout = new AtomicInteger(HANDLE_FOR_RESET); // implies not running by default + + private final int RUNNABLE_TIMEOUT = 3000; // 3 seconds + private final Handler timeoutHandler = new Handler(Looper.getMainLooper()); + + private BluetoothLeScanner mBluetoothLeScanner = null; + + private class TimeoutRunnable implements Runnable { + public TimeoutRunnable(int handle) { pendingJobHandle = handle; } + @Override + public void run() { + boolean timeoutStillValid = handleForTimeout.compareAndSet(pendingJobHandle, HANDLE_FOR_RESET); + if (timeoutStillValid) { + Log.w(TAG, "****** Timeout for request on handle " + (pendingJobHandle & 0xffff)); + Log.w(TAG, "****** Looks like the peripheral does NOT act in " + + "accordance to Bluetooth 4.x spec."); + Log.w(TAG, "****** Please check server implementation. Continuing under " + + "reservation."); + + if (pendingJobHandle > HANDLE_FOR_RESET) + interruptCurrentIO(pendingJobHandle & 0xffff); + else if (pendingJobHandle < HANDLE_FOR_RESET) + interruptCurrentIO(pendingJobHandle); + } + } + + // contains handle (0xffff) and top 2 byte contain the job type (0xffff0000) + private int pendingJobHandle = -1; + }; + + // The handleOn* functions in this class are callback handlers which are synchronized + // to "this" client object. This protects the member variables which could be + // concurrently accessed from Qt (JNI) thread and different Java threads *) + // *) The newer Android API (starting Android 8.1) synchronizes callbacks to one + // Java thread, but this is not true for the earlier API which we still support. + // + // In case bond state has been changed due to access to a restricted handle, + // Android never completes the operation which triggered the devices to bind + // and thus never fires on(Characteristic|Descriptor)(Read|Write) callback, + // causing TimeoutRunnable to interrupt pending job, + // albeit the read/write job hasn't been actually executed by the peripheral; + // re-add the currently pending job to the queue's head and re-run it. + // If, by some reason, bonding process has been interrupted, either + // re-add the currently pending job to the queue's head and re-run it. + private synchronized void handleOnReceive(Context context, Intent intent) + { + if (mBluetoothGatt == null) + return; + + final BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); + if (device == null || !device.getAddress().equals(mBluetoothGatt.getDevice().getAddress())) + return; + + final int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1); + final int previousBondState = + intent.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, -1); + + if (bondState == BluetoothDevice.BOND_BONDING) { + if (pendingJob == null + || pendingJob.jobType == IoJobType.Mtu || pendingJob.jobType == IoJobType.Rssi) { + return; + } + + timeoutHandler.removeCallbacksAndMessages(null); + handleForTimeout.set(HANDLE_FOR_RESET); + } else if (previousBondState == BluetoothDevice.BOND_BONDING && + (bondState == BluetoothDevice.BOND_BONDED || bondState == BluetoothDevice.BOND_NONE)) { + if (pendingJob == null + || pendingJob.jobType == IoJobType.Mtu || pendingJob.jobType == IoJobType.Rssi) { + return; + } + + readWriteQueue.addFirst(pendingJob); + pendingJob = null; + + performNextIO(); + } else if (previousBondState == BluetoothDevice.BOND_BONDED + && bondState == BluetoothDevice.BOND_NONE) { + // peripheral or central removed the bond information; + // if it was peripheral, the connection attempt would fail with PIN_OR_KEY_MISSING, + // which is handled by Android by broadcasting ACTION_BOND_STATE_CHANGED + // with new state BOND_NONE, without actually deleting the bond information :facepalm: + // if we get there, it is safer to delete it now, by invoking the undocumented API call + try { + device.getClass().getMethod("removeBond").invoke(device); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } + + private class BondStateBroadcastReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + handleOnReceive(context, intent); + } + }; + private BroadcastReceiver bondStateBroadcastReceiver = null; + + /* Pointer to the Qt object that "owns" the Java object */ + @SuppressWarnings({"CanBeFinal", "WeakerAccess"}) + long qtObject = 0; + @SuppressWarnings("WeakerAccess") + Context qtContext = null; + + @SuppressWarnings("WeakerAccess") + public QtBluetoothLE(Context context) { + qtContext = context; + + BluetoothManager manager = + (BluetoothManager)qtContext.getSystemService(Context.BLUETOOTH_SERVICE); + if (manager == null) + return; + + mBluetoothAdapter = manager.getAdapter(); + if (mBluetoothAdapter == null) + return; + + mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner(); + } + + public QtBluetoothLE(final String remoteAddress, Context context) { + this(context); + mRemoteGattAddress = remoteAddress; + } + + /*************************************************************/ + /* Device scan */ + /* Returns true, if request was successfully completed */ + /* This function is called from Qt thread, but only accesses */ + /* variables that are not accessed from Java threads */ + /*************************************************************/ + + public boolean scanForLeDevice(final boolean isEnabled) { + if (isEnabled == mLeScanRunning) + return true; + + if (mBluetoothLeScanner == null) { + Log.w(TAG, "Cannot start LE scan, no bluetooth scanner"); + return false; + } + + if (isEnabled) { + Log.d(TAG, "Attempting to start BTLE scan"); + ScanSettings.Builder settingsBuilder = new ScanSettings.Builder(); + settingsBuilder = settingsBuilder.setScanMode(ScanSettings.SCAN_MODE_BALANCED); + ScanSettings settings = settingsBuilder.build(); + + List filterList = new ArrayList(); + + mBluetoothLeScanner.startScan(filterList, settings, leScanCallback); + mLeScanRunning = true; + } else { + Log.d(TAG, "Attempting to stop BTLE scan"); + try { + mBluetoothLeScanner.stopScan(leScanCallback); + } catch (IllegalStateException isex) { + // when trying to stop a scan while bluetooth is offline + // java.lang.IllegalStateException: BT Adapter is not turned ON + Log.d(TAG, "Stopping LE scan not possible: " + isex.getMessage()); + } + mLeScanRunning = false; + } + + return (mLeScanRunning == isEnabled); + } + + private final ScanCallback leScanCallback = new ScanCallback() { + @Override + public void onScanResult(int callbackType, ScanResult result) { + super.onScanResult(callbackType, result); + leScanResult(qtObject, result.getDevice(), result.getRssi(), result.getScanRecord().getBytes()); + } + + @Override + public void onBatchScanResults(List results) { + super.onBatchScanResults(results); + for (ScanResult result : results) + leScanResult(qtObject, result.getDevice(), result.getRssi(), result.getScanRecord().getBytes()); + + } + + @Override + public void onScanFailed(int errorCode) { + super.onScanFailed(errorCode); + Log.d(TAG, "BTLE device scan failed with " + errorCode); + } + }; + + public native void leScanResult(long qtObject, BluetoothDevice device, int rssi, byte[] scanRecord); + + private synchronized void handleOnConnectionStateChange(BluetoothGatt gatt, + int status, int newState) { + + Log.d(TAG, "Connection state changes to: " + newState + ", status: " + status + + ", qtObject: " + (qtObject != 0)); + if (qtObject == 0) + return; + + int qLowEnergyController_State = 0; + //This must be in sync with QLowEnergyController::ControllerState + switch (newState) { + case BluetoothProfile.STATE_DISCONNECTED: + if (bondStateBroadcastReceiver != null) { + qtContext.unregisterReceiver(bondStateBroadcastReceiver); + bondStateBroadcastReceiver = null; + } + + qLowEnergyController_State = 0; + // we disconnected -> get rid of data from previous run + resetData(); + // reset mBluetoothGatt, reusing same object is not very reliable + // sometimes it reconnects and sometimes it does not. + if (mBluetoothGatt != null) { + mBluetoothGatt.close(); + if (mHandler != null) { + mHandler.getLooper().quitSafely(); + mHandler = null; + } + } + mBluetoothGatt = null; + break; + case BluetoothProfile.STATE_CONNECTED: + if (bondStateBroadcastReceiver == null) { + bondStateBroadcastReceiver = new BondStateBroadcastReceiver(); + qtContext.registerReceiver(bondStateBroadcastReceiver, + new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED)); + } + qLowEnergyController_State = 2; + } + + //This must be in sync with QLowEnergyController::Error + int errorCode; + switch (status) { + case BluetoothGatt.GATT_SUCCESS: + errorCode = 0; //QLowEnergyController::NoError + break; + case BluetoothGatt.GATT_FAILURE: // Android's equivalent of "do not know what error" + errorCode = 1; //QLowEnergyController::UnknownError + break; + case 8: // BLE_HCI_CONNECTION_TIMEOUT + Log.w(TAG, "Connection Error: Try to delay connect() call after previous activity"); + errorCode = 5; //QLowEnergyController::ConnectionError + break; + case 19: // BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION + case 20: // BLE_HCI_REMOTE_DEV_TERMINATION_DUE_TO_LOW_RESOURCES + case 21: // BLE_HCI_REMOTE_DEV_TERMINATION_DUE_TO_POWER_OFF + Log.w(TAG, "The remote host closed the connection"); + errorCode = 7; //QLowEnergyController::RemoteHostClosedError + break; + case 22: // BLE_HCI_LOCAL_HOST_TERMINATED_CONNECTION + // Internally, Android maps PIN_OR_KEY_MISSING to GATT_CONN_TERMINATE_LOCAL_HOST + errorCode = 8; //QLowEnergyController::AuthorizationError + break; + default: + Log.w(TAG, "Unhandled error code on connectionStateChanged: " + + status + " " + newState); + errorCode = status; + break; //TODO deal with all errors + } + leConnectionStateChange(qtObject, errorCode, qLowEnergyController_State); + } + + private synchronized void handleOnServicesDiscovered(BluetoothGatt gatt, int status) { + //This must be in sync with QLowEnergyController::Error + int errorCode; + StringBuilder builder = new StringBuilder(); + switch (status) { + case BluetoothGatt.GATT_SUCCESS: + errorCode = 0; //QLowEnergyController::NoError + final List services = mBluetoothGatt.getServices(); + for (BluetoothGattService service: services) { + builder.append(service.getUuid().toString()).append(" "); //space is separator + } + break; + default: + Log.w(TAG, "Unhandled error code on onServicesDiscovered: " + status); + errorCode = status; break; //TODO deal with all errors + } + leServicesDiscovered(qtObject, errorCode, builder.toString()); + if (status == BluetoothGatt.GATT_SUCCESS) + scheduleMtuExchange(); + } + + private synchronized void handleOnCharacteristicRead(BluetoothGatt gatt, + BluetoothGattCharacteristic characteristic, + byte[] value, + int status) + { + int foundHandle = handleForCharacteristic(characteristic); + if (foundHandle == -1 || foundHandle >= entries.size() ) { + Log.w(TAG, "Cannot find characteristic read request for read notification - handle: " + + foundHandle + " size: " + entries.size()); + + //unlock the queue for next item + pendingJob = null; + + performNextIO(); + return; + } + + boolean requestTimedOut = !handleForTimeout.compareAndSet( + modifiedReadWriteHandle(foundHandle, IoJobType.Read), + HANDLE_FOR_RESET); + if (requestTimedOut) { + Log.w(TAG, "Late char read reply after timeout was hit for handle " + foundHandle); + // Timeout has hit before this response -> ignore the response + // no need to unlock pendingJob -> the timeout has done that already + return; + } + + GattEntry entry = entries.get(foundHandle); + final boolean isServiceDiscoveryRun = !entry.valueKnown; + entry.valueKnown = true; + + if (status == BluetoothGatt.GATT_SUCCESS) { + // Qt manages handles starting at 1, in Java we use a system starting with 0 + //TODO avoid sending service uuid -> service handle should be sufficient + leCharacteristicRead(qtObject, + characteristic.getService().getUuid().toString(), + foundHandle + 1, characteristic.getUuid().toString(), + characteristic.getProperties(), value); + } else { + if (isServiceDiscoveryRun) { + Log.w(TAG, "onCharacteristicRead during discovery error: " + status); + + Log.d(TAG, "Non-readable characteristic " + characteristic.getUuid() + + " for service " + characteristic.getService().getUuid()); + leCharacteristicRead(qtObject, characteristic.getService().getUuid().toString(), + foundHandle + 1, characteristic.getUuid().toString(), + characteristic.getProperties(), value); + } else { + // This must be in sync with QLowEnergyService::CharacteristicReadError + final int characteristicReadError = 5; + leServiceError(qtObject, foundHandle + 1, characteristicReadError); + } + } + + if (isServiceDiscoveryRun) { + + // last entry of pending service discovery run -> send discovery finished state update + GattEntry serviceEntry = entries.get(entry.associatedServiceHandle); + if (serviceEntry.endHandle == foundHandle) + finishCurrentServiceDiscovery(entry.associatedServiceHandle); + } + + //unlock the queue for next item + pendingJob = null; + + performNextIO(); + } + + private synchronized void handleOnCharacteristicChanged(android.bluetooth.BluetoothGatt gatt, + android.bluetooth.BluetoothGattCharacteristic characteristic, + byte[] value) + { + int handle = handleForCharacteristic(characteristic); + if (handle == -1) { + Log.w(TAG,"onCharacteristicChanged: cannot find handle"); + return; + } + + leCharacteristicChanged(qtObject, handle+1, value); + } + + private synchronized void handleOnCharacteristicWrite(android.bluetooth.BluetoothGatt gatt, + android.bluetooth.BluetoothGattCharacteristic characteristic, + int status) + { + if (status != BluetoothGatt.GATT_SUCCESS) + Log.w(TAG, "onCharacteristicWrite: error " + status); + + int handle = handleForCharacteristic(characteristic); + if (handle == -1) { + Log.w(TAG,"onCharacteristicWrite: cannot find handle"); + return; + } + + boolean requestTimedOut = !handleForTimeout.compareAndSet( + modifiedReadWriteHandle(handle, IoJobType.Write), + HANDLE_FOR_RESET); + if (requestTimedOut) { + Log.w(TAG, "Late char write reply after timeout was hit for handle " + handle); + // Timeout has hit before this response -> ignore the response + // no need to unlock pendingJob -> the timeout has done that already + return; + } + + int errorCode; + //This must be in sync with QLowEnergyService::ServiceError + switch (status) { + case BluetoothGatt.GATT_SUCCESS: + errorCode = 0; + break; // NoError + default: + errorCode = 2; + break; // CharacteristicWriteError + } + + byte[] value; + value = pendingJob.newValue; + pendingJob = null; + + leCharacteristicWritten(qtObject, handle+1, value, errorCode); + performNextIO(); + } + + private synchronized void handleOnDescriptorRead(android.bluetooth.BluetoothGatt gatt, + android.bluetooth.BluetoothGattDescriptor descriptor, + int status, byte[] newValue) + { + int foundHandle = handleForDescriptor(descriptor); + if (foundHandle == -1 || foundHandle >= entries.size() ) { + Log.w(TAG, "Cannot find descriptor read request for read notification - handle: " + + foundHandle + " size: " + entries.size()); + + //unlock the queue for next item + pendingJob = null; + + performNextIO(); + return; + } + + boolean requestTimedOut = !handleForTimeout.compareAndSet( + modifiedReadWriteHandle(foundHandle, IoJobType.Read), + HANDLE_FOR_RESET); + if (requestTimedOut) { + Log.w(TAG, "Late descriptor read reply after timeout was hit for handle " + + foundHandle); + // Timeout has hit before this response -> ignore the response + // no need to unlock pendingJob -> the timeout has done that already + return; + } + + GattEntry entry = entries.get(foundHandle); + final boolean isServiceDiscoveryRun = !entry.valueKnown; + entry.valueKnown = true; + + if (status == BluetoothGatt.GATT_SUCCESS) { + //TODO avoid sending service and characteristic uuid -> handles should be sufficient + leDescriptorRead(qtObject, + descriptor.getCharacteristic().getService().getUuid().toString(), + descriptor.getCharacteristic().getUuid().toString(), foundHandle + 1, + descriptor.getUuid().toString(), newValue); + } else { + if (isServiceDiscoveryRun) { + // Cannot read but still advertise the fact that we found a descriptor + // The value will be empty. + Log.w(TAG, "onDescriptorRead during discovery error: " + status); + Log.d(TAG, "Non-readable descriptor " + descriptor.getUuid() + + " for characteristic " + descriptor.getCharacteristic().getUuid() + + " for service " + descriptor.getCharacteristic().getService().getUuid()); + leDescriptorRead(qtObject, + descriptor.getCharacteristic().getService().getUuid().toString(), + descriptor.getCharacteristic().getUuid().toString(), foundHandle + 1, + descriptor.getUuid().toString(), newValue); + } else { + // This must be in sync with QLowEnergyService::DescriptorReadError + final int descriptorReadError = 6; + leServiceError(qtObject, foundHandle + 1, descriptorReadError); + } + + } + + if (isServiceDiscoveryRun) { + // last entry of pending service discovery run? ->send discovery finished state update + GattEntry serviceEntry = entries.get(entry.associatedServiceHandle); + if (serviceEntry.endHandle == foundHandle) { + finishCurrentServiceDiscovery(entry.associatedServiceHandle); + } + + /* Some devices preset ClientCharacteristicConfiguration descriptors + * to enable notifications out of the box. However the additional + * BluetoothGatt.setCharacteristicNotification call prevents + * automatic notifications from coming through. Hence we manually set them + * up here. + */ + if (descriptor.getUuid().compareTo(clientCharacteristicUuid) == 0) { + byte[] bytearray = newValue; + final int value = (bytearray != null && bytearray.length > 0) ? bytearray[0] : 0; + // notification or indication bit set? + if ((value & 0x03) > 0) { + Log.d(TAG, "Found descriptor with automatic notifications."); + mBluetoothGatt.setCharacteristicNotification( + descriptor.getCharacteristic(), true); + } + } + } + + //unlock the queue for next item + pendingJob = null; + + performNextIO(); + } + + private synchronized void handleOnDescriptorWrite(android.bluetooth.BluetoothGatt gatt, + android.bluetooth.BluetoothGattDescriptor descriptor, + int status) + { + if (status != BluetoothGatt.GATT_SUCCESS) + Log.w(TAG, "onDescriptorWrite: error " + status); + + int handle = handleForDescriptor(descriptor); + + boolean requestTimedOut = !handleForTimeout.compareAndSet( + modifiedReadWriteHandle(handle, IoJobType.Write), + HANDLE_FOR_RESET); + if (requestTimedOut) { + Log.w(TAG, "Late descriptor write reply after timeout was hit for handle " + + handle); + // Timeout has hit before this response -> ignore the response + // no need to unlock pendingJob -> the timeout has done that already + return; + } + + int errorCode; + //This must be in sync with QLowEnergyService::ServiceError + switch (status) { + case BluetoothGatt.GATT_SUCCESS: + errorCode = 0; break; // NoError + default: + errorCode = 3; break; // DescriptorWriteError + } + + byte[] value = pendingJob.newValue; + pendingJob = null; + + leDescriptorWritten(qtObject, handle+1, value, errorCode); + performNextIO(); + } + + private synchronized void handleOnMtuChanged(android.bluetooth.BluetoothGatt gatt, + int mtu, int status) + { + int previousMtu = mSupportedMtu; + if (status == BluetoothGatt.GATT_SUCCESS) { + Log.w(TAG, "MTU changed to " + mtu); + mSupportedMtu = mtu; + } else { + Log.w(TAG, "MTU change error " + status + ". New MTU " + mtu); + mSupportedMtu = DEFAULT_MTU; + } + if (previousMtu != mSupportedMtu) + leMtuChanged(qtObject, mSupportedMtu); + + boolean requestTimedOut = !handleForTimeout.compareAndSet( + modifiedReadWriteHandle(HANDLE_FOR_MTU_EXCHANGE, IoJobType.Mtu), HANDLE_FOR_RESET); + if (requestTimedOut) { + Log.w(TAG, "Late mtu reply after timeout was hit"); + // Timeout has hit before this response -> ignore the response + // no need to unlock pendingJob -> the timeout has done that already + return; + } + + pendingJob = null; + + performNextIO(); + } + + private synchronized void handleOnReadRemoteRssi(android.bluetooth.BluetoothGatt gatt, + int rssi, int status) + { + Log.d(TAG, "RSSI read callback, rssi: " + rssi + ", status: " + status); + leRemoteRssiRead(qtObject, rssi, status == BluetoothGatt.GATT_SUCCESS); + + boolean requestTimedOut = !handleForTimeout.compareAndSet( + modifiedReadWriteHandle(HANDLE_FOR_RSSI_READ, IoJobType.Rssi), HANDLE_FOR_RESET); + if (requestTimedOut) { + Log.w(TAG, "Late RSSI read reply after timeout was hit"); + // Timeout has hit before this response -> ignore the response + // no need to unlock pendingJob -> the timeout has done that already + return; + } + pendingJob = null; + performNextIO(); + } + + /*************************************************************/ + /* Service Discovery */ + /*************************************************************/ + + private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() { + + public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { + super.onConnectionStateChange(gatt, status, newState); + handleOnConnectionStateChange(gatt, status, newState); + } + + public void onServicesDiscovered(BluetoothGatt gatt, int status) { + super.onServicesDiscovered(gatt, status); + handleOnServicesDiscovered(gatt, status); + + } + + // API < 33 + public void onCharacteristicRead(android.bluetooth.BluetoothGatt gatt, + android.bluetooth.BluetoothGattCharacteristic characteristic, + int status) + { + super.onCharacteristicRead(gatt, characteristic, status); + handleOnCharacteristicRead(gatt, characteristic, characteristic.getValue(), status); + } + + // API >= 33 + public void onCharacteristicRead(android.bluetooth.BluetoothGatt gatt, + android.bluetooth.BluetoothGattCharacteristic characteristic, + byte[] value, + int status) + { + // Note: here we don't call the super implementation as it calls the old "< API 33" + // callback, and the callback would be handled twice + handleOnCharacteristicRead(gatt, characteristic, value, status); + } + + public void onCharacteristicWrite(android.bluetooth.BluetoothGatt gatt, + android.bluetooth.BluetoothGattCharacteristic characteristic, + int status) + { + super.onCharacteristicWrite(gatt, characteristic, status); + handleOnCharacteristicWrite(gatt, characteristic, status); + } + + // API < 33 + public void onCharacteristicChanged(android.bluetooth.BluetoothGatt gatt, + android.bluetooth.BluetoothGattCharacteristic characteristic) + { + super.onCharacteristicChanged(gatt, characteristic); + handleOnCharacteristicChanged(gatt, characteristic, characteristic.getValue()); + } + + // API >= 33 + public void onCharacteristicChanged(android.bluetooth.BluetoothGatt gatt, + android.bluetooth.BluetoothGattCharacteristic characteristic, + byte[] value) + { + // Note: here we don't call the super implementation as it calls the old "< API 33" + // callback, and the callback would be handled twice + handleOnCharacteristicChanged(gatt, characteristic, value); + } + + // API < 33 + public void onDescriptorRead(android.bluetooth.BluetoothGatt gatt, + android.bluetooth.BluetoothGattDescriptor descriptor, + int status) + { + super.onDescriptorRead(gatt, descriptor, status); + handleOnDescriptorRead(gatt, descriptor, status, descriptor.getValue()); + } + + // API >= 33 + public void onDescriptorRead(android.bluetooth.BluetoothGatt gatt, + android.bluetooth.BluetoothGattDescriptor descriptor, + int status, + byte[] value) + { + // Note: here we don't call the super implementation as it calls the old "< API 33" + // callback, and the callback would be handled twice + handleOnDescriptorRead(gatt, descriptor, status, value); + } + + public void onDescriptorWrite(android.bluetooth.BluetoothGatt gatt, + android.bluetooth.BluetoothGattDescriptor descriptor, + int status) + { + super.onDescriptorWrite(gatt, descriptor, status); + handleOnDescriptorWrite(gatt, descriptor, status); + } + //TODO currently not supported +// public void onReliableWriteCompleted(android.bluetooth.BluetoothGatt gatt, +// int status) { +// System.out.println("onReliableWriteCompleted"); +// } +// + public void onReadRemoteRssi(android.bluetooth.BluetoothGatt gatt, int rssi, int status) + { + super.onReadRemoteRssi(gatt, rssi, status); + handleOnReadRemoteRssi(gatt, rssi, status); + } + + public void onMtuChanged(android.bluetooth.BluetoothGatt gatt, int mtu, int status) + { + super.onMtuChanged(gatt, mtu, status); + handleOnMtuChanged(gatt, mtu, status); + } + }; + + // This function is called from Qt thread + public synchronized int mtu() { + if (mSupportedMtu == -1) { + return DEFAULT_MTU; + } else { + return mSupportedMtu; + } + } + + // This function is called from Qt thread + public synchronized boolean readRemoteRssi() { + if (mBluetoothGatt == null) + return false; + + // Reading of RSSI can sometimes be 'lost' especially if amidst + // characteristic reads/writes ('lost' here meaning that there is no callback). + // To avoid this schedule the RSSI read in the job queue. + ReadWriteJob newJob = new ReadWriteJob(); + newJob.jobType = IoJobType.Rssi; + newJob.entry = null; + + if (!readWriteQueue.add(newJob)) { + Log.w(TAG, "Cannot add remote RSSI read to queue" ); + return false; + } + + performNextIOThreaded(); + return true; + } + + // This function is called from Qt thread + public synchronized boolean connect() { + BluetoothDevice mRemoteGattDevice; + + if (mBluetoothAdapter == null) { + Log.w(TAG, "Cannot connect, no bluetooth adapter"); + return false; + } + + try { + mRemoteGattDevice = mBluetoothAdapter.getRemoteDevice(mRemoteGattAddress); + } catch (IllegalArgumentException ex) { + Log.w(TAG, "Remote address is not valid: " + mRemoteGattAddress); + return false; + } + + /* The required connectGatt function is already available in SDK v26, but Android 8.0 + * contains a race condition in the Changed callback such that it can return the value that + * was written. This is fixed in Android 8.1, which matches SDK v27. */ + if (Build.VERSION.SDK_INT >= 27) { + HandlerThread handlerThread = new HandlerThread("QtBluetoothLEHandlerThread"); + handlerThread.start(); + mHandler = new Handler(handlerThread.getLooper()); + + Class[] args = new Class[6]; + args[0] = android.content.Context.class; + args[1] = boolean.class; + args[2] = android.bluetooth.BluetoothGattCallback.class; + args[3] = int.class; + args[4] = int.class; + args[5] = android.os.Handler.class; + + try { + Method connectMethod = mRemoteGattDevice.getClass().getDeclaredMethod("connectGatt", args); + if (connectMethod != null) { + mBluetoothGatt = (BluetoothGatt) connectMethod.invoke(mRemoteGattDevice, qtContext, false, + gattCallback, 2 /* TRANSPORT_LE */, 1 /*BluetoothDevice.PHY_LE_1M*/, mHandler); + Log.w(TAG, "Using Android v26 BluetoothDevice.connectGatt()"); + } + } catch (Exception ex) { + Log.w(TAG, "connectGatt() v26 not available"); + ex.printStackTrace(); + } + + if (mBluetoothGatt == null) { + mHandler.getLooper().quitSafely(); + mHandler = null; + } + } + + if (mBluetoothGatt == null) { + try { + //This API element is currently: greylist-max-o (API level 27), reflection, allowed + //It may change in the future + Class[] constr_args = new Class[5]; + constr_args[0] = android.bluetooth.BluetoothGattService.class; + constr_args[1] = java.util.UUID.class; + constr_args[2] = int.class; + constr_args[3] = int.class; + constr_args[4] = int.class; + mCharacteristicConstructor = BluetoothGattCharacteristic.class.getDeclaredConstructor(constr_args); + mCharacteristicConstructor.setAccessible(true); + } catch (NoSuchMethodException ex) { + Log.w(TAG, "Unable get characteristic constructor. Buffer race condition are possible"); + /* For some reason we don't get the private BluetoothGattCharacteristic ctor. + This means that we cannot protect ourselves from issues where concurrent + read and write operations on the same char can overwrite each others buffer. + Nevertheless we continue with best effort. + */ + } + try { + mBluetoothGatt = + mRemoteGattDevice.connectGatt(qtContext, false, + gattCallback, 2 /* TRANSPORT_LE */); + } catch (IllegalArgumentException ex) { + Log.w(TAG, "Gatt connection failed"); + ex.printStackTrace(); + } + } + return mBluetoothGatt != null; + } + + // This function is called from Qt thread + public synchronized void disconnect() { + if (mBluetoothGatt == null) + return; + + mBluetoothGatt.disconnect(); + } + + // This function is called from Qt thread + public synchronized boolean discoverServices() + { + return mBluetoothGatt != null && mBluetoothGatt.discoverServices(); + } + + private enum GattEntryType + { + Service, Characteristic, CharacteristicValue, Descriptor + } + private class GattEntry + { + public GattEntryType type; + public boolean valueKnown = false; + public BluetoothGattService service = null; + public BluetoothGattCharacteristic characteristic = null; + public BluetoothGattDescriptor descriptor = null; + /* + * endHandle defined for GattEntryType.Service and GattEntryType.CharacteristicValue + * If the type is service this is the value of the last Gatt entry belonging to the very + * same service. If the type is a char value it is the entries index inside + * the "entries" list. + */ + public int endHandle = -1; + // pointer back to the handle that describes the service that this GATT entry belongs to + public int associatedServiceHandle; + } + + private enum IoJobType + { + Read, Write, Mtu, + SkippedRead, Rssi + // a skipped read is a read which is not executed + // introduced in Qt 6.2 to skip reads without changing service discovery logic + } + + private class ReadWriteJob + { + public GattEntry entry; + public byte[] newValue; + public int requestedWriteType; + public IoJobType jobType; + } + + // service uuid -> service handle mapping (there can be more than one service with same uuid) + private final Hashtable> uuidToEntry = new Hashtable>(100); + // index into array is equivalent to handle id + private final ArrayList entries = new ArrayList(100); + //backlog of to be discovered services + private final LinkedList servicesToBeDiscovered = new LinkedList(); + + + private final LinkedList readWriteQueue = new LinkedList(); + private ReadWriteJob pendingJob; + + /* + Internal helper function + Returns the handle id for the given characteristic; otherwise returns -1. + + Note that this is the Java handle. The Qt handle is the Java handle +1. + */ + private int handleForCharacteristic(BluetoothGattCharacteristic characteristic) + { + if (characteristic == null) + return -1; + + List handles = uuidToEntry.get(characteristic.getService().getUuid()); + if (handles == null || handles.isEmpty()) + return -1; + + //TODO for now we assume we always want the first service in case of uuid collision + int serviceHandle = handles.get(0); + + try { + GattEntry entry; + for (int i = serviceHandle+1; i < entries.size(); i++) { + entry = entries.get(i); + if (entry == null) + continue; + + switch (entry.type) { + case Descriptor: + case CharacteristicValue: + continue; + case Service: + break; + case Characteristic: + if (entry.characteristic == characteristic) + return i; + break; + } + } + } catch (IndexOutOfBoundsException ex) { /*nothing*/ } + return -1; + } + + /* + Internal helper function + Returns the handle id for the given descriptor; otherwise returns -1. + + Note that this is the Java handle. The Qt handle is the Java handle +1. + */ + private int handleForDescriptor(BluetoothGattDescriptor descriptor) + { + if (descriptor == null) + return -1; + + List handles = uuidToEntry.get(descriptor.getCharacteristic().getService().getUuid()); + if (handles == null || handles.isEmpty()) + return -1; + + //TODO for now we assume we always want the first service in case of uuid collision + int serviceHandle = handles.get(0); + + try { + GattEntry entry; + for (int i = serviceHandle+1; i < entries.size(); i++) { + entry = entries.get(i); + if (entry == null) + continue; + + switch (entry.type) { + case Characteristic: + case CharacteristicValue: + continue; + case Service: + break; + case Descriptor: + if (entry.descriptor == descriptor) + return i; + break; + } + } + } catch (IndexOutOfBoundsException ignored) { } + return -1; + } + + // This function is called from Qt thread (indirectly) + private void populateHandles() + { + // We introduce the notion of artificial handles. While GATT handles + // are not exposed on Android they help to quickly identify GATT attributes + // on the C++ side. The Qt Api will not expose the handles + GattEntry entry = null; + List services = mBluetoothGatt.getServices(); + for (BluetoothGattService service: services) { + GattEntry serviceEntry = new GattEntry(); + serviceEntry.type = GattEntryType.Service; + serviceEntry.service = service; + entries.add(serviceEntry); + + // remember handle for the service for later update + int serviceHandle = entries.size() - 1; + //point to itself -> mostly done for consistence reasons with other entries + serviceEntry.associatedServiceHandle = serviceHandle; + + //some devices may have more than one service with the same uuid + List old = uuidToEntry.get(service.getUuid()); + if (old == null) + old = new ArrayList(); + old.add(entries.size()-1); + uuidToEntry.put(service.getUuid(), old); + + // add all characteristics + List charList = service.getCharacteristics(); + for (BluetoothGattCharacteristic characteristic: charList) { + entry = new GattEntry(); + entry.type = GattEntryType.Characteristic; + entry.characteristic = characteristic; + entry.associatedServiceHandle = serviceHandle; + //entry.endHandle = .. undefined + entries.add(entry); + + // this emulates GATT value attributes + entry = new GattEntry(); + entry.type = GattEntryType.CharacteristicValue; + entry.associatedServiceHandle = serviceHandle; + entry.endHandle = entries.size(); // special case -> current index in entries list + entries.add(entry); + + // add all descriptors + List descList = characteristic.getDescriptors(); + for (BluetoothGattDescriptor desc: descList) { + entry = new GattEntry(); + entry.type = GattEntryType.Descriptor; + entry.descriptor = desc; + entry.associatedServiceHandle = serviceHandle; + //entry.endHandle = .. undefined + entries.add(entry); + } + } + + // update endHandle of current service + serviceEntry.endHandle = entries.size() - 1; + } + + entries.trimToSize(); + } + + private void resetData() + { + uuidToEntry.clear(); + entries.clear(); + servicesToBeDiscovered.clear(); + + // kill all timeout handlers + timeoutHandler.removeCallbacksAndMessages(null); + handleForTimeout.set(HANDLE_FOR_RESET); + + readWriteQueue.clear(); + pendingJob = null; + } + + // This function is called from Qt thread + public synchronized boolean discoverServiceDetails(String serviceUuid, boolean fullDiscovery) + { + Log.d(TAG, "Discover service details for: " + serviceUuid + ", fullDiscovery: " + + fullDiscovery + ", BluetoothGatt: " + (mBluetoothGatt != null)); + try { + if (mBluetoothGatt == null) + return false; + + if (entries.isEmpty()) + populateHandles(); + + GattEntry entry; + int serviceHandle; + try { + UUID service = UUID.fromString(serviceUuid); + List handles = uuidToEntry.get(service); + if (handles == null || handles.isEmpty()) { + Log.w(TAG, "Unknown service uuid for current device: " + service.toString()); + return false; + } + + //TODO for now we assume we always want the first service in case of uuid collision + serviceHandle = handles.get(0); + entry = entries.get(serviceHandle); + if (entry == null) { + Log.w(TAG, "Service with UUID " + service.toString() + " not found"); + return false; + } + } catch (IllegalArgumentException ex) { + //invalid UUID string passed + Log.w(TAG, "Cannot parse given UUID"); + return false; + } + + if (entry.type != GattEntryType.Service) { + Log.w(TAG, "Given UUID is not a service UUID: " + serviceUuid); + return false; + } + + // current service already discovered or under investigation + if (entry.valueKnown || servicesToBeDiscovered.contains(serviceHandle)) { + Log.w(TAG, "Service already known or to be discovered"); + return true; + } + + servicesToBeDiscovered.add(serviceHandle); + scheduleServiceDetailDiscovery(serviceHandle, fullDiscovery); + performNextIOThreaded(); + } catch (Exception ex) { + ex.printStackTrace(); + return false; + } + + return true; + } + + /* + Returns the uuids of the services included by the given service. Otherwise returns null. + This function is called from Qt thread + */ + public synchronized String includedServices(String serviceUuid) + { + if (mBluetoothGatt == null) + return null; + + UUID uuid; + try { + uuid = UUID.fromString(serviceUuid); + } catch (Exception ex) { + ex.printStackTrace(); + return null; + } + + //TODO Breaks in case of two services with same uuid + BluetoothGattService service = mBluetoothGatt.getService(uuid); + if (service == null) + return null; + + final List includes = service.getIncludedServices(); + if (includes.isEmpty()) + return null; + + StringBuilder builder = new StringBuilder(); + for (BluetoothGattService includedService: includes) { + builder.append(includedService.getUuid().toString()).append(" "); //space is separator + } + + return builder.toString(); + } + + private synchronized void finishCurrentServiceDiscovery(int handleDiscoveredService) + { + Log.w(TAG, "Finished current discovery for service handle " + handleDiscoveredService); + GattEntry discoveredService = entries.get(handleDiscoveredService); + discoveredService.valueKnown = true; + try { + servicesToBeDiscovered.removeFirst(); + } catch (NoSuchElementException ex) { + Log.w(TAG, "Expected queued service but didn't find any"); + } + + leServiceDetailDiscoveryFinished(qtObject, discoveredService.service.getUuid().toString(), + handleDiscoveredService + 1, discoveredService.endHandle + 1); + } + + // Executes under "this" client mutex. Returns true + // if no actual MTU exchange is initiated + private boolean executeMtuExchange() + { + if (mBluetoothGatt.requestMtu(MAX_MTU)) { + Log.w(TAG, "MTU change initiated"); + return false; + } else { + Log.w(TAG, "MTU change request failed"); + } + + Log.w(TAG, "Assuming default MTU value of 23 bytes"); + mSupportedMtu = DEFAULT_MTU; + return true; + } + + private boolean executeRemoteRssiRead() + { + if (mBluetoothGatt.readRemoteRssi()) { + Log.d(TAG, "RSSI read initiated"); + return false; + } + Log.w(TAG, "Initiating remote RSSI read failed"); + leRemoteRssiRead(qtObject, 0, false); + return true; + } + + /* + * Already executed in GattCallback so executed by the HandlerThread. No need to + * post it to the Hander. + */ + private void scheduleMtuExchange() { + ReadWriteJob newJob = new ReadWriteJob(); + newJob.jobType = IoJobType.Mtu; + newJob.entry = null; + + readWriteQueue.add(newJob); + + performNextIO(); + } + + /* + Internal Helper function for discoverServiceDetails() + + Adds all Gatt entries for the given service to the readWriteQueue to be discovered. + This function only ever adds read requests to the queue. + + */ + private void scheduleServiceDetailDiscovery(int serviceHandle, boolean fullDiscovery) + { + GattEntry serviceEntry = entries.get(serviceHandle); + final int endHandle = serviceEntry.endHandle; + + if (serviceHandle == endHandle) { + Log.w(TAG, "scheduleServiceDetailDiscovery: service is empty; nothing to discover"); + finishCurrentServiceDiscovery(serviceHandle); + return; + } + + // serviceHandle + 1 -> ignore service handle itself + for (int i = serviceHandle + 1; i <= endHandle; i++) { + GattEntry entry = entries.get(i); + + if (entry.type == GattEntryType.Service) { + // should not really happen unless endHandle is wrong + Log.w(TAG, "scheduleServiceDetailDiscovery: wrong endHandle"); + return; + } + + ReadWriteJob newJob = new ReadWriteJob(); + newJob.entry = entry; + if (fullDiscovery) { + newJob.jobType = IoJobType.Read; + } else { + newJob.jobType = IoJobType.SkippedRead; + } + + final boolean result = readWriteQueue.add(newJob); + if (!result) + Log.w(TAG, "Cannot add service discovery job for " + serviceEntry.service.getUuid() + + " on item " + entry.type); + } + } + + /*************************************************************/ + /* Write Characteristics */ + /* This function is called from Qt thread */ + /*************************************************************/ + + public synchronized boolean writeCharacteristic(int charHandle, byte[] newValue, + int writeMode) + { + if (mBluetoothGatt == null) + return false; + + GattEntry entry; + try { + entry = entries.get(charHandle-1); //Qt always uses handles+1 + } catch (IndexOutOfBoundsException ex) { + ex.printStackTrace(); + return false; + } + + ReadWriteJob newJob = new ReadWriteJob(); + newJob.newValue = newValue; + newJob.entry = entry; + newJob.jobType = IoJobType.Write; + + // writeMode must be in sync with QLowEnergyService::WriteMode + switch (writeMode) { + case 1: //WriteWithoutResponse + newJob.requestedWriteType = BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE; + break; + case 2: //WriteSigned + newJob.requestedWriteType = BluetoothGattCharacteristic.WRITE_TYPE_SIGNED; + break; + default: + newJob.requestedWriteType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT; + break; + } + + boolean result; + result = readWriteQueue.add(newJob); + + if (!result) { + Log.w(TAG, "Cannot add characteristic write request for " + charHandle + " to queue" ); + return false; + } + + performNextIOThreaded(); + return true; + } + + /*************************************************************/ + /* Write Descriptors */ + /* This function is called from Qt thread */ + /*************************************************************/ + + public synchronized boolean writeDescriptor(int descHandle, byte[] newValue) + { + if (mBluetoothGatt == null) + return false; + + GattEntry entry; + try { + entry = entries.get(descHandle-1); //Qt always uses handles+1 + } catch (IndexOutOfBoundsException ex) { + ex.printStackTrace(); + return false; + } + + ReadWriteJob newJob = new ReadWriteJob(); + newJob.newValue = newValue; + newJob.entry = entry; + newJob.requestedWriteType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT; + newJob.jobType = IoJobType.Write; + + boolean result; + result = readWriteQueue.add(newJob); + + if (!result) { + Log.w(TAG, "Cannot add descriptor write request for " + descHandle + " to queue" ); + return false; + } + + performNextIOThreaded(); + return true; + } + + /*************************************************************/ + /* Read Characteristics */ + /* This function is called from Qt thread */ + /*************************************************************/ + + public synchronized boolean readCharacteristic(int charHandle) + { + if (mBluetoothGatt == null) + return false; + + GattEntry entry; + try { + entry = entries.get(charHandle-1); //Qt always uses handles+1 + } catch (IndexOutOfBoundsException ex) { + ex.printStackTrace(); + return false; + } + + ReadWriteJob newJob = new ReadWriteJob(); + newJob.entry = entry; + newJob.jobType = IoJobType.Read; + + boolean result; + result = readWriteQueue.add(newJob); + + if (!result) { + Log.w(TAG, "Cannot add characteristic read request for " + charHandle + " to queue" ); + return false; + } + + performNextIOThreaded(); + return true; + } + + // This function is called from Qt thread + public synchronized boolean readDescriptor(int descHandle) + { + if (mBluetoothGatt == null) + return false; + + GattEntry entry; + try { + entry = entries.get(descHandle-1); //Qt always uses handles+1 + } catch (IndexOutOfBoundsException ex) { + ex.printStackTrace(); + return false; + } + + ReadWriteJob newJob = new ReadWriteJob(); + newJob.entry = entry; + newJob.jobType = IoJobType.Read; + + boolean result; + result = readWriteQueue.add(newJob); + + if (!result) { + Log.w(TAG, "Cannot add descriptor read request for " + descHandle + " to queue" ); + return false; + } + + performNextIOThreaded(); + return true; + } + + // Called by TimeoutRunnable if the current I/O job timed out. + // By the time we reach this point the handleForTimeout counter has already been reset + // and the regular responses will be blocked off. + private synchronized void interruptCurrentIO(int handle) + { + //unlock the queue for next item + pendingJob = null; + + performNextIOThreaded(); + + if (handle == HANDLE_FOR_MTU_EXCHANGE || handle == HANDLE_FOR_RSSI_READ) + return; + + try { + GattEntry entry = entries.get(handle); + if (entry == null) + return; + if (entry.valueKnown) + return; + entry.valueKnown = true; + + GattEntry serviceEntry = entries.get(entry.associatedServiceHandle); + if (serviceEntry != null && serviceEntry.endHandle == handle) + finishCurrentServiceDiscovery(entry.associatedServiceHandle); + } catch (IndexOutOfBoundsException outOfBounds) { + Log.w(TAG, "interruptCurrentIO(): Unknown gatt entry, index: " + + handle + " size: " + entries.size()); + } + } + + /* + Wrapper around performNextIO() ensuring that performNextIO() is executed inside + the mHandler/mHandlerThread if it exists. + */ + private void performNextIOThreaded() + { + if (mHandler != null) { + mHandler.post(new Runnable() { + @Override + public void run() { + performNextIO(); + } + }); + } else { + performNextIO(); + } + } + + /* + The queuing is required because two writeCharacteristic/writeDescriptor calls + cannot execute at the same time. The second write must happen after the + previous write has finished with on(Characteristic|Descriptor)Write(). + */ + private synchronized void performNextIO() + { + Log.d(TAG, "Perform next BTLE IO, job queue size: " + readWriteQueue.size() + + ", a job is pending: " + (pendingJob != null) + ", BluetoothGatt: " + + (mBluetoothGatt != null)); + + if (mBluetoothGatt == null) + return; + + boolean skip = false; + final ReadWriteJob nextJob; + int handle = HANDLE_FOR_RESET; + + if (readWriteQueue.isEmpty() || pendingJob != null) + return; + + nextJob = readWriteQueue.remove(); + // MTU requests and RSSI reads are special cases + if (nextJob.jobType == IoJobType.Mtu) { + handle = HANDLE_FOR_MTU_EXCHANGE; + } else if (nextJob.jobType == IoJobType.Rssi) { + handle = HANDLE_FOR_RSSI_READ; + } else { + switch (nextJob.entry.type) { + case Characteristic: + handle = handleForCharacteristic(nextJob.entry.characteristic); + break; + case Descriptor: + handle = handleForDescriptor(nextJob.entry.descriptor); + break; + case CharacteristicValue: + handle = nextJob.entry.endHandle; + default: + break; + } + } + + // timeout handler and handleForTimeout atomic must be setup before + // executing the request. Sometimes the callback is quicker than executing the + // remainder of this function. Therefore enable the atomic early + timeoutHandler.removeCallbacksAndMessages(null); // remove any timeout handlers + handleForTimeout.set(modifiedReadWriteHandle(handle, nextJob.jobType)); + + switch (nextJob.jobType) { + case Read: + skip = executeReadJob(nextJob); + break; + case SkippedRead: + skip = true; + break; + case Write: + skip = executeWriteJob(nextJob); + break; + case Mtu: + skip = executeMtuExchange(); + case Rssi: + skip = executeRemoteRssiRead(); + break; + } + + if (skip) { + handleForTimeout.set(HANDLE_FOR_RESET); // not a pending call -> release atomic + } else { + pendingJob = nextJob; + timeoutHandler.postDelayed(new TimeoutRunnable( + modifiedReadWriteHandle(handle, nextJob.jobType)), RUNNABLE_TIMEOUT); + } + + if (nextJob.jobType != IoJobType.Mtu && nextJob.jobType != IoJobType.Rssi) { + Log.d(TAG, "Performing queued job, handle: " + handle + " " + nextJob.jobType + " (" + + (nextJob.requestedWriteType == BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE) + + ") ValueKnown: " + nextJob.entry.valueKnown + " Skipping: " + skip + + " " + nextJob.entry.type); + } + + GattEntry entry = nextJob.entry; + + if (skip) { + /* + BluetoothGatt.[read|write][Characteristic|Descriptor]() immediately + return in cases where meta data doesn't match the intended action + (e.g. trying to write to read-only char). When this happens + we have to report an error back to Qt. The error report is not required during + the initial service discovery though. + */ + if (handle > HANDLE_FOR_RESET) { + // during service discovery we do not report error but emit characteristicRead() + // any other time a failure emits serviceError() signal + + final boolean isServiceDiscovery = !entry.valueKnown; + + if (isServiceDiscovery) { + entry.valueKnown = true; + switch (entry.type) { + case Characteristic: + Log.d(TAG, + nextJob.jobType == IoJobType.Read ? "Non-readable" : "Skipped reading of" + + " characteristic " + entry.characteristic.getUuid() + + " for service " + entry.characteristic.getService().getUuid()); + leCharacteristicRead(qtObject, entry.characteristic.getService().getUuid().toString(), + handle + 1, entry.characteristic.getUuid().toString(), + entry.characteristic.getProperties(), null); + break; + case Descriptor: + Log.d(TAG, + nextJob.jobType == IoJobType.Read ? "Non-readable" : "Skipped reading of" + + " descriptor " + entry.descriptor.getUuid() + + " for service/char " + entry.descriptor.getCharacteristic().getService().getUuid() + + "/" + entry.descriptor.getCharacteristic().getUuid()); + leDescriptorRead(qtObject, + entry.descriptor.getCharacteristic().getService().getUuid().toString(), + entry.descriptor.getCharacteristic().getUuid().toString(), + handle + 1, entry.descriptor.getUuid().toString(), + null); + break; + case CharacteristicValue: + // for more details see scheduleServiceDetailDiscovery(int, boolean) + break; + case Service: + Log.w(TAG, "Scheduling of Service Gatt entry for service discovery should never happen."); + break; + } + + // last entry of current discovery run? + try { + GattEntry serviceEntry = entries.get(entry.associatedServiceHandle); + if (serviceEntry.endHandle == handle) + finishCurrentServiceDiscovery(entry.associatedServiceHandle); + } catch (IndexOutOfBoundsException outOfBounds) { + Log.w(TAG, "performNextIO(): Unknown service for entry, index: " + + entry.associatedServiceHandle + " size: " + entries.size()); + } + } else { + int errorCode = 0; + + // The error codes below must be in sync with QLowEnergyService::ServiceError + if (nextJob.jobType == IoJobType.Read) { + errorCode = (entry.type == GattEntryType.Characteristic) ? + 5 : 6; // CharacteristicReadError : DescriptorReadError + } else { + errorCode = (entry.type == GattEntryType.Characteristic) ? + 2 : 3; // CharacteristicWriteError : DescriptorWriteError + } + + leServiceError(qtObject, handle + 1, errorCode); + } + } + + performNextIO(); + } + } + + private BluetoothGattCharacteristic cloneChararacteristic(BluetoothGattCharacteristic other) { + try { + return (BluetoothGattCharacteristic) mCharacteristicConstructor.newInstance(other.getService(), + other.getUuid(), other.getInstanceId(), other.getProperties(), other.getPermissions()); + } catch (Exception ex) { + Log.w(TAG, "Cloning characteristic failed!" + ex); + return null; + } + } + + // Returns true if nextJob should be skipped. + private boolean executeWriteJob(ReadWriteJob nextJob) + { + boolean result; + switch (nextJob.entry.type) { + case Characteristic: + if (Build.VERSION.SDK_INT >= 33) { + int writeResult = mBluetoothGatt.writeCharacteristic( + nextJob.entry.characteristic, nextJob.newValue, nextJob.requestedWriteType); + return (writeResult != BluetoothStatusCodes.SUCCESS); + } + if (mHandler != null || mCharacteristicConstructor == null) { + if (nextJob.entry.characteristic.getWriteType() != nextJob.requestedWriteType) { + nextJob.entry.characteristic.setWriteType(nextJob.requestedWriteType); + } + result = nextJob.entry.characteristic.setValue(nextJob.newValue); + return !result || !mBluetoothGatt.writeCharacteristic(nextJob.entry.characteristic); + } else { + BluetoothGattCharacteristic orig = nextJob.entry.characteristic; + BluetoothGattCharacteristic tmp = cloneChararacteristic(orig); + if (tmp == null) + return true; + tmp.setWriteType(nextJob.requestedWriteType); + return !tmp.setValue(nextJob.newValue) || !mBluetoothGatt.writeCharacteristic(tmp); + } + case Descriptor: + if (nextJob.entry.descriptor.getUuid().compareTo(clientCharacteristicUuid) == 0) { + /* + For some reason, Android splits characteristic notifications + into two operations. BluetoothGatt.enableCharacteristicNotification + ensures the local Bluetooth stack forwards the notifications. In addition, + BluetoothGattDescriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE) + must be written to the peripheral. + */ + + + /* There is no documentation on indication behavior. The assumption is + that when indication or notification are requested we call + BluetoothGatt.setCharacteristicNotification. Furthermore it is assumed + indications are send via onCharacteristicChanged too and Android itself + will do the confirmation required for an indication as per + Bluetooth spec Vol 3, Part G, 4.11 . If neither of the two bits are set + we disable the signals. + */ + boolean enableNotifications = false; + int value = (nextJob.newValue[0] & 0xff); + // first or second bit must be set + if (((value & 0x1) == 1) || (((value >> 1) & 0x1) == 1)) { + enableNotifications = true; + } + + result = mBluetoothGatt.setCharacteristicNotification( + nextJob.entry.descriptor.getCharacteristic(), enableNotifications); + if (!result) { + Log.w(TAG, "Cannot set characteristic notification"); + //we continue anyway to ensure that we write the requested value + //to the device + } + + Log.d(TAG, "Enable notifications: " + enableNotifications); + } + + if (Build.VERSION.SDK_INT >= 33) { + int writeResult = mBluetoothGatt.writeDescriptor( + nextJob.entry.descriptor, nextJob.newValue); + return (writeResult != BluetoothStatusCodes.SUCCESS); + } + result = nextJob.entry.descriptor.setValue(nextJob.newValue); + if (!result || !mBluetoothGatt.writeDescriptor(nextJob.entry.descriptor)) + return true; + + break; + case Service: + case CharacteristicValue: + return true; + } + return false; + } + + // Returns true if nextJob should be skipped. + private boolean executeReadJob(ReadWriteJob nextJob) + { + boolean result; + switch (nextJob.entry.type) { + case Characteristic: + try { + result = mBluetoothGatt.readCharacteristic(nextJob.entry.characteristic); + } catch (java.lang.SecurityException se) { + // QTBUG-59917 -> HID services cause problems since Android 5.1 + se.printStackTrace(); + result = false; + } + if (!result) + return true; // skip + break; + case Descriptor: + try { + result = mBluetoothGatt.readDescriptor(nextJob.entry.descriptor); + } catch (java.lang.SecurityException se) { + // QTBUG-59917 -> HID services cause problems since Android 5.1 + se.printStackTrace(); + result = false; + } + if (!result) + return true; // skip + break; + case Service: + return true; + case CharacteristicValue: + return true; //skip + } + return false; + } + + /* + * Modifies and returns the given \a handle such that the job + * \a type is encoded into the returned handle. Hereby we take advantage of the fact that + * a Bluetooth Low Energy handle is only 16 bit. The handle will be the bottom two bytes + * and the job type will be in the top 2 bytes. + * + * top 2 bytes + * - 0x01 -> Read Job + * - 0x02 -> Write Job + * + * This is done in connection with handleForTimeout and assists in the process of + * detecting accidental interruption by the timeout handler. + * If two requests for the same handle are scheduled behind each other there is the + * theoretical chance that the first request comes back normally while the second request + * is interrupted by the timeout handler. This risk still exists but this function ensures that + * at least back to back requests of differing types cannot affect each other via the timeout + * handler. + */ + private int modifiedReadWriteHandle(int handle, IoJobType type) + { + int modifiedHandle = handle; + // ensure we have 16bit handle only + if (handle > 0xFFFF) + Log.w(TAG, "Invalid handle"); + + modifiedHandle = (modifiedHandle & 0xFFFF); + + switch (type) { + case Write: + modifiedHandle = (modifiedHandle | 0x00010000); + break; + case Read: + modifiedHandle = (modifiedHandle | 0x00020000); + break; + case Mtu: + modifiedHandle = HANDLE_FOR_MTU_EXCHANGE; + break; + case Rssi: + modifiedHandle = HANDLE_FOR_RSSI_READ; + break; + } + + return modifiedHandle; + } + + // This function is called from Qt thread + public synchronized boolean requestConnectionUpdatePriority(double minimalInterval) + { + if (mBluetoothGatt == null) + return false; + + int requestPriority = 0; // BluetoothGatt.CONNECTION_PRIORITY_BALANCED + if (minimalInterval < 30) + requestPriority = 1; // BluetoothGatt.CONNECTION_PRIORITY_HIGH + else if (minimalInterval > 100) + requestPriority = 2; //BluetoothGatt.CONNECTION_PRIORITY_LOW_POWER + + try { + return mBluetoothGatt.requestConnectionPriority(requestPriority); + } catch (IllegalArgumentException ex) { + Log.w(TAG, "Connection update priority out of range: " + requestPriority); + return false; + } + } + + public native void leConnectionStateChange(long qtObject, int wasErrorTransition, int newState); + public native void leMtuChanged(long qtObject, int mtu); + public native void leRemoteRssiRead(long qtObject, int rssi, boolean success); + public native void leServicesDiscovered(long qtObject, int errorCode, String uuidList); + public native void leServiceDetailDiscoveryFinished(long qtObject, final String serviceUuid, + int startHandle, int endHandle); + public native void leCharacteristicRead(long qtObject, String serviceUuid, + int charHandle, String charUuid, + int properties, byte[] data); + public native void leDescriptorRead(long qtObject, String serviceUuid, String charUuid, + int descHandle, String descUuid, byte[] data); + public native void leCharacteristicWritten(long qtObject, int charHandle, byte[] newData, + int errorCode); + public native void leDescriptorWritten(long qtObject, int charHandle, byte[] newData, + int errorCode); + public native void leCharacteristicChanged(long qtObject, int charHandle, byte[] newData); + public native void leServiceError(long qtObject, int attributeHandle, int errorCode); +} + diff --git a/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLEServer.java b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLEServer.java new file mode 100644 index 0000000..9460140 --- /dev/null +++ b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLEServer.java @@ -0,0 +1,989 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +package org.qtproject.qt.android.bluetooth; + +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothGattCharacteristic; +import android.bluetooth.BluetoothGattDescriptor; +import android.bluetooth.BluetoothGattService; +import android.content.Context; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattServer; +import android.bluetooth.BluetoothGattServerCallback; +import android.bluetooth.BluetoothManager; +import android.bluetooth.BluetoothProfile; +import android.bluetooth.le.AdvertiseCallback; +import android.bluetooth.le.AdvertiseData; +import android.bluetooth.le.AdvertiseData.Builder; +import android.bluetooth.le.AdvertiseSettings; +import android.bluetooth.le.BluetoothLeAdvertiser; +import android.os.ParcelUuid; +import android.os.Build; +import android.util.Log; +import android.util.Pair; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.HashMap; +import java.util.UUID; + +public class QtBluetoothLEServer { + private static final String TAG = "QtBluetoothGattServer"; + + /* Pointer to the Qt object that "owns" the Java object */ + @SuppressWarnings({"CanBeFinal", "WeakerAccess"}) + long qtObject = 0; + @SuppressWarnings("WeakerAccess") + + private Context qtContext = null; + + // Bluetooth members + private BluetoothAdapter mBluetoothAdapter = null; + private BluetoothManager mBluetoothManager = null; + private BluetoothGattServer mGattServer = null; + private BluetoothLeAdvertiser mLeAdvertiser = null; + + private ArrayList mPendingServiceAdditions = + new ArrayList(); + + private String mRemoteName = ""; + // This function is called from Qt thread + public synchronized String remoteName() { + return mRemoteName; + } + + private String mRemoteAddress = ""; + // This function is called from Qt thread + public synchronized String remoteAddress() { + return mRemoteAddress; + } + + // BT Core v5.3, 5.2.1, Vol 3, Part G + private static final int DEFAULT_LE_ATT_MTU = 23; + // Holds the currently supported/used MTU + private int mSupportedMtu = DEFAULT_LE_ATT_MTU; + // Implementation defined limit + private static final int MAX_PENDING_WRITE_COUNT = 1024; + // BT Core v5.3, 3.4.6.1, Vol 3, Part F + private static final int GATT_ERROR_PREPARE_QUEUE_FULL = 0x9; + // BT Core v5.3, 3.2.9, Vol 3, Part F + private static final int BTLE_MAX_ATTRIBUTE_VALUE_SIZE = 512; + + // The class stores queued writes from the remote device. The writes are + // executed later when instructed to do so by onExecuteWrite() callback. + private class WriteEntry { + WriteEntry(BluetoothDevice remoteDevice, Object target) { + this.remoteDevice = remoteDevice; + this.target = target; + this.writes = new ArrayList>(); + } + // Returns true if this is a proper entry for given device + target + public boolean match(BluetoothDevice device, Object target) { + return remoteDevice.equals(device) && target.equals(target); + } + public final BluetoothDevice remoteDevice; // Device that issued the writes + public final Object target; // Characteristic or Descriptor + public final List> writes; // Value, offset + } + private final List mPendingPreparedWrites = new ArrayList<>(); + + // Helper function to clear the pending writes of a remote device. If the provided device + // is null, all writes are cleared + private void clearPendingPreparedWrites(Object device) { + if (device == null) + mPendingPreparedWrites.clear(); + ListIterator iterator = mPendingPreparedWrites.listIterator(); + while (iterator.hasNext()) { + if (iterator.next().remoteDevice.equals(device)) + iterator.remove(); + } + } + + // The function adds a 'prepared write' entry to target's queue. If the "target + device" + // didn't have a queue before (this being the first write), the queue is created. + // Targets must be either descriptors or characteristics. + private int addPendingPreparedWrite(BluetoothDevice device, Object target, + int offset, byte[] value) { + WriteEntry entry = null; + int currentWriteCount = 0; + + // Try to find an existing matching entry. Also while looping, count + // the total number of writes so far in order to know if we exceed the + // write queue size we have set for ourselves + for (WriteEntry e : mPendingPreparedWrites) { + if (e.match(device, target)) + entry = e; + currentWriteCount += e.writes.size(); + } + + // BT Core v5.3, 3.4.6.1, Vol 3, Part F + if (currentWriteCount > MAX_PENDING_WRITE_COUNT) { + Log.w(TAG, "Prepared write queue is full, returning an error."); + return GATT_ERROR_PREPARE_QUEUE_FULL; + } + + // If no matching entry, create a new one. This means this is the first prepared + // write request to this "device + target" combination + if (entry == null) + mPendingPreparedWrites.add(entry = new WriteEntry(device, target)); + + // Append the newly received chunk of data along with its offset + entry.writes.add(new Pair(value, offset)); + return BluetoothGatt.GATT_SUCCESS; + } + + /* + As per Bluetooth specification each connected device can have individual and persistent + Client characteristic configurations (see Bluetooth Spec 5.0 Vol 3 Part G 3.3.3.3) + This class manages the existing configurrations. + */ + private class ClientCharacteristicManager { + private final HashMap> notificationStore = new HashMap>(); + + private class Entry { + BluetoothDevice device = null; + byte[] value = null; + boolean isConnected = false; + } + + public void insertOrUpdate(BluetoothGattCharacteristic characteristic, + BluetoothDevice device, byte[] newValue) + { + if (notificationStore.containsKey(characteristic)) { + + List entries = notificationStore.get(characteristic); + for (int i = 0; i < entries.size(); i++) { + if (entries.get(i).device.equals(device)) { + Entry e = entries.get(i); + e.value = newValue; + entries.set(i, e); + return; + } + } + + // not match so far -> add device to list + Entry e = new Entry(); + e.device = device; + e.value = newValue; + e.isConnected = true; + entries.add(e); + return; + } + + // new characteristic + Entry e = new Entry(); + e.device = device; + e.value = newValue; + e.isConnected = true; + List list = new LinkedList(); + list.add(e); + notificationStore.put(characteristic, list); + } + + /* + Marks client characteristic configuration entries as (in)active based the associated + devices general connectivity state. + This function avoids that existing configurations are not acted + upon when the associated device is not connected. + */ + public void markDeviceConnectivity(BluetoothDevice device, boolean isConnected) + { + final Iterator keys = notificationStore.keySet().iterator(); + while (keys.hasNext()) { + final BluetoothGattCharacteristic characteristic = keys.next(); + final List entries = notificationStore.get(characteristic); + if (entries == null) + continue; + + ListIterator charConfig = entries.listIterator(); + while (charConfig.hasNext()) { + Entry e = charConfig.next(); + if (e.device.equals(device)) + e.isConnected = isConnected; + } + } + } + + // Returns list of all BluetoothDevices which require notification or indication. + // No match returns an empty list. + List getToBeUpdatedDevices(BluetoothGattCharacteristic characteristic) + { + ArrayList result = new ArrayList(); + if (!notificationStore.containsKey(characteristic)) + return result; + + final ListIterator iter = notificationStore.get(characteristic).listIterator(); + while (iter.hasNext()) + result.add(iter.next().device); + + return result; + } + + // Returns null if no match; otherwise the configured actual client characteristic + // configuration value + byte[] valueFor(BluetoothGattCharacteristic characteristic, BluetoothDevice device) + { + if (!notificationStore.containsKey(characteristic)) + return null; + + List entries = notificationStore.get(characteristic); + for (int i = 0; i < entries.size(); i++) { + final Entry entry = entries.get(i); + if (entry.device.equals(device) && entry.isConnected == true) + return entries.get(i).value; + } + + return null; + } + } + + private static final UUID CLIENT_CHARACTERISTIC_CONFIGURATION_UUID = UUID + .fromString("00002902-0000-1000-8000-00805f9b34fb"); + ClientCharacteristicManager clientCharacteristicManager = new ClientCharacteristicManager(); + + public QtBluetoothLEServer(Context context) + { + qtContext = context; + if (qtContext == null) { + Log.w(TAG, "Missing context object. Peripheral role disabled."); + return; + } + + mBluetoothManager = + (BluetoothManager) qtContext.getSystemService(Context.BLUETOOTH_SERVICE); + if (mBluetoothManager == null) { + Log.w(TAG, "Bluetooth service not available. Peripheral role disabled."); + return; + } + + mBluetoothAdapter = mBluetoothManager.getAdapter(); + if (mBluetoothAdapter == null) { + Log.w(TAG, "Missing Bluetooth adapter. Peripheral role disabled."); + return; + } + + Log.w(TAG, "Let's do BTLE Peripheral."); + } + + // The following functions are synchronized callback handlers. The callbacks + // from Android are forwarded to these methods to synchronize member variable + // access with other threads (the Qt thread's JNI calls in particular). + // + // We use a single lock object (this server) for simplicity because: + // - Some variables may change and would thus not be suitable as locking objects but + // would require their own additional objects => overhead + // - Many accesses to shared variables are infrequent and the code paths are fast and + // deterministic meaning that long "wait times" on a lock should not happen + // - Typically several shared variables are accessed in a single code block. + // If each variable would be protected individually, the amount of (nested) locking + // would become quite unreasonable + + public synchronized void handleOnConnectionStateChange(BluetoothDevice device, + int status, int newState) + { + if (mGattServer == null) { + Log.w(TAG, "Ignoring connection state event, server is disconnected"); + return; + } + // Multiple GATT devices may be connected. Check if we still have connected + // devices or not, and set the server state accordingly. Note: it seems we get + // notifications from all GATT clients, not just from the ones interested in + // the services provided by this BT LE Server. Furthermore the list of + // currently connected devices does not appear to be in any particular order. + List connectedDevices = + mBluetoothManager.getConnectedDevices(BluetoothProfile.GATT_SERVER); + Log.w(TAG, "Device " + device + " connection state: " + newState + ", status: " + + status + ", connected devices: " + connectedDevices); + // 0 == QLowEnergyController::UnconnectedState + // 2 == QLowEnergyController::ConnectedState + int qtControllerState = connectedDevices.size() > 0 ? 2 : 0; + + switch (newState) { + case BluetoothProfile.STATE_CONNECTED: + clientCharacteristicManager.markDeviceConnectivity(device, true); + mRemoteName = device.getName(); + mRemoteAddress = device.getAddress(); + break; + case BluetoothProfile.STATE_DISCONNECTED: + clientCharacteristicManager.markDeviceConnectivity(device, false); + clearPendingPreparedWrites(device); + // Update the remoteAddress and remoteName if needed + if (device.getAddress().equals(mRemoteAddress) + && !connectedDevices.isEmpty()) { + mRemoteName = connectedDevices.get(0).getName(); + mRemoteAddress = connectedDevices.get(0).getAddress(); + } + break; + default: + // According to the API doc of this callback this should not happen + Log.w(TAG, "Unhandled connection state change: " + newState); + return; + } + + // If last client disconnected, close down the server + if (qtControllerState == 0) { // QLowEnergyController::UnconnectedState + mPendingServiceAdditions.clear(); + mGattServer.close(); + mGattServer = null; + mRemoteName = ""; + mRemoteAddress = ""; + mSupportedMtu = DEFAULT_LE_ATT_MTU; + } + + int qtErrorCode; + switch (status) { + case BluetoothGatt.GATT_SUCCESS: + qtErrorCode = 0; + break; + default: + Log.w(TAG, "Unhandled error code on peripheral connectionStateChanged: " + + status + " " + newState); + qtErrorCode = status; + break; + } + + leConnectionStateChange(qtObject, qtErrorCode, qtControllerState); + } + + public synchronized void handleOnServiceAdded(int status, BluetoothGattService service) + { + if (mGattServer == null) { + Log.w(TAG, "Ignoring service addition event, server is disconnected"); + return; + } + + Log.d(TAG, "Service " + service.getUuid().toString() + " addition result: " + status); + + // Remove the indicated service from the pending queue + ListIterator iterator = mPendingServiceAdditions.listIterator(); + while (iterator.hasNext()) { + if (iterator.next().getUuid().equals(service.getUuid())) { + iterator.remove(); + break; + } + } + + // If there are more services in the queue, add the next whose add initiation succeeds + iterator = mPendingServiceAdditions.listIterator(); + while (iterator.hasNext()) { + BluetoothGattService nextService = iterator.next(); + if (mGattServer.addService(nextService)) { + break; + } else { + Log.w(TAG, "Adding service " + nextService.getUuid().toString() + " failed"); + iterator.remove(); + } + } + } + + public synchronized void handleOnCharacteristicReadRequest(BluetoothDevice device, + int requestId, int offset, + BluetoothGattCharacteristic characteristic) + { + if (mGattServer == null) { + Log.w(TAG, "Ignoring characteristic read, server is disconnected"); + return; + } + + byte[] characteristicData = + ((QtBluetoothGattCharacteristic)characteristic).getLocalValue(); + + try { + byte[] dataArray = Arrays.copyOfRange(characteristicData, + offset, characteristicData.length); + mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, + offset, dataArray); + } catch (Exception ex) { + Log.w(TAG, "onCharacteristicReadRequest: " + requestId + " " + + offset + " " + characteristicData.length); + ex.printStackTrace(); + mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_FAILURE, + offset, null); + } + } + + public synchronized void handleOnCharacteristicWriteRequest(BluetoothDevice device, + int requestId, + BluetoothGattCharacteristic characteristic, + boolean preparedWrite, boolean responseNeeded, + int offset, byte[] value) + { + if (mGattServer == null) { + Log.w(TAG, "Ignoring characteristic write, server is disconnected"); + return; + } + Log.w(TAG, "onCharacteristicWriteRequest " + preparedWrite + " " + offset + " " + + value.length); + final int minValueLen = ((QtBluetoothGattCharacteristic)characteristic).minValueLength; + final int maxValueLen = ((QtBluetoothGattCharacteristic)characteristic).maxValueLength; + + int resultStatus = BluetoothGatt.GATT_SUCCESS; + boolean sendNotificationOrIndication = false; + + if (!preparedWrite) { // regular write + // User may have defined minimum and maximum size for the value, which + // we enforce here. If the user has not defined these limits, the default + // values 0..INT_MAX do not limit anything. + if (value.length < minValueLen || value.length > maxValueLen) { + // BT Core v 5.3, 4.9.3, Vol 3, Part G + Log.w(TAG, "onCharacteristicWriteRequest invalid char value length: " + + value.length + ", min: " + minValueLen + ", max: " + maxValueLen); + resultStatus = BluetoothGatt.GATT_INVALID_ATTRIBUTE_LENGTH; + } else if (offset == 0) { + ((QtBluetoothGattCharacteristic)characteristic).setLocalValue(value); + leServerCharacteristicChanged(qtObject, characteristic, value); + sendNotificationOrIndication = true; + } else { + // This should not really happen as per Bluetooth spec + Log.w(TAG, "onCharacteristicWriteRequest: !preparedWrite, offset " + + offset + ", Not supported"); + resultStatus = BluetoothGatt.GATT_INVALID_OFFSET; + } + } else { + // BT Core v5.3, 3.4.6, Vol 3, Part F + // This is a prepared write which is used to write characteristics larger than + // MTU. We need to record all requests and execute them in one go once + // onExecuteWrite() is received. We use a queue to remember the pending + // requests. + resultStatus = addPendingPreparedWrite(device, characteristic, offset, value); + } + + if (responseNeeded) + mGattServer.sendResponse(device, requestId, resultStatus, offset, value); + if (sendNotificationOrIndication) + sendNotificationsOrIndications(characteristic); + } + + public synchronized void handleOnDescriptorReadRequest(BluetoothDevice device, int requestId, + int offset, BluetoothGattDescriptor descriptor) + { + if (mGattServer == null) { + Log.w(TAG, "Ignoring descriptor read, server is disconnected"); + return; + } + + byte[] dataArray = ((QtBluetoothGattDescriptor)descriptor).getLocalValue(); + + try { + if (descriptor.getUuid().equals(CLIENT_CHARACTERISTIC_CONFIGURATION_UUID)) { + dataArray = clientCharacteristicManager.valueFor( + descriptor.getCharacteristic(), device); + if (dataArray == null) + dataArray = ((QtBluetoothGattDescriptor)descriptor).getLocalValue(); + } + + dataArray = Arrays.copyOfRange(dataArray, offset, dataArray.length); + mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, + offset, dataArray); + } catch (Exception ex) { + Log.w(TAG, "onDescriptorReadRequest: " + requestId + " " + + offset + " " + dataArray.length); + ex.printStackTrace(); + mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_FAILURE, + offset, null); + } + } + + public synchronized void handleOnDescriptorWriteRequest(BluetoothDevice device, int requestId, + BluetoothGattDescriptor descriptor, boolean preparedWrite, + boolean responseNeeded, int offset, byte[] value) + { + if (mGattServer == null) { + Log.w(TAG, "Ignoring descriptor write, server is disconnected"); + return; + } + + Log.w(TAG, "onDescriptorWriteRequest " + preparedWrite + " " + offset + " " + value.length); + int resultStatus = BluetoothGatt.GATT_SUCCESS; + + if (!preparedWrite) { // regular write + if (offset == 0) { + if (descriptor.getUuid().equals(CLIENT_CHARACTERISTIC_CONFIGURATION_UUID)) { + // If both IND and NTF are requested, resort to NTF only. BT + // specification does not prohibit nor mention using both, but it is + // unlikely what the client intended. Stack behaviours vary; + // Apple client-side stack does not allow this, while Bluez client-side + // stack erroneously sends this even if the developer only asked for + // the other. The 0x03 value is a bitwise combination of 0x01 and 0x02 + // as per specification: BT Core v5.3, 3.3.3.3, Vol 3, Part G + if (value[0] == 0x03) { + Log.w(TAG, "Warning: In CCC of characteristic: " + + descriptor.getCharacteristic().getUuid() + + " enabling both NTF & IND requested, enabling NTF only."); + value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE; + } + clientCharacteristicManager.insertOrUpdate( + descriptor.getCharacteristic(), + device, value); + } + ((QtBluetoothGattDescriptor)descriptor).setLocalValue(value); + leServerDescriptorWritten(qtObject, descriptor, value); + } else { + // This should not really happen as per Bluetooth spec + Log.w(TAG, "onDescriptorWriteRequest: !preparedWrite, offset " + + offset + ", Not supported"); + resultStatus = BluetoothGatt.GATT_REQUEST_NOT_SUPPORTED; + } + } else { + // BT Core v5.3, 3.4.6, Vol 3, Part F + // This is a prepared write which is used to write descriptors larger than MTU. + // We need to record all requests and execute them in one go once + // onExecuteWrite() is received. We use a queue to remember the pending + // requests. + resultStatus = addPendingPreparedWrite(device, descriptor, offset, value); + } + + if (responseNeeded) + mGattServer.sendResponse(device, requestId, resultStatus, offset, value); + } + + public synchronized void handleOnExecuteWrite(BluetoothDevice device, + int requestId, boolean execute) + { + if (mGattServer == null) { + Log.w(TAG, "Ignoring execute write, server is disconnected"); + return; + } + + Log.w(TAG, "onExecuteWrite " + device + " " + requestId + " " + execute); + + if (execute) { + // BT Core v5.3, 3.4.6.3, Vol 3, Part F + // Execute all pending prepared writes for the provided 'device' + for (WriteEntry entry : mPendingPreparedWrites) { + if (!entry.remoteDevice.equals(device)) + continue; + + byte[] newValue = null; + // The target can be a descriptor or a characteristic + byte[] currentValue = (entry.target instanceof BluetoothGattCharacteristic) + ? ((QtBluetoothGattCharacteristic)entry.target).getLocalValue() + : ((QtBluetoothGattDescriptor)entry.target).getLocalValue(); + + // Iterate writes and apply them to the currentValue in received order + for (Pair write : entry.writes) { + // write.first is data, write.second.intValue() is offset. Check + // that the offset is not beyond the length of the current value + if (write.second.intValue() > currentValue.length) { + clearPendingPreparedWrites(device); + // BT Core v5.3, 3.4.6.3, Vol 3, Part F + mGattServer.sendResponse(device, requestId, + BluetoothGatt.GATT_INVALID_OFFSET, + 0, null); + return; + } + + // User may have defined value minimum and maximum sizes for + // characteristics, which we enforce here. If the user has not defined + // these limits, the default values 0..INT_MAX do not limit anything. + // The value size cannot decrease in prepared write (small write is a + // partial update) => no check for the minimum size limit here. + if (entry.target instanceof QtBluetoothGattCharacteristic && + (write.second.intValue() + write.first.length > + ((QtBluetoothGattCharacteristic)entry.target).maxValueLength)) { + clearPendingPreparedWrites(device); + // BT Core v5.3, 3.4.6.3, Vol 3, Part F + mGattServer.sendResponse(device, requestId, + BluetoothGatt.GATT_INVALID_ATTRIBUTE_LENGTH, + 0, null); + return; + } + + // Determine the size of the new value as we may be extending the + // current value size + newValue = new byte[Math.max(write.second.intValue() + + write.first.length, currentValue.length)]; + // Copy the current value to the newValue. We can't use the currentValue + // directly because the length of value might increase by this write + System.arraycopy(currentValue, 0, newValue, 0, currentValue.length); + // Apply this iteration's write to the newValue + System.arraycopy(write.first, 0, newValue, write.second.intValue(), + write.first.length); + // Update the currentValue as there may be more writes to apply + currentValue = newValue; + } + + // Update value and inform the Qt/C++ side on the update + if (entry.target instanceof BluetoothGattCharacteristic) { + ((QtBluetoothGattCharacteristic)entry.target).setLocalValue(newValue); + leServerCharacteristicChanged( + qtObject, (BluetoothGattCharacteristic)entry.target, newValue); + } else { + ((QtBluetoothGattDescriptor)entry.target).setLocalValue(newValue); + leServerDescriptorWritten( + qtObject, (BluetoothGattDescriptor)entry.target, newValue); + } + } + } + // Either we executed all writes or were asked to cancel. + // In any case clear writes and respond. + clearPendingPreparedWrites(device); + mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, null); + } + + public synchronized void handleOnMtuChanged(BluetoothDevice device, int mtu) + { + if (mSupportedMtu == mtu) + return; + mSupportedMtu = mtu; + leMtuChanged(qtObject, mSupportedMtu); + } + + /* + * Call back handler for the Gatt Server. + */ + private BluetoothGattServerCallback mGattServerListener = new BluetoothGattServerCallback() + { + @Override + public void onConnectionStateChange(BluetoothDevice device, int status, int newState) { + super.onConnectionStateChange(device, status, newState); + handleOnConnectionStateChange(device, status, newState); + } + + @Override + public void onServiceAdded(int status, BluetoothGattService service) { + super.onServiceAdded(status, service); + handleOnServiceAdded(status, service); + } + + @Override + public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) + { + super.onCharacteristicReadRequest(device, requestId, offset, characteristic); + handleOnCharacteristicReadRequest(device, requestId, offset, characteristic); + } + + @Override + public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, + boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) + { + super.onCharacteristicWriteRequest(device, requestId, characteristic, + preparedWrite, responseNeeded, offset, value); + handleOnCharacteristicWriteRequest(device, requestId, characteristic, + preparedWrite, responseNeeded, offset, value); + } + + @Override + public void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattDescriptor descriptor) + { + super.onDescriptorReadRequest(device, requestId, offset, descriptor); + handleOnDescriptorReadRequest(device, requestId, offset, descriptor); + } + + @Override + public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, + boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) + { + super.onDescriptorWriteRequest(device, requestId, descriptor, preparedWrite, + responseNeeded, offset, value); + handleOnDescriptorWriteRequest(device, requestId, descriptor, preparedWrite, + responseNeeded, offset, value); + } + + @Override + public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) + { + super.onExecuteWrite(device, requestId, execute); + handleOnExecuteWrite(device, requestId, execute); + } + + @Override + public void onNotificationSent(BluetoothDevice device, int status) { + super.onNotificationSent(device, status); + Log.w(TAG, "onNotificationSent" + device + " " + status); + } + + @Override + public void onMtuChanged(BluetoothDevice device, int mtu) { + handleOnMtuChanged(device, mtu); + } + }; + + // This function is called from Qt thread + public synchronized int mtu() { + return mSupportedMtu; + } + + // This function is called from Qt thread + public synchronized boolean connectServer() + { + if (mGattServer != null) + return true; + + BluetoothManager manager = (BluetoothManager) qtContext.getSystemService(Context.BLUETOOTH_SERVICE); + if (manager == null) { + Log.w(TAG, "Bluetooth service not available."); + return false; + } + + mGattServer = manager.openGattServer(qtContext, mGattServerListener); + + return (mGattServer != null); + } + + // This function is called from Qt thread + public synchronized void disconnectServer() + { + if (mGattServer == null) + return; + + clearPendingPreparedWrites(null); + mPendingServiceAdditions.clear(); + mGattServer.close(); + mGattServer = null; + + mRemoteName = mRemoteAddress = ""; + leConnectionStateChange(qtObject, 0 /*NoError*/, + 0 /*QLowEnergyController::UnconnectedState*/); + } + + // This function is called from Qt thread + public boolean startAdvertising(AdvertiseData advertiseData, + AdvertiseData scanResponse, + AdvertiseSettings settings) + { + // Check that the bluetooth is on + if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) { + Log.w(TAG, "StartAdvertising: Bluetooth not available or offline"); + return false; + } + + // According to Android doc this check should always precede the advertiser creation + if (mLeAdvertiser == null && mBluetoothAdapter.isMultipleAdvertisementSupported()) + mLeAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser(); + + if (mLeAdvertiser == null) { + Log.w(TAG, "StartAdvertising: LE advertisement not supported"); + return false; + } + + if (!connectServer()) { + Log.w(TAG, "Server::startAdvertising: Cannot open GATT server"); + return false; + } + + Log.w(TAG, "Starting to advertise."); + mLeAdvertiser.startAdvertising(settings, advertiseData, scanResponse, mAdvertiseListener); + + return true; + } + + // This function is called from Qt thread + public void stopAdvertising() + { + if (mLeAdvertiser == null) + return; + + mLeAdvertiser.stopAdvertising(mAdvertiseListener); + Log.w(TAG, "Advertisement stopped."); + } + + // This function is called from Qt thread + public synchronized void addService(BluetoothGattService service) + { + if (!connectServer()) { + Log.w(TAG, "Server::addService: Cannot open GATT server"); + return; + } + + // When we add a service, we must wait for onServiceAdded callback before adding the + // next one. If the pending service queue is empty it means that there are no ongoing + // service additions => add the service to the server. If there are services in the + // queue it means there is an initiated addition ongoing, and we only add to the queue. + if (mPendingServiceAdditions.isEmpty()) { + if (mGattServer.addService(service)) + mPendingServiceAdditions.add(service); + else + Log.w(TAG, "Adding service " + service.getUuid().toString() + " failed."); + } else { + mPendingServiceAdditions.add(service); + } + } + + /* + Check the client characteristics configuration for the given characteristic + and sends notifications or indications as per required. + + This function is called from Qt and Java threads and calls must be protected + */ + private void sendNotificationsOrIndications(BluetoothGattCharacteristic characteristic) + { + final ListIterator iter = + clientCharacteristicManager.getToBeUpdatedDevices(characteristic).listIterator(); + + // TODO This quick loop over multiple devices should be synced with onNotificationSent(). + // The next notifyCharacteristicChanged() call must wait until onNotificationSent() + // was received. At this becomes an issue when the server accepts multiple remote + // devices at the same time. + while (iter.hasNext()) { + final BluetoothDevice device = iter.next(); + final byte[] clientCharacteristicConfig = + clientCharacteristicManager.valueFor(characteristic, device); + if (clientCharacteristicConfig != null) { + if (Arrays.equals(clientCharacteristicConfig, + BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE)) { + if (Build.VERSION.SDK_INT >= 33) { + mGattServer.notifyCharacteristicChanged(device, characteristic, false, + ((QtBluetoothGattCharacteristic)characteristic).getLocalValue()); + } else { + mGattServer.notifyCharacteristicChanged(device, characteristic, false); + } + } else if (Arrays.equals(clientCharacteristicConfig, + BluetoothGattDescriptor.ENABLE_INDICATION_VALUE)) { + if (Build.VERSION.SDK_INT >= 33) { + mGattServer.notifyCharacteristicChanged(device, characteristic, true, + ((QtBluetoothGattCharacteristic)characteristic).getLocalValue()); + } else { + mGattServer.notifyCharacteristicChanged(device, characteristic, true); + } + } + } + } + } + + /* + Updates the local database value for the given characteristic with \a charUuid and + \a newValue. If notifications for this task are enabled an appropriate notification will + be send to the remote client. + + This function is called from the Qt thread. + */ + public boolean writeCharacteristic(BluetoothGattService service, UUID charUuid, byte[] newValue) + { + BluetoothGattCharacteristic foundChar = null; + List charList = service.getCharacteristics(); + for (BluetoothGattCharacteristic iter: charList) { + if (iter.getUuid().equals(charUuid) && foundChar == null) { + foundChar = iter; + // don't break here since we want to check next condition below on next iteration + } else if (iter.getUuid().equals(charUuid)) { + Log.w(TAG, "Found second char with same UUID. Wrong char may have been selected."); + break; + } + } + + if (foundChar == null) { + Log.w(TAG, "writeCharacteristic: update for unknown characteristic failed"); + return false; + } + + // User may have set minimum and/or maximum characteristic value size. Enforce + // them here. If the user has not defined these limits, the default values 0..INT_MAX + // do not limit anything. + final int minValueLength = ((QtBluetoothGattCharacteristic)foundChar).minValueLength; + final int maxValueLength = ((QtBluetoothGattCharacteristic)foundChar).maxValueLength; + if (newValue.length < minValueLength || newValue.length > maxValueLength) { + Log.w(TAG, "writeCharacteristic: invalid value length: " + + newValue.length + ", min: " + minValueLength + ", max: " + maxValueLength); + return false; + } + + synchronized (this) // a value update might be in progress + { + ((QtBluetoothGattCharacteristic)foundChar).setLocalValue(newValue); + // Value is updated even if server is not connected, but notifying is not possible + if (mGattServer != null) + sendNotificationsOrIndications(foundChar); + } + + return true; + } + + /* + Updates the local database value for the given \a descUuid to \a newValue. + + This function is called from the Qt thread. + */ + public boolean writeDescriptor(BluetoothGattService service, UUID charUuid, UUID descUuid, + byte[] newValue) + { + BluetoothGattDescriptor foundDesc = null; + BluetoothGattCharacteristic foundChar = null; + final List charList = service.getCharacteristics(); + for (BluetoothGattCharacteristic iter: charList) { + if (!iter.getUuid().equals(charUuid)) + continue; + + if (foundChar == null) { + foundChar = iter; + } else { + Log.w(TAG, "Found second char with same UUID. Wrong char may have been selected."); + break; + } + } + + if (foundChar != null) + foundDesc = foundChar.getDescriptor(descUuid); + + if (foundChar == null || foundDesc == null) { + Log.w(TAG, "writeDescriptor: update for unknown char or desc failed (" + foundChar + ")"); + return false; + } + + // we even write CLIENT_CHARACTERISTIC_CONFIGURATION_UUID this way as we choose + // to interpret the server's call as a change of the default value. + synchronized (this) // a value update might be in progress + { + ((QtBluetoothGattDescriptor)foundDesc).setLocalValue(newValue); + } + + return true; + } + + /* + * Call back handler for Advertisement requests. + */ + private AdvertiseCallback mAdvertiseListener = new AdvertiseCallback() + { + @Override + public void onStartSuccess(AdvertiseSettings settingsInEffect) { + super.onStartSuccess(settingsInEffect); + } + + @Override + public void onStartFailure(int errorCode) { + Log.e(TAG, "Advertising failure: " + errorCode); + super.onStartFailure(errorCode); + + // changing errorCode here implies changes to errorCode handling on Qt side + int qtErrorCode = 0; + switch (errorCode) { + case AdvertiseCallback.ADVERTISE_FAILED_ALREADY_STARTED: + return; // ignore -> noop + case AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE: + Log.e(TAG, "Please reduce size of advertising data."); + qtErrorCode = 1; + break; + case AdvertiseCallback.ADVERTISE_FAILED_FEATURE_UNSUPPORTED: + qtErrorCode = 2; + break; + default: // default maps to internal error + case AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR: + qtErrorCode = 3; + break; + case AdvertiseCallback.ADVERTISE_FAILED_TOO_MANY_ADVERTISERS: + qtErrorCode = 4; + break; + } + + if (qtErrorCode > 0) + leServerAdvertisementError(qtObject, qtErrorCode); + } + }; + + public native void leConnectionStateChange(long qtObject, int errorCode, int newState); + public native void leMtuChanged(long qtObject, int mtu); + public native void leServerAdvertisementError(long qtObject, int status); + public native void leServerCharacteristicChanged(long qtObject, + BluetoothGattCharacteristic characteristic, + byte[] newValue); + public native void leServerDescriptorWritten(long qtObject, + BluetoothGattDescriptor descriptor, + byte[] newValue); +} diff --git a/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothSocketServer.java b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothSocketServer.java new file mode 100644 index 0000000..cc78c5d --- /dev/null +++ b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothSocketServer.java @@ -0,0 +1,154 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +package org.qtproject.qt.android.bluetooth; + +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothServerSocket; +import android.bluetooth.BluetoothManager; +import android.bluetooth.BluetoothSocket; +import android.content.Context; +import android.util.Log; +import java.io.IOException; +import java.util.UUID; + +@SuppressWarnings("WeakerAccess") +public class QtBluetoothSocketServer extends Thread +{ + + /* Pointer to the Qt object that "owns" the Java object */ + @SuppressWarnings({"WeakerAccess", "CanBeFinal"}) + long qtObject = 0; + @SuppressWarnings({"WeakerAccess", "CanBeFinal"}) + public boolean logEnabled = false; + @SuppressWarnings("WeakerAccess") + static Context qtContext = null; + + private static final String TAG = "QtBluetooth"; + private boolean m_isSecure = false; + private UUID m_uuid; + private String m_serviceName; + private BluetoothServerSocket m_serverSocket = null; + + //error codes + private static final int QT_NO_BLUETOOTH_SUPPORTED = 0; + private static final int QT_LISTEN_FAILED = 1; + private static final int QT_ACCEPT_FAILED = 2; + + public QtBluetoothSocketServer(Context context) + { + qtContext = context; + setName("QtSocketServerThread"); + } + + public void setServiceDetails(String uuid, String serviceName, boolean isSecure) + { + m_uuid = UUID.fromString(uuid); + m_serviceName = serviceName; + m_isSecure = isSecure; + + } + + public void run() + { + BluetoothManager manager = + (BluetoothManager)qtContext.getSystemService(Context.BLUETOOTH_SERVICE); + + if (manager == null) { + errorOccurred(qtObject, QT_NO_BLUETOOTH_SUPPORTED); + return; + } + + BluetoothAdapter adapter = manager.getAdapter(); + if (adapter == null) { + errorOccurred(qtObject, QT_NO_BLUETOOTH_SUPPORTED); + return; + } + + try { + if (m_isSecure) { + m_serverSocket = adapter.listenUsingRfcommWithServiceRecord(m_serviceName, m_uuid); + if (logEnabled) + Log.d(TAG, "Using secure socket listener"); + } else { + m_serverSocket = adapter.listenUsingInsecureRfcommWithServiceRecord(m_serviceName, m_uuid); + if (logEnabled) + Log.d(TAG, "Using insecure socket listener"); + } + } catch (IOException ex) { + if (logEnabled) + Log.d(TAG, "Server socket listen() failed:" + ex.toString()); + ex.printStackTrace(); + errorOccurred(qtObject, QT_LISTEN_FAILED); + return; + } + + if (isInterrupted()) // close() may have been called + return; + + BluetoothSocket s; + if (m_serverSocket != null) { + try { + while (!isInterrupted()) { + //this blocks until we see incoming connection + //or close() is called + if (logEnabled) + Log.d(TAG, "Waiting for new incoming socket"); + s = m_serverSocket.accept(); + + if (logEnabled) + Log.d(TAG, "New socket accepted"); + newSocket(qtObject, s); + } + } catch (IOException ex) { + if (logEnabled) + Log.d(TAG, "Server socket accept() failed:" + ex.toString()); + ex.printStackTrace(); + errorOccurred(qtObject, QT_ACCEPT_FAILED); + } + } + + Log.d(TAG, "Leaving server socket thread."); + } + + // This function closes the socket server + // + // A note on threading behavior + // 1. This function is called from Qt thread which is different from the Java thread (run()) + // 2. The caller of this function expects the Java thread to be finished upon return + // + // First we mark the Java thread as interrupted, then call close() on the + // listening socket if it had been created, and lastly wait for the thread to finish. + // The close() method of the socket is intended to be used to abort the accept() from + // another thread, as per the accept() documentation. + // + // If the Java thread was in the middle of creating a socket with the non-blocking + // listen* call, the run() will notice after the returning from the listen* that it has + // been interrupted and returns early from the run(). + // + // If the Java thread was in the middle of the blocking accept() call, it will get + // interrupated by the close() call on the socket. After returning the run() will + // notice it has been interrupted and return from the run() + public void close() + { + if (!isAlive()) + return; + + try { + //ensure closing of thread if we are not currently blocking on accept() + interrupt(); + + //interrupts accept() call above + if (m_serverSocket != null) + m_serverSocket.close(); + // Wait for the thread to finish + join(20); // Maximum wait in ms, typically takes < 1ms + } catch (Exception ex) { + Log.d(TAG, "Closing server socket close() failed:" + ex.toString()); + ex.printStackTrace(); + } + } + + public static native void errorOccurred(long qtObject, int errorCode); + public static native void newSocket(long qtObject, BluetoothSocket socket); +} diff --git a/src/android/nfc/AndroidManifest.xml b/src/android/nfc/AndroidManifest.xml new file mode 100644 index 0000000..30db61f --- /dev/null +++ b/src/android/nfc/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/src/android/nfc/CMakeLists.txt b/src/android/nfc/CMakeLists.txt new file mode 100644 index 0000000..f16f60c --- /dev/null +++ b/src/android/nfc/CMakeLists.txt @@ -0,0 +1,22 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +set(java_sources + src/org/qtproject/qt/android/nfc/QtNfc.java + src/org/qtproject/qt/android/nfc/QtNfcBroadcastReceiver.java +) + +qt_internal_add_jar(Qt${QtConnectivity_VERSION_MAJOR}AndroidNfc + INCLUDE_JARS ${QT_ANDROID_JAR} + SOURCES ${java_sources} + OUTPUT_DIR "${QT_BUILD_DIR}/jar" +) + +qt_path_join(destination ${INSTALL_DATADIR} "jar") + +install_jar(Qt${QtConnectivity_VERSION_MAJOR}AndroidNfc + DESTINATION ${destination} + COMPONENT Devel +) + +add_dependencies(Nfc Qt${QtConnectivity_VERSION_MAJOR}AndroidNfc) diff --git a/src/android/nfc/src/org/qtproject/qt/android/nfc/QtNfc.java b/src/android/nfc/src/org/qtproject/qt/android/nfc/QtNfc.java new file mode 100644 index 0000000..9d8cae9 --- /dev/null +++ b/src/android/nfc/src/org/qtproject/qt/android/nfc/QtNfc.java @@ -0,0 +1,145 @@ +// Copyright (C) 2016 Centria research and development +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +package org.qtproject.qt.android.nfc; + +import java.lang.Runnable; + +import android.content.Context; +import android.app.Activity; +import android.app.PendingIntent; +import android.content.Intent; +import android.content.IntentFilter; +import android.nfc.NfcAdapter; +import android.content.IntentFilter.MalformedMimeTypeException; +import android.os.Build; +import android.os.Parcelable; +import android.util.Log; +import android.content.pm.PackageManager; + +public class QtNfc +{ + static private final String TAG = "QtNfc"; + static private NfcAdapter m_adapter = null; + static private PendingIntent m_pendingIntent = null; + static private Context m_context = null; + static private Activity m_activity = null; + + static public void setContext(Context context) + { + m_context = context; + if (context instanceof Activity) m_activity = (Activity) context; + m_adapter = NfcAdapter.getDefaultAdapter(context); + + if (m_activity == null) { + Log.w(TAG, "New NFC tags will only be recognized with Android activities and not with Android services."); + return; + } + + if (m_adapter == null) { + return; + } + + // Since Android 12 (API level 31) it's mandatory to specify mutability + // of PendingIntent. We need a mutable intent, which was a default + // option earlier. + int flags = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) ? PendingIntent.FLAG_MUTABLE + : 0; + m_pendingIntent = PendingIntent.getActivity( + m_activity, + 0, + new Intent(m_activity, m_activity.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), + flags); + } + + static public boolean startDiscovery() + { + if (m_adapter == null || m_activity == null + || !m_activity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC)) + return false; + + m_activity.runOnUiThread(new Runnable() { + public void run() { + IntentFilter[] filters = new IntentFilter[3]; + filters[0] = new IntentFilter(); + filters[0].addAction(NfcAdapter.ACTION_TAG_DISCOVERED); + filters[0].addCategory(Intent.CATEGORY_DEFAULT); + filters[1] = new IntentFilter(); + filters[1].addAction(NfcAdapter.ACTION_NDEF_DISCOVERED); + filters[1].addCategory(Intent.CATEGORY_DEFAULT); + try { + filters[1].addDataType("*/*"); + } catch (MalformedMimeTypeException e) { + throw new RuntimeException("IntentFilter.addDataType() failed"); + } + // some tags will report as tech, even if they are ndef formatted/formattable. + filters[2] = new IntentFilter(); + filters[2].addAction(NfcAdapter.ACTION_TECH_DISCOVERED); + String[][] techList = new String[][]{ + {"android.nfc.tech.Ndef"}, + {"android.nfc.tech.NdefFormatable"} + }; + try { + m_adapter.enableForegroundDispatch(m_activity, m_pendingIntent, filters, techList); + } catch(IllegalStateException e) { + // On Android we must call enableForegroundDispatch when the activity is in foreground, only. + Log.d(TAG, "enableForegroundDispatch failed: " + e.toString()); + } + } + }); + return true; + } + + static public boolean stopDiscovery() + { + if (m_adapter == null || m_activity == null + || !m_activity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC)) + return false; + + m_activity.runOnUiThread(new Runnable() { + public void run() { + try { + m_adapter.disableForegroundDispatch(m_activity); + } catch(IllegalStateException e) { + // On Android we must call disableForegroundDispatch when the activity is in foreground, only. + Log.d(TAG, "disableForegroundDispatch failed: " + e.toString()); + } + } + }); + return true; + } + + static public boolean isEnabled() + { + if (m_adapter == null) { + return false; + } + + return m_adapter.isEnabled(); + } + + static public boolean isSupported() + { + return (m_adapter != null); + } + + static public Intent getStartIntent() + { + Log.d(TAG, "getStartIntent"); + if (m_activity == null) return null; + + Intent intent = m_activity.getIntent(); + if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction()) || + NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction()) || + NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) { + return intent; + } else { + return null; + } + } + + static public Parcelable getTag(Intent intent) + { + return intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); + } +} diff --git a/src/android/nfc/src/org/qtproject/qt/android/nfc/QtNfcBroadcastReceiver.java b/src/android/nfc/src/org/qtproject/qt/android/nfc/QtNfcBroadcastReceiver.java new file mode 100644 index 0000000..e70ec9a --- /dev/null +++ b/src/android/nfc/src/org/qtproject/qt/android/nfc/QtNfcBroadcastReceiver.java @@ -0,0 +1,37 @@ +// Copyright (C) 2018 Governikus GmbH & Co. KG +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +package org.qtproject.qt.android.nfc; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.nfc.NfcAdapter; + +public class QtNfcBroadcastReceiver extends BroadcastReceiver +{ + final private long qtObject; + final private Context qtContext; + + public QtNfcBroadcastReceiver(long obj, Context context) + { + qtObject = obj; + qtContext = context; + IntentFilter filter = new IntentFilter(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED); + qtContext.registerReceiver(this, filter); + } + + public void unregisterReceiver() + { + qtContext.unregisterReceiver(this); + } + + public void onReceive(Context context, Intent intent) + { + final int state = intent.getIntExtra(NfcAdapter.EXTRA_ADAPTER_STATE, NfcAdapter.STATE_OFF); + jniOnReceive(qtObject, state); + } + + public native void jniOnReceive(long qtObject, int state); +} diff --git a/src/bluetooth/CMakeLists.txt b/src/bluetooth/CMakeLists.txt new file mode 100644 index 0000000..148f835 --- /dev/null +++ b/src/bluetooth/CMakeLists.txt @@ -0,0 +1,273 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## Bluetooth Module: +##################################################################### + +qt_internal_add_module(Bluetooth + SOURCES + lecmaccalculator_p.h + removed_api.cpp + qbluetooth.cpp qbluetooth.h + qbluetoothaddress.cpp qbluetoothaddress.h + qbluetoothdevicediscoveryagent.cpp qbluetoothdevicediscoveryagent.h qbluetoothdevicediscoveryagent_p.h + qbluetoothdeviceinfo.cpp qbluetoothdeviceinfo.h qbluetoothdeviceinfo_p.h + qbluetoothhostinfo.cpp qbluetoothhostinfo.h qbluetoothhostinfo_p.h + qbluetoothlocaldevice.cpp qbluetoothlocaldevice.h qbluetoothlocaldevice_p.h + qbluetoothserver.cpp qbluetoothserver.h qbluetoothserver_p.h + qbluetoothservicediscoveryagent.cpp qbluetoothservicediscoveryagent.h qbluetoothservicediscoveryagent_p.h + qbluetoothserviceinfo.cpp qbluetoothserviceinfo.h qbluetoothserviceinfo_p.h + qbluetoothsocket.cpp qbluetoothsocket.h + qbluetoothsocketbase.cpp qbluetoothsocketbase_p.h + qbluetoothuuid.cpp qbluetoothuuid.h + qlowenergyadvertisingdata.cpp qlowenergyadvertisingdata.h + qlowenergyadvertisingparameters.cpp qlowenergyadvertisingparameters.h + qlowenergycharacteristic.cpp qlowenergycharacteristic.h + qlowenergycharacteristicdata.cpp qlowenergycharacteristicdata.h + qlowenergyconnectionparameters.cpp qlowenergyconnectionparameters.h + qlowenergycontroller.cpp qlowenergycontroller.h + qlowenergycontrollerbase.cpp qlowenergycontrollerbase_p.h + qlowenergydescriptor.cpp qlowenergydescriptor.h + qlowenergydescriptordata.cpp qlowenergydescriptordata.h + qlowenergyservice.cpp qlowenergyservice.h + qlowenergyservicedata.cpp qlowenergyservicedata.h + qlowenergyserviceprivate.cpp qlowenergyserviceprivate_p.h + qprivatelinearbuffer_p.h + qtbluetoothglobal.h qtbluetoothglobal_p.h + DEFINES + QT_NO_CONTEXTLESS_CONNECT + LIBRARIES + Qt::CorePrivate + Qt::NetworkPrivate + PUBLIC_LIBRARIES + Qt::Core + Qt::Network + PRIVATE_MODULE_INTERFACE + Qt::CorePrivate + Qt::NetworkPrivate + GENERATE_CPP_EXPORTS + GENERATE_PRIVATE_CPP_EXPORTS +) + +#### Keys ignored in scope 1:.:.:bluetooth.pro:: +# OTHER_FILES = "doc/src/*.qdoc" + +## Scopes: +##################################################################### + +if(QT_FEATURE_bluez) + qt_internal_extend_target(Bluetooth + SOURCES + bluez/adapter1_bluez5.cpp bluez/adapter1_bluez5_p.h + bluez/battery1.cpp bluez/battery1_p.h + bluez/bluetoothmanagement.cpp bluez/bluetoothmanagement_p.h + bluez/bluez5_helper.cpp bluez/bluez5_helper_p.h + bluez/bluez_data.cpp bluez/bluez_data_p.h + bluez/device1_bluez5.cpp bluez/device1_bluez5_p.h + bluez/gattchar1.cpp bluez/gattchar1_p.h + bluez/gattdesc1.cpp bluez/gattdesc1_p.h + bluez/gattservice1.cpp bluez/gattservice1_p.h + bluez/hcimanager.cpp bluez/hcimanager_p.h + bluez/objectmanager.cpp bluez/objectmanager_p.h + bluez/profile1.cpp bluez/profile1_p.h + bluez/profile1context.cpp bluez/profile1context_p.h + bluez/profilemanager1.cpp bluez/profilemanager1_p.h + bluez/properties.cpp bluez/properties_p.h + bluez/remotedevicemanager.cpp bluez/remotedevicemanager_p.h + bluez/servicemap.cpp bluez/servicemap_p.h + bluez/gattmanager1.cpp bluez/gattmanager1_p.h + bluez/leadvertisement1.cpp bluez/leadvertisement1_p.h + bluez/leadvertisingmanager1.cpp bluez/leadvertisingmanager1_p.h + bluez/objectmanageradaptor.cpp bluez/objectmanageradaptor_p.h + bluez/propertiesadaptor.cpp bluez/propertiesadaptor_p.h + bluez/gattcharacteristic1adaptor.cpp bluez/gattcharacteristic1adaptor_p.h + bluez/gattdescriptor1adaptor.cpp bluez/gattdescriptor1adaptor_p.h + bluez/gattservice1adaptor.cpp bluez/gattservice1adaptor_p.h + bluez/bluezperipheralapplication.cpp bluez/bluezperipheralapplication_p.h + bluez/bluezperipheralobjects.cpp bluez/bluezperipheralobjects_p.h + bluez/bluezperipheralconnectionmanager.cpp bluez/bluezperipheralconnectionmanager_p.h + qbluetoothdevicediscoveryagent_bluez.cpp + qbluetoothlocaldevice_bluez.cpp + qbluetoothserver_bluez.cpp + qbluetoothservicediscoveryagent_bluez.cpp + qbluetoothserviceinfo_bluez.cpp + qbluetoothsocket_bluez.cpp qbluetoothsocket_bluez_p.h + qbluetoothsocket_bluezdbus.cpp qbluetoothsocket_bluezdbus_p.h + PUBLIC_LIBRARIES # for Linux QEMU (gcc-armv7) on Linux Ubuntu_20_04 (gcc-x86_64) + Qt::DBus + ) + + if(QT_FEATURE_bluez_le) + qt_internal_extend_target(Bluetooth + SOURCES + lecmaccalculator.cpp + qleadvertiser_bluez.cpp qleadvertiser_bluez_p.h + qleadvertiser_bluezdbus.cpp qleadvertiser_bluezdbus_p.h + qlowenergycontroller_bluez.cpp qlowenergycontroller_bluez_p.h + qlowenergycontroller_bluezdbus.cpp qlowenergycontroller_bluezdbus_p.h + ) + + if(QT_FEATURE_linux_crypto_api) + qt_internal_extend_target(Bluetooth + DEFINES + CONFIG_LINUX_CRYPTO_API + ) + endif() + else() + qt_internal_extend_target(Bluetooth + SOURCES + dummy/dummy_helper.cpp dummy/dummy_helper_p.h + qlowenergycontroller_dummy.cpp qlowenergycontroller_dummy_p.h + DEFINES + QT_BLUEZ_NO_BTLE + ) + endif() + +elseif(ANDROID AND NOT ANDROID_EMBEDDED) + set_property(TARGET Bluetooth APPEND PROPERTY QT_ANDROID_BUNDLED_JAR_DEPENDENCIES + jar/Qt${QtConnectivity_VERSION_MAJOR}AndroidBluetooth.jar:org.qtproject.qt.android.bluetooth.QtBluetoothBroadcastReceiver + ) + set_property(TARGET Bluetooth APPEND PROPERTY QT_ANDROID_PERMISSIONS + android.permission.ACCESS_FINE_LOCATION + android.permission.BLUETOOTH + android.permission.BLUETOOTH_ADMIN + # Android 12 / SDK 31+ + android.permission.BLUETOOTH_SCAN + android.permission.BLUETOOTH_ADVERTISE + android.permission.BLUETOOTH_CONNECT + ) + + qt_internal_extend_target(Bluetooth + SOURCES + android/androidbroadcastreceiver.cpp android/androidbroadcastreceiver_p.h + android/devicediscoverybroadcastreceiver.cpp android/devicediscoverybroadcastreceiver_p.h + android/inputstreamthread.cpp android/inputstreamthread_p.h + android/jni_android.cpp android/jni_android_p.h + android/localdevicebroadcastreceiver.cpp android/localdevicebroadcastreceiver_p.h + android/lowenergynotificationhub.cpp android/lowenergynotificationhub_p.h + android/serveracceptancethread.cpp android/serveracceptancethread_p.h + android/servicediscoverybroadcastreceiver.cpp android/servicediscoverybroadcastreceiver_p.h + android/androidutils.cpp android/androidutils_p.h + qbluetoothdevicediscoveryagent_android.cpp + qbluetoothlocaldevice_android.cpp + qbluetoothserver_android.cpp + qbluetoothservicediscoveryagent_android.cpp + qbluetoothserviceinfo_android.cpp + qbluetoothsocket_android.cpp qbluetoothsocket_android_p.h + qlowenergycontroller_android.cpp qlowenergycontroller_android_p.h + DEFINES + QT_ANDROID_BLUETOOTH + LIBRARIES + Qt::CorePrivate + PRIVATE_MODULE_INTERFACE + Qt::CorePrivate + ) +elseif(MACOS) + qt_internal_extend_target(Bluetooth + SOURCES + darwin/btcentralmanager.mm darwin/btcentralmanager_p.h + darwin/btconnectionmonitor.mm darwin/btconnectionmonitor_p.h + darwin/btdelegates.cpp darwin/btdelegates_p.h + darwin/btdeviceinquiry.mm darwin/btdeviceinquiry_p.h + darwin/btdevicepair.mm darwin/btdevicepair_p.h + darwin/btgcdtimer.mm darwin/btgcdtimer_p.h + darwin/btl2capchannel.mm darwin/btl2capchannel_p.h + darwin/btledeviceinquiry.mm darwin/btledeviceinquiry_p.h + darwin/btnotifier.cpp darwin/btnotifier_p.h + darwin/btperipheralmanager.mm darwin/btperipheralmanager_p.h + darwin/btraii.mm darwin/btraii_p.h + darwin/btrfcommchannel.mm darwin/btrfcommchannel_p.h + darwin/btsdpinquiry.mm darwin/btsdpinquiry_p.h + darwin/btservicerecord.mm darwin/btservicerecord_p.h + darwin/btsocketlistener.mm darwin/btsocketlistener_p.h + darwin/btutility.mm darwin/btutility_p.h + darwin/uistrings.cpp darwin/uistrings_p.h + qbluetoothdevicediscoveryagent_darwin.mm + qbluetoothlocaldevice_macos.mm + qbluetoothserver_macos.mm + qbluetoothservicediscoveryagent_macos.mm + qbluetoothserviceinfo_macos.mm + qbluetoothsocket_macos.mm qbluetoothsocket_macos_p.h + qlowenergycontroller_darwin.mm qlowenergycontroller_darwin_p.h + qbluetoothuuid_darwin.mm + DEFINES + QT_OSX_BLUETOOTH + LIBRARIES + Qt::CorePrivate + ${FWFoundation} + ${FWIOBluetooth} + ) +elseif(IOS) + qt_internal_extend_target(Bluetooth + SOURCES + darwin/btcentralmanager.mm darwin/btcentralmanager_p.h + darwin/btdelegates.cpp darwin/btdelegates_p.h + darwin/btgcdtimer.mm darwin/btgcdtimer_p.h + darwin/btledeviceinquiry.mm darwin/btledeviceinquiry_p.h + darwin/btnotifier.cpp darwin/btnotifier_p.h + darwin/btraii.mm darwin/btraii_p.h + darwin/btutility.mm darwin/btutility_p.h + darwin/uistrings.cpp darwin/uistrings_p.h + qbluetoothdevicediscoveryagent_darwin.mm + qbluetoothlocaldevice_p.cpp + qbluetoothserver_p.cpp + qbluetoothservicediscoveryagent_p.cpp + qbluetoothserviceinfo_p.cpp + qbluetoothsocket_dummy.cpp qbluetoothsocket_dummy_p.h + qlowenergycontroller_darwin.mm qlowenergycontroller_darwin_p.h + darwin/btperipheralmanager.mm darwin/btperipheralmanager_p.h + qbluetoothuuid_darwin.mm + DEFINES + QT_IOS_BLUETOOTH + LIBRARIES + Qt::CorePrivate + ${FWCoreBluetooth} + ${FWFoundation} + ) +elseif(QT_FEATURE_winrt_bt) + qt_internal_extend_target(Bluetooth + SOURCES + qbluetoothdevicediscoveryagent_winrt.cpp + qbluetoothlocaldevice_winrt.cpp + qbluetoothserver_winrt.cpp + qbluetoothservicediscoveryagent_winrt.cpp + qbluetoothserviceinfo_winrt.cpp + qbluetoothsocket_winrt.cpp qbluetoothsocket_winrt_p.h + qbluetoothutils_winrt.cpp qbluetoothutils_winrt_p.h + qlowenergycontroller_winrt.cpp qlowenergycontroller_winrt_p.h + qbluetoothdevicewatcher_winrt.cpp qbluetoothdevicewatcher_winrt_p.h + NO_UNITY_BUILD_SOURCES + qbluetoothdevicediscoveryagent_winrt.cpp + qbluetoothdevicewatcher_winrt.cpp + qbluetoothlocaldevice_winrt.cpp + DEFINES + QT_WINRT_BLUETOOTH + LIBRARIES + Qt::CorePrivate + PUBLIC_LIBRARIES + Qt::Core + runtimeobject + user32 + PRIVATE_MODULE_INTERFACE + Qt::CorePrivate + ) +else() + qt_internal_extend_target(Bluetooth + SOURCES + dummy/dummy_helper.cpp dummy/dummy_helper_p.h + qbluetoothdevicediscoveryagent_p.cpp + qbluetoothlocaldevice_p.cpp + qbluetoothserver_p.cpp + qbluetoothservicediscoveryagent_p.cpp + qbluetoothserviceinfo_p.cpp + qbluetoothsocket_dummy.cpp qbluetoothsocket_dummy_p.h + qlowenergycontroller_dummy.cpp qlowenergycontroller_dummy_p.h + ) +endif() +qt_update_ignore_pch_source(Bluetooth removed_api.cpp) + +qt_internal_add_docs(Bluetooth + doc/qtbluetooth.qdocconf +) + diff --git a/src/bluetooth/android/androidbroadcastreceiver.cpp b/src/bluetooth/android/androidbroadcastreceiver.cpp new file mode 100644 index 0000000..da551be --- /dev/null +++ b/src/bluetooth/android/androidbroadcastreceiver.cpp @@ -0,0 +1,65 @@ +// Copyright (C) 2016 Lauri Laanmets (Proekspert AS) +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include +#include +#include "android/androidbroadcastreceiver_p.h" +#include +#include +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID) + + +AndroidBroadcastReceiver::AndroidBroadcastReceiver(QObject* parent) + : QObject(parent), valid(false) +{ + // get Qt Context + contextObject = QJniObject(QNativeInterface::QAndroidApplication::context()); + + broadcastReceiverObject = QJniObject::construct(); + if (!broadcastReceiverObject.isValid()) + return; + broadcastReceiverObject.setField("qtObject", reinterpret_cast(this)); + + intentFilterObject = QJniObject::construct(); + if (!intentFilterObject.isValid()) + return; + + valid = true; +} + +AndroidBroadcastReceiver::~AndroidBroadcastReceiver() +{ +} + +bool AndroidBroadcastReceiver::isValid() const +{ + return valid; +} + +void AndroidBroadcastReceiver::unregisterReceiver() +{ + if (!valid) + return; + + broadcastReceiverObject.callMethod("unregisterReceiver"); +} + +void AndroidBroadcastReceiver::addAction(const QJniObject &action) +{ + if (!valid || !action.isValid()) + return; + + intentFilterObject.callMethod("addAction", action.object()); + + contextObject.callMethod( + "registerReceiver", + broadcastReceiverObject.object(), + intentFilterObject.object()); +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/android/androidbroadcastreceiver_p.h b/src/bluetooth/android/androidbroadcastreceiver_p.h new file mode 100644 index 0000000..08ecd5f --- /dev/null +++ b/src/bluetooth/android/androidbroadcastreceiver_p.h @@ -0,0 +1,58 @@ +// Copyright (C) 2017 Lauri Laanmets (Proekspert AS) +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef JNIBROADCASTRECEIVER_H +#define JNIBROADCASTRECEIVER_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 + +QT_BEGIN_NAMESPACE + +void QtBroadcastReceiver_jniOnReceive(JNIEnv *, jobject, jlong, + QtJniTypes::Context, QtJniTypes::Intent); + +class AndroidBroadcastReceiver: public QObject +{ + Q_OBJECT +public: + AndroidBroadcastReceiver(QObject* parent = nullptr); + virtual ~AndroidBroadcastReceiver(); + + void addAction(const QJniObject &filter); + bool isValid() const; + void unregisterReceiver(); + +protected: + friend void QtBroadcastReceiver_jniOnReceive(JNIEnv *, jobject, jlong, QtJniTypes::Context, + QtJniTypes::Intent); + virtual void onReceive(JNIEnv *env, jobject context, jobject intent) = 0; + friend void QtBluetoothLE_leScanResult(JNIEnv *, jobject, jlong, QtJniTypes::BluetoothDevice, + jint, jbyteArray); + virtual void onReceiveLeScan(JNIEnv *env, jobject jBluetoothDevice, jint rssi, jbyteArray scanRecord) = 0; + + + QJniObject contextObject; + QJniObject intentFilterObject; + QJniObject broadcastReceiverObject; + bool valid; +}; + +QT_END_NAMESPACE +#endif // JNIBROADCASTRECEIVER_H diff --git a/src/bluetooth/android/androidutils.cpp b/src/bluetooth/android/androidutils.cpp new file mode 100644 index 0000000..22160ab --- /dev/null +++ b/src/bluetooth/android/androidutils.cpp @@ -0,0 +1,50 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "androidutils_p.h" +#include "jni_android_p.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID) + +bool ensureAndroidPermission(QBluetoothPermission::CommunicationModes modes) +{ + QBluetoothPermission permission; + permission.setCommunicationModes(modes); + + if (qApp->checkPermission(permission) == Qt::PermissionStatus::Granted) + return true; + + qCWarning(QT_BT_ANDROID) << "Permissions not authorized for a specified mode:" << modes; + return false; +} + +QJniObject getDefaultBluetoothAdapter() +{ + QJniObject service = QJniObject::getStaticField( + "BLUETOOTH_SERVICE"); + QJniObject context = QNativeInterface::QAndroidApplication::context(); + QJniObject manager = + context.callMethod("getSystemService", service.object()); + QJniObject adapter; + if (manager.isValid()) + adapter = manager.callMethod("getAdapter"); + + // ### Qt 7 check if the below double-get of the adapter can be removed. + // It is a workaround for QTBUG-57489, fixed in 2016. According to the bug it occurred on + // a certain device running Android 6.0.1 (Qt 6 supports Android 6.0 as the minimum). + // For completeness: the original workaround was for the deprecated getDefaultAdapter() + // method, and it is thus unclear if this is needed even in Qt 6 anymore. In addition the + // impacted device is updateable to Android 8 which may also have fixed the issue. + if (!adapter.isValid()) + adapter = manager.callMethod("getAdapter"); + + return adapter; +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/android/androidutils_p.h b/src/bluetooth/android/androidutils_p.h new file mode 100644 index 0000000..5c83fc6 --- /dev/null +++ b/src/bluetooth/android/androidutils_p.h @@ -0,0 +1,32 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QANDROIDBLUETOOTHUTILS_H +#define QANDROIDBLUETOOTHUTILS_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 + +// Checks if a permssion is already authorized or not +bool ensureAndroidPermission(QBluetoothPermission::CommunicationModes modes); + +// Returns the default bluetooth adapter, or an invalid object if not available +QJniObject getDefaultBluetoothAdapter(); + +QT_END_NAMESPACE + +#endif // QANDROIDBLUETOOTHUTILS_H diff --git a/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp b/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp new file mode 100644 index 0000000..34f1082 --- /dev/null +++ b/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp @@ -0,0 +1,564 @@ +// Copyright (C) 2016 Lauri Laanmets (Proekspert AS) +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "android/devicediscoverybroadcastreceiver_p.h" +#include +#include +#include +#include +#include +#include +#include "android/jni_android_p.h" +#include +#include +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID) + +typedef QHash JCachedBtTypes; +Q_GLOBAL_STATIC(JCachedBtTypes, cachedBtTypes) +typedef QHash JCachedMajorTypes; +Q_GLOBAL_STATIC(JCachedMajorTypes, cachedMajorTypes) + +typedef QHash JCachedMinorTypes; +Q_GLOBAL_STATIC(JCachedMinorTypes, cachedMinorTypes) + +static QBitArray initializeMinorCaches() +{ + const qsizetype numberOfMajorDeviceClasses = 11; // count QBluetoothDeviceInfo::MajorDeviceClass values + + // switch below used to ensure that we notice additions to MajorDeviceClass enum + const QBluetoothDeviceInfo::MajorDeviceClass classes = QBluetoothDeviceInfo::ComputerDevice; + switch (classes) { + case QBluetoothDeviceInfo::MiscellaneousDevice: + case QBluetoothDeviceInfo::ComputerDevice: + case QBluetoothDeviceInfo::PhoneDevice: + case QBluetoothDeviceInfo::NetworkDevice: + case QBluetoothDeviceInfo::AudioVideoDevice: + case QBluetoothDeviceInfo::PeripheralDevice: + case QBluetoothDeviceInfo::ImagingDevice: + case QBluetoothDeviceInfo::WearableDevice: + case QBluetoothDeviceInfo::ToyDevice: + case QBluetoothDeviceInfo::HealthDevice: + case QBluetoothDeviceInfo::UncategorizedDevice: + break; + default: + qCWarning(QT_BT_ANDROID) << "Unknown category of major device class:" << classes; + } + + return QBitArray(numberOfMajorDeviceClasses, false); +} + +Q_GLOBAL_STATIC_WITH_ARGS(QBitArray, initializedCacheTracker, (initializeMinorCaches())) + + +// class names +static const char javaBluetoothDeviceClassName[] = "android/bluetooth/BluetoothDevice"; +static const char javaBluetoothClassDeviceMajorClassName[] = "android/bluetooth/BluetoothClass$Device$Major"; +static const char javaBluetoothClassDeviceClassName[] = "android/bluetooth/BluetoothClass$Device"; + +// field names device type (LE vs classic) +static const char javaDeviceTypeClassic[] = "DEVICE_TYPE_CLASSIC"; +static const char javaDeviceTypeDual[] = "DEVICE_TYPE_DUAL"; +static const char javaDeviceTypeLE[] = "DEVICE_TYPE_LE"; +static const char javaDeviceTypeUnknown[] = "DEVICE_TYPE_UNKNOWN"; + +struct MajorClassJavaToQtMapping +{ + const char javaFieldName[14]; + QBluetoothDeviceInfo::MajorDeviceClass qtMajor : 16; +}; +static_assert(sizeof(MajorClassJavaToQtMapping) == 16); + +static constexpr MajorClassJavaToQtMapping majorMappings[] = { + { "AUDIO_VIDEO", QBluetoothDeviceInfo::AudioVideoDevice }, + { "COMPUTER", QBluetoothDeviceInfo::ComputerDevice }, + { "HEALTH", QBluetoothDeviceInfo::HealthDevice }, + { "IMAGING", QBluetoothDeviceInfo::ImagingDevice }, + { "MISC", QBluetoothDeviceInfo::MiscellaneousDevice }, + { "NETWORKING", QBluetoothDeviceInfo::NetworkDevice }, + { "PERIPHERAL", QBluetoothDeviceInfo::PeripheralDevice }, + { "PHONE", QBluetoothDeviceInfo::PhoneDevice }, + { "TOY", QBluetoothDeviceInfo::ToyDevice }, + { "UNCATEGORIZED", QBluetoothDeviceInfo::UncategorizedDevice }, + { "WEARABLE", QBluetoothDeviceInfo::WearableDevice }, +}; + +// QBluetoothDeviceInfo::MajorDeviceClass value plus 1 matches index +// UncategorizedDevice shifts to index 0 +static constexpr quint8 minorIndexSizes[] = { + 64, // QBluetoothDevice::UncategorizedDevice + 61, // QBluetoothDevice::MiscellaneousDevice + 18, // QBluetoothDevice::ComputerDevice + 35, // QBluetoothDevice::PhoneDevice + 62, // QBluetoothDevice::NetworkDevice + 0, // QBluetoothDevice::AudioVideoDevice + 56, // QBluetoothDevice::PeripheralDevice + 63, // QBluetoothDevice::ImagingDEvice + 49, // QBluetoothDevice::WearableDevice + 42, // QBluetoothDevice::ToyDevice + 26, // QBluetoothDevice::HealthDevice +}; + +struct MinorClassJavaToQtMapping +{ + char const * javaFieldName; + quint8 qtMinor; +}; + +static const MinorClassJavaToQtMapping minorMappings[] = { + // QBluetoothDevice::AudioVideoDevice -> 17 entries + { "AUDIO_VIDEO_CAMCORDER", QBluetoothDeviceInfo::Camcorder }, //index 0 + { "AUDIO_VIDEO_CAR_AUDIO", QBluetoothDeviceInfo::CarAudio }, + { "AUDIO_VIDEO_HANDSFREE", QBluetoothDeviceInfo::HandsFreeDevice }, + { "AUDIO_VIDEO_HEADPHONES", QBluetoothDeviceInfo::Headphones }, + { "AUDIO_VIDEO_HIFI_AUDIO", QBluetoothDeviceInfo::HiFiAudioDevice }, + { "AUDIO_VIDEO_LOUDSPEAKER", QBluetoothDeviceInfo::Loudspeaker }, + { "AUDIO_VIDEO_MICROPHONE", QBluetoothDeviceInfo::Microphone }, + { "AUDIO_VIDEO_PORTABLE_AUDIO", QBluetoothDeviceInfo::PortableAudioDevice }, + { "AUDIO_VIDEO_SET_TOP_BOX", QBluetoothDeviceInfo::SetTopBox }, + { "AUDIO_VIDEO_UNCATEGORIZED", QBluetoothDeviceInfo::UncategorizedAudioVideoDevice }, + { "AUDIO_VIDEO_VCR", QBluetoothDeviceInfo::Vcr }, + { "AUDIO_VIDEO_VIDEO_CAMERA", QBluetoothDeviceInfo::VideoCamera }, + { "AUDIO_VIDEO_VIDEO_CONFERENCING", QBluetoothDeviceInfo::VideoConferencing }, + { "AUDIO_VIDEO_VIDEO_DISPLAY_AND_LOUDSPEAKER", QBluetoothDeviceInfo::VideoDisplayAndLoudspeaker }, + { "AUDIO_VIDEO_VIDEO_GAMING_TOY", QBluetoothDeviceInfo::GamingDevice }, + { "AUDIO_VIDEO_VIDEO_MONITOR", QBluetoothDeviceInfo::VideoMonitor }, + { "AUDIO_VIDEO_WEARABLE_HEADSET", QBluetoothDeviceInfo::WearableHeadsetDevice }, + { nullptr, 0 }, // separator + + // QBluetoothDevice::ComputerDevice -> 7 entries + { "COMPUTER_UNCATEGORIZED", QBluetoothDeviceInfo::UncategorizedComputer }, // index 18 + { "COMPUTER_DESKTOP", QBluetoothDeviceInfo::DesktopComputer }, + { "COMPUTER_HANDHELD_PC_PDA", QBluetoothDeviceInfo::HandheldComputer }, + { "COMPUTER_LAPTOP", QBluetoothDeviceInfo::LaptopComputer }, + { "COMPUTER_PALM_SIZE_PC_PDA", QBluetoothDeviceInfo::HandheldClamShellComputer }, + { "COMPUTER_SERVER", QBluetoothDeviceInfo::ServerComputer }, + { "COMPUTER_WEARABLE", QBluetoothDeviceInfo::WearableComputer }, + { nullptr, 0 }, // separator + + // QBluetoothDevice::HealthDevice -> 8 entries + { "HEALTH_BLOOD_PRESSURE", QBluetoothDeviceInfo::HealthBloodPressureMonitor }, // index 26 + { "HEALTH_DATA_DISPLAY", QBluetoothDeviceInfo::HealthDataDisplay }, + { "HEALTH_GLUCOSE", QBluetoothDeviceInfo::HealthGlucoseMeter }, + { "HEALTH_PULSE_OXIMETER", QBluetoothDeviceInfo::HealthPulseOximeter }, + { "HEALTH_PULSE_RATE", QBluetoothDeviceInfo::HealthStepCounter }, + { "HEALTH_THERMOMETER", QBluetoothDeviceInfo::HealthThermometer }, + { "HEALTH_UNCATEGORIZED", QBluetoothDeviceInfo::UncategorizedHealthDevice }, + { "HEALTH_WEIGHING", QBluetoothDeviceInfo::HealthWeightScale }, + { nullptr, 0 }, // separator + + // QBluetoothDevice::PhoneDevice -> 6 entries + { "PHONE_CELLULAR", QBluetoothDeviceInfo::CellularPhone }, // index 35 + { "PHONE_CORDLESS", QBluetoothDeviceInfo::CordlessPhone }, + { "PHONE_ISDN", QBluetoothDeviceInfo::CommonIsdnAccessPhone }, + { "PHONE_MODEM_OR_GATEWAY", QBluetoothDeviceInfo::WiredModemOrVoiceGatewayPhone }, + { "PHONE_SMART", QBluetoothDeviceInfo::SmartPhone }, + { "PHONE_UNCATEGORIZED", QBluetoothDeviceInfo::UncategorizedPhone }, + { nullptr, 0 }, // separator + + // QBluetoothDevice::ToyDevice -> 6 entries + { "TOY_CONTROLLER", QBluetoothDeviceInfo::ToyController }, // index 42 + { "TOY_DOLL_ACTION_FIGURE", QBluetoothDeviceInfo::ToyDoll }, + { "TOY_GAME", QBluetoothDeviceInfo::ToyGame }, + { "TOY_ROBOT", QBluetoothDeviceInfo::ToyRobot }, + { "TOY_UNCATEGORIZED", QBluetoothDeviceInfo::UncategorizedToy }, + { "TOY_VEHICLE", QBluetoothDeviceInfo::ToyVehicle }, + { nullptr, 0 }, // separator + + // QBluetoothDevice::WearableDevice -> 6 entries + { "WEARABLE_GLASSES", QBluetoothDeviceInfo::WearableGlasses }, // index 49 + { "WEARABLE_HELMET", QBluetoothDeviceInfo::WearableHelmet }, + { "WEARABLE_JACKET", QBluetoothDeviceInfo::WearableJacket }, + { "WEARABLE_PAGER", QBluetoothDeviceInfo::WearablePager }, + { "WEARABLE_UNCATEGORIZED", QBluetoothDeviceInfo::UncategorizedWearableDevice }, + { "WEARABLE_WRIST_WATCH", QBluetoothDeviceInfo::WearableWristWatch }, + { nullptr, 0 }, // separator + + // QBluetoothDevice::PeripheralDevice -> 3 entries + // For some reason these are not mentioned in Android docs but still exist + { "PERIPHERAL_NON_KEYBOARD_NON_POINTING", QBluetoothDeviceInfo::UncategorizedPeripheral }, // index 56 + { "PERIPHERAL_KEYBOARD", QBluetoothDeviceInfo::KeyboardPeripheral }, + { "PERIPHERAL_POINTING", QBluetoothDeviceInfo::PointingDevicePeripheral }, + { "PERIPHERAL_KEYBOARD_POINTING", QBluetoothDeviceInfo::KeyboardWithPointingDevicePeripheral }, + { nullptr, 0 }, // separator + + // the following entries do not exist on Android + // we map them to the unknown minor version case + // QBluetoothDevice::Miscellaneous + { nullptr, 0 }, // index 61 & separator + + // QBluetoothDevice::NetworkDevice + { nullptr, 0 }, // index 62 & separator + + // QBluetoothDevice::ImagingDevice + { nullptr, 0 }, // index 63 & separator + + // QBluetoothDevice::UncategorizedDevice + { nullptr, 0 }, // index 64 & separator +}; + +/* + Advertising Data Type (AD type) for LE scan records, as defined in + https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile +*/ +enum ADType { + ADType16BitUuidIncomplete = 0x02, + ADType16BitUuidComplete = 0x03, + ADType32BitUuidIncomplete = 0x04, + ADType32BitUuidComplete = 0x05, + ADType128BitUuidIncomplete = 0x06, + ADType128BitUuidComplete = 0x07, + ADTypeShortenedLocalName = 0x08, + ADTypeCompleteLocalName = 0x09, + ADTypeServiceData16Bit = 0x16, + ADTypeServiceData32Bit = 0x20, + ADTypeServiceData128Bit = 0x21, + ADTypeManufacturerSpecificData = 0xff, + // .. more will be added when required +}; + +QBluetoothDeviceInfo::CoreConfigurations qtBtTypeForJavaBtType(jint javaType) +{ + const JCachedBtTypes::iterator it = cachedBtTypes()->find(javaType); + if (it == cachedBtTypes()->end()) { + + if (javaType == QJniObject::getStaticField( + javaBluetoothDeviceClassName, javaDeviceTypeClassic)) { + cachedBtTypes()->insert(javaType, + QBluetoothDeviceInfo::BaseRateCoreConfiguration); + return QBluetoothDeviceInfo::BaseRateCoreConfiguration; + } else if (javaType == QJniObject::getStaticField( + javaBluetoothDeviceClassName, javaDeviceTypeLE)) { + cachedBtTypes()->insert(javaType, + QBluetoothDeviceInfo::LowEnergyCoreConfiguration); + return QBluetoothDeviceInfo::LowEnergyCoreConfiguration; + } else if (javaType == QJniObject::getStaticField( + javaBluetoothDeviceClassName, javaDeviceTypeDual)) { + cachedBtTypes()->insert(javaType, + QBluetoothDeviceInfo::BaseRateAndLowEnergyCoreConfiguration); + return QBluetoothDeviceInfo::BaseRateAndLowEnergyCoreConfiguration; + } else if (javaType == QJniObject::getStaticField( + javaBluetoothDeviceClassName, javaDeviceTypeUnknown)) { + cachedBtTypes()->insert(javaType, + QBluetoothDeviceInfo::UnknownCoreConfiguration); + } else { + qCWarning(QT_BT_ANDROID) << "Unknown Bluetooth device type value"; + } + + return QBluetoothDeviceInfo::UnknownCoreConfiguration; + } else { + return it.value(); + } +} + +QBluetoothDeviceInfo::MajorDeviceClass resolveAndroidMajorClass(jint javaType) +{ + const JCachedMajorTypes::iterator it = cachedMajorTypes()->find(javaType); + if (it == cachedMajorTypes()->end()) { + QJniEnvironment env; + // precache all major device class fields + jint fieldValue; + QBluetoothDeviceInfo::MajorDeviceClass result = QBluetoothDeviceInfo::UncategorizedDevice; + auto clazz = env->FindClass(javaBluetoothClassDeviceMajorClassName); + for (const auto &majorMapping : majorMappings) { + auto fieldId = env->GetStaticFieldID(clazz, majorMapping.javaFieldName, "I"); + if (!env->ExceptionCheck()) + fieldValue = env->GetStaticIntField(clazz, fieldId); + if (env.checkAndClearExceptions()) { + qCWarning(QT_BT_ANDROID) << "Unknown BluetoothClass.Device.Major field" << javaType; + + // add fallback value because field not readable + cachedMajorTypes()->insert(javaType, QBluetoothDeviceInfo::UncategorizedDevice); + } else { + cachedMajorTypes()->insert(fieldValue, majorMapping.qtMajor); + } + + if (fieldValue == javaType) + result = majorMapping.qtMajor; + } + + return result; + } else { + return it.value(); + } +} + +/* + The index for major into the MinorClassJavaToQtMapping and initializedCacheTracker + is major+1 except for UncategorizedDevice which is at index 0. +*/ +int mappingIndexForMajor(QBluetoothDeviceInfo::MajorDeviceClass major) +{ + int mappingIndex = (int) major; + if (major == QBluetoothDeviceInfo::UncategorizedDevice) + mappingIndex = 0; + else + mappingIndex++; + + Q_ASSERT(mappingIndex >=0 + && mappingIndex <= (QBluetoothDeviceInfo::HealthDevice + 1)); + + return mappingIndex; +} + +void triggerCachingOfMinorsForMajor(QBluetoothDeviceInfo::MajorDeviceClass major) +{ + //qCDebug(QT_BT_ANDROID) << "Caching minor values for major" << major; + int mappingIndex = mappingIndexForMajor(major); + quint8 sizeIndex = minorIndexSizes[mappingIndex]; + + while (minorMappings[sizeIndex].javaFieldName != nullptr) { + jint fieldValue = QJniObject::getStaticField( + javaBluetoothClassDeviceClassName, minorMappings[sizeIndex].javaFieldName); + + Q_ASSERT(fieldValue >= 0); + cachedMinorTypes()->insert(fieldValue, minorMappings[sizeIndex].qtMinor); + sizeIndex++; + } + + initializedCacheTracker()->setBit(mappingIndex); +} + +quint8 resolveAndroidMinorClass(QBluetoothDeviceInfo::MajorDeviceClass major, jint javaMinor) +{ + // there are no minor device classes in java with value 0 + //qCDebug(QT_BT_ANDROID) << "received minor class device:" << javaMinor; + if (javaMinor == 0) + return 0; + + int mappingIndex = mappingIndexForMajor(major); + + // whenever we encounter a not yet seen major device class + // we populate the cache with all its related minor values + if (!initializedCacheTracker()->at(mappingIndex)) + triggerCachingOfMinorsForMajor(major); + + const JCachedMinorTypes::iterator it = cachedMinorTypes()->find(javaMinor); + if (it == cachedMinorTypes()->end()) + return 0; + else + return it.value(); +} + + +DeviceDiscoveryBroadcastReceiver::DeviceDiscoveryBroadcastReceiver(QObject* parent): AndroidBroadcastReceiver(parent) +{ + addAction(QJniObject::fromString( + valueForStaticField())); + addAction(QJniObject::fromString( + valueForStaticField())); + addAction(QJniObject::fromString( + valueForStaticField())); +} + +// Runs in Java thread +void DeviceDiscoveryBroadcastReceiver::onReceive(JNIEnv *env, jobject context, jobject intent) +{ + Q_UNUSED(context) + Q_UNUSED(env) + + QJniObject intentObject(intent); + const QString action = intentObject.callMethod("getAction").toString(); + + qCDebug(QT_BT_ANDROID) << "DeviceDiscoveryBroadcastReceiver::onReceive() - event:" << action; + + if (action == valueForStaticField()) { + emit finished(); + } else if (action == valueForStaticField()) { + emit discoveryStarted(); + } else if (action == valueForStaticField()) { + //get BluetoothDevice + QJniObject keyExtra = + QJniObject::fromString(valueForStaticField()); + const QJniObject bluetoothDevice = + intentObject.callMethod("getParcelableExtra", + keyExtra.object()); + + if (!bluetoothDevice.isValid()) + return; + + keyExtra = QJniObject::fromString(valueForStaticField()); + int rssi = intentObject.callMethod("getShortExtra", + keyExtra.object(), jshort(0)); + + const QBluetoothDeviceInfo info = retrieveDeviceInfo(bluetoothDevice, rssi); + if (info.isValid()) + emit deviceDiscovered(info, false); + } +} + +// Runs in Java thread +void DeviceDiscoveryBroadcastReceiver::onReceiveLeScan( + JNIEnv */*env*/, jobject jBluetoothDevice, jint rssi, jbyteArray scanRecord) +{ + const QJniObject bluetoothDevice(jBluetoothDevice); + if (!bluetoothDevice.isValid()) + return; + + const QBluetoothDeviceInfo info = retrieveDeviceInfo(bluetoothDevice, rssi, scanRecord); + if (info.isValid()) + emit deviceDiscovered(info, true); +} + +QBluetoothDeviceInfo DeviceDiscoveryBroadcastReceiver::retrieveDeviceInfo(const QJniObject &bluetoothDevice, int rssi, jbyteArray scanRecord) +{ + const QString deviceName = bluetoothDevice.callMethod("getName").toString(); + const QBluetoothAddress deviceAddress( + bluetoothDevice.callMethod("getAddress").toString()); + const QJniObject bluetoothClass = + bluetoothDevice.callMethod("getBluetoothClass"); + + if (!bluetoothClass.isValid()) + return QBluetoothDeviceInfo(); + + QBluetoothDeviceInfo::MajorDeviceClass majorClass = resolveAndroidMajorClass( + bluetoothClass.callMethod("getMajorDeviceClass")); + // major device class is 5 bits from index 8 - 12 + quint32 classType = ((quint32(majorClass) & 0x1f) << 8); + + jint javaMinor = bluetoothClass.callMethod("getDeviceClass"); + quint8 minorDeviceType = resolveAndroidMinorClass(majorClass, javaMinor); + + // minor device class is 6 bits from index 2 - 7 + classType |= ((quint32(minorDeviceType) & 0x3f) << 2); + + static constexpr quint32 services[] = { + QBluetoothDeviceInfo::PositioningService, + QBluetoothDeviceInfo::NetworkingService, + QBluetoothDeviceInfo::RenderingService, + QBluetoothDeviceInfo::CapturingService, + QBluetoothDeviceInfo::ObjectTransferService, + QBluetoothDeviceInfo::AudioService, + QBluetoothDeviceInfo::TelephonyService, + QBluetoothDeviceInfo::InformationService, + }; + + // Matching BluetoothClass.Service values + quint32 serviceResult = 0; + for (quint32 current : services) { + int androidId = (current << 16); // Android values shift by 2 bytes compared to Qt enums + if (bluetoothClass.callMethod("hasService", androidId)) + serviceResult |= current; + } + + // service class info is 11 bits from index 13 - 23 + classType |= (serviceResult << 13); + + QBluetoothDeviceInfo info(deviceAddress, deviceName, classType); + info.setRssi(rssi); + QJniEnvironment env; + if (scanRecord != nullptr) { + // Parse scan record + jboolean isCopy; + jbyte *elems = env->GetByteArrayElements(scanRecord, &isCopy); + const char *scanRecordBuffer = reinterpret_cast(elems); + const jsize scanRecordLength = env->GetArrayLength(scanRecord); + + QList serviceUuids; + jsize i = 0; + + // Spec 4.2, Vol 3, Part C, Chapter 11 + QString localName; + while (i < scanRecordLength) { + // sizeof(EIR Data) = sizeof(Length) + sizeof(EIR data Type) + sizeof(EIR Data) + // Length = sizeof(EIR data Type) + sizeof(EIR Data) + + const int nBytes = scanRecordBuffer[i]; + if (nBytes == 0) + break; + + if (i >= scanRecordLength - nBytes) + break; + + const int adType = scanRecordBuffer[i+1]; + const char *dataPtr = &scanRecordBuffer[i+2]; + QBluetoothUuid foundService; + + switch (adType) { + case ADType16BitUuidIncomplete: + case ADType16BitUuidComplete: + foundService = QBluetoothUuid(qFromLittleEndian(dataPtr)); + break; + case ADType32BitUuidIncomplete: + case ADType32BitUuidComplete: + foundService = QBluetoothUuid(qFromLittleEndian(dataPtr)); + break; + case ADType128BitUuidIncomplete: + case ADType128BitUuidComplete: + foundService = + QBluetoothUuid(qToBigEndian(qFromLittleEndian(dataPtr))); + break; + case ADTypeServiceData16Bit: + if (nBytes >= 3) { + info.setServiceData(QBluetoothUuid(qFromLittleEndian(dataPtr)), + QByteArray(dataPtr + 2, nBytes - 3)); + } + break; + case ADTypeServiceData32Bit: + if (nBytes >= 5) { + info.setServiceData(QBluetoothUuid(qFromLittleEndian(dataPtr)), + QByteArray(dataPtr + 4, nBytes - 5)); + } + break; + case ADTypeServiceData128Bit: + if (nBytes >= 17) { + info.setServiceData(QBluetoothUuid(qToBigEndian( + qFromLittleEndian(dataPtr))), + QByteArray(dataPtr + 16, nBytes - 17)); + } + break; + case ADTypeManufacturerSpecificData: + if (nBytes >= 3) { + info.setManufacturerData(qFromLittleEndian(dataPtr), + QByteArray(dataPtr + 2, nBytes - 3)); + } + break; + // According to Spec 5.0, Vol 3, Part C, Chapter 12.1 + // the device's local name is utf8 encoded + case ADTypeShortenedLocalName: + if (localName.isEmpty()) + localName = QString::fromUtf8(dataPtr, nBytes - 1); + break; + case ADTypeCompleteLocalName: + localName = QString::fromUtf8(dataPtr, nBytes - 1); + break; + default: + // qWarning() << "Unhandled AD Type" << Qt::hex << adType; + // no other types supported yet and therefore skipped + // https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile + break; + } + + i += nBytes + 1; + + if (!foundService.isNull() && !serviceUuids.contains(foundService)) + serviceUuids.append(foundService); + } + + if (info.name().isEmpty()) + info.setName(localName); + + info.setServiceUuids(serviceUuids); + + env->ReleaseByteArrayElements(scanRecord, elems, JNI_ABORT); + } + + auto methodId = env.findMethod(bluetoothDevice.objectClass(), "getType", "()I"); + jint javaBtType = env->CallIntMethod(bluetoothDevice.object(), methodId); + if (!env.checkAndClearExceptions()) { + info.setCoreConfigurations(qtBtTypeForJavaBtType(javaBtType)); + } + + return info; +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/android/devicediscoverybroadcastreceiver_p.h b/src/bluetooth/android/devicediscoverybroadcastreceiver_p.h new file mode 100644 index 0000000..ba677ac --- /dev/null +++ b/src/bluetooth/android/devicediscoverybroadcastreceiver_p.h @@ -0,0 +1,46 @@ +// Copyright (C) 2016 Lauri Laanmets (Proekspert AS) +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef DEVICEDISCOVERYBROADCASTRECEIVER_H +#define DEVICEDISCOVERYBROADCASTRECEIVER_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 "android/androidbroadcastreceiver_p.h" +#include + +QT_BEGIN_NAMESPACE + +class QBluetoothDeviceInfo; + +class DeviceDiscoveryBroadcastReceiver : public AndroidBroadcastReceiver +{ + Q_OBJECT +public: + DeviceDiscoveryBroadcastReceiver(QObject* parent = nullptr); + virtual void onReceive(JNIEnv *env, jobject context, jobject intent); + virtual void onReceiveLeScan(JNIEnv *env, jobject jBluetoothDevice, jint rssi, + jbyteArray scanRecord); + +signals: + void deviceDiscovered(const QBluetoothDeviceInfo &info, bool isLeScanResult); + void discoveryStarted(); + void finished(); + +private: + QBluetoothDeviceInfo retrieveDeviceInfo(const QJniObject& bluetoothDevice, + int rssi, jbyteArray scanRecord = nullptr); +}; + +QT_END_NAMESPACE +#endif // DEVICEDISCOVERYBROADCASTRECEIVER_H diff --git a/src/bluetooth/android/inputstreamthread.cpp b/src/bluetooth/android/inputstreamthread.cpp new file mode 100644 index 0000000..14fab8b --- /dev/null +++ b/src/bluetooth/android/inputstreamthread.cpp @@ -0,0 +1,89 @@ +// Copyright (C) 2016 Lauri Laanmets (Proekspert AS) +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include +#include + +#include "android/inputstreamthread_p.h" +#include "android/jni_android_p.h" +#include "qbluetoothsocket_android_p.h" + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID) + +InputStreamThread::InputStreamThread(QBluetoothSocketPrivateAndroid *socket) + : QObject(), m_socket_p(socket), expectClosure(false) +{ +} + +bool InputStreamThread::run() +{ + QMutexLocker lock(&m_mutex); + + javaInputStreamThread = QJniObject::construct(); + if (!javaInputStreamThread.isValid() || !m_socket_p->inputStream.isValid()) + return false; + + javaInputStreamThread.callMethod("setInputStream", + m_socket_p->inputStream.object()); + javaInputStreamThread.setField("qtObject", reinterpret_cast(this)); + javaInputStreamThread.setField("logEnabled", QT_BT_ANDROID().isDebugEnabled()); + + javaInputStreamThread.callMethod("start"); + + return true; +} + +qint64 InputStreamThread::bytesAvailable() const +{ + QMutexLocker locker(&m_mutex); + return m_socket_p->rxBuffer.size(); +} + +bool InputStreamThread::canReadLine() const +{ + QMutexLocker locker(&m_mutex); + return m_socket_p->rxBuffer.canReadLine(); +} + +qint64 InputStreamThread::readData(char *data, qint64 maxSize) +{ + QMutexLocker locker(&m_mutex); + + if (!m_socket_p->rxBuffer.isEmpty()) + return m_socket_p->rxBuffer.read(data, maxSize); + + return 0; +} + +//inside the java thread +void InputStreamThread::javaThreadErrorOccurred(int errorCode) +{ + QMutexLocker lock(&m_mutex); + + if (!expectClosure) + emit errorOccurred(errorCode); + else + emit errorOccurred(-1); // magic error, -1 means error was expected due to expected close() +} + +//inside the java thread +void InputStreamThread::javaReadyRead(jbyteArray buffer, int bufferLength) +{ + QJniEnvironment env; + + QMutexLocker lock(&m_mutex); + char *writePtr = m_socket_p->rxBuffer.reserve(bufferLength); + env->GetByteArrayRegion(buffer, 0, bufferLength, reinterpret_cast(writePtr)); + emit dataAvailable(); +} + +void InputStreamThread::prepareForClosure() +{ + QMutexLocker lock(&m_mutex); + expectClosure = true; +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/android/inputstreamthread_p.h b/src/bluetooth/android/inputstreamthread_p.h new file mode 100644 index 0000000..7aa8e69 --- /dev/null +++ b/src/bluetooth/android/inputstreamthread_p.h @@ -0,0 +1,58 @@ +// Copyright (C) 2017 Lauri Laanmets (Proekspert AS) +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef INPUTSTREAMTHREAD_H +#define INPUTSTREAMTHREAD_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 QBluetoothSocketPrivateAndroid; + +class InputStreamThread : public QObject +{ + Q_OBJECT +public: + explicit InputStreamThread(QBluetoothSocketPrivateAndroid *socket_p); + + qint64 bytesAvailable() const; + bool canReadLine() const; + bool run(); + + qint64 readData(char *data, qint64 maxSize); + void javaThreadErrorOccurred(int errorCode); + void javaReadyRead(jbyteArray buffer, int bufferLength); + + void prepareForClosure(); + +signals: + void dataAvailable(); + void errorOccurred(int errorCode); + +private: + QBluetoothSocketPrivateAndroid *m_socket_p; + QJniObject javaInputStreamThread; + mutable QMutex m_mutex; + bool expectClosure; +}; + +QT_END_NAMESPACE + +#endif // INPUTSTREAMTHREAD_H diff --git a/src/bluetooth/android/jni_android.cpp b/src/bluetooth/android/jni_android.cpp new file mode 100644 index 0000000..90641b6 --- /dev/null +++ b/src/bluetooth/android/jni_android.cpp @@ -0,0 +1,220 @@ +// Copyright (C) 2016 Lauri Laanmets (Proekspert AS) +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include +#include +#include +#include +#include "android/jni_android_p.h" +#include "android/androidbroadcastreceiver_p.h" +#include "android/serveracceptancethread_p.h" +#include "android/inputstreamthread_p.h" +#include "android/lowenergynotificationhub_p.h" + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID) + +typedef QHash JCachedStringFields; +Q_GLOBAL_STATIC(JCachedStringFields, cachedStringFields) +Q_GLOBAL_STATIC(QMutex, stringCacheMutex); + +/* + * This function operates on the assumption that each + * field is of type java/lang/String. + */ +QString valueFromStaticFieldCache(const char *key, const char *className, const char *fieldName) +{ + QMutexLocker lock(stringCacheMutex()); + JCachedStringFields::iterator it = cachedStringFields()->find(key); + if (it == cachedStringFields()->end()) { + QJniEnvironment env; + QJniObject fieldValue = QJniObject::getStaticObjectField( + className, fieldName, "Ljava/lang/String;"); + if (!fieldValue.isValid()) { + cachedStringFields()->insert(key, {}); + return {}; + } + const QString string = fieldValue.toString(); + cachedStringFields()->insert(key, string); + return string; + } else { + return it.value(); + } +} + +void QtBroadcastReceiver_jniOnReceive(JNIEnv *env, jobject /*javaObject*/, + jlong qtObject, QtJniTypes::Context context, + QtJniTypes::Intent intent) +{ + reinterpret_cast(qtObject)->onReceive(env, context.object(), intent.object()); +} +Q_DECLARE_JNI_NATIVE_METHOD(QtBroadcastReceiver_jniOnReceive, jniOnReceive) + +static void QtBluetoothSocketServer_errorOccurred(JNIEnv */*env*/, jobject /*javaObject*/, + jlong qtObject, jint errorCode) +{ + reinterpret_cast(qtObject)->javaThreadErrorOccurred(errorCode); +} +Q_DECLARE_JNI_NATIVE_METHOD(QtBluetoothSocketServer_errorOccurred, errorOccurred) + +static void QtBluetoothSocketServer_newSocket(JNIEnv */*env*/, jobject /*javaObject*/, + jlong qtObject, QtJniTypes::BluetoothSocket socket) +{ + reinterpret_cast(qtObject)->javaNewSocket(socket.object()); +} +Q_DECLARE_JNI_NATIVE_METHOD(QtBluetoothSocketServer_newSocket, newSocket) + +static void QtBluetoothInputStreamThread_errorOccurred(JNIEnv */*env*/, jobject /*javaObject*/, + jlong qtObject, jint errorCode) +{ + reinterpret_cast(qtObject)->javaThreadErrorOccurred(errorCode); +} +Q_DECLARE_JNI_NATIVE_METHOD(QtBluetoothInputStreamThread_errorOccurred, errorOccurred) + +static void QtBluetoothInputStreamThread_readyData(JNIEnv */*env*/, jobject /*javaObject*/, + jlong qtObject, jbyteArray buffer, jint bufferLength) +{ + reinterpret_cast(qtObject)->javaReadyRead(buffer, bufferLength); +} +Q_DECLARE_JNI_NATIVE_METHOD(QtBluetoothInputStreamThread_readyData, readyData) + +void QtBluetoothLE_leScanResult(JNIEnv *env, jobject, jlong qtObject, + QtJniTypes::BluetoothDevice bluetoothDevice, jint rssi, + jbyteArray scanRecord) +{ + if (Q_UNLIKELY(qtObject == 0)) + return; + + reinterpret_cast(qtObject)->onReceiveLeScan( + env, bluetoothDevice.object(), rssi, + scanRecord); +} +Q_DECLARE_JNI_NATIVE_METHOD(QtBluetoothLE_leScanResult, leScanResult) + +static const char logTag[] = "QtBluetooth"; +static const char classErrorMsg[] = "Can't find class \"%s\""; + +#define FIND_AND_CHECK_CLASS(CLASS_NAME) \ +clazz = env.findClass(); \ +if (!clazz) { \ + __android_log_print(ANDROID_LOG_FATAL, logTag, classErrorMsg, \ + QtJniTypes::Traits::className().data()); \ + return JNI_FALSE; \ +} \ + +#define LEHUB_SCOPED_METHOD(Method) Q_JNI_NATIVE_SCOPED_METHOD(Method, LowEnergyNotificationHub) + +static bool registerNatives() +{ + jclass clazz; + QJniEnvironment env; + + FIND_AND_CHECK_CLASS(QtJniTypes::QtBtBroadcastReceiver); + if (!env.registerNativeMethods(clazz, + { + Q_JNI_NATIVE_METHOD(QtBroadcastReceiver_jniOnReceive) + })) + { + __android_log_print(ANDROID_LOG_FATAL, logTag, + "registerNativeMethods for BroadcastReceiver failed"); + return false; + } + + FIND_AND_CHECK_CLASS(QtJniTypes::QtBtLECentral); + if (!env.registerNativeMethods(clazz, + { + Q_JNI_NATIVE_METHOD(QtBluetoothLE_leScanResult), + LEHUB_SCOPED_METHOD(lowEnergy_connectionChange), + LEHUB_SCOPED_METHOD(lowEnergy_mtuChanged), + LEHUB_SCOPED_METHOD(lowEnergy_servicesDiscovered), + LEHUB_SCOPED_METHOD(lowEnergy_serviceDetailsDiscovered), + LEHUB_SCOPED_METHOD(lowEnergy_characteristicRead), + LEHUB_SCOPED_METHOD(lowEnergy_descriptorRead), + LEHUB_SCOPED_METHOD(lowEnergy_characteristicWritten), + LEHUB_SCOPED_METHOD(lowEnergy_descriptorWritten), + LEHUB_SCOPED_METHOD(lowEnergy_characteristicChanged), + LEHUB_SCOPED_METHOD(lowEnergy_serviceError), + LEHUB_SCOPED_METHOD(lowEnergy_remoteRssiRead) + })) + { + __android_log_print(ANDROID_LOG_FATAL, logTag, + "registerNativeMethods for QBLuetoothLE failed"); + return false; + } + + FIND_AND_CHECK_CLASS(QtJniTypes::QtBtLEServer); + if (!env.registerNativeMethods(clazz, + { + LEHUB_SCOPED_METHOD(lowEnergy_connectionChange), + LEHUB_SCOPED_METHOD(lowEnergy_mtuChanged), + LEHUB_SCOPED_METHOD(lowEnergy_advertisementError), + LEHUB_SCOPED_METHOD(lowEnergy_serverCharacteristicChanged), + LEHUB_SCOPED_METHOD(lowEnergy_serverDescriptorWritten) + })) + { + __android_log_print(ANDROID_LOG_FATAL, logTag, + "registerNativeMethods for QBLuetoothLEServer failed"); + return false; + } + + FIND_AND_CHECK_CLASS(QtJniTypes::QtBtSocketServer); + if (!env.registerNativeMethods(clazz, + { + Q_JNI_NATIVE_METHOD(QtBluetoothSocketServer_errorOccurred), + Q_JNI_NATIVE_METHOD(QtBluetoothSocketServer_newSocket) + })) + { + __android_log_print(ANDROID_LOG_FATAL, logTag, + "registerNativeMethods for SocketServer failed"); + return false; + } + + FIND_AND_CHECK_CLASS(QtJniTypes::QtBtInputStreamThread); + if (!env.registerNativeMethods(clazz, + { + Q_JNI_NATIVE_METHOD(QtBluetoothInputStreamThread_errorOccurred), + Q_JNI_NATIVE_METHOD(QtBluetoothInputStreamThread_readyData) + })) + { + __android_log_print(ANDROID_LOG_FATAL, logTag, + "registerNativeMethods for InputStreamThread failed"); + return false; + } + + return true; +} + +QT_END_NAMESPACE + +Q_BLUETOOTH_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; + + UnionJNIEnvToVoid uenv; + uenv.venv = 0; + + if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_6) != JNI_OK) { + __android_log_print(ANDROID_LOG_FATAL, logTag, "GetEnv failed"); + return -1; + } + + if (!registerNatives()) { + __android_log_print(ANDROID_LOG_FATAL, logTag, "registerNatives failed"); + return -1; + } + + if (QT_BT_ANDROID().isDebugEnabled()) + __android_log_print(ANDROID_LOG_INFO, logTag, "Bluetooth start"); + + return JNI_VERSION_1_6; +} diff --git a/src/bluetooth/android/jni_android_p.h b/src/bluetooth/android/jni_android_p.h new file mode 100644 index 0000000..b94a847 --- /dev/null +++ b/src/bluetooth/android/jni_android_p.h @@ -0,0 +1,140 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef JNI_ANDROID_P_H +#define JNI_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 "qbluetooth.h" +#include +#include +#include + +QT_BEGIN_NAMESPACE + +// CLASS declaration implies also TYPE declaration +Q_DECLARE_JNI_CLASS(QtBtBroadcastReceiver, + "org/qtproject/qt/android/bluetooth/QtBluetoothBroadcastReceiver"); +Q_DECLARE_JNI_CLASS(QtBtGattCharacteristic, + "org/qtproject/qt/android/bluetooth/QtBluetoothGattCharacteristic"); +Q_DECLARE_JNI_CLASS(QtBtGattDescriptor, + "org/qtproject/qt/android/bluetooth/QtBluetoothGattDescriptor"); +Q_DECLARE_JNI_CLASS(QtBtInputStreamThread, + "org/qtproject/qt/android/bluetooth/QtBluetoothInputStreamThread") +Q_DECLARE_JNI_CLASS(QtBtSocketServer, "org/qtproject/qt/android/bluetooth/QtBluetoothSocketServer") +Q_DECLARE_JNI_CLASS(QtBtLEServer, "org/qtproject/qt/android/bluetooth/QtBluetoothLEServer") +Q_DECLARE_JNI_CLASS(QtBtLECentral, "org/qtproject/qt/android/bluetooth/QtBluetoothLE") +Q_DECLARE_JNI_CLASS(BluetoothAdapter, "android/bluetooth/BluetoothAdapter") +Q_DECLARE_JNI_CLASS(ParcelUuid, "android/os/ParcelUuid") +Q_DECLARE_JNI_CLASS(AdvertiseDataBuilder, "android/bluetooth/le/AdvertiseData$Builder") +Q_DECLARE_JNI_CLASS(AdvertiseSettingsBuilder, "android/bluetooth/le/AdvertiseSettings$Builder") +Q_DECLARE_JNI_CLASS(BluetoothGattService, "android/bluetooth/BluetoothGattService") +Q_DECLARE_JNI_CLASS(BluetoothGattDescriptor, "android/bluetooth/BluetoothGattDescriptor") +Q_DECLARE_JNI_CLASS(BluetoothGattCharacteristic, "android/bluetooth/BluetoothGattCharacteristic") +Q_DECLARE_JNI_CLASS(BluetoothDevice, "android/bluetooth/BluetoothDevice") +Q_DECLARE_JNI_CLASS(IntentFilter, "android/content/IntentFilter") +Q_DECLARE_JNI_CLASS(AndroidContext, "android/content/Context") +Q_DECLARE_JNI_CLASS(UUID, "java/util/UUID") + +Q_DECLARE_JNI_TYPE(ParcelableArray, "[Landroid/os/Parcelable;") +Q_DECLARE_JNI_TYPE(ParcelUuidArray, "[Landroid/os/ParcelUuid;") +Q_DECLARE_JNI_TYPE(StringArray, "[Ljava/lang/String;") + +Q_DECLARE_JNI_CLASS(BluetoothManager, "android/bluetooth/BluetoothManager") +Q_DECLARE_JNI_CLASS(AdvertiseData, "android/bluetooth/le/AdvertiseData") +Q_DECLARE_JNI_CLASS(AdvertiseSettings, "android/bluetooth/le/AdvertiseSettings") +Q_DECLARE_JNI_CLASS(InputStream, "java/io/InputStream") +Q_DECLARE_JNI_CLASS(OutputStream, "java/io/OutputStream") +Q_DECLARE_JNI_CLASS(BluetoothSocket, "android/bluetooth/BluetoothSocket") +Q_DECLARE_JNI_CLASS(BroadcastReceiver, "android/content/BroadcastReceiver") +Q_DECLARE_JNI_CLASS(BluetoothClass, "android/bluetooth/BluetoothClass") +Q_DECLARE_JNI_CLASS(Parcelable, "android/os/Parcelable") +Q_DECLARE_JNI_CLASS(Intent, "android/content/Intent") +Q_DECLARE_JNI_CLASS(Bundle, "android/os/Bundle") +Q_DECLARE_JNI_CLASS(List, "java/util/List") + +// QLowEnergyHandle is a quint16, ensure it is interpreted as jint +template<> +constexpr auto QtJniTypes::Traits::signature() +{ + return QtJniTypes::Traits::signature(); +} + +enum JavaNames { + BluetoothAdapter = 0, + BluetoothDevice, + ActionAclConnected, + ActionAclDisconnected, + ActionBondStateChanged, + ActionDiscoveryStarted, + ActionDiscoveryFinished, + ActionFound, + ActionScanModeChanged, + ActionUuid, + ExtraBondState, + ExtraDevice, + ExtraPairingKey, + ExtraPairingVariant, + ExtraRssi, + ExtraScanMode, + ExtraUuid +}; + +QString valueFromStaticFieldCache(const char *key, const char *className, const char *fieldName); + + +template +QString valueForStaticField() +{ + constexpr auto className = QtJniTypes::Traits::className(); + constexpr auto fieldName = []() -> auto { + if constexpr (Field == JavaNames::ActionAclConnected) + return QtJniTypes::CTString("ACTION_ACL_CONNECTED"); + else if constexpr (Field == ActionAclDisconnected) + return QtJniTypes::CTString("ACTION_ACL_DISCONNECTED"); + else if constexpr (Field == ActionBondStateChanged) + return QtJniTypes::CTString("ACTION_BOND_STATE_CHANGED"); + else if constexpr (Field == ActionDiscoveryStarted) + return QtJniTypes::CTString("ACTION_DISCOVERY_STARTED"); + else if constexpr (Field == ActionDiscoveryFinished) + return QtJniTypes::CTString("ACTION_DISCOVERY_FINISHED"); + else if constexpr (Field == ActionFound) + return QtJniTypes::CTString("ACTION_FOUND"); + else if constexpr (Field == ActionScanModeChanged) + return QtJniTypes::CTString("ACTION_SCAN_MODE_CHANGED"); + else if constexpr (Field == ActionUuid) + return QtJniTypes::CTString("ACTION_UUID"); + else if constexpr (Field == ExtraBondState) + return QtJniTypes::CTString("EXTRA_BOND_STATE"); + else if constexpr (Field == ExtraDevice) + return QtJniTypes::CTString("EXTRA_DEVICE"); + else if constexpr (Field == ExtraPairingKey) + return QtJniTypes::CTString("EXTRA_PAIRING_KEY"); + else if constexpr (Field == ExtraPairingVariant) + return QtJniTypes::CTString("EXTRA_PAIRING_VARIANT"); + else if constexpr (Field == ExtraRssi) + return QtJniTypes::CTString("EXTRA_RSSI"); + else if constexpr (Field == ExtraScanMode) + return QtJniTypes::CTString("EXTRA_SCAN_MODE"); + else if constexpr (Field == ExtraUuid) + return QtJniTypes::CTString("EXTRA_UUID"); + else + static_assert(QtPrivate::value_dependent_false()); + }(); + + return valueFromStaticFieldCache(className + fieldName, className.data(), fieldName.data()); +} + +QT_END_NAMESPACE + +#endif // JNI_ANDROID_P_H diff --git a/src/bluetooth/android/localdevicebroadcastreceiver.cpp b/src/bluetooth/android/localdevicebroadcastreceiver.cpp new file mode 100644 index 0000000..b1b7837 --- /dev/null +++ b/src/bluetooth/android/localdevicebroadcastreceiver.cpp @@ -0,0 +1,131 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include +#include +#include "localdevicebroadcastreceiver_p.h" +#include "android/jni_android_p.h" + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID) + +const char *scanModes[] = {"SCAN_MODE_NONE", "SCAN_MODE_CONNECTABLE", "SCAN_MODE_CONNECTABLE_DISCOVERABLE"}; +const char *bondModes[] = {"BOND_NONE", "BOND_BONDING", "BOND_BONDED"}; + +LocalDeviceBroadcastReceiver::LocalDeviceBroadcastReceiver(QObject *parent) : + AndroidBroadcastReceiver(parent), previousScanMode(0) +{ + addAction(QJniObject::fromString( + valueForStaticField())); + addAction(QJniObject::fromString( + valueForStaticField())); + addAction(QJniObject::fromString( + valueForStaticField())); + addAction(QJniObject::fromString( + valueForStaticField())); + + //cache integer values for host & bonding mode + //don't use the java fields directly but refer to them by name + for (uint i = 0; i < (sizeof(hostModePreset)/sizeof(hostModePreset[0])); i++) { + hostModePreset[i] = QJniObject::getStaticField( + QtJniTypes::Traits::className(), + scanModes[i]); + } + + for (uint i = 0; i < (sizeof(bondingModePreset)/sizeof(bondingModePreset[0])); i++) { + bondingModePreset[i] = QJniObject::getStaticField( + QtJniTypes::Traits::className(), + bondModes[i]); + } +} + +void LocalDeviceBroadcastReceiver::onReceive(JNIEnv *env, jobject context, jobject intent) +{ + Q_UNUSED(context); + Q_UNUSED(env); + + QJniObject intentObject(intent); + const QString action = intentObject.callMethod("getAction").toString(); + qCDebug(QT_BT_ANDROID) << QStringLiteral("LocalDeviceBroadcastReceiver::onReceive() - event: %1").arg(action); + + if (action == valueForStaticField()) { + + const QJniObject extrasBundle = + intentObject.callMethod("getExtras"); + const QJniObject keyExtra = + QJniObject::fromString(valueForStaticField()); + + int extra = extrasBundle.callMethod("getInt", keyExtra.object()); + + if (previousScanMode != extra) { + previousScanMode = extra; + + if (extra == hostModePreset[0]) + emit hostModeStateChanged(QBluetoothLocalDevice::HostPoweredOff); + else if (extra == hostModePreset[1]) + emit hostModeStateChanged(QBluetoothLocalDevice::HostConnectable); + else if (extra == hostModePreset[2]) + emit hostModeStateChanged(QBluetoothLocalDevice::HostDiscoverable); + else + qCWarning(QT_BT_ANDROID) << "Unknown Host State"; + } + } else if (action == valueForStaticField()) { + //get BluetoothDevice + QJniObject keyExtra = QJniObject::fromString( + valueForStaticField()); + const QJniObject bluetoothDevice = + intentObject.callMethod("getParcelableExtra", + keyExtra.object()); + + //get new bond state + keyExtra = QJniObject::fromString(valueForStaticField()); + const QJniObject extrasBundle = + intentObject.callMethod("getExtras"); + int bondState = extrasBundle.callMethod("getInt", keyExtra.object()); + + QBluetoothAddress address(bluetoothDevice.callMethod("getAddress").toString()); + if (address.isNull()) + return; + + if (bondState == bondingModePreset[0]) + emit pairingStateChanged(address, QBluetoothLocalDevice::Unpaired); + else if (bondState == bondingModePreset[1]) + ; //we ignore this as Qt doesn't have equivalent API value + else if (bondState == bondingModePreset[2]) + emit pairingStateChanged(address, QBluetoothLocalDevice::Paired); + else + qCWarning(QT_BT_ANDROID) << "Unknown BOND_STATE_CHANGED value:" << bondState; + + } else if (action == valueForStaticField() || + action == valueForStaticField()) { + + const QString connectEvent = valueForStaticField(); + const bool isConnectEvent = + action == connectEvent ? true : false; + + //get BluetoothDevice + const QJniObject keyExtra = + QJniObject::fromString(valueForStaticField()); + QJniObject bluetoothDevice = + intentObject.callMethod("getParcelableExtra", + keyExtra.object()); + + QBluetoothAddress address(bluetoothDevice.callMethod("getAddress").toString()); + if (address.isNull()) + return; + + emit connectDeviceChanges(address, isConnectEvent); + } +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/android/localdevicebroadcastreceiver_p.h b/src/bluetooth/android/localdevicebroadcastreceiver_p.h new file mode 100644 index 0000000..9f0f40d --- /dev/null +++ b/src/bluetooth/android/localdevicebroadcastreceiver_p.h @@ -0,0 +1,48 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "android/androidbroadcastreceiver_p.h" +#include +#include + +// +// 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 LOCALDEVICEBROADCASTRECEIVER_H +#define LOCALDEVICEBROADCASTRECEIVER_H + +QT_BEGIN_NAMESPACE + +class LocalDeviceBroadcastReceiver : public AndroidBroadcastReceiver +{ + Q_OBJECT +public: + explicit LocalDeviceBroadcastReceiver(QObject *parent = nullptr); + virtual ~LocalDeviceBroadcastReceiver() {} + virtual void onReceive(JNIEnv *env, jobject context, jobject intent); + virtual void onReceiveLeScan(JNIEnv *, jobject, jint, jbyteArray) {} + +signals: + void hostModeStateChanged(QBluetoothLocalDevice::HostMode state); + void pairingStateChanged(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing); + void connectDeviceChanges(const QBluetoothAddress &address, bool isConnectEvent); + +private: + int previousScanMode; + QJniObject pairingDevice; + + int bondingModePreset[3]; + int hostModePreset[3]; +}; + +QT_END_NAMESPACE + +#endif // LOCALDEVICEBROADCASTRECEIVER_H diff --git a/src/bluetooth/android/lowenergynotificationhub.cpp b/src/bluetooth/android/lowenergynotificationhub.cpp new file mode 100644 index 0000000..cf79059 --- /dev/null +++ b/src/bluetooth/android/lowenergynotificationhub.cpp @@ -0,0 +1,355 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "lowenergynotificationhub_p.h" +#include "android/jni_android_p.h" + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +typedef QHash HubMapType; +Q_GLOBAL_STATIC(HubMapType, hubMap) + +QReadWriteLock LowEnergyNotificationHub::lock; + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID) + +LowEnergyNotificationHub::LowEnergyNotificationHub(const QBluetoothAddress &remote, + bool isPeripheral, QObject *parent) + : QObject(parent), javaToCtoken(0) +{ + QJniEnvironment env; + + if (isPeripheral) { + qCDebug(QT_BT_ANDROID) << "Creating Android Peripheral/Server support for BTLE"; + jBluetoothLe = QJniObject::construct( + QNativeInterface::QAndroidApplication::context()); + } else { + qCDebug(QT_BT_ANDROID) << "Creating Android Central/Client support for BTLE"; + const QJniObject address = + QJniObject::fromString(remote.toString()); + jBluetoothLe = QJniObject::construct( + address.object(), QNativeInterface::QAndroidApplication::context()); + } + + if (!jBluetoothLe.isValid()) return; + + // register C++ class pointer in Java + lock.lockForWrite(); + + while (true) { + javaToCtoken = QRandomGenerator::global()->generate(); + if (!hubMap()->contains(javaToCtoken)) + break; + } + + hubMap()->insert(javaToCtoken, this); + lock.unlock(); + + jBluetoothLe.setField("qtObject", javaToCtoken); +} + +LowEnergyNotificationHub::~LowEnergyNotificationHub() +{ + lock.lockForWrite(); + hubMap()->remove(javaToCtoken); + lock.unlock(); +} + +// runs in Java thread +void LowEnergyNotificationHub::lowEnergy_connectionChange(JNIEnv *, jobject, jlong qtObject, jint errorCode, jint newState) +{ + lock.lockForRead(); + LowEnergyNotificationHub *hub = hubMap()->value(qtObject); + lock.unlock(); + if (!hub) + return; + + QMetaObject::invokeMethod(hub, "connectionUpdated", Qt::QueuedConnection, + Q_ARG(QLowEnergyController::ControllerState, + (QLowEnergyController::ControllerState)newState), + Q_ARG(QLowEnergyController::Error, + (QLowEnergyController::Error)errorCode)); +} + +void LowEnergyNotificationHub::lowEnergy_mtuChanged( + JNIEnv *, jobject, jlong qtObject, jint mtu) +{ + lock.lockForRead(); + LowEnergyNotificationHub *hub = hubMap()->value(qtObject); + lock.unlock(); + if (!hub) + return; + + QMetaObject::invokeMethod(hub, "mtuChanged", Qt::QueuedConnection, Q_ARG(int, mtu)); +} + +void LowEnergyNotificationHub::lowEnergy_remoteRssiRead(JNIEnv *, jobject, jlong qtObject, + int rssi, bool success) +{ + lock.lockForRead(); + LowEnergyNotificationHub *hub = hubMap()->value(qtObject); + lock.unlock(); + if (!hub) + return; + + QMetaObject::invokeMethod(hub, "remoteRssiRead", Qt::QueuedConnection, + Q_ARG(int, rssi), Q_ARG(bool, success)); +} + + +void LowEnergyNotificationHub::lowEnergy_servicesDiscovered( + JNIEnv *, jobject, jlong qtObject, jint errorCode, jstring uuidList) +{ + lock.lockForRead(); + LowEnergyNotificationHub *hub = hubMap()->value(qtObject); + lock.unlock(); + if (!hub) + return; + + const QString uuids = QJniObject(uuidList).toString(); + QMetaObject::invokeMethod(hub, "servicesDiscovered", Qt::QueuedConnection, + Q_ARG(QLowEnergyController::Error, + (QLowEnergyController::Error)errorCode), + Q_ARG(QString, uuids)); +} + +void LowEnergyNotificationHub::lowEnergy_serviceDetailsDiscovered( + JNIEnv *, jobject, jlong qtObject, jstring uuid, jint startHandle, + jint endHandle) +{ + lock.lockForRead(); + LowEnergyNotificationHub *hub = hubMap()->value(qtObject); + lock.unlock(); + if (!hub) + return; + + const QString serviceUuid = QJniObject(uuid).toString(); + QMetaObject::invokeMethod(hub, "serviceDetailsDiscoveryFinished", + Qt::QueuedConnection, + Q_ARG(QString, serviceUuid), + Q_ARG(int, startHandle), + Q_ARG(int, endHandle)); +} + +void LowEnergyNotificationHub::lowEnergy_characteristicRead( + JNIEnv *env, jobject, jlong qtObject, jstring sUuid, jint handle, + jstring cUuid, jint properties, jbyteArray data) +{ + lock.lockForRead(); + LowEnergyNotificationHub *hub = hubMap()->value(qtObject); + lock.unlock(); + if (!hub) + return; + + const QBluetoothUuid serviceUuid(QJniObject(sUuid).toString()); + if (serviceUuid.isNull()) + return; + + const QBluetoothUuid charUuid(QJniObject(cUuid).toString()); + if (charUuid.isNull()) + return; + + QByteArray payload; + if (data) { //empty Java byte array is 0x0 + jsize length = env->GetArrayLength(data); + payload.resize(length); + env->GetByteArrayRegion(data, 0, length, + reinterpret_cast(payload.data())); + } + + QMetaObject::invokeMethod(hub, "characteristicRead", Qt::QueuedConnection, + Q_ARG(QBluetoothUuid, serviceUuid), + Q_ARG(int, handle), + Q_ARG(QBluetoothUuid, charUuid), + Q_ARG(int, properties), + Q_ARG(QByteArray, payload)); + +} + +void LowEnergyNotificationHub::lowEnergy_descriptorRead( + JNIEnv *env, jobject, jlong qtObject, jstring sUuid, jstring cUuid, + jint handle, jstring dUuid, jbyteArray data) +{ + lock.lockForRead(); + LowEnergyNotificationHub *hub = hubMap()->value(qtObject); + lock.unlock(); + if (!hub) + return; + + const QBluetoothUuid serviceUuid(QJniObject(sUuid).toString()); + if (serviceUuid.isNull()) + return; + + const QBluetoothUuid charUuid(QJniObject(cUuid).toString()); + const QBluetoothUuid descUuid(QJniObject(dUuid).toString()); + if (charUuid.isNull() || descUuid.isNull()) + return; + + QByteArray payload; + if (data) { //empty Java byte array is 0x0 + jsize length = env->GetArrayLength(data); + payload.resize(length); + env->GetByteArrayRegion(data, 0, length, + reinterpret_cast(payload.data())); + } + + QMetaObject::invokeMethod(hub, "descriptorRead", Qt::QueuedConnection, + Q_ARG(QBluetoothUuid, serviceUuid), + Q_ARG(QBluetoothUuid, charUuid), + Q_ARG(int, handle), + Q_ARG(QBluetoothUuid, descUuid), + Q_ARG(QByteArray, payload)); +} + +void LowEnergyNotificationHub::lowEnergy_characteristicWritten( + JNIEnv *env, jobject, jlong qtObject, jint charHandle, + jbyteArray data, jint errorCode) +{ + lock.lockForRead(); + LowEnergyNotificationHub *hub = hubMap()->value(qtObject); + lock.unlock(); + if (!hub) + return; + + QByteArray payload; + if (data) { //empty Java byte array is 0x0 + jsize length = env->GetArrayLength(data); + payload.resize(length); + env->GetByteArrayRegion(data, 0, length, + reinterpret_cast(payload.data())); + } + + QMetaObject::invokeMethod(hub, "characteristicWritten", Qt::QueuedConnection, + Q_ARG(int, charHandle), + Q_ARG(QByteArray, payload), + Q_ARG(QLowEnergyService::ServiceError, + (QLowEnergyService::ServiceError)errorCode)); +} + +void LowEnergyNotificationHub::lowEnergy_descriptorWritten( + JNIEnv *env, jobject, jlong qtObject, jint descHandle, + jbyteArray data, jint errorCode) +{ + lock.lockForRead(); + LowEnergyNotificationHub *hub = hubMap()->value(qtObject); + lock.unlock(); + if (!hub) + return; + + QByteArray payload; + if (data) { //empty Java byte array is 0x0 + jsize length = env->GetArrayLength(data); + payload.resize(length); + env->GetByteArrayRegion(data, 0, length, + reinterpret_cast(payload.data())); + } + + QMetaObject::invokeMethod(hub, "descriptorWritten", Qt::QueuedConnection, + Q_ARG(int, descHandle), + Q_ARG(QByteArray, payload), + Q_ARG(QLowEnergyService::ServiceError, + (QLowEnergyService::ServiceError)errorCode)); +} + +void LowEnergyNotificationHub::lowEnergy_serverDescriptorWritten( + JNIEnv *env, jobject, jlong qtObject, QtJniTypes::BluetoothGattDescriptor descriptor, + jbyteArray newValue) +{ + lock.lockForRead(); + LowEnergyNotificationHub *hub = hubMap()->value(qtObject); + lock.unlock(); + if (!hub) + return; + + QByteArray payload; + if (newValue) { //empty Java byte array is 0x0 + jsize length = env->GetArrayLength(newValue); + payload.resize(length); + env->GetByteArrayRegion(newValue, 0, length, + reinterpret_cast(payload.data())); + } + + QMetaObject::invokeMethod(hub, "serverDescriptorWritten", Qt::QueuedConnection, + Q_ARG(QJniObject, descriptor), + Q_ARG(QByteArray, payload)); +} + +void LowEnergyNotificationHub::lowEnergy_characteristicChanged( + JNIEnv *env, jobject, jlong qtObject, jint charHandle, jbyteArray data) +{ + lock.lockForRead(); + LowEnergyNotificationHub *hub = hubMap()->value(qtObject); + lock.unlock(); + if (!hub) + return; + + QByteArray payload; + if (data) { //empty Java byte array is 0x0 + jsize length = env->GetArrayLength(data); + payload.resize(length); + env->GetByteArrayRegion(data, 0, length, + reinterpret_cast(payload.data())); + } + + QMetaObject::invokeMethod(hub, "characteristicChanged", Qt::QueuedConnection, + Q_ARG(int, charHandle), Q_ARG(QByteArray, payload)); +} + +void LowEnergyNotificationHub::lowEnergy_serverCharacteristicChanged( + JNIEnv *env, jobject, jlong qtObject, + QtJniTypes::BluetoothGattCharacteristic characteristic, jbyteArray newValue) +{ + lock.lockForRead(); + LowEnergyNotificationHub *hub = hubMap()->value(qtObject); + lock.unlock(); + if (!hub) + return; + + QByteArray payload; + if (newValue) { //empty Java byte array is 0x0 + jsize length = env->GetArrayLength(newValue); + payload.resize(length); + env->GetByteArrayRegion(newValue, 0, length, + reinterpret_cast(payload.data())); + } + + QMetaObject::invokeMethod(hub, "serverCharacteristicChanged", Qt::QueuedConnection, + Q_ARG(QJniObject, characteristic), + Q_ARG(QByteArray, payload)); +} + +void LowEnergyNotificationHub::lowEnergy_serviceError( + JNIEnv *, jobject, jlong qtObject, jint attributeHandle, int errorCode) +{ + lock.lockForRead(); + LowEnergyNotificationHub *hub = hubMap()->value(qtObject); + lock.unlock(); + if (!hub) + return; + + QMetaObject::invokeMethod(hub, "serviceError", Qt::QueuedConnection, + Q_ARG(int, attributeHandle), + Q_ARG(QLowEnergyService::ServiceError, + (QLowEnergyService::ServiceError)errorCode)); +} + +void LowEnergyNotificationHub::lowEnergy_advertisementError( + JNIEnv *, jobject, jlong qtObject, jint status) +{ + lock.lockForRead(); + LowEnergyNotificationHub *hub = hubMap()->value(qtObject); + lock.unlock(); + if (!hub) + return; + + QMetaObject::invokeMethod(hub, "advertisementError", Qt::QueuedConnection, + Q_ARG(int, status)); +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/android/lowenergynotificationhub_p.h b/src/bluetooth/android/lowenergynotificationhub_p.h new file mode 100644 index 0000000..238590a --- /dev/null +++ b/src/bluetooth/android/lowenergynotificationhub_p.h @@ -0,0 +1,151 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef LOWENERGYNOTIFICATIONHUB_H +#define LOWENERGYNOTIFICATIONHUB_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 "android/jni_android_p.h" +#include + +#include + +QT_BEGIN_NAMESPACE + +class LowEnergyNotificationHub : public QObject +{ + Q_OBJECT +public: + explicit LowEnergyNotificationHub(const QBluetoothAddress &remote, bool isPeripheral, + QObject *parent = nullptr); + ~LowEnergyNotificationHub(); + + static void lowEnergy_connectionChange(JNIEnv*, jobject, jlong qtObject, + jint errorCode, jint newState); + Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(lowEnergy_connectionChange, + leConnectionStateChange) + + static void lowEnergy_mtuChanged(JNIEnv*, jobject, jlong qtObject, jint mtu); + Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(lowEnergy_mtuChanged, leMtuChanged) + + static void lowEnergy_servicesDiscovered(JNIEnv*, jobject, jlong qtObject, + jint errorCode, jstring uuidList); + Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(lowEnergy_servicesDiscovered, + leServicesDiscovered) + + static void lowEnergy_serviceDetailsDiscovered(JNIEnv *, jobject, + jlong qtObject, jstring uuid, + jint startHandle, jint endHandle); + Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(lowEnergy_serviceDetailsDiscovered, + leServiceDetailDiscoveryFinished) + + static void lowEnergy_characteristicRead(JNIEnv*env, jobject, jlong qtObject, + jstring serviceUuid, + jint handle, jstring charUuid, + jint properties, jbyteArray data); + Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(lowEnergy_characteristicRead, + leCharacteristicRead) + + static void lowEnergy_descriptorRead(JNIEnv *env, jobject, jlong qtObject, + jstring sUuid, jstring cUuid, + jint handle, jstring dUuid, jbyteArray data); + Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(lowEnergy_descriptorRead, leDescriptorRead) + + static void lowEnergy_characteristicWritten(JNIEnv *, jobject, jlong qtObject, + jint charHandle, jbyteArray data, + jint errorCode); + Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(lowEnergy_characteristicWritten, + leCharacteristicWritten) + + static void lowEnergy_descriptorWritten(JNIEnv *, jobject, jlong qtObject, + jint descHandle, jbyteArray data, + jint errorCode); + Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(lowEnergy_descriptorWritten, + leDescriptorWritten) + + static void lowEnergy_serverDescriptorWritten(JNIEnv *, jobject, jlong qtObject, + QtJniTypes::BluetoothGattDescriptor descriptor, + jbyteArray newValue); + Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(lowEnergy_serverDescriptorWritten, + leServerDescriptorWritten) + + static void lowEnergy_characteristicChanged(JNIEnv *, jobject, jlong qtObject, + jint charHandle, jbyteArray data); + Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(lowEnergy_characteristicChanged, + leCharacteristicChanged) + + static void lowEnergy_serverCharacteristicChanged(JNIEnv *, jobject, jlong qtObject, + QtJniTypes::BluetoothGattCharacteristic characteristic, + jbyteArray newValue); + Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(lowEnergy_serverCharacteristicChanged, + leServerCharacteristicChanged) + + static void lowEnergy_serviceError(JNIEnv *, jobject, jlong qtObject, + jint attributeHandle, int errorCode); + Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(lowEnergy_serviceError, leServiceError) + + static void lowEnergy_advertisementError(JNIEnv *, jobject, jlong qtObject, jint status); + Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(lowEnergy_advertisementError, + leServerAdvertisementError) + + static void lowEnergy_remoteRssiRead(JNIEnv *, jobject, jlong qtObject, int rssi, + bool success); + Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(lowEnergy_remoteRssiRead, leRemoteRssiRead); + + QJniObject javaObject() + { + return jBluetoothLe; + } + +signals: + void connectionUpdated(QLowEnergyController::ControllerState newState, + QLowEnergyController::Error errorCode); + void mtuChanged(int mtu); + void remoteRssiRead(int rssi, bool success); + void servicesDiscovered(QLowEnergyController::Error errorCode, const QString &uuids); + void serviceDetailsDiscoveryFinished(const QString& serviceUuid, + int startHandle, int endHandle); + void characteristicRead(const QBluetoothUuid &serviceUuid, + int handle, const QBluetoothUuid &charUuid, + int properties, const QByteArray &data); + void descriptorRead(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid, + int handle, const QBluetoothUuid &descUuid, const QByteArray &data); + void characteristicWritten(int charHandle, const QByteArray &data, + QLowEnergyService::ServiceError errorCode); + void descriptorWritten(int descHandle, const QByteArray &data, + QLowEnergyService::ServiceError errorCode); + void serverDescriptorWritten(const QJniObject &descriptor, const QByteArray &newValue); + void characteristicChanged(int charHandle, const QByteArray &data); + void serverCharacteristicChanged(const QJniObject &characteristic, const QByteArray &newValue); + void serviceError(int attributeHandle, QLowEnergyService::ServiceError errorCode); + void advertisementError(int status); + +private: + static QReadWriteLock lock; + + QJniObject jBluetoothLe; + long javaToCtoken; + +}; + +QT_END_NAMESPACE + +#endif // LOWENERGYNOTIFICATIONHUB_H + diff --git a/src/bluetooth/android/serveracceptancethread.cpp b/src/bluetooth/android/serveracceptancethread.cpp new file mode 100644 index 0000000..55f0f4d --- /dev/null +++ b/src/bluetooth/android/serveracceptancethread.cpp @@ -0,0 +1,153 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include +#include + +#include "android/serveracceptancethread_p.h" +#include "android/jni_android_p.h" + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID) + +ServerAcceptanceThread::ServerAcceptanceThread(QObject *parent) : + QObject(parent), maxPendingConnections(1) +{ + qRegisterMetaType(); +} + +ServerAcceptanceThread::~ServerAcceptanceThread() +{ + Q_ASSERT(!isRunning()); + QMutexLocker lock(&m_mutex); + shutdownPendingConnections(); +} + +void ServerAcceptanceThread::setServiceDetails(const QBluetoothUuid &uuid, + const QString &serviceName, + QBluetooth::SecurityFlags securityFlags) +{ + QMutexLocker lock(&m_mutex); + m_uuid = uuid; + m_serviceName = serviceName; + secFlags = securityFlags; +} + +bool ServerAcceptanceThread::hasPendingConnections() const +{ + QMutexLocker lock(&m_mutex); + return !pendingSockets.isEmpty(); +} + +/* + * Returns the next pending connection or an invalid JNI object. + * Note that even a stopped thread may still have pending + * connections. Pending connections are only terminated upon + * thread restart or destruction. + */ +QJniObject ServerAcceptanceThread::nextPendingConnection() +{ + QMutexLocker lock(&m_mutex); + if (pendingSockets.isEmpty()) + return QJniObject(); + else + return pendingSockets.takeFirst(); +} + +void ServerAcceptanceThread::setMaxPendingConnections(int maximumCount) +{ + QMutexLocker lock(&m_mutex); + maxPendingConnections = maximumCount; +} + +void ServerAcceptanceThread::run() +{ + QMutexLocker lock(&m_mutex); + + if (!validSetup()) { + qCWarning(QT_BT_ANDROID) << "Invalid Server Socket setup"; + return; + } + + if (isRunning()) { + stop(); + shutdownPendingConnections(); + } + + javaThread = QJniObject::construct( + QNativeInterface::QAndroidApplication::context()); + if (!javaThread.isValid()) + return; + + javaThread.setField("qtObject", reinterpret_cast(this)); + javaThread.setField("logEnabled", QT_BT_ANDROID().isDebugEnabled()); + + QString tempUuid = m_uuid.toString(QUuid::WithoutBraces); + + QJniObject uuidString = QJniObject::fromString(tempUuid); + QJniObject serviceNameString = QJniObject::fromString(m_serviceName); + bool isSecure = !(secFlags == QBluetooth::SecurityFlags(QBluetooth::Security::NoSecurity)); + javaThread.callMethod("setServiceDetails", + uuidString.object(), + serviceNameString.object(), + isSecure); + javaThread.callMethod("start"); +} + +void ServerAcceptanceThread::stop() +{ + if (javaThread.isValid()) { + qCDebug(QT_BT_ANDROID) << "Closing server socket"; + javaThread.callMethod("close"); + } +} + +bool ServerAcceptanceThread::isRunning() const +{ + if (javaThread.isValid()) + return javaThread.callMethod("isAlive"); + + return false; +} + +//Runs inside the java thread +void ServerAcceptanceThread::javaThreadErrorOccurred(int errorCode) +{ + qCDebug(QT_BT_ANDROID) << "JavaThread error:" << errorCode; + emit errorOccurred(QBluetoothServer::InputOutputError); +} + +//Runs inside the Java thread +void ServerAcceptanceThread::javaNewSocket(jobject s) +{ + QMutexLocker lock(&m_mutex); + + QJniObject socket(s); + if (!socket.isValid()) + return; + + if (pendingSockets.size() < maxPendingConnections) { + qCDebug(QT_BT_ANDROID) << "New incoming java socket detected"; + pendingSockets.append(socket); + emit newConnection(); + } else { + qCWarning(QT_BT_ANDROID) << "Refusing connection due to limited pending socket queue"; + socket.callMethod("close"); + } +} + +bool ServerAcceptanceThread::validSetup() const +{ + return (!m_uuid.isNull() && !m_serviceName.isEmpty()); +} + +void ServerAcceptanceThread::shutdownPendingConnections() +{ + while (!pendingSockets.isEmpty()) { + QJniObject socket = pendingSockets.takeFirst(); + socket.callMethod("close"); + } +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/android/serveracceptancethread_p.h b/src/bluetooth/android/serveracceptancethread_p.h new file mode 100644 index 0000000..bbdd7fc --- /dev/null +++ b/src/bluetooth/android/serveracceptancethread_p.h @@ -0,0 +1,69 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef SERVERACCEPTANCETHREAD_H +#define SERVERACCEPTANCETHREAD_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 "qbluetooth.h" +#include "private/qglobal_p.h" + +QT_BEGIN_NAMESPACE + +class ServerAcceptanceThread : public QObject +{ + Q_OBJECT +public: + explicit ServerAcceptanceThread(QObject *parent = nullptr); + ~ServerAcceptanceThread(); + void setServiceDetails(const QBluetoothUuid &uuid, const QString &serviceName, + QBluetooth::SecurityFlags securityFlags); + + + bool hasPendingConnections() const; + QJniObject nextPendingConnection(); + void setMaxPendingConnections(int maximumCount); + + void javaThreadErrorOccurred(int errorCode); + void javaNewSocket(jobject socket); + + void run(); + void stop(); + bool isRunning() const; + +signals: + void newConnection(); + void errorOccurred(QBluetoothServer::Error); + +private: + bool validSetup() const; + void shutdownPendingConnections(); + + QList pendingSockets; + mutable QMutex m_mutex; + QString m_serviceName; + QBluetoothUuid m_uuid; + int maxPendingConnections; + QBluetooth::SecurityFlags secFlags; + + QJniObject javaThread; + +}; + +QT_END_NAMESPACE + +#endif // SERVERACCEPTANCETHREAD_H diff --git a/src/bluetooth/android/servicediscoverybroadcastreceiver.cpp b/src/bluetooth/android/servicediscoverybroadcastreceiver.cpp new file mode 100644 index 0000000..a708035 --- /dev/null +++ b/src/bluetooth/android/servicediscoverybroadcastreceiver.cpp @@ -0,0 +1,83 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "android/servicediscoverybroadcastreceiver_p.h" +#include +#include +#include +#include +#include +#include "android/jni_android_p.h" + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID) + +ServiceDiscoveryBroadcastReceiver::ServiceDiscoveryBroadcastReceiver(QObject* parent): AndroidBroadcastReceiver(parent) +{ + addAction(QJniObject::fromString( + valueForStaticField())); +} + +void ServiceDiscoveryBroadcastReceiver::onReceive(JNIEnv *env, jobject context, jobject intent) +{ + Q_UNUSED(context); + Q_UNUSED(env); + + QJniObject intentObject(intent); + const QString action = intentObject.callMethod("getAction").toString(); + + qCDebug(QT_BT_ANDROID) << "ServiceDiscoveryBroadcastReceiver::onReceive() - event:" << action; + + if (action == valueForStaticField()) { + + QJniObject keyExtra = QJniObject::fromString( + valueForStaticField()); + QJniObject parcelableUuids = intentObject.callMethod( + "getParcelableArrayExtra", + keyExtra.object()); + if (!parcelableUuids.isValid()) { + emit uuidFetchFinished(QBluetoothAddress(), QList()); + return; + } + const QList result = ServiceDiscoveryBroadcastReceiver::convertParcelableArray(parcelableUuids); + + keyExtra = QJniObject::fromString( + valueForStaticField()); + QJniObject bluetoothDevice = + intentObject.callMethod("getParcelableExtra", + keyExtra.object()); + QBluetoothAddress address; + if (bluetoothDevice.isValid()) { + address = + QBluetoothAddress(bluetoothDevice.callMethod("getAddress").toString()); + emit uuidFetchFinished(address, result); + } else { + emit uuidFetchFinished(QBluetoothAddress(), QList()); + } + } +} + +QList ServiceDiscoveryBroadcastReceiver::convertParcelableArray(const QJniObject &parcelUuidArray) +{ + QList result; + QJniEnvironment env; + + jobjectArray parcels = parcelUuidArray.object(); + if (!parcels) + return result; + + jint size = env->GetArrayLength(parcels); + for (jint i = 0; i < size; ++i) { + auto p = QJniObject::fromLocalRef(env->GetObjectArrayElement(parcels, i)); + + QBluetoothUuid uuid(p.callMethod("toString").toString()); + //qCDebug(QT_BT_ANDROID) << uuid.toString(); + result.append(uuid); + } + + return result; +} + +QT_END_NAMESPACE + diff --git a/src/bluetooth/android/servicediscoverybroadcastreceiver_p.h b/src/bluetooth/android/servicediscoverybroadcastreceiver_p.h new file mode 100644 index 0000000..0514982 --- /dev/null +++ b/src/bluetooth/android/servicediscoverybroadcastreceiver_p.h @@ -0,0 +1,42 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef SERVICEDISCOVERYBROADCASTRECEIVER_H +#define SERVICEDISCOVERYBROADCASTRECEIVER_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 "android/androidbroadcastreceiver_p.h" +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QBluetoothDeviceInfo; + +class ServiceDiscoveryBroadcastReceiver : public AndroidBroadcastReceiver +{ + Q_OBJECT +public: + ServiceDiscoveryBroadcastReceiver(QObject* parent = nullptr); + virtual void onReceive(JNIEnv *env, jobject context, jobject intent); + virtual void onReceiveLeScan(JNIEnv *, jobject, jint, jbyteArray) {} + + static QList convertParcelableArray(const QJniObject &obj); + +signals: + void uuidFetchFinished(const QBluetoothAddress &addr, const QList &serviceUuid); +}; + +QT_END_NAMESPACE +#endif // SERVICEDISCOVERYBROADCASTRECEIVER_H diff --git a/src/bluetooth/bluez/adapter1_bluez5.cpp b/src/bluetooth/bluez/adapter1_bluez5.cpp new file mode 100644 index 0000000..285c79b --- /dev/null +++ b/src/bluetooth/bluez/adapter1_bluez5.cpp @@ -0,0 +1,28 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -I QtCore/private/qglobal_p.h -p adapter1_bluez5_p.h:adapter1_bluez5.cpp org.bluez.Adapter1.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "adapter1_bluez5_p.h" + +/* + * Implementation of interface class OrgBluezAdapter1Interface + */ + +OrgBluezAdapter1Interface::OrgBluezAdapter1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +OrgBluezAdapter1Interface::~OrgBluezAdapter1Interface() +{ +} + + +#include "moc_adapter1_bluez5_p.cpp" diff --git a/src/bluetooth/bluez/adapter1_bluez5_p.h b/src/bluetooth/bluez/adapter1_bluez5_p.h new file mode 100644 index 0000000..fc641b3 --- /dev/null +++ b/src/bluetooth/bluez/adapter1_bluez5_p.h @@ -0,0 +1,145 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -I QtCore/private/qglobal_p.h -p adapter1_bluez5_p.h:adapter1_bluez5.cpp org.bluez.Adapter1.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#ifndef ADAPTER1_BLUEZ5_P_H +#define ADAPTER1_BLUEZ5_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 + +/* + * Proxy class for interface org.bluez.Adapter1 + */ +class OrgBluezAdapter1Interface: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "org.bluez.Adapter1"; } + +public: + OrgBluezAdapter1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); + + ~OrgBluezAdapter1Interface(); + + Q_PROPERTY(QString Address READ address) + inline QString address() const + { return qvariant_cast< QString >(property("Address")); } + + Q_PROPERTY(QString Alias READ alias WRITE setAlias) + inline QString alias() const + { return qvariant_cast< QString >(property("Alias")); } + inline void setAlias(const QString &value) + { setProperty("Alias", QVariant::fromValue(value)); } + + Q_PROPERTY(uint Class READ classProperty) + inline uint classProperty() const + { return qvariant_cast< uint >(property("Class")); } + + Q_PROPERTY(bool Discoverable READ discoverable WRITE setDiscoverable) + inline bool discoverable() const + { return qvariant_cast< bool >(property("Discoverable")); } + inline void setDiscoverable(bool value) + { setProperty("Discoverable", QVariant::fromValue(value)); } + + Q_PROPERTY(uint DiscoverableTimeout READ discoverableTimeout WRITE setDiscoverableTimeout) + inline uint discoverableTimeout() const + { return qvariant_cast< uint >(property("DiscoverableTimeout")); } + inline void setDiscoverableTimeout(uint value) + { setProperty("DiscoverableTimeout", QVariant::fromValue(value)); } + + Q_PROPERTY(bool Discovering READ discovering) + inline bool discovering() const + { return qvariant_cast< bool >(property("Discovering")); } + + Q_PROPERTY(QString Modalias READ modalias) + inline QString modalias() const + { return qvariant_cast< QString >(property("Modalias")); } + + Q_PROPERTY(QString Name READ name) + inline QString name() const + { return qvariant_cast< QString >(property("Name")); } + + Q_PROPERTY(bool Pairable READ pairable WRITE setPairable) + inline bool pairable() const + { return qvariant_cast< bool >(property("Pairable")); } + inline void setPairable(bool value) + { setProperty("Pairable", QVariant::fromValue(value)); } + + Q_PROPERTY(uint PairableTimeout READ pairableTimeout WRITE setPairableTimeout) + inline uint pairableTimeout() const + { return qvariant_cast< uint >(property("PairableTimeout")); } + inline void setPairableTimeout(uint value) + { setProperty("PairableTimeout", QVariant::fromValue(value)); } + + Q_PROPERTY(bool Powered READ powered WRITE setPowered) + inline bool powered() const + { return qvariant_cast< bool >(property("Powered")); } + inline void setPowered(bool value) + { setProperty("Powered", QVariant::fromValue(value)); } + + Q_PROPERTY(QStringList UUIDs READ uUIDs) + inline QStringList uUIDs() const + { return qvariant_cast< QStringList >(property("UUIDs")); } + +public Q_SLOTS: // METHODS + inline QDBusPendingReply<> RemoveDevice(const QDBusObjectPath &device) + { + QList argumentList; + argumentList << QVariant::fromValue(device); + return asyncCallWithArgumentList(QStringLiteral("RemoveDevice"), argumentList); + } + + inline QDBusPendingReply<> SetDiscoveryFilter(const QVariantMap &properties) + { + QList argumentList; + argumentList << QVariant::fromValue(properties); + return asyncCallWithArgumentList(QStringLiteral("SetDiscoveryFilter"), argumentList); + } + + inline QDBusPendingReply<> StartDiscovery() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("StartDiscovery"), argumentList); + } + + inline QDBusPendingReply<> StopDiscovery() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("StopDiscovery"), argumentList); + } + +Q_SIGNALS: // SIGNALS +}; + +namespace org { + namespace bluez { + using Adapter1 = ::OrgBluezAdapter1Interface; + } +} +#endif diff --git a/src/bluetooth/bluez/battery1.cpp b/src/bluetooth/bluez/battery1.cpp new file mode 100644 index 0000000..abbad84 --- /dev/null +++ b/src/bluetooth/bluez/battery1.cpp @@ -0,0 +1,28 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -I QtCore/private/qglobal_p.h -p battery1_p.h:battery1.cpp org.bluez.Battery1.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "battery1_p.h" + +/* + * Implementation of interface class OrgBluezBattery1Interface + */ + +OrgBluezBattery1Interface::OrgBluezBattery1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +OrgBluezBattery1Interface::~OrgBluezBattery1Interface() +{ +} + + +#include "moc_battery1_p.cpp" diff --git a/src/bluetooth/bluez/battery1_p.h b/src/bluetooth/bluez/battery1_p.h new file mode 100644 index 0000000..8211209 --- /dev/null +++ b/src/bluetooth/bluez/battery1_p.h @@ -0,0 +1,63 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -I QtCore/private/qglobal_p.h -p battery1_p.h:battery1.cpp org.bluez.Battery1.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#ifndef BATTERY1_P_H +#define BATTERY1_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 + +/* + * Proxy class for interface org.bluez.Battery1 + */ +class OrgBluezBattery1Interface: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "org.bluez.Battery1"; } + +public: + OrgBluezBattery1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); + + ~OrgBluezBattery1Interface(); + + Q_PROPERTY(uchar Percentage READ percentage) + inline uchar percentage() const + { return qvariant_cast< uchar >(property("Percentage")); } + +public Q_SLOTS: // METHODS +Q_SIGNALS: // SIGNALS +}; + +namespace org { + namespace bluez { + using Battery1 = ::OrgBluezBattery1Interface; + } +} +#endif diff --git a/src/bluetooth/bluez/bluetoothmanagement.cpp b/src/bluetooth/bluez/bluetoothmanagement.cpp new file mode 100644 index 0000000..15ca8e5 --- /dev/null +++ b/src/bluetooth/bluez/bluetoothmanagement.cpp @@ -0,0 +1,272 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include +#include +#include + +#include "bluetoothmanagement_p.h" +#include "bluez_data_p.h" +#include "../qbluetoothsocketbase_p.h" + +#include +#include +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +// Packet data structures for Mgmt API bluez.git/doc/mgmt-api.txt + +struct MgmtHdr { + quint16 cmdCode; + quint16 controllerIndex; + quint16 length; +} __attribute__((packed)); + +struct MgmtEventDeviceFound { + bdaddr_t bdaddr; + quint8 type; + quint8 rssi; + quint32 flags; + quint16 eirLength; + quint8 eirData[0]; +} __attribute__((packed)); + + +/* + * This class encapsulates access to the Bluetooth Management API as introduced by + * Linux kernel 3.4. Some Bluetooth information is not exposed via the usual DBus + * API (e.g. the random/public address type info). In those cases we have to fall back + * to this mgmt API. + * + * Note that opening such a Bluetooth mgmt socket requires CAP_NET_ADMIN (root) capability. + * + * Documentation can be found in bluez-git/doc/mgmt-api.txt + */ + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ) + +// These structs and defines come straight from linux/capability.h. +// To avoid missing definitions we re-define them if not existing. +// In addition, we don't want to pull in a libcap2 dependency +struct capHdr { + quint32 version; + int pid; +}; + +struct capData { + quint32 effective; + quint32 permitted; + quint32 inheritable; +}; + +#ifndef _LINUX_CAPABILITY_VERSION_3 +#define _LINUX_CAPABILITY_VERSION_3 0x20080522 +#endif + +#ifndef _LINUX_CAPABILITY_U32S_3 +#define _LINUX_CAPABILITY_U32S_3 2 +#endif + +#ifndef CAP_NET_ADMIN +#define CAP_NET_ADMIN 12 +#endif + +#ifndef CAP_TO_INDEX +#define CAP_TO_INDEX(x) ((x) >> 5) /* 1 << 5 == bits in __u32 */ +#endif + +#ifndef CAP_TO_MASK +#define CAP_TO_MASK(x) (1 << ((x) & 31)) /* mask for indexed __u32 */ +#endif + +const int msecInADay = 1000*60*60*24; + +static int sysCallCapGet(capHdr *header, capData *data) +{ + return syscall(__NR_capget, header, data); +} + +/* + * Checks that the current process has the effective CAP_NET_ADMIN permission. + */ +static bool hasBtMgmtPermission() +{ + // We only care for cap version 3 introduced by kernel 2.6.26 + // because the new BlueZ management API only exists since kernel 3.4. + + struct capHdr header = {}; + struct capData data[_LINUX_CAPABILITY_U32S_3] = {{}}; + header.version = _LINUX_CAPABILITY_VERSION_3; + header.pid = getpid(); + + if (sysCallCapGet(&header, data) < 0) { + qCWarning(QT_BT_BLUEZ, "BluetoothManangement: getCap failed with %s", + qPrintable(qt_error_string(errno))); + return false; + } + + return (data[CAP_TO_INDEX(CAP_NET_ADMIN)].effective & CAP_TO_MASK(CAP_NET_ADMIN)); +} + +BluetoothManagement::BluetoothManagement(QObject *parent) : QObject(parent) +{ + bool hasPermission = hasBtMgmtPermission(); + if (!hasPermission) { + qCInfo(QT_BT_BLUEZ, "Missing CAP_NET_ADMIN permission. Cannot determine whether " + "a found address is of random or public type."); + return; + } + + sockaddr_hci hciAddr; + + fd = ::socket(AF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, BTPROTO_HCI); + if (fd < 0) { + qCWarning(QT_BT_BLUEZ, "Cannot open Bluetooth Management socket: %s", + qPrintable(qt_error_string(errno))); + return; + } + + memset(&hciAddr, 0, sizeof(hciAddr)); + hciAddr.hci_dev = HCI_DEV_NONE; + hciAddr.hci_channel = HCI_CHANNEL_CONTROL; + hciAddr.hci_family = AF_BLUETOOTH; + + if (::bind(fd, (struct sockaddr *)(&hciAddr), sizeof(hciAddr)) < 0) { + qCWarning(QT_BT_BLUEZ, "Cannot bind Bluetooth Management socket: %s", + qPrintable(qt_error_string(errno))); + ::close(fd); + fd = -1; + return; + } + + notifier = new QSocketNotifier(fd, QSocketNotifier::Read, this); + connect(notifier, &QSocketNotifier::activated, this, &BluetoothManagement::_q_readNotifier); + + // ensure cache is regularly cleaned (once every 24h) + QTimer* timer = new QTimer(this); + timer->setInterval(msecInADay); + timer->setTimerType(Qt::VeryCoarseTimer); + connect(timer, &QTimer::timeout, this, &BluetoothManagement::cleanupOldAddressFlags); + timer->start(); +} + +Q_GLOBAL_STATIC(BluetoothManagement, bluetoothKernelManager) + +BluetoothManagement *BluetoothManagement::instance() +{ + return bluetoothKernelManager(); +} + +void BluetoothManagement::_q_readNotifier() +{ + char *dst = buffer.reserve(QPRIVATELINEARBUFFER_BUFFERSIZE); + const auto readCount = ::read(fd, dst, QPRIVATELINEARBUFFER_BUFFERSIZE); + buffer.chop(QPRIVATELINEARBUFFER_BUFFERSIZE - (readCount < 0 ? 0 : readCount)); + if (readCount < 0) { + qCWarning(QT_BT_BLUEZ, "Management Control read error %s", qPrintable(qt_error_string(errno))); + return; + } + + // do we have at least one complete mgmt header? + if (size_t(buffer.size()) < sizeof(MgmtHdr)) + return; + + QByteArray data = buffer.readAll(); + + while (true) { + if (size_t(data.size()) < sizeof(MgmtHdr)) + break; + + const MgmtHdr *hdr = reinterpret_cast(data.constData()); + const auto nextPackageSize = qsizetype(qFromLittleEndian(hdr->length) + sizeof(MgmtHdr)); + const qsizetype remainingPackageSize = data.size() - nextPackageSize; + + if (data.size() < nextPackageSize) + break; // not a complete event header -> wait for next notifier + + switch (static_cast(qFromLittleEndian(hdr->cmdCode))) { + case EventCode::DeviceFoundEvent: + { + const MgmtEventDeviceFound *event = reinterpret_cast + (data.constData() + sizeof(MgmtHdr)); + + if (event->type == BDADDR_LE_RANDOM) { + const bdaddr_t address = event->bdaddr; + quint64 bdaddr; + + convertAddress(address.b, &bdaddr); + const QBluetoothAddress qtAddress(bdaddr); + qCDebug(QT_BT_BLUEZ) << "BluetoothManagement: found random device" + << qtAddress; + processRandomAddressFlagInformation(qtAddress); + } + + break; + } + default: + qCDebug(QT_BT_BLUEZ) << "BluetoothManagement: Ignored event:" + << Qt::hex << (EventCode)qFromLittleEndian(hdr->cmdCode); + break; + } + + if (data.size() > nextPackageSize) + data = data.right(remainingPackageSize); + else + data.clear(); + + if (data.isEmpty()) + break; + } + + if (!data.isEmpty()) + buffer.ungetBlock(data.constData(), data.size()); +} + +void BluetoothManagement::processRandomAddressFlagInformation(const QBluetoothAddress &address) +{ + // insert or update + QMutexLocker locker(&accessLock); + privateFlagAddresses[address] = QDateTime::currentDateTimeUtc(); +} + +/* + * Ensure that private address cache is not older than 24h. + */ +void BluetoothManagement::cleanupOldAddressFlags() +{ + const auto cutOffTime = QDateTime::currentDateTimeUtc().addDays(-1); + + QMutexLocker locker(&accessLock); + + auto i = privateFlagAddresses.begin(); + while (i != privateFlagAddresses.end()) { + if (i.value() < cutOffTime) + i = privateFlagAddresses.erase(i); + else + i++; + } +} + +bool BluetoothManagement::isAddressRandom(const QBluetoothAddress &address) const +{ + if (fd == -1 || address.isNull()) + return false; + + QMutexLocker locker(&accessLock); + return privateFlagAddresses.contains(address); +} + +bool BluetoothManagement::isMonitoringEnabled() const +{ + return (fd == -1) ? false : true; +} + + +QT_END_NAMESPACE + +#include "moc_bluetoothmanagement_p.cpp" diff --git a/src/bluetooth/bluez/bluetoothmanagement_p.h b/src/bluetooth/bluez/bluetoothmanagement_p.h new file mode 100644 index 0000000..c45d31f --- /dev/null +++ b/src/bluetooth/bluez/bluetoothmanagement_p.h @@ -0,0 +1,113 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef BLUETOOTHMANAGEMENT_P_H +#define BLUETOOTHMANAGEMENT_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 + +#ifndef QPRIVATELINEARBUFFER_BUFFERSIZE +#define QPRIVATELINEARBUFFER_BUFFERSIZE qsizetype(16384) +#endif +#include "../qprivatelinearbuffer_p.h" + +QT_BEGIN_NAMESPACE + +class QSocketNotifier; + +class BluetoothManagement : public QObject +{ + Q_OBJECT + +public: + + enum class EventCode { + CommandCompleteEvent = 0x0001, + CommandStatusEvent = 0x0002, + ControllerErrorEvent = 0x0003, + IndexAddedEvent = 0x0004, + IndexRemovedEvent = 0x0005, + NewSettingsEvent = 0x0006, + ClassOfDeviceChangedEvent = 0x0007, + LocalNameChangedEvent = 0x0008, + NewLinkKeyEvent = 0x0009, + NewLongTermKeyEvent = 0x000A, + DeviceConnectedEvent = 0x000B, + DeviceDisconnectedEvent = 0x000C, + ConnectFailedEvent = 0x000D, + PINCodeRequestEvent = 0x000E, + UserConfirmationRequestEvent = 0x000F, + UserPasskeyRequestEvent = 0x0010, + AuthenticationFailedEvent = 0x0011, + DeviceFoundEvent = 0x0012, + DiscoveringEvent = 0x0013, + DeviceBlockedEvent = 0x0014, + DeviceUnblockedEvent = 0x00150, + DeviceUnpairedEvent = 0x0016, + PasskeyNotifyEvent = 0x0017, + NewIdentityResolvingKeyEvent = 0x0018, + NewSignatureResolvingKeyEvent = 0x0019, + DeviceAddedEvent = 0x001a, + DeviceRemovedEvent = 0x001b, + NewConnectionParameterEvent = 0x001c, + UnconfiguredIndexAddedEvent = 0x001d, + UnconfiguredIndexRemovedEvent = 0x001e, + NewConfigurationOptionsEvent = 0x001f, + ExtendedIndexAddedEvent = 0x0020, + ExtendedIndexRemovedEvent = 0x0021, + LocalOutOfBandExtendedDataUpdatedEvent = 0x0022, + AdvertisingAddedEvent = 0x0023, + AdvertisingRemovedEvent = 0x0024, + ExtendedControllerInformationChangedEvent = 0x0025, + PHYConfigurationChangedEvent = 0x0026, + ExperimentalFeatureChangedEvent = 0x0027, + DefaultSystemConfigurationChangedEvent = 0x0028, + DefaultRuntimeConfigurationChangedEvent = 0x0029, + DeviceFlagsChangedEvent = 0x002a, + AdvertisementMonitorAddedEvent = 0x002b, + AdvertisementMonitorRemovedEvent = 0x002c, + ControllerSuspendEvent = 0x002d, + ControllerResumeEvent = 0x002e + }; + Q_ENUM(EventCode) + + explicit BluetoothManagement(QObject *parent = nullptr); + static BluetoothManagement *instance(); + + bool isAddressRandom(const QBluetoothAddress &address) const; + bool isMonitoringEnabled() const; + +private slots: + void _q_readNotifier(); + void processRandomAddressFlagInformation(const QBluetoothAddress &address); + void cleanupOldAddressFlags(); + +private: + void readyRead(); + + int fd = -1; + QSocketNotifier* notifier; + QPrivateLinearBuffer buffer; + QHash privateFlagAddresses; + mutable QMutex accessLock; +}; + + +QT_END_NAMESPACE + +#endif // BLUETOOTHMANAGEMENT_P_H diff --git a/src/bluetooth/bluez/bluez5_helper.cpp b/src/bluetooth/bluez/bluez5_helper.cpp new file mode 100644 index 0000000..3b74ee6 --- /dev/null +++ b/src/bluetooth/bluez/bluez5_helper.cpp @@ -0,0 +1,575 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include +#include +#include +#include +#include +#include "bluez5_helper_p.h" +#include "bluez_data_p.h" +#include "objectmanager_p.h" +#include "properties_p.h" +#include "adapter1_bluez5_p.h" + +QT_BEGIN_NAMESPACE + +QT_IMPL_METATYPE_EXTERN(InterfaceList) +QT_IMPL_METATYPE_EXTERN(ManufacturerDataList) +QT_IMPL_METATYPE_EXTERN(ServiceDataList) +QT_IMPL_METATYPE_EXTERN(ManagedObjectList) + + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ) + +typedef enum Bluez5TestResultType +{ + BluezVersionUnknown, + BluezVersion5, + BluezNotAvailable +} Bluez5TestResult; + +Q_GLOBAL_STATIC_WITH_ARGS(Bluez5TestResult, bluezVersion, (BluezVersionUnknown)) +Q_GLOBAL_STATIC_WITH_ARGS(QVersionNumber, bluezDaemonVersion, (QVersionNumber())) + +/* + Ensures that the DBus types are registered + */ + +void initializeBluez5() +{ + if (*bluezVersion() == BluezVersionUnknown) { + OrgFreedesktopDBusObjectManagerInterface manager(QStringLiteral("org.bluez"), + QStringLiteral("/"), + QDBusConnection::systemBus()); + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); + + QDBusPendingReply reply = manager.GetManagedObjects(); + reply.waitForFinished(); + if (reply.isError()) { + *bluezVersion() = BluezNotAvailable; + qWarning() << "Cannot find a compatible running Bluez. " + "Please check the Bluez installation. " + "QtBluetooth requires at least BlueZ version 5."; + } else { + *bluezVersion() = BluezVersion5; + qCDebug(QT_BT_BLUEZ) << "Bluez 5 detected."; + } + } +} + +/* + Checks that the mandatory Bluetooth HCI ioctls are offered + by Linux kernel. Returns \c true if the ictls are available; otherwise \c false. + + Mandatory ioctls: + - HCIGETCONNLIST + - HCIGETDEVINFO + - HCIGETDEVLIST + */ +bool mandatoryHciIoctlsAvailable() +{ + // open hci socket + int hciSocket = ::qt_safe_socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); + if (hciSocket < 0) { + qCWarning(QT_BT_BLUEZ) << "Cannot open HCI socket:" << qt_error_string(errno); + return false; + } + + // check HCIGETDEVLIST & HCIGETDEVLIST + struct hci_dev_req *devRequest = nullptr; + struct hci_dev_list_req *devRequestList = nullptr; + struct hci_dev_info devInfo; + const int devListSize = sizeof(struct hci_dev_list_req) + + HCI_MAX_DEV * sizeof(struct hci_dev_req); + + devRequestList = (hci_dev_list_req *) malloc(devListSize); + if (!devRequestList) { + qt_safe_close(hciSocket); + return false; // if we cannot malloc nothing will help anyway + } + + QScopedPointer pDevList(devRequestList); + memset(pDevList.data(), 0, devListSize); + pDevList->dev_num = HCI_MAX_DEV; + devRequest = pDevList->dev_req; + + if (qt_safe_ioctl(hciSocket, HCIGETDEVLIST, devRequestList) < 0) { + qt_safe_close(hciSocket); + qCWarning(QT_BT_BLUEZ) << "HCI icotl HCIGETDEVLIST:" << qt_error_string(errno); + return false; + } + + if (devRequestList->dev_num > 0) { + devInfo.dev_id = devRequest->dev_id; + if (qt_safe_ioctl(hciSocket, HCIGETDEVINFO, &devInfo) < 0) { + qt_safe_close(hciSocket); + qCWarning(QT_BT_BLUEZ) << "HCI icotl HCIGETDEVINFO:" << qt_error_string(errno); + return false; + } + } + + // check HCIGETCONNLIST + const int maxNoOfConnections = 20; + hci_conn_list_req *infoList = nullptr; + infoList = (hci_conn_list_req *) + malloc(sizeof(hci_conn_list_req) + maxNoOfConnections * sizeof(hci_conn_info)); + + if (!infoList) { + qt_safe_close(hciSocket); + return false; + } + + QScopedPointer pInfoList(infoList); + pInfoList->conn_num = maxNoOfConnections; + pInfoList->dev_id = devInfo.dev_id; + + if (qt_safe_ioctl(hciSocket, HCIGETCONNLIST, (void *) infoList) < 0) { + qCWarning(QT_BT_BLUEZ) << "HCI icotl HCIGETCONNLIST:" << qt_error_string(errno); + qt_safe_close(hciSocket); + return false; + } + + qt_safe_close(hciSocket); + return true; +} + +/* + * This function returns the version of bluetoothd in use on the system. + * This is required to determine which QLEControllerPrivate implementation + * is required. The following version tags are of significance: + * + * Version < 4.0 -> QLEControllerPrivateCommon + * Version < 5.42 -> QLEControllerPrivateBluez + * Version >= 5.42 -> QLEControllerPrivateBluezDBus + * + * This function utilizes a singleton pattern. It always returns a cached + * version tag which is determined on first call. This is necessary to + * avoid continuesly running the somewhat expensive tests. + * + * The function must never return a null QVersionNumber. + */ +QVersionNumber bluetoothdVersion() +{ + if (bluezDaemonVersion()->isNull()) { + // Register DBus specific meta types (copied from isBluez5()) + // Not all code paths run through isBluez5() but still need the + // registration. + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); + + qCDebug(QT_BT_BLUEZ) << "Detecting bluetoothd version"; + //Order of matching + // 1. Pick whatever the user decides via BLUETOOTH_FORCE_DBUS_LE_VERSION + // Set version to below version 5.42 to use custom/old GATT stack implementation + const QString version = qEnvironmentVariable("BLUETOOTH_FORCE_DBUS_LE_VERSION"); + if (!version.isNull()) { + const QVersionNumber vn = QVersionNumber::fromString(version); + if (!vn.isNull()) { + *bluezDaemonVersion() = vn; + qCDebug(QT_BT_BLUEZ) << "Forcing Bluez LE API selection:" + << bluezDaemonVersion()->toString(); + } + } + + // 2. Find bluetoothd binary and check "bluetoothd --version" + if (bluezDaemonVersion()->isNull() && qt_haveLinuxProcfs()) { + QDBusConnection session = QDBusConnection::systemBus(); + qint64 pid = session.interface()->servicePid(QStringLiteral("org.bluez")).value(); + QByteArray buffer; + + auto determineBinaryVersion = [](const QString &binary) -> QVersionNumber { + QProcess process; + process.start(binary, {QStringLiteral("--version")}); + process.waitForFinished(); + + const QString version = QString::fromLocal8Bit(process.readAll()); + const QVersionNumber vn = QVersionNumber::fromString(version); + if (!vn.isNull()) + qCDebug(QT_BT_BLUEZ) << "Detected bluetoothd version" << vn; + return vn; + }; + + //try reading /proc//exe first -> requires process owner + qCDebug(QT_BT_BLUEZ) << "Using /proc//exe"; + const QString procExe = QStringLiteral("/proc/%1/exe").arg(pid); + const QVersionNumber vn = determineBinaryVersion(procExe); + if (!vn.isNull()) + *bluezDaemonVersion() = vn; + + if (bluezDaemonVersion()->isNull()) { + qCDebug(QT_BT_BLUEZ) << "Using /proc//cmdline"; + //try to reading /proc//cmdline (does not require additional process rights) + QFile procFile(QStringLiteral("/proc/%1/cmdline").arg(pid)); + if (procFile.open(QIODevice::ReadOnly|QIODevice::Text)) { + buffer = procFile.readAll(); + procFile.close(); + + // cmdline params separated by character \0 -> first is bluetoothd binary + const QString binary = QString::fromLocal8Bit(buffer.split('\0').at(0)); + QFileInfo info(binary); + if (info.isExecutable()) + *bluezDaemonVersion() = determineBinaryVersion(binary); + else + qCDebug(QT_BT_BLUEZ) << "Cannot determine bluetoothd version via cmdline:" + << binary; + } + } + } + + // 3. Fall back to custom ATT backend, if possible? + if (bluezDaemonVersion()->isNull()) { + // Check mandatory HCI ioctls are available + if (mandatoryHciIoctlsAvailable()) { + // default 4.0 for now -> implies custom (G)ATT implementation + *bluezDaemonVersion() = QVersionNumber(4, 0); + } + } + + // 4. Ultimate fallback -> enable dummy backend + if (bluezDaemonVersion()->isNull()) { + // version 3 represents disabled BTLE + // bluezDaemonVersion should not be null to avoid repeated version tests + *bluezDaemonVersion() = QVersionNumber(3, 0); + qCWarning(QT_BT_BLUEZ) << "Cannot determine bluetoothd version and required Bluetooth HCI ioctols"; + qCWarning(QT_BT_BLUEZ) << "Disabling Qt Bluetooth LE feature"; + } + + qCDebug(QT_BT_BLUEZ) << "Bluetoothd:" << bluezDaemonVersion()->toString(); + } + + Q_ASSERT(!bluezDaemonVersion()->isNull()); + return *bluezDaemonVersion(); +} + +struct AdapterData +{ +public: + AdapterData() : reference(1), wasListeningAlready(false) {} + + int reference; + bool wasListeningAlready; + OrgFreedesktopDBusPropertiesInterface *propteryListener = nullptr; +}; + +class QtBluezDiscoveryManagerPrivate +{ +public: + QMap references; + OrgFreedesktopDBusObjectManagerInterface *manager = nullptr; +}; + +Q_GLOBAL_STATIC(QtBluezDiscoveryManager, discoveryManager) + +/*! + \internal + \class QtBluezDiscoveryManager + + This class manages the access to "org.bluez.Adapter1::Start/StopDiscovery. + + The flag is a system flag. We want to ensure that the various Qt classes don't turn + the flag on and off and thereby get into their way. If some other system component + changes the flag (e.g. adapter removed) we notify all Qt classes about the change by emitting + \l discoveryInterrupted(QString). Classes should indicate this via an appropriate + error message to the user. + + Once the signal was emitted, all existing requests for discovery mode on the same adapter + have to be renewed via \l registerDiscoveryInterest(QString). +*/ + +QtBluezDiscoveryManager::QtBluezDiscoveryManager(QObject *parent) : + QObject(parent) +{ + qCDebug(QT_BT_BLUEZ) << "Creating QtBluezDiscoveryManager"; + d = new QtBluezDiscoveryManagerPrivate(); + + d->manager = new OrgFreedesktopDBusObjectManagerInterface( + QStringLiteral("org.bluez"), QStringLiteral("/"), + QDBusConnection::systemBus(), this); + connect(d->manager, SIGNAL(InterfacesRemoved(QDBusObjectPath,QStringList)), + SLOT(InterfacesRemoved(QDBusObjectPath,QStringList))); +} + +QtBluezDiscoveryManager::~QtBluezDiscoveryManager() +{ + qCDebug(QT_BT_BLUEZ) << "Destroying QtBluezDiscoveryManager"; + + const QList adapterPaths = d->references.keys(); + for (const QString &adapterPath : adapterPaths) { + AdapterData *data = d->references.take(adapterPath); + delete data->propteryListener; + + // turn discovery off if it wasn't on already + if (!data->wasListeningAlready) { + OrgBluezAdapter1Interface iface(QStringLiteral("org.bluez"), adapterPath, + QDBusConnection::systemBus()); + iface.StopDiscovery(); + } + + delete data; + } + + delete d; +} + +QtBluezDiscoveryManager *QtBluezDiscoveryManager::instance() +{ + return discoveryManager(); +} + +bool QtBluezDiscoveryManager::registerDiscoveryInterest(const QString &adapterPath) +{ + if (adapterPath.isEmpty()) + return false; + + // already monitored adapter? -> increase ref count -> done + if (d->references.contains(adapterPath)) { + d->references[adapterPath]->reference++; + return true; + } + + AdapterData *data = new AdapterData(); + + OrgFreedesktopDBusPropertiesInterface *propIface = new OrgFreedesktopDBusPropertiesInterface( + QStringLiteral("org.bluez"), adapterPath, QDBusConnection::systemBus()); + connect(propIface, &OrgFreedesktopDBusPropertiesInterface::PropertiesChanged, + this, &QtBluezDiscoveryManager::PropertiesChanged); + data->propteryListener = propIface; + + OrgBluezAdapter1Interface iface(QStringLiteral("org.bluez"), adapterPath, + QDBusConnection::systemBus()); + data->wasListeningAlready = iface.discovering(); + + d->references[adapterPath] = data; + + if (!data->wasListeningAlready) + iface.StartDiscovery(); + + return true; +} + +void QtBluezDiscoveryManager::unregisterDiscoveryInterest(const QString &adapterPath) +{ + if (!d->references.contains(adapterPath)) + return; + + AdapterData *data = d->references[adapterPath]; + data->reference--; + + if (data->reference > 0) // more than one client requested discovery mode + return; + + d->references.remove(adapterPath); + if (!data->wasListeningAlready) { // Qt turned discovery mode on, Qt has to turn it off again + OrgBluezAdapter1Interface iface(QStringLiteral("org.bluez"), adapterPath, + QDBusConnection::systemBus()); + iface.StopDiscovery(); + } + + delete data->propteryListener; + delete data; +} + +//void QtBluezDiscoveryManager::dumpState() const +//{ +// qCDebug(QT_BT_BLUEZ) << "-------------------------"; +// if (d->references.isEmpty()) { +// qCDebug(QT_BT_BLUEZ) << "No running registration"; +// } else { +// const QList paths = d->references.keys(); +// for (const QString &path : paths) { +// qCDebug(QT_BT_BLUEZ) << path << "->" << d->references[path]->reference; +// } +// } +// qCDebug(QT_BT_BLUEZ) << "-------------------------"; +//} + +void QtBluezDiscoveryManager::InterfacesRemoved(const QDBusObjectPath &object_path, + const QStringList &interfaces) +{ + if (!d->references.contains(object_path.path()) + || !interfaces.contains(QStringLiteral("org.bluez.Adapter1"))) + return; + + removeAdapterFromMonitoring(object_path.path()); +} + +void QtBluezDiscoveryManager::PropertiesChanged(const QString &interface, + const QVariantMap &changed_properties, + const QStringList &invalidated_properties, + const QDBusMessage &) +{ + Q_UNUSED(invalidated_properties); + + OrgFreedesktopDBusPropertiesInterface *propIface = + qobject_cast(sender()); + + if (!propIface) + return; + + if (interface == QStringLiteral("org.bluez.Adapter1") + && d->references.contains(propIface->path()) + && changed_properties.contains(QStringLiteral("Discovering"))) { + bool isDiscovering = changed_properties.value(QStringLiteral("Discovering")).toBool(); + if (!isDiscovering) { + + /* + Once we stop the Discovering flag will switch a few ms later. This comes through this code + path. If a new device discovery is started while we are still + waiting for the flag change signal, then the new device discovery will be aborted prematurely. + To compensate we check whether there was renewed interest. + */ + + AdapterData *data = d->references[propIface->path()]; + if (!data) { + removeAdapterFromMonitoring(propIface->path()); + } else { + OrgBluezAdapter1Interface iface(QStringLiteral("org.bluez"), propIface->path(), + QDBusConnection::systemBus()); + iface.StartDiscovery(); + } + } + } +} + +void QtBluezDiscoveryManager::removeAdapterFromMonitoring(const QString &dbusPath) +{ + // remove adapter from monitoring + AdapterData *data = d->references.take(dbusPath); + delete data->propteryListener; + delete data; + + emit discoveryInterrupted(dbusPath); +} + +/* + Finds the path for the local adapter with \a wantedAddress or an empty string + if no local adapter with the given address can be found. + If \a wantedAddress is \c null it returns the first/default adapter or an empty + string if none is available. + + If \a ok is false the lookup was aborted due to a dbus error and this function + returns an empty string. + */ +QString findAdapterForAddress(const QBluetoothAddress &wantedAddress, bool *ok = nullptr) +{ + OrgFreedesktopDBusObjectManagerInterface manager(QStringLiteral("org.bluez"), + QStringLiteral("/"), + QDBusConnection::systemBus()); + + QDBusPendingReply reply = manager.GetManagedObjects(); + reply.waitForFinished(); + if (reply.isError()) { + if (ok) + *ok = false; + + return QString(); + } + + typedef QPair AddressForPathType; + QList localAdapters; + + ManagedObjectList managedObjectList = reply.value(); + for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) { + const QDBusObjectPath &path = it.key(); + const InterfaceList &ifaceList = it.value(); + + for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) { + const QString &iface = jt.key(); + + if (iface == QStringLiteral("org.bluez.Adapter1")) { + AddressForPathType pair; + pair.first = path.path(); + pair.second = QBluetoothAddress(ifaceList.value(iface).value( + QStringLiteral("Address")).toString()); + if (!pair.second.isNull()) + localAdapters.append(pair); + break; + } + } + } + + if (ok) + *ok = true; + + if (localAdapters.isEmpty()) + return QString(); // -> no local adapter found + + if (wantedAddress.isNull()) + return localAdapters.front().first; // -> return first found adapter + + for (const AddressForPathType &pair : std::as_const(localAdapters)) { + if (pair.second == wantedAddress) + return pair.first; // -> found local adapter with wanted address + } + + return QString(); // nothing matching found +} + +/* + + Checks the presence of peripheral interface and returns path to the adapter + +*/ + +QString adapterWithDBusPeripheralInterface(const QBluetoothAddress &localAddress) +{ + initializeBluez5(); + + // First find the object path to the desired adapter + bool ok = false; + const QString hostAdapterPath = findAdapterForAddress(localAddress, &ok); + if (!ok || hostAdapterPath.isEmpty()) + return {}; + + // Then check if that adapter provides peripheral dbus interface + OrgFreedesktopDBusObjectManagerInterface manager(QStringLiteral("org.bluez"), + QStringLiteral("/"), + QDBusConnection::systemBus()); + QDBusPendingReply reply = manager.GetManagedObjects(); + reply.waitForFinished(); + if (reply.isError()) + return {}; + + using namespace Qt::StringLiterals; + // For example /org/bluez/hci0 contains org.bluezLEAdvertisingManager1 + const bool peripheralSupported = reply.value() + .value(QDBusObjectPath(hostAdapterPath)) + .contains("org.bluez.LEAdvertisingManager1"_L1); + + qCDebug(QT_BT_BLUEZ) << "Peripheral role" + << (peripheralSupported ? "" : "not") + << "supported on" << hostAdapterPath; + return peripheralSupported ? hostAdapterPath : QString{}; +} + +/* + Removes every character that cannot be used in QDbusObjectPath + + See QDbusUtil::isValidObjectPath(QString) for more details. + */ +QString sanitizeNameForDBus(const QString &text) +{ + QString appName = text; + for (qsizetype i = 0; i < appName.size(); ++i) { + ushort us = appName[i].unicode(); + bool valid = (us >= 'a' && us <= 'z') + || (us >= 'A' && us <= 'Z') + || (us >= '0' && us <= '9') + || (us == '_'); + + if (!valid) + appName[i] = QLatin1Char('_'); + } + + return appName; +} + +QT_END_NAMESPACE + +#include "moc_bluez5_helper_p.cpp" diff --git a/src/bluetooth/bluez/bluez5_helper_p.h b/src/bluetooth/bluez/bluez5_helper_p.h new file mode 100644 index 0000000..7601c9c --- /dev/null +++ b/src/bluetooth/bluez/bluez5_helper_p.h @@ -0,0 +1,81 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef BLUEZ5_HELPER_H +#define BLUEZ5_HELPER_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 + +typedef QMap InterfaceList; +typedef QMap ManagedObjectList; +typedef QMap ManufacturerDataList; +typedef QMap ServiceDataList; + +QT_DECL_METATYPE_EXTERN(InterfaceList, /* not exported */) +QT_DECL_METATYPE_EXTERN(ManufacturerDataList, /* not exported */) +QT_DECL_METATYPE_EXTERN(ServiceDataList, /* not exported */) +QT_DECL_METATYPE_EXTERN(ManagedObjectList, /* not exported */) + +QT_BEGIN_NAMESPACE + +void initializeBluez5(); +bool isBluez5(); + +// exported for unit test purposes +Q_BLUETOOTH_PRIVATE_EXPORT QVersionNumber bluetoothdVersion(); + +QString sanitizeNameForDBus(const QString& text); + +QString findAdapterForAddress(const QBluetoothAddress &wantedAddress, bool *ok); + +QString adapterWithDBusPeripheralInterface(const QBluetoothAddress &localAddress); + +class QtBluezDiscoveryManagerPrivate; +class QtBluezDiscoveryManager : public QObject +{ + Q_OBJECT +public: + QtBluezDiscoveryManager(QObject* parent = nullptr); + ~QtBluezDiscoveryManager(); + static QtBluezDiscoveryManager *instance(); + + bool registerDiscoveryInterest(const QString &adapterPath); + void unregisterDiscoveryInterest(const QString &adapterPath); + + //void dumpState() const; + +signals: + void discoveryInterrupted(const QString &adapterPath); + +private slots: + void InterfacesRemoved(const QDBusObjectPath &object_path, + const QStringList &interfaces); + void PropertiesChanged(const QString &interface, + const QVariantMap &changed_properties, + const QStringList &invalidated_properties, + const QDBusMessage &msg); + +private: + void removeAdapterFromMonitoring(const QString &dbusPath); + + QtBluezDiscoveryManagerPrivate *d; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/bluetooth/bluez/bluez_data.cpp b/src/bluetooth/bluez/bluez_data.cpp new file mode 100644 index 0000000..8ffd23b --- /dev/null +++ b/src/bluetooth/bluez/bluez_data.cpp @@ -0,0 +1,10 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "bluez_data_p.h" + +QT_BEGIN_NAMESPACE + +QT_END_NAMESPACE + +#include "moc_bluez_data_p.cpp" diff --git a/src/bluetooth/bluez/bluez_data_p.h b/src/bluetooth/bluez/bluez_data_p.h new file mode 100644 index 0000000..65ddeb9 --- /dev/null +++ b/src/bluetooth/bluez/bluez_data_p.h @@ -0,0 +1,394 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef BLUEZ_DATA_P_H +#define BLUEZ_DATA_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 + +#define ATTRIBUTE_CHANNEL_ID 4 +#define SIGNALING_CHANNEL_ID 5 +#define SECURITY_CHANNEL_ID 6 + +#define BTPROTO_L2CAP 0 +#define BTPROTO_HCI 1 +#define BTPROTO_RFCOMM 3 + +#define SOL_HCI 0 +#define SOL_L2CAP 6 +#define SOL_RFCOMM 18 +#ifndef SOL_BLUETOOTH +#define SOL_BLUETOOTH 274 +#endif + +#define RFCOMM_LM 0x03 + +#define RFCOMM_LM_AUTH 0x0002 +#define RFCOMM_LM_ENCRYPT 0x0004 +#define RFCOMM_LM_TRUSTED 0x0008 +#define RFCOMM_LM_SECURE 0x0020 + +#define L2CAP_LM 0x03 +#define L2CAP_LM_AUTH 0x0002 +#define L2CAP_LM_ENCRYPT 0x0004 +#define L2CAP_LM_TRUSTED 0x0008 +#define L2CAP_LM_SECURE 0x0020 + +#define BT_SECURITY 4 +struct bt_security { + quint8 level; + quint8 key_size; +}; +#define BT_SECURITY_SDP 0 +#define BT_SECURITY_LOW 1 +#define BT_SECURITY_MEDIUM 2 +#define BT_SECURITY_HIGH 3 + +#define BDADDR_LE_PUBLIC 0x01 +#define BDADDR_LE_RANDOM 0x02 + +#define SCO_LINK 0x00 +#define ACL_LINK 0x01 +#define ESCO_LINK 0x02 +#define LE_LINK 0x80 // based on hcitool.c -> no fixed constant available + +/* Byte order conversions */ +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define htobs(d) (d) +#define htobl(d) (d) +#define htobll(d) (d) +#define btohs(d) (d) +#define btohl(d) (d) +#define btohll(d) (d) +#elif __BYTE_ORDER == __BIG_ENDIAN +#define htobs(d) qbswap((quint16)(d)) +#define htobl(d) qbswap((quint32)(d)) +#define htobll(d) qbswap((quint64)(d)) +#define btohs(d) qbswap((quint16)(d)) +#define btohl(d) qbswap((quint32)(d)) +#define btohll(d) qbswap((quint64)(d)) +#else +#error "Unknown byte order" +#endif + +#define HCIGETCONNLIST _IOR('H', 212, int) +#define HCIGETDEVINFO _IOR('H', 211, int) +#define HCIGETDEVLIST _IOR('H', 210, int) + +// Generic 128 bits of data +typedef QUuid::Id128Bytes BluezUint128; + +// Bluetooth address +typedef struct { + quint8 b[6]; +} __attribute__((packed)) bdaddr_t; + +// L2CP socket +struct sockaddr_l2 { + sa_family_t l2_family; + unsigned short l2_psm; + bdaddr_t l2_bdaddr; + unsigned short l2_cid; +#if !defined(QT_BLUEZ_NO_BTLE) + quint8 l2_bdaddr_type; +#endif +}; + +// RFCOMM socket +struct sockaddr_rc { + sa_family_t rc_family; + bdaddr_t rc_bdaddr; + quint8 rc_channel; +}; + +// Bt Low Energy related + +template inline T getBtData(const void *ptr) +{ + return qFromLittleEndian(reinterpret_cast(ptr)); +} + +static inline quint16 bt_get_le16(const void *ptr) +{ + return getBtData(ptr); +} + +template inline void putBtData(T src, void *dst) +{ + qToLittleEndian(src, reinterpret_cast(dst)); +} + +// HCI related + +#define HCI_MAX_DEV 16 +#define HCI_DEV_NONE 0xffff + +#define HCI_CHANNEL_CONTROL 0x3 + +#define HCI_MAX_EVENT_SIZE 260 + +// HCI sockopts +#define HCI_FILTER 2 + +// HCI packet types +#define HCI_COMMAND_PKT 0x01 +#define HCI_ACL_PKT 0x02 +#define HCI_EVENT_PKT 0x04 +#define HCI_VENDOR_PKT 0xff + +#define HCI_FLT_TYPE_BITS 31 +#define HCI_FLT_EVENT_BITS 63 + + +struct sockaddr_hci { + sa_family_t hci_family; + unsigned short hci_dev; + unsigned short hci_channel; +}; + +struct hci_dev_req { + quint16 dev_id; + quint32 dev_opt; +}; + +struct hci_dev_list_req { + quint16 dev_num; + struct hci_dev_req dev_req[0]; +}; + +struct hci_dev_stats { + quint32 err_rx; + quint32 err_tx; + quint32 cmd_tx; + quint32 evt_rx; + quint32 acl_tx; + quint32 acl_rx; + quint32 sco_tx; + quint32 sco_rx; + quint32 byte_rx; + quint32 byte_tx; +}; + +struct hci_dev_info { + quint16 dev_id; + char name[8]; + + bdaddr_t bdaddr; + + quint32 flags; + quint8 type; + + quint8 features[8]; + + quint32 pkt_type; + quint32 link_policy; + quint32 link_mode; + + quint16 acl_mtu; + quint16 acl_pkts; + quint16 sco_mtu; + quint16 sco_pkts; + + struct hci_dev_stats stat; +}; + +struct hci_conn_info { + quint16 handle; + bdaddr_t bdaddr; + quint8 type; + quint8 out; + quint16 state; + quint32 link_mode; +}; + +struct hci_conn_list_req { + quint16 dev_id; + quint16 conn_num; + struct hci_conn_info conn_info[0]; +}; + +struct hci_filter { + quint32 type_mask; + quint32 event_mask[2]; + quint16 opcode; +}; + +static inline void hci_set_bit(int nr, void *addr) +{ + *((quint32 *) addr + (nr >> 5)) |= (1 << (nr & 31)); +} +static inline void hci_clear_bit(int nr, void *addr) +{ + *((quint32 *) addr + (nr >> 5)) &= ~(1 << (nr & 31)); +} +static inline void hci_filter_clear(struct hci_filter *f) +{ + memset(f, 0, sizeof(*f)); +} +static inline void hci_filter_set_ptype(int t, struct hci_filter *f) +{ + hci_set_bit((t == HCI_VENDOR_PKT) ? 0 : (t & HCI_FLT_TYPE_BITS), &f->type_mask); +} +static inline void hci_filter_clear_ptype(int t, struct hci_filter *f) +{ + hci_clear_bit((t == HCI_VENDOR_PKT) ? 0 : (t & HCI_FLT_TYPE_BITS), &f->type_mask); +} +static inline void hci_filter_set_event(int e, struct hci_filter *f) +{ + hci_set_bit((e & HCI_FLT_EVENT_BITS), &f->event_mask); +} +static inline void hci_filter_clear_event(int e, struct hci_filter *f) +{ + hci_clear_bit((e & HCI_FLT_EVENT_BITS), &f->event_mask); +} +static inline void hci_filter_all_ptypes(struct hci_filter *f) +{ + memset((void *) &f->type_mask, 0xff, sizeof(f->type_mask)); +} +static inline void hci_filter_all_events(struct hci_filter *f) +{ + memset((void *) f->event_mask, 0xff, sizeof(f->event_mask)); +} + +typedef struct { + quint8 evt; + quint8 plen; +} __attribute__ ((packed)) hci_event_hdr; +#define HCI_EVENT_HDR_SIZE 2 + +typedef struct { + quint8 status; + quint16 handle; + quint8 encrypt; +} __attribute__ ((packed)) evt_encrypt_change; +#define EVT_ENCRYPT_CHANGE_SIZE 4 + +struct evt_cmd_complete { + quint8 ncmd; + quint16 opcode; +} __attribute__ ((packed)); + +struct AclData { + quint16 handle: 12; + quint16 pbFlag: 2; + quint16 bcFlag: 2; + quint16 dataLen; +}; + +struct L2CapHeader { + quint16 length; + quint16 channelId; +}; + +struct hci_command_hdr { + quint16 opcode; /* OCF & OGF */ + quint8 plen; +} __attribute__ ((packed)); + +namespace QBluezConst { + Q_NAMESPACE + enum OpCodeGroupField { + OgfLinkControl = 0x8, + }; + Q_ENUM_NS(OpCodeGroupField) + + enum OpCodeCommandField { + OcfLeSetAdvParams = 0x6, + OcfLeReadTxPowerLevel = 0x7, + OcfLeSetAdvData = 0x8, + OcfLeSetScanResponseData = 0x9, + OcfLeSetAdvEnable = 0xa, + OcfLeClearWhiteList = 0x10, + OcfLeAddToWhiteList = 0x11, + OcfLeConnectionUpdate = 0x13, + }; + Q_ENUM_NS(OpCodeCommandField) + + enum class AttCommand : quint8 { + ATT_OP_ERROR_RESPONSE = 0x01, + ATT_OP_EXCHANGE_MTU_REQUEST = 0x02, //send own mtu + ATT_OP_EXCHANGE_MTU_RESPONSE = 0x03, //receive server MTU + ATT_OP_FIND_INFORMATION_REQUEST = 0x04, //discover individual attribute info + ATT_OP_FIND_INFORMATION_RESPONSE = 0x05, + ATT_OP_FIND_BY_TYPE_VALUE_REQUEST = 0x06, + ATT_OP_FIND_BY_TYPE_VALUE_RESPONSE = 0x07, + ATT_OP_READ_BY_TYPE_REQUEST = 0x08, //discover characteristics + ATT_OP_READ_BY_TYPE_RESPONSE = 0x09, + ATT_OP_READ_REQUEST = 0x0A, //read characteristic & descriptor values + ATT_OP_READ_RESPONSE = 0x0B, + ATT_OP_READ_BLOB_REQUEST = 0x0C, //read values longer than MTU-1 + ATT_OP_READ_BLOB_RESPONSE = 0x0D, + ATT_OP_READ_MULTIPLE_REQUEST = 0x0E, + ATT_OP_READ_MULTIPLE_RESPONSE = 0x0F, + ATT_OP_READ_BY_GROUP_REQUEST = 0x10, //discover services + ATT_OP_READ_BY_GROUP_RESPONSE = 0x11, + ATT_OP_WRITE_REQUEST = 0x12, //write characteristic with response + ATT_OP_WRITE_RESPONSE = 0x13, + ATT_OP_PREPARE_WRITE_REQUEST = 0x16, //write values longer than MTU-3 -> queueing + ATT_OP_PREPARE_WRITE_RESPONSE = 0x17, + ATT_OP_EXECUTE_WRITE_REQUEST = 0x18, //write values longer than MTU-3 -> execute queue + ATT_OP_EXECUTE_WRITE_RESPONSE = 0x19, + ATT_OP_HANDLE_VAL_NOTIFICATION = 0x1b, //informs about value change + ATT_OP_HANDLE_VAL_INDICATION = 0x1d, //informs about value change -> requires reply + ATT_OP_HANDLE_VAL_CONFIRMATION = 0x1e, //answer for ATT_OP_HANDLE_VAL_INDICATION + ATT_OP_WRITE_COMMAND = 0x52, //write characteristic without response + ATT_OP_SIGNED_WRITE_COMMAND = 0xD2 + }; + Q_ENUM_NS(AttCommand) + + enum class AttError : quint8 { + ATT_ERROR_NO_ERROR = 0x00, + ATT_ERROR_INVALID_HANDLE = 0x01, + ATT_ERROR_READ_NOT_PERM = 0x02, + ATT_ERROR_WRITE_NOT_PERM = 0x03, + ATT_ERROR_INVALID_PDU = 0x04, + ATT_ERROR_INSUF_AUTHENTICATION = 0x05, + ATT_ERROR_REQUEST_NOT_SUPPORTED = 0x06, + ATT_ERROR_INVALID_OFFSET = 0x07, + ATT_ERROR_INSUF_AUTHORIZATION = 0x08, + ATT_ERROR_PREPARE_QUEUE_FULL = 0x09, + ATT_ERROR_ATTRIBUTE_NOT_FOUND = 0x0A, + ATT_ERROR_ATTRIBUTE_NOT_LONG = 0x0B, + ATT_ERROR_INSUF_ENCR_KEY_SIZE = 0x0C, + ATT_ERROR_INVAL_ATTR_VALUE_LEN = 0x0D, + ATT_ERROR_UNLIKELY = 0x0E, + ATT_ERROR_INSUF_ENCRYPTION = 0x0F, + ATT_ERROR_UNSUPPRTED_GROUP_TYPE = 0x10, + ATT_ERROR_INSUF_RESOURCES = 0x11, + ATT_ERROR_APPLICATION_START = 0x80, + //------------------------------------------ + // The error codes in this block are + // implementation specific errors + + ATT_ERROR_REQUEST_STALLED = 0x81, + + //------------------------------------------ + ATT_ERROR_APPLICATION_END = 0x9f + }; + Q_ENUM_NS(AttError) +} +/* Command opcode pack/unpack */ +#define opCodePack(ogf, ocf) (quint16(((ocf) & 0x03ff)|((ogf) << 10))) +#define ogfFromOpCode(op) ((op) >> 10) +#define ocfFromOpCode(op) ((op) & 0x03ff) + +QT_END_NAMESPACE + +#endif // BLUEZ_DATA_P_H diff --git a/src/bluetooth/bluez/bluezperipheralapplication.cpp b/src/bluetooth/bluez/bluezperipheralapplication.cpp new file mode 100644 index 0000000..5a8e489 --- /dev/null +++ b/src/bluetooth/bluez/bluezperipheralapplication.cpp @@ -0,0 +1,280 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "bluezperipheralapplication_p.h" +#include "bluezperipheralobjects_p.h" +#include "objectmanageradaptor_p.h" +#include "gattmanager1_p.h" + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ) + +using namespace Qt::StringLiterals; + +static constexpr QLatin1String appObjectPathTemplate{"/qt/btle/application/%1%2/%3"}; + +QtBluezPeripheralApplication::QtBluezPeripheralApplication(const QString& hostAdapterPath, + QObject* parent) + : QObject(parent), + m_objectPath(QString(appObjectPathTemplate). + arg(sanitizeNameForDBus(QCoreApplication::applicationName())). + arg(QCoreApplication::applicationPid()). + arg(QRandomGenerator::global()->generate())) +{ + m_objectManager = new OrgFreedesktopDBusObjectManagerAdaptor(this); + m_gattManager = new OrgBluezGattManager1Interface("org.bluez"_L1, hostAdapterPath, + QDBusConnection::systemBus(), this); +} + +QtBluezPeripheralApplication::~QtBluezPeripheralApplication() +{ + unregisterApplication(); +} + +void QtBluezPeripheralApplication::registerApplication() +{ + if (m_applicationRegistered) { + // Can happen eg. if advertisement is start-stop-started + qCDebug(QT_BT_BLUEZ) << "Bluez peripheral application already registered"; + return; + } + + if (m_services.isEmpty()) { + // Registering the application to bluez without services would fail + qCDebug(QT_BT_BLUEZ) << "No services, omiting Bluez peripheral application registration"; + return; + } + + qCDebug(QT_BT_BLUEZ) << "Registering bluez peripheral application:" << m_objectPath; + + // Register this application object on DBus + if (!QDBusConnection::systemBus().registerObject(m_objectPath, m_objectManager, + QDBusConnection::ExportAllContents)) { + qCWarning(QT_BT_BLUEZ) << "Peripheral application object registration failed"; + emit errorOccurred(); + return; + } + + // Register the service objects on DBus + registerServices(); + + // Register the gatt application to Bluez. After successful registration Bluez + // is aware of this peripheral application and will inquiry which services this application + // provides, see GetManagedObjects() + auto reply = m_gattManager->RegisterApplication(QDBusObjectPath(m_objectPath), {}); + QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this); + QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, + [this](QDBusPendingCallWatcher* watcher) { + QDBusPendingReply<> reply = *watcher; + if (reply.isError()) { + qCWarning(QT_BT_BLUEZ) << "Application registration failed" << reply.error(); + QDBusConnection::systemBus().unregisterObject(m_objectPath); + emit errorOccurred(); + } else { + qCDebug(QT_BT_BLUEZ) << "Peripheral application registered as" << m_objectPath; + m_applicationRegistered = true; + emit registered(); + } + watcher->deleteLater(); + }); +} + +void QtBluezPeripheralApplication::unregisterApplication() +{ + if (!m_applicationRegistered) + return; + m_applicationRegistered = false; + auto reply = m_gattManager->UnregisterApplication(QDBusObjectPath(m_objectPath)); + reply.waitForFinished(); + if (reply.isError()) + qCWarning(QT_BT_BLUEZ) << "Error in unregistering peripheral application"; + else + qCDebug(QT_BT_BLUEZ) << "Peripheral application unregistered successfully"; + QDBusConnection::systemBus().unregisterObject(m_objectPath); + unregisterServices(); + + qCDebug(QT_BT_BLUEZ) << "Unregistered Bluez peripheral application on DBus:" << m_objectPath; +} + +void QtBluezPeripheralApplication::registerServices() +{ + // Register the service objects on DBus + for (const auto service: std::as_const(m_services)) + service->registerObject(); + for (const auto& characteristic : std::as_const(m_characteristics)) + characteristic->registerObject(); + for (const auto& descriptor : std::as_const(m_descriptors)) + descriptor->registerObject(); +} + +void QtBluezPeripheralApplication::unregisterServices() +{ + // Unregister the service objects from DBus + for (const auto service: std::as_const(m_services)) + service->unregisterObject(); + for (const auto& characteristic : std::as_const(m_characteristics)) + characteristic->unregisterObject(); + for (const auto& descriptor : std::as_const(m_descriptors)) + descriptor->unregisterObject(); +} + +void QtBluezPeripheralApplication::reset() +{ + unregisterApplication(); + + qDeleteAll(m_services); + m_services.clear(); + qDeleteAll(m_descriptors); + m_descriptors.clear(); + qDeleteAll(m_characteristics); + m_characteristics.clear(); +} + +void QtBluezPeripheralApplication::addService(const QLowEnergyServiceData &serviceData, + QSharedPointer servicePrivate, + QLowEnergyHandle serviceHandle) +{ + if (m_applicationRegistered) { + qCWarning(QT_BT_BLUEZ) << "Adding services to a registered application is not supported " + "on Bluez DBus. Add services only before first advertisement or " + "after disconnection"; + return; + } + + // The ordinal numbers in the below object creation are used to create paths such as: + // ../service0/char0/desc0 + // ../service0/char1/desc0 + // ../service1/char0/desc0 + // ../service1/char0/desc1 + // For the Service object itself the ordinal number is the size of the service container + QtBluezPeripheralService* service = new QtBluezPeripheralService( + serviceData, m_objectPath, m_services.size(), serviceHandle, this); + m_services.insert(serviceHandle, service); + + // Add included services + for (const auto includedService : serviceData.includedServices()) { + // As per Qt documentation the included service must have been added earlier + for (const auto s : std::as_const(m_services)) { + if (QBluetoothUuid(s->uuid) == includedService->serviceUuid()) { + service->addIncludedService(s->objectPath); + } + } + } + + // Set characteristics and their descriptors + quint16 characteristicOrdinal{0}; + for (const auto& characteristicData : serviceData.characteristics()) { + auto characteristicHandle = handleForCharacteristic( + characteristicData.uuid(), servicePrivate); + QtBluezPeripheralCharacteristic* characteristic = + new QtBluezPeripheralCharacteristic(characteristicData, + service->objectPath, characteristicOrdinal++, + characteristicHandle, this); + m_characteristics.insert(characteristicHandle, characteristic); + QObject::connect(characteristic, &QtBluezPeripheralCharacteristic::valueUpdatedByRemote, + this, &QtBluezPeripheralApplication::characteristicValueUpdatedByRemote); + QObject::connect(characteristic, &QtBluezPeripheralCharacteristic::remoteDeviceAccessEvent, + this, &QtBluezPeripheralApplication::remoteDeviceAccessEvent); + + quint16 descriptorOrdinal{0}; + for (const auto& descriptorData : characteristicData.descriptors()) { + // With bluez we don't use the CCCD user has provided, because Bluez + // generates it if 'notify/indicate' flag is set. Similarly the extended properties + // descriptor is generated by Bluez if the related flags are set. Using the application + // provided descriptors would result in duplicate descriptors. + if (descriptorData.uuid() + == QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration + || descriptorData.uuid() + == QBluetoothUuid::DescriptorType::CharacteristicExtendedProperties) { + continue; + } + auto descriptorHandle = handleForDescriptor(descriptorData.uuid(), + servicePrivate, + characteristicHandle); + QtBluezPeripheralDescriptor* descriptor = + new QtBluezPeripheralDescriptor(descriptorData, + characteristic->objectPath, descriptorOrdinal++, + descriptorHandle, characteristicHandle, this); + QObject::connect(descriptor, &QtBluezPeripheralDescriptor::valueUpdatedByRemote, + this, &QtBluezPeripheralApplication::descriptorValueUpdatedByRemote); + QObject::connect(descriptor, &QtBluezPeripheralCharacteristic::remoteDeviceAccessEvent, + this, &QtBluezPeripheralApplication::remoteDeviceAccessEvent); + m_descriptors.insert(descriptorHandle, descriptor); + } + } +} + +// This function is called when characteristic is written to from Qt API +bool QtBluezPeripheralApplication::localCharacteristicWrite(QLowEnergyHandle handle, + const QByteArray& value) +{ + auto characteristic = m_characteristics.value(handle); + if (!characteristic) { + qCWarning(QT_BT_BLUEZ) << "DBus characteristic not found for write"; + return false; + } + return characteristic->localValueUpdate(value); +} + +// This function is called when characteristic is written to from Qt API +bool QtBluezPeripheralApplication::localDescriptorWrite(QLowEnergyHandle handle, + const QByteArray& value) +{ + auto descriptor = m_descriptors.value(handle); + if (!descriptor) { + qCWarning(QT_BT_BLUEZ) << "DBus descriptor not found for write"; + return false; + } + return descriptor->localValueUpdate(value); +} + +bool QtBluezPeripheralApplication::registrationNeeded() +{ + return !m_applicationRegistered && !m_services.isEmpty(); +} + +// org.freedesktop.DBus.ObjectManager +// This is called by Bluez when we register the application +ManagedObjectList QtBluezPeripheralApplication::GetManagedObjects() +{ + ManagedObjectList managedObjects; + for (const auto service: std::as_const(m_services)) + managedObjects.insert(QDBusObjectPath(service->objectPath), service->properties()); + for (const auto& charac : std::as_const(m_characteristics)) + managedObjects.insert(QDBusObjectPath(charac->objectPath), charac->properties()); + for (const auto& descriptor : std::as_const(m_descriptors)) + managedObjects.insert(QDBusObjectPath(descriptor->objectPath), descriptor->properties()); + + return managedObjects; +} + +// Returns the Qt-internal handle for the characteristic +QLowEnergyHandle QtBluezPeripheralApplication::handleForCharacteristic(QBluetoothUuid uuid, + QSharedPointer service) +{ + const auto handles = service->characteristicList.keys(); + for (const auto handle : handles) { + if (uuid == service->characteristicList[handle].uuid) + return handle; + } + return 0; +} + +// Returns the Qt-internal handle for the descriptor +QLowEnergyHandle QtBluezPeripheralApplication::handleForDescriptor(QBluetoothUuid uuid, + QSharedPointer service, + QLowEnergyHandle characteristicHandle) +{ + const auto characteristicData = service->characteristicList[characteristicHandle]; + const auto handles = characteristicData.descriptorList.keys(); + for (const auto handle : handles) { + if (uuid == characteristicData.descriptorList[handle].uuid) + return handle; + } + return 0; +} + +QT_END_NAMESPACE + +#include "moc_bluezperipheralapplication_p.cpp" diff --git a/src/bluetooth/bluez/bluezperipheralapplication_p.h b/src/bluetooth/bluez/bluezperipheralapplication_p.h new file mode 100644 index 0000000..1b8287b --- /dev/null +++ b/src/bluetooth/bluez/bluezperipheralapplication_p.h @@ -0,0 +1,100 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef BLUEZ_PERIPHERAL_APPLICATION_P_H +#define BLUEZ_PERIPHERAL_APPLICATION_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 "bluez5_helper_p.h" + +#include +#include + +class OrgFreedesktopDBusObjectManagerAdaptor; +class OrgBluezGattManager1Interface; + +QT_BEGIN_NAMESPACE + +class QLowEnergyControllerPrivateBluezDBus; +class QtBluezPeripheralService; +class QtBluezPeripheralCharacteristic; +class QtBluezPeripheralDescriptor; +class QtBluezPeripheralConnectionManager; + +class QtBluezPeripheralApplication : public QObject +{ + Q_OBJECT + +public: + QtBluezPeripheralApplication(const QString& localAdapterPath, QObject* parent = nullptr); + ~QtBluezPeripheralApplication(); + + // Register the application and its services to DBus & Bluez + void registerApplication(); + // Unregister the application and its services from DBus & Bluez. + // Calling this doesn't invalidate the services + void unregisterApplication(); + // Unregister and release all resources, invalidates services + void reset(); + + void addService(const QLowEnergyServiceData &serviceData, + QSharedPointer servicePrivate, + QLowEnergyHandle serviceHandle); + + // Call these when the user application has updated the attribute value + // Returns whether the new value was accepted + bool localCharacteristicWrite(QLowEnergyHandle handle, const QByteArray& value); + bool localDescriptorWrite(QLowEnergyHandle handle, const QByteArray& value); + + // Returns true if application has services and is not registered + bool registrationNeeded(); + + // org.freedesktop.DBus.ObjectManager + Q_INVOKABLE ManagedObjectList GetManagedObjects(); + +signals: + void errorOccurred(); + void registered(); + + // Emitted when remote device reads a characteristic + void remoteDeviceAccessEvent(const QString& remoteDeviceObjectPath, quint16 mtu); + + // These are emitted when remote has written a new value + void characteristicValueUpdatedByRemote(QLowEnergyHandle handle, const QByteArray& value); + void descriptorValueUpdatedByRemote(QLowEnergyHandle characteristicHandle, + QLowEnergyHandle descriptorHandle, + const QByteArray& value); +private: + void registerServices(); + void unregisterServices(); + + QLowEnergyHandle handleForCharacteristic(QBluetoothUuid uuid, + QSharedPointer service); + QLowEnergyHandle handleForDescriptor(QBluetoothUuid uuid, + QSharedPointer service, + QLowEnergyHandle characteristicHandle); + + QMap m_services; + QMap m_characteristics; + QMap m_descriptors; + + QString m_objectPath; + OrgFreedesktopDBusObjectManagerAdaptor* m_objectManager{}; + OrgBluezGattManager1Interface* m_gattManager{}; + bool m_applicationRegistered{false}; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/bluetooth/bluez/bluezperipheralconnectionmanager.cpp b/src/bluetooth/bluez/bluezperipheralconnectionmanager.cpp new file mode 100644 index 0000000..64350d2 --- /dev/null +++ b/src/bluetooth/bluez/bluezperipheralconnectionmanager.cpp @@ -0,0 +1,96 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "bluezperipheralconnectionmanager_p.h" +#include "device1_bluez5_p.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ) + +using namespace Qt::StringLiterals; + +QtBluezPeripheralConnectionManager::QtBluezPeripheralConnectionManager( + const QBluetoothAddress& localAddress, QObject* parent) + : QObject(parent), + m_localDevice(new QBluetoothLocalDevice(localAddress, this)) +{ + QObject::connect(m_localDevice, &QBluetoothLocalDevice::deviceDisconnected, + this, &QtBluezPeripheralConnectionManager::remoteDeviceDisconnected); +} + +void QtBluezPeripheralConnectionManager::remoteDeviceAccessEvent( + const QString& remoteDeviceObjectPath, quint16 mtu) +{ + if (m_clients.contains(remoteDeviceObjectPath)) + return; // Already aware of the client + + std::unique_ptr device{new OrgBluezDevice1Interface( + "org.bluez"_L1, remoteDeviceObjectPath, + QDBusConnection::systemBus(), this)}; + + qCDebug(QT_BT_BLUEZ) << "New LE Gatt client connected: " << remoteDeviceObjectPath + << device->address() << device->name() << "mtu:" << mtu; + + RemoteDeviceDetails details{QBluetoothAddress{device->address()}, device->name(), mtu}; + + m_clients.insert(remoteDeviceObjectPath, details); + if (!m_connected) { + m_connected = true; + emit connectivityStateChanged(true); + } + emit remoteDeviceChanged(details.address, details.name, details.mtu); +} + +void QtBluezPeripheralConnectionManager::remoteDeviceDisconnected(const QBluetoothAddress& address) +{ + // Find if the disconnected device was gatt client + bool remoteDetailsChanged{false}; + for (auto it = m_clients.begin(); it != m_clients.end(); it++) { + if (it.value().address == address) { + qCDebug(QT_BT_BLUEZ) << "LE Gatt client disconnected:" << address; + remoteDetailsChanged = true; + m_clients.remove(it.key()); + break; + } + } + + if (!remoteDetailsChanged) + return; + + if (m_clients.isEmpty() && m_connected) { + m_connected = false; + emit connectivityStateChanged(false); + } + + // If a client disconnected but there are others, pick any other. + // Qt API doesn't distinguish between clients + if (!m_clients.isEmpty()) { + emit remoteDeviceChanged(m_clients.last().address, + m_clients.last().name, m_clients.last().mtu); + } +} + +void QtBluezPeripheralConnectionManager::disconnectDevices() +{ + for (auto it = m_clients.begin(); it != m_clients.end(); it++) { + std::unique_ptr device{new OrgBluezDevice1Interface( + "org.bluez"_L1, it.key(), QDBusConnection::systemBus())}; + device->Disconnect(); + } + reset(); +} + +void QtBluezPeripheralConnectionManager::reset() +{ + m_connected = false; + m_clients.clear(); +} + +QT_END_NAMESPACE + +#include "moc_bluezperipheralconnectionmanager_p.cpp" diff --git a/src/bluetooth/bluez/bluezperipheralconnectionmanager_p.h b/src/bluetooth/bluez/bluezperipheralconnectionmanager_p.h new file mode 100644 index 0000000..42e839c --- /dev/null +++ b/src/bluetooth/bluez/bluezperipheralconnectionmanager_p.h @@ -0,0 +1,68 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef BLUEZ_PERIPHERAL_CONNECTION_MANAGER_P_H +#define BLUEZ_PERIPHERAL_CONNECTION_MANAGER_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 QBluetoothLocalDevice; + +/* + QtBluezPeripheralConnectionManager determines + - when remote Gatt client(s) connect and disconnect + - the remote device details (name, address, mtu) + + 'Connected' state is assumed when first client reads a characteristic. + 'Disconnected' state is assumed when all such clients have disconnected. +*/ + +class QtBluezPeripheralConnectionManager : public QObject +{ + Q_OBJECT +public: + QtBluezPeripheralConnectionManager(const QBluetoothAddress& localAddress, + QObject* parent = nullptr); + void reset(); + void disconnectDevices(); + +public slots: + void remoteDeviceAccessEvent(const QString& remoteDeviceObjectPath, quint16 mtu); + +signals: + void connectivityStateChanged(bool connected); + void remoteDeviceChanged(const QBluetoothAddress& address, const QString& name, quint16 mtu); + +private slots: + void remoteDeviceDisconnected(const QBluetoothAddress& address); + +private: + struct RemoteDeviceDetails { + QBluetoothAddress address; + QString name; + quint16 mtu; + }; + bool m_connected{false}; + QString m_hostAdapterPath; + QMap m_clients; + QBluetoothLocalDevice* m_localDevice; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/bluetooth/bluez/bluezperipheralobjects.cpp b/src/bluetooth/bluez/bluezperipheralobjects.cpp new file mode 100644 index 0000000..1caa42c --- /dev/null +++ b/src/bluetooth/bluez/bluezperipheralobjects.cpp @@ -0,0 +1,403 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "bluezperipheralobjects_p.h" + +#include "propertiesadaptor_p.h" +#include "gattservice1adaptor_p.h" +#include "gattcharacteristic1adaptor_p.h" +#include "gattdescriptor1adaptor_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ) + +using namespace Qt::StringLiterals; + +static constexpr auto characteristicPathTemplate{"%1/char%2"_L1}; +static constexpr auto descriptorPathTemplate{"%1/desc%2"_L1}; +static constexpr auto servicePathTemplate{"%1/service%2"_L1}; + +// The interface names and error values are from BlueZ "gatt-api" documentation +static constexpr auto bluezServiceInterface{"org.bluez.GattService1"_L1}; +static constexpr auto bluezCharacteristicInterface{"org.bluez.GattCharacteristic1"_L1}; +static constexpr auto bluezDescriptorInterface{"org.bluez.GattDescriptor1"_L1}; + +static constexpr auto bluezErrorInvalidValueLength{"org.bluez.Error.InvalidValueLength"_L1}; +static constexpr auto bluezErrorInvalidOffset{"org.bluez.Error.InvalidOffset"_L1}; +static constexpr auto bluezErrorNotAuthorized{"org.bluez.Error.NotAuthorized"_L1}; +// Bluetooth Core v5.3, 3.2.9, Vol 3, Part F +static constexpr int maximumAttributeLength{512}; + + +QtBluezPeripheralGattObject::QtBluezPeripheralGattObject(const QString& objectPath, + const QString& uuid, QLowEnergyHandle handle, QObject* parent) + : QObject(parent), objectPath(objectPath), uuid(uuid), handle(handle), + propertiesAdaptor(new OrgFreedesktopDBusPropertiesAdaptor(this)) +{} + +QtBluezPeripheralGattObject::~QtBluezPeripheralGattObject() +{ + unregisterObject(); +} + +bool QtBluezPeripheralGattObject::registerObject() +{ + if (m_registered) + return true; + + if (QDBusConnection::systemBus().registerObject(objectPath, this)) { + qCDebug(QT_BT_BLUEZ) << "Registered object on DBus:" << objectPath << uuid; + m_registered = true; + return true; + } else { + qCWarning(QT_BT_BLUEZ) << "Failed to register object on DBus:" << objectPath << uuid; + return false; + } +} + +void QtBluezPeripheralGattObject::unregisterObject() +{ + if (!m_registered) + return; + QDBusConnection::systemBus().unregisterObject(objectPath); + qCDebug(QT_BT_BLUEZ) << "Unregistered object on DBus:" << objectPath << uuid; + m_registered = false; +} + +void QtBluezPeripheralGattObject::accessEvent(const QVariantMap& options) +{ + // Report this event for connection management purposes + const auto remoteDevice = options.value("device"_L1).value().path(); + if (!remoteDevice.isEmpty()) + emit remoteDeviceAccessEvent(remoteDevice, options.value("mtu"_L1).toUInt()); +} + +QtBluezPeripheralDescriptor::QtBluezPeripheralDescriptor( + const QLowEnergyDescriptorData& descriptorData, + const QString& characteristicPath, quint16 ordinal, + QLowEnergyHandle handle, QLowEnergyHandle characteristicHandle, + QObject* parent) + : QtBluezPeripheralGattObject(descriptorPathTemplate.arg(characteristicPath).arg(ordinal), + descriptorData.uuid().toString(QUuid::WithoutBraces), handle, parent), + m_adaptor(new OrgBluezGattDescriptor1Adaptor(this)), + m_characteristicPath(characteristicPath), + m_characteristicHandle(characteristicHandle) +{ + if (descriptorData.value().size() > maximumAttributeLength) { + qCWarning(QT_BT_BLUEZ) << "Descriptor value is too large, cropping it to" + << maximumAttributeLength; + m_value = descriptorData.value().sliced(0, maximumAttributeLength); + } else { + m_value = descriptorData.value(); + } + initializeFlags(descriptorData); +} + +InterfaceList QtBluezPeripheralDescriptor::properties() const +{ + InterfaceList properties; + properties.insert(bluezDescriptorInterface, + { + {"UUID"_L1, uuid}, + {"Characteristic"_L1, QDBusObjectPath(m_characteristicPath)}, + {"Flags"_L1, m_flags} + }); + return properties; +} + +// org.bluez.GattDescriptor1 +// This function is invoked when remote device reads the value +QByteArray QtBluezPeripheralDescriptor::ReadValue(const QVariantMap &options, QString& error) +{ + accessEvent(options); + // Offset is set by Bluez when the value size is more than MTU size. + // Bluez deduces the value size from the first ReadValue. If the + // received data size is larger than MTU, Bluez will take the first MTU bytes and + // issue more ReadValue calls with the 'offset' set + const quint16 offset = options.value("offset"_L1).toUInt(); + const quint16 mtu = options.value("mtu"_L1).toUInt(); + + if (offset > m_value.length() - 1) { + qCWarning(QT_BT_BLUEZ) << "Invalid offset" << offset << ", value len:" << m_value.length(); + error = bluezErrorInvalidOffset; + return {}; + } + + if (offset > 0) + return m_value.mid(offset, mtu); + else + return m_value; +} + +// org.bluez.GattDescriptor1 +// This function is invoked when remote device writes a value +QString QtBluezPeripheralDescriptor::WriteValue(const QByteArray &value, + const QVariantMap &options) +{ + accessEvent(options); + + if (options.value("prepare-authorize"_L1).toBool()) { + // Qt API doesn't provide the means for application to authorize + qCWarning(QT_BT_BLUEZ) << "Descriptor write requires authorization." + << "The client device needs to be trusted beforehand"; + return bluezErrorNotAuthorized; + } + + if (value.size() > maximumAttributeLength) { + qCWarning(QT_BT_BLUEZ) << "Descriptor value is too large:" << value.size(); + return bluezErrorInvalidValueLength; + } + m_value = value; + emit valueUpdatedByRemote(m_characteristicHandle, handle, value); + return {}; +} + +// This function is called when the value has been updated locally (server-side) +bool QtBluezPeripheralDescriptor::localValueUpdate(const QByteArray& value) +{ + if (value.size() > maximumAttributeLength) { + qCWarning(QT_BT_BLUEZ) << "Descriptor value is too large:" << value.size(); + return false; + } + m_value = value; + return true; +} + +void QtBluezPeripheralDescriptor::initializeFlags(const QLowEnergyDescriptorData& data) +{ + // Flag tokens are from org.bluez.GattDescriptor1 documentation + if (data.isReadable()) + m_flags.append("read"_L1); + if (data.readConstraints() & QBluetooth::AttAccessConstraint::AttEncryptionRequired) + m_flags.append("encrypt-read"_L1); + if (data.readConstraints() & QBluetooth::AttAccessConstraint::AttAuthenticationRequired) + m_flags.append("encrypt-authenticated-read"_L1); + + if (data.isWritable()) + m_flags.append("write"_L1); + if (data.writeConstraints() & QBluetooth::AttAccessConstraint::AttEncryptionRequired) + m_flags.append("encrypt-write"_L1); + if (data.writeConstraints() & QBluetooth::AttAccessConstraint::AttAuthenticationRequired) + m_flags.append("encrypt-authenticated-write"_L1); + + if (data.readConstraints() & QBluetooth::AttAccessConstraint::AttAuthorizationRequired + || data.writeConstraints() & QBluetooth::AttAccessConstraint::AttAuthorizationRequired) + m_flags.append("authorize"_L1); + + if (m_flags.isEmpty()) { + qCWarning(QT_BT_BLUEZ) << "Descriptor property flags not set" << uuid + << "Peripheral may fail to register"; + } +} + +QtBluezPeripheralCharacteristic::QtBluezPeripheralCharacteristic( + const QLowEnergyCharacteristicData& characteristicData, + const QString& servicePath, quint16 ordinal, + QLowEnergyHandle handle, QObject* parent) + : QtBluezPeripheralGattObject(characteristicPathTemplate.arg(servicePath).arg(ordinal), + characteristicData.uuid().toString(QUuid::WithoutBraces), handle, parent), + m_adaptor(new OrgBluezGattCharacteristic1Adaptor(this)), + m_servicePath(servicePath), + m_minimumValueLength(std::min(characteristicData.minimumValueLength(), + maximumAttributeLength)), + m_maximumValueLength(std::min(characteristicData.maximumValueLength(), + maximumAttributeLength)) +{ + initializeFlags(characteristicData); + initializeValue(characteristicData.value()); +} + +InterfaceList QtBluezPeripheralCharacteristic::properties() const +{ + InterfaceList properties; + properties.insert(bluezCharacteristicInterface, + { + {"UUID"_L1, uuid}, + {"Service"_L1, QDBusObjectPath(m_servicePath)}, + {"Flags"_L1, m_flags} + }); + return properties; +} + +// org.bluez.GattCharacteristic1 +// This function is invoked when remote device reads the value +QByteArray QtBluezPeripheralCharacteristic::ReadValue(const QVariantMap &options, QString& error) +{ + accessEvent(options); + // Offset is set by Bluez when the value size is more than MTU size. + // Bluez deduces the value size from the first ReadValue. If the + // received data size is larger than MTU, Bluez will take the first MTU bytes and + // issue more ReadValue calls with the 'offset' set + const quint16 offset = options.value("offset"_L1).toUInt(); + const quint16 mtu = options.value("mtu"_L1).toUInt(); + + if (offset > m_value.length() - 1) { + qCWarning(QT_BT_BLUEZ) << "Invalid offset" << offset << ", value len:" << m_value.length(); + error = bluezErrorInvalidOffset; + return {}; + } + + if (offset > 0) + return m_value.mid(offset, mtu); + else + return m_value; +} + +// org.bluez.GattCharacteristic1 +// This function is invoked when remote device writes a value +QString QtBluezPeripheralCharacteristic::WriteValue(const QByteArray &value, + const QVariantMap &options) +{ + accessEvent(options); + + if (options.value("prepare-authorize"_L1).toBool()) { + // Qt API doesn't provide the means for application to authorize + qCWarning(QT_BT_BLUEZ) << "Characteristic write requires authorization." + << "The client device needs to be trusted beforehand"; + return bluezErrorNotAuthorized; + } + + if (value.size() < m_minimumValueLength || value.size() > m_maximumValueLength) { + qCWarning(QT_BT_BLUEZ) << "Characteristic value has invalid length" << value.size() + << "min:" << m_minimumValueLength + << "max:" << m_maximumValueLength; + return bluezErrorInvalidValueLength; + } + m_value = value; + emit valueUpdatedByRemote(handle, value); + return {}; +} + +// This function is called when the value has been updated locally (server-side) +bool QtBluezPeripheralCharacteristic::localValueUpdate(const QByteArray& value) +{ + if (value.size() < m_minimumValueLength || value.size() > m_maximumValueLength) { + qCWarning(QT_BT_BLUEZ) << "Characteristic value has invalid length" << value.size() + << "min:" << m_minimumValueLength + << "max:" << m_maximumValueLength; + return false; + } + m_value = value; + if (m_notifying) { + emit propertiesAdaptor->PropertiesChanged( + bluezCharacteristicInterface, {{"Value"_L1, m_value}}, {}); + } + return true; +} + +// org.bluez.GattCharacteristic1 +// These are called when remote client enables or disables NTF/IND +void QtBluezPeripheralCharacteristic::StartNotify() +{ + qCDebug(QT_BT_BLUEZ) << "NTF or IND enabled for characteristic" << uuid; + m_notifying = true; +} + +void QtBluezPeripheralCharacteristic::StopNotify() +{ + qCDebug(QT_BT_BLUEZ) << "NTF or IND disabled for characteristic" << uuid; + m_notifying = false; +} + + +void QtBluezPeripheralCharacteristic::initializeValue(const QByteArray& value) +{ + const auto valueSize = value.size(); + if (valueSize < m_minimumValueLength || valueSize > m_maximumValueLength) { + qCWarning(QT_BT_BLUEZ) << "Characteristic value has invalid length" << valueSize + << "min:" << m_minimumValueLength + << "max:" << m_maximumValueLength; + m_value = QByteArray(m_minimumValueLength, 0); + } else { + m_value = value; + } +} + +void QtBluezPeripheralCharacteristic::initializeFlags(const QLowEnergyCharacteristicData& data) +{ + // Flag tokens are from org.bluez.GattCharacteristic1 documentation + if (data.properties() & QLowEnergyCharacteristic::PropertyType::Broadcasting) + m_flags.append("broadcast"_L1); + if (data.properties() & QLowEnergyCharacteristic::PropertyType::WriteNoResponse) + m_flags.append("write-without-response"_L1); + if (data.properties() & QLowEnergyCharacteristic::PropertyType::Read) + m_flags.append("read"_L1); + if (data.properties() & QLowEnergyCharacteristic::PropertyType::Write) + m_flags.append("write"_L1); + if (data.properties() & QLowEnergyCharacteristic::PropertyType::Notify) + m_flags.append("notify"_L1); + if (data.properties() & QLowEnergyCharacteristic::PropertyType::Indicate) + m_flags.append("indicate"_L1); + if (data.properties() & QLowEnergyCharacteristic::PropertyType::WriteSigned) + m_flags.append("authenticated-signed-writes"_L1); + if (data.properties() & QLowEnergyCharacteristic::PropertyType::ExtendedProperty) { + // If extended properties property is set, check if we have the descriptor + // describing them. Bluez will generate the actual descriptor based on these + // flags. For clarity: the 'extended-properties' token mentioned in the Bluez + // API is implied by these flags. + for (const auto& descriptor : data.descriptors()) { + // Core Bluetooth v5.3 Vol 3, Part G, 3.3.3.1 + if (descriptor.uuid() + == QBluetoothUuid::DescriptorType::CharacteristicExtendedProperties + && descriptor.value().size() == 2) { + const auto properties = descriptor.value().at(0); + if (properties & 0x01) + m_flags.append("reliable-write"_L1); + if (properties & 0x02) + m_flags.append("writable-auxiliaries"_L1); + } + } + } + + if (data.readConstraints() & QBluetooth::AttAccessConstraint::AttEncryptionRequired) + m_flags.append("encrypt-read"_L1); + if (data.readConstraints() & QBluetooth::AttAccessConstraint::AttAuthenticationRequired) + m_flags.append("encrypt-authenticated-read"_L1); + if (data.writeConstraints() & QBluetooth::AttAccessConstraint::AttEncryptionRequired) + m_flags.append("encrypt-write"_L1); + if (data.writeConstraints() & QBluetooth::AttAccessConstraint::AttAuthenticationRequired) + m_flags.append("encrypt-authenticated-write"_L1); + + if (data.readConstraints() & QBluetooth::AttAccessConstraint::AttAuthorizationRequired + || data.writeConstraints() & QBluetooth::AttAccessConstraint::AttAuthorizationRequired) + m_flags.append("authorize"_L1); + + if (m_flags.isEmpty()) { + qCWarning(QT_BT_BLUEZ) << "Characteristic property flags not set" << uuid + << "Peripheral may fail to register"; + } +} + + +QtBluezPeripheralService::QtBluezPeripheralService(const QLowEnergyServiceData &serviceData, + const QString& applicationPath, quint16 ordinal, + QLowEnergyHandle handle, QObject* parent) + : QtBluezPeripheralGattObject(servicePathTemplate.arg(applicationPath).arg(ordinal), + serviceData.uuid().toString(QUuid::WithoutBraces), handle, parent), + m_isPrimary(serviceData.type() == QLowEnergyServiceData::ServiceTypePrimary), + m_adaptor(new OrgBluezGattService1Adaptor(this)) +{ +} + +void QtBluezPeripheralService::addIncludedService(const QString& objectPath) { + qCDebug(QT_BT_BLUEZ) << "Adding included service" << objectPath << "for" << uuid; + m_includedServices.append(QDBusObjectPath(objectPath)); +} + +InterfaceList QtBluezPeripheralService::properties() const { + InterfaceList interfaces; + interfaces.insert(bluezServiceInterface,{ + {"UUID"_L1, uuid}, + {"Primary"_L1, m_isPrimary}, + {"Includes"_L1, QVariant::fromValue(m_includedServices)} + }); + return interfaces; +}; + +QT_END_NAMESPACE + +#include "moc_bluezperipheralobjects_p.cpp" diff --git a/src/bluetooth/bluez/bluezperipheralobjects_p.h b/src/bluetooth/bluez/bluezperipheralobjects_p.h new file mode 100644 index 0000000..dbc9c4e --- /dev/null +++ b/src/bluetooth/bluez/bluezperipheralobjects_p.h @@ -0,0 +1,171 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef BLUEZ_PERIPHERAL_OBJECTS_P_H +#define BLUEZ_PERIPHERAL_OBJECTS_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 "bluez5_helper_p.h" + +#include +#include +#include +#include +#include + +class OrgFreedesktopDBusPropertiesAdaptor; +class OrgBluezGattCharacteristic1Adaptor; +class OrgBluezGattDescriptor1Adaptor; +class OrgBluezGattService1Adaptor; + +QT_BEGIN_NAMESPACE + +// The QtBluezPeripheralGattObject is the base class for services, characteristics, and descriptors +class QtBluezPeripheralGattObject : public QObject +{ + Q_OBJECT + +public: + QtBluezPeripheralGattObject(const QString& objectPath, const QString& uuid, + QLowEnergyHandle handle, QObject* parent = nullptr); + virtual ~QtBluezPeripheralGattObject(); + + // List of properties exposed by this object, used when Bluez inquiries details + virtual InterfaceList properties() const = 0; + + bool registerObject(); + void unregisterObject(); + +public: + // DBus object path + QString objectPath; + // UUID of the gatt object + QString uuid; + // QtBluetooth internal handle and reference to the application + // to read and write values towards the Qt API + QLowEnergyHandle handle; + // Bluez DBus Gatt objects need to provide this + OrgFreedesktopDBusPropertiesAdaptor* propertiesAdaptor{}; + +signals: + void remoteDeviceAccessEvent(const QString& remoteDeviceObjectPath, quint16 mtu); + +protected: + void accessEvent(const QVariantMap& options); + +private: + bool m_registered = false; +}; + +class QtBluezPeripheralDescriptor : public QtBluezPeripheralGattObject +{ + Q_OBJECT + +public: + QtBluezPeripheralDescriptor(const QLowEnergyDescriptorData& descriptorData, + const QString& characteristicPath, quint16 ordinal, + QLowEnergyHandle handle, QLowEnergyHandle characteristicHandle, + QObject* parent); + + InterfaceList properties() const final; + + // org.bluez.GattDescriptor1 + // This function is invoked when remote device reads the value. Sets error if any + Q_INVOKABLE QByteArray ReadValue(const QVariantMap &options, QString &error); + + // org.bluez.GattDescriptor1 + // This function is invoked when remote device writes a value. Returns Bluez DBus error if any + Q_INVOKABLE QString WriteValue(const QByteArray &value, const QVariantMap &options); + + // Call this function when value has been updated locally (server/user application side) + bool localValueUpdate(const QByteArray& value); + +signals: + void valueUpdatedByRemote(QLowEnergyHandle characteristicHandle, + QLowEnergyHandle descriptorHandle, const QByteArray& value); + +private: + void initializeFlags(const QLowEnergyDescriptorData& data); + + OrgBluezGattDescriptor1Adaptor* m_adaptor{}; + QString m_characteristicPath; + QByteArray m_value; + QStringList m_flags; + QLowEnergyHandle m_characteristicHandle; +}; + + +class QtBluezPeripheralCharacteristic : public QtBluezPeripheralGattObject +{ + Q_OBJECT + +public: + QtBluezPeripheralCharacteristic(const QLowEnergyCharacteristicData& characteristicData, + const QString& servicePath, quint16 ordinal, + QLowEnergyHandle handle, QObject* parent); + + InterfaceList properties() const final; + + // org.bluez.GattCharacteristic1 + // This function is invoked when remote device reads the value. Sets error if any + Q_INVOKABLE QByteArray ReadValue(const QVariantMap &options, QString& error); + + // org.bluez.GattCharacteristic1 + // This function is invoked when remote device writes a value. Returns Bluez DBus error if any + Q_INVOKABLE QString WriteValue(const QByteArray &value, const QVariantMap &options); + + // org.bluez.GattCharacteristic1 + // These are called when remote client enables or disables NTF/IND + Q_INVOKABLE void StartNotify(); + Q_INVOKABLE void StopNotify(); + + // Call this function when value has been updated locally (server/user application side) + bool localValueUpdate(const QByteArray& value); + +signals: + void valueUpdatedByRemote(QLowEnergyHandle handle, const QByteArray& value); + +private: + void initializeValue(const QByteArray& value); + void initializeFlags(const QLowEnergyCharacteristicData& data); + + OrgBluezGattCharacteristic1Adaptor* m_adaptor{}; + QString m_servicePath; + bool m_notifying{false}; + QByteArray m_value; + QStringList m_flags; + int m_minimumValueLength; + int m_maximumValueLength; +}; + +class QtBluezPeripheralService : public QtBluezPeripheralGattObject +{ + Q_OBJECT +public: + QtBluezPeripheralService(const QLowEnergyServiceData &serviceData, + const QString& applicationPath, quint16 ordinal, + QLowEnergyHandle handle, QObject* parent); + + InterfaceList properties() const final; + void addIncludedService(const QString& objectPath); + +private: + const bool m_isPrimary; + OrgBluezGattService1Adaptor* m_adaptor{}; + QList m_includedServices; +}; + + +QT_END_NAMESPACE + +#endif diff --git a/src/bluetooth/bluez/device1_bluez5.cpp b/src/bluetooth/bluez/device1_bluez5.cpp new file mode 100644 index 0000000..1dc644f --- /dev/null +++ b/src/bluetooth/bluez/device1_bluez5.cpp @@ -0,0 +1,28 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -i bluez5_helper_p.h -I QtCore/private/qglobal_p.h -p device1_bluez5_p.h:device1_bluez5.cpp org.bluez.Device1.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "device1_bluez5_p.h" + +/* + * Implementation of interface class OrgBluezDevice1Interface + */ + +OrgBluezDevice1Interface::OrgBluezDevice1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +OrgBluezDevice1Interface::~OrgBluezDevice1Interface() +{ +} + + +#include "moc_device1_bluez5_p.cpp" diff --git a/src/bluetooth/bluez/device1_bluez5_p.h b/src/bluetooth/bluez/device1_bluez5_p.h new file mode 100644 index 0000000..281ae23 --- /dev/null +++ b/src/bluetooth/bluez/device1_bluez5_p.h @@ -0,0 +1,180 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -i bluez5_helper_p.h -I QtCore/private/qglobal_p.h -p device1_bluez5_p.h:device1_bluez5.cpp org.bluez.Device1.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#ifndef DEVICE1_BLUEZ5_P_H +#define DEVICE1_BLUEZ5_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 "bluez5_helper_p.h" +#include + +/* + * Proxy class for interface org.bluez.Device1 + */ +class OrgBluezDevice1Interface: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "org.bluez.Device1"; } + +public: + OrgBluezDevice1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); + + ~OrgBluezDevice1Interface(); + + Q_PROPERTY(QDBusObjectPath Adapter READ adapter) + inline QDBusObjectPath adapter() const + { return qvariant_cast< QDBusObjectPath >(property("Adapter")); } + + Q_PROPERTY(QString Address READ address) + inline QString address() const + { return qvariant_cast< QString >(property("Address")); } + + Q_PROPERTY(QString Alias READ alias WRITE setAlias) + inline QString alias() const + { return qvariant_cast< QString >(property("Alias")); } + inline void setAlias(const QString &value) + { setProperty("Alias", QVariant::fromValue(value)); } + + Q_PROPERTY(ushort Appearance READ appearance) + inline ushort appearance() const + { return qvariant_cast< ushort >(property("Appearance")); } + + Q_PROPERTY(bool Blocked READ blocked WRITE setBlocked) + inline bool blocked() const + { return qvariant_cast< bool >(property("Blocked")); } + inline void setBlocked(bool value) + { setProperty("Blocked", QVariant::fromValue(value)); } + + Q_PROPERTY(uint Class READ classProperty) + inline uint classProperty() const + { return qvariant_cast< uint >(property("Class")); } + + Q_PROPERTY(bool Connected READ connected) + inline bool connected() const + { return qvariant_cast< bool >(property("Connected")); } + + Q_PROPERTY(QString Icon READ icon) + inline QString icon() const + { return qvariant_cast< QString >(property("Icon")); } + + Q_PROPERTY(bool LegacyPairing READ legacyPairing) + inline bool legacyPairing() const + { return qvariant_cast< bool >(property("LegacyPairing")); } + + Q_PROPERTY(ManufacturerDataList ManufacturerData READ manufacturerData) + inline ManufacturerDataList manufacturerData() const + { return qvariant_cast< ManufacturerDataList >(property("ManufacturerData")); } + + Q_PROPERTY(QString Modalias READ modalias) + inline QString modalias() const + { return qvariant_cast< QString >(property("Modalias")); } + + Q_PROPERTY(QString Name READ name) + inline QString name() const + { return qvariant_cast< QString >(property("Name")); } + + Q_PROPERTY(bool Paired READ paired) + inline bool paired() const + { return qvariant_cast< bool >(property("Paired")); } + + Q_PROPERTY(short RSSI READ rSSI) + inline short rSSI() const + { return qvariant_cast< short >(property("RSSI")); } + + Q_PROPERTY(ServiceDataList ServiceData READ serviceData) + inline ServiceDataList serviceData() const + { return qvariant_cast< ServiceDataList >(property("ServiceData")); } + + Q_PROPERTY(bool ServicesResolved READ servicesResolved) + inline bool servicesResolved() const + { return qvariant_cast< bool >(property("ServicesResolved")); } + + Q_PROPERTY(bool Trusted READ trusted WRITE setTrusted) + inline bool trusted() const + { return qvariant_cast< bool >(property("Trusted")); } + inline void setTrusted(bool value) + { setProperty("Trusted", QVariant::fromValue(value)); } + + Q_PROPERTY(short TxPower READ txPower) + inline short txPower() const + { return qvariant_cast< short >(property("TxPower")); } + + Q_PROPERTY(QStringList UUIDs READ uUIDs) + inline QStringList uUIDs() const + { return qvariant_cast< QStringList >(property("UUIDs")); } + +public Q_SLOTS: // METHODS + inline QDBusPendingReply<> CancelPairing() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("CancelPairing"), argumentList); + } + + inline QDBusPendingReply<> Connect() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("Connect"), argumentList); + } + + inline QDBusPendingReply<> ConnectProfile(const QString &UUID) + { + QList argumentList; + argumentList << QVariant::fromValue(UUID); + return asyncCallWithArgumentList(QStringLiteral("ConnectProfile"), argumentList); + } + + inline QDBusPendingReply<> Disconnect() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("Disconnect"), argumentList); + } + + inline QDBusPendingReply<> DisconnectProfile(const QString &UUID) + { + QList argumentList; + argumentList << QVariant::fromValue(UUID); + return asyncCallWithArgumentList(QStringLiteral("DisconnectProfile"), argumentList); + } + + inline QDBusPendingReply<> Pair() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("Pair"), argumentList); + } + +Q_SIGNALS: // SIGNALS +}; + +namespace org { + namespace bluez { + using Device1 = ::OrgBluezDevice1Interface; + } +} +#endif diff --git a/src/bluetooth/bluez/gattchar1.cpp b/src/bluetooth/bluez/gattchar1.cpp new file mode 100644 index 0000000..3a358a0 --- /dev/null +++ b/src/bluetooth/bluez/gattchar1.cpp @@ -0,0 +1,28 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -I QtCore/private/qglobal_p.h -p gattchar1_p.h:gattchar1.cpp org.bluez.GattCharacteristic1.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "gattchar1_p.h" + +/* + * Implementation of interface class OrgBluezGattCharacteristic1Interface + */ + +OrgBluezGattCharacteristic1Interface::OrgBluezGattCharacteristic1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +OrgBluezGattCharacteristic1Interface::~OrgBluezGattCharacteristic1Interface() +{ +} + + +#include "moc_gattchar1_p.cpp" diff --git a/src/bluetooth/bluez/gattchar1_p.h b/src/bluetooth/bluez/gattchar1_p.h new file mode 100644 index 0000000..860002a --- /dev/null +++ b/src/bluetooth/bluez/gattchar1_p.h @@ -0,0 +1,105 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -I QtCore/private/qglobal_p.h -p gattchar1_p.h:gattchar1.cpp org.bluez.GattCharacteristic1.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#ifndef GATTCHAR1_P_H +#define GATTCHAR1_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 + +/* + * Proxy class for interface org.bluez.GattCharacteristic1 + */ +class OrgBluezGattCharacteristic1Interface: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "org.bluez.GattCharacteristic1"; } + +public: + OrgBluezGattCharacteristic1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); + + ~OrgBluezGattCharacteristic1Interface(); + + Q_PROPERTY(QStringList Flags READ flags) + inline QStringList flags() const + { return qvariant_cast< QStringList >(property("Flags")); } + + Q_PROPERTY(bool Notifying READ notifying) + inline bool notifying() const + { return qvariant_cast< bool >(property("Notifying")); } + + Q_PROPERTY(QDBusObjectPath Service READ service) + inline QDBusObjectPath service() const + { return qvariant_cast< QDBusObjectPath >(property("Service")); } + + Q_PROPERTY(QString UUID READ uUID) + inline QString uUID() const + { return qvariant_cast< QString >(property("UUID")); } + + Q_PROPERTY(QByteArray Value READ value) + inline QByteArray value() const + { return qvariant_cast< QByteArray >(property("Value")); } + +public Q_SLOTS: // METHODS + inline QDBusPendingReply ReadValue(const QVariantMap &options) + { + QList argumentList; + argumentList << QVariant::fromValue(options); + return asyncCallWithArgumentList(QStringLiteral("ReadValue"), argumentList); + } + + inline QDBusPendingReply<> StartNotify() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("StartNotify"), argumentList); + } + + inline QDBusPendingReply<> StopNotify() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("StopNotify"), argumentList); + } + + inline QDBusPendingReply<> WriteValue(const QByteArray &value, const QVariantMap &options) + { + QList argumentList; + argumentList << QVariant::fromValue(value) << QVariant::fromValue(options); + return asyncCallWithArgumentList(QStringLiteral("WriteValue"), argumentList); + } + +Q_SIGNALS: // SIGNALS +}; + +namespace org { + namespace bluez { + using GattCharacteristic1 = ::OrgBluezGattCharacteristic1Interface; + } +} +#endif diff --git a/src/bluetooth/bluez/gattcharacteristic1adaptor.cpp b/src/bluetooth/bluez/gattcharacteristic1adaptor.cpp new file mode 100644 index 0000000..d6eb0a1 --- /dev/null +++ b/src/bluetooth/bluez/gattcharacteristic1adaptor.cpp @@ -0,0 +1,108 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -a gattcharacteristic1adaptor_p.h:gattcharacteristic1adaptor.cpp -c OrgBluezGattCharacteristic1Adaptor -i bluez5_helper_p.h org.bluez.GattCharacteristic1.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#include "gattcharacteristic1adaptor_p.h" +#include +#include +#include +#include +#include +#include +#include + +/* + * Implementation of adaptor class OrgBluezGattCharacteristic1Adaptor + */ + +OrgBluezGattCharacteristic1Adaptor::OrgBluezGattCharacteristic1Adaptor(QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + // constructor + setAutoRelaySignals(true); +} + +OrgBluezGattCharacteristic1Adaptor::~OrgBluezGattCharacteristic1Adaptor() +{ + // destructor +} + +QStringList OrgBluezGattCharacteristic1Adaptor::flags() const +{ + // get the value of property Flags + return qvariant_cast< QStringList >(parent()->property("Flags")); +} + +bool OrgBluezGattCharacteristic1Adaptor::notifying() const +{ + // get the value of property Notifying + return qvariant_cast< bool >(parent()->property("Notifying")); +} + +QDBusObjectPath OrgBluezGattCharacteristic1Adaptor::service() const +{ + // get the value of property Service + return qvariant_cast< QDBusObjectPath >(parent()->property("Service")); +} + +QString OrgBluezGattCharacteristic1Adaptor::uUID() const +{ + // get the value of property UUID + return qvariant_cast< QString >(parent()->property("UUID")); +} + +QByteArray OrgBluezGattCharacteristic1Adaptor::value() const +{ + // get the value of property Value + return qvariant_cast< QByteArray >(parent()->property("Value")); +} + +QByteArray OrgBluezGattCharacteristic1Adaptor::ReadValue(const QVariantMap &options, + const QDBusMessage& msg) +{ + // handle method call org.bluez.GattCharacteristic1.ReadValue + QByteArray value; + QString error; + QMetaObject::invokeMethod(parent(), "ReadValue", Q_RETURN_ARG(QByteArray, value), + Q_ARG(QVariantMap, options), Q_ARG(QString&, error)); + if (!error.isEmpty()) { + // Reply with error if needed + auto reply = msg.createErrorReply(error, {}); + QDBusConnection::systemBus().send(reply); + } + return value; +} + +void OrgBluezGattCharacteristic1Adaptor::StartNotify() +{ + // handle method call org.bluez.GattCharacteristic1.StartNotify + QMetaObject::invokeMethod(parent(), "StartNotify"); +} + +void OrgBluezGattCharacteristic1Adaptor::StopNotify() +{ + // handle method call org.bluez.GattCharacteristic1.StopNotify + QMetaObject::invokeMethod(parent(), "StopNotify"); +} + +void OrgBluezGattCharacteristic1Adaptor::WriteValue(const QByteArray &value, + const QVariantMap &options, + const QDBusMessage& msg) +{ + // handle method call org.bluez.GattCharacteristic1.WriteValue + QString error; + QMetaObject::invokeMethod(parent(), "WriteValue", Q_RETURN_ARG(QString, error), + Q_ARG(QByteArray, value), Q_ARG(QVariantMap, options)); + + if (!error.isEmpty()) { + // Reply with error if needed + auto reply = msg.createErrorReply(error, {}); + QDBusConnection::systemBus().send(reply); + } +} diff --git a/src/bluetooth/bluez/gattcharacteristic1adaptor_p.h b/src/bluetooth/bluez/gattcharacteristic1adaptor_p.h new file mode 100644 index 0000000..7f80e8f --- /dev/null +++ b/src/bluetooth/bluez/gattcharacteristic1adaptor_p.h @@ -0,0 +1,87 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -a gattcharacteristic1adaptor_p.h:gattcharacteristic1adaptor.cpp -c OrgBluezGattCharacteristic1Adaptor -i bluez5_helper_p.h org.bluez.GattCharacteristic1.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#ifndef GATTCHARACTERISTIC1ADAPTOR_P_H +#define GATTCHARACTERISTIC1ADAPTOR_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 "bluez5_helper_p.h" +#include + +/* + * Adaptor class for interface org.bluez.GattCharacteristic1 + */ +class OrgBluezGattCharacteristic1Adaptor: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.bluez.GattCharacteristic1") + Q_CLASSINFO("D-Bus Introspection", "" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" + "") +public: + OrgBluezGattCharacteristic1Adaptor(QObject *parent); + virtual ~OrgBluezGattCharacteristic1Adaptor(); + +public: // PROPERTIES + Q_PROPERTY(QStringList Flags READ flags) + QStringList flags() const; + + Q_PROPERTY(bool Notifying READ notifying) + bool notifying() const; + + Q_PROPERTY(QDBusObjectPath Service READ service) + QDBusObjectPath service() const; + + Q_PROPERTY(QString UUID READ uUID) + QString uUID() const; + + Q_PROPERTY(QByteArray Value READ value) + QByteArray value() const; + +public Q_SLOTS: // METHODS + QByteArray ReadValue(const QVariantMap &options, const QDBusMessage &msg); + void StartNotify(); + void StopNotify(); + void WriteValue(const QByteArray &value, const QVariantMap &options, const QDBusMessage& msg); +Q_SIGNALS: // SIGNALS +}; + +#endif diff --git a/src/bluetooth/bluez/gattdesc1.cpp b/src/bluetooth/bluez/gattdesc1.cpp new file mode 100644 index 0000000..abe846a --- /dev/null +++ b/src/bluetooth/bluez/gattdesc1.cpp @@ -0,0 +1,28 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -I QtCore/private/qglobal_p.h -p gattdesc1_p.h:gattdesc1.cpp org.bluez.GattDescriptor1.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "gattdesc1_p.h" + +/* + * Implementation of interface class OrgBluezGattDescriptor1Interface + */ + +OrgBluezGattDescriptor1Interface::OrgBluezGattDescriptor1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +OrgBluezGattDescriptor1Interface::~OrgBluezGattDescriptor1Interface() +{ +} + + +#include "moc_gattdesc1_p.cpp" diff --git a/src/bluetooth/bluez/gattdesc1_p.h b/src/bluetooth/bluez/gattdesc1_p.h new file mode 100644 index 0000000..a054edf --- /dev/null +++ b/src/bluetooth/bluez/gattdesc1_p.h @@ -0,0 +1,85 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -I QtCore/private/qglobal_p.h -p gattdesc1_p.h:gattdesc1.cpp org.bluez.GattDescriptor1.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#ifndef GATTDESC1_P_H +#define GATTDESC1_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 + +/* + * Proxy class for interface org.bluez.GattDescriptor1 + */ +class OrgBluezGattDescriptor1Interface: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "org.bluez.GattDescriptor1"; } + +public: + OrgBluezGattDescriptor1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); + + ~OrgBluezGattDescriptor1Interface(); + + Q_PROPERTY(QDBusObjectPath Characteristic READ characteristic) + inline QDBusObjectPath characteristic() const + { return qvariant_cast< QDBusObjectPath >(property("Characteristic")); } + + Q_PROPERTY(QString UUID READ uUID) + inline QString uUID() const + { return qvariant_cast< QString >(property("UUID")); } + + Q_PROPERTY(QByteArray Value READ value) + inline QByteArray value() const + { return qvariant_cast< QByteArray >(property("Value")); } + +public Q_SLOTS: // METHODS + inline QDBusPendingReply ReadValue(const QVariantMap &options) + { + QList argumentList; + argumentList << QVariant::fromValue(options); + return asyncCallWithArgumentList(QStringLiteral("ReadValue"), argumentList); + } + + inline QDBusPendingReply<> WriteValue(const QByteArray &value, const QVariantMap &options) + { + QList argumentList; + argumentList << QVariant::fromValue(value) << QVariant::fromValue(options); + return asyncCallWithArgumentList(QStringLiteral("WriteValue"), argumentList); + } + +Q_SIGNALS: // SIGNALS +}; + +namespace org { + namespace bluez { + using GattDescriptor1 = ::OrgBluezGattDescriptor1Interface; + } +} +#endif diff --git a/src/bluetooth/bluez/gattdescriptor1adaptor.cpp b/src/bluetooth/bluez/gattdescriptor1adaptor.cpp new file mode 100644 index 0000000..b717738 --- /dev/null +++ b/src/bluetooth/bluez/gattdescriptor1adaptor.cpp @@ -0,0 +1,84 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -a gattdescriptor1adaptor_p.h:gattdescriptor1adaptor.cpp -c OrgBluezGattDescriptor1Adaptor -i bluez5_helper_p.h org.bluez.GattDescriptor1.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#include "gattdescriptor1adaptor_p.h" +#include +#include +#include +#include +#include +#include +#include + +/* + * Implementation of adaptor class OrgBluezGattDescriptor1Adaptor + */ + +OrgBluezGattDescriptor1Adaptor::OrgBluezGattDescriptor1Adaptor(QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + // constructor + setAutoRelaySignals(true); +} + +OrgBluezGattDescriptor1Adaptor::~OrgBluezGattDescriptor1Adaptor() +{ + // destructor +} + +QDBusObjectPath OrgBluezGattDescriptor1Adaptor::characteristic() const +{ + // get the value of property Characteristic + return qvariant_cast< QDBusObjectPath >(parent()->property("Characteristic")); +} + +QString OrgBluezGattDescriptor1Adaptor::uUID() const +{ + // get the value of property UUID + return qvariant_cast< QString >(parent()->property("UUID")); +} + +QByteArray OrgBluezGattDescriptor1Adaptor::value() const +{ + // get the value of property Value + return qvariant_cast< QByteArray >(parent()->property("Value")); +} + +QByteArray OrgBluezGattDescriptor1Adaptor::ReadValue(const QVariantMap &options, + const QDBusMessage& msg) +{ + // handle method call org.bluez.GattDescriptor1.ReadValue + QByteArray value; + QString error; + QMetaObject::invokeMethod(parent(), "ReadValue", Q_RETURN_ARG(QByteArray, value), + Q_ARG(QVariantMap, options), Q_ARG(QString&, error)); + if (!error.isEmpty()) { + // Reply with error if needed + auto reply = msg.createErrorReply(error, {}); + QDBusConnection::systemBus().send(reply); + } + return value; +} + +void OrgBluezGattDescriptor1Adaptor::WriteValue(const QByteArray &value, + const QVariantMap &options, + const QDBusMessage& msg) +{ + // handle method call org.bluez.GattDescriptor1.WriteValue + QString error; + QMetaObject::invokeMethod(parent(), "WriteValue", Q_RETURN_ARG(QString, error), + Q_ARG(QByteArray, value), Q_ARG(QVariantMap, options)); + + if (!error.isEmpty()) { + // Reply with error if needed + auto reply = msg.createErrorReply(error, {}); + QDBusConnection::systemBus().send(reply); + } +} diff --git a/src/bluetooth/bluez/gattdescriptor1adaptor_p.h b/src/bluetooth/bluez/gattdescriptor1adaptor_p.h new file mode 100644 index 0000000..a7eacb9 --- /dev/null +++ b/src/bluetooth/bluez/gattdescriptor1adaptor_p.h @@ -0,0 +1,75 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -a gattdescriptor1adaptor_p.h:gattdescriptor1adaptor.cpp -c OrgBluezGattDescriptor1Adaptor -i bluez5_helper_p.h org.bluez.GattDescriptor1.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#ifndef GATTDESCRIPTOR1ADAPTOR_P_H +#define GATTDESCRIPTOR1ADAPTOR_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 "bluez5_helper_p.h" +#include + +/* + * Adaptor class for interface org.bluez.GattDescriptor1 + */ +class OrgBluezGattDescriptor1Adaptor: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.bluez.GattDescriptor1") + Q_CLASSINFO("D-Bus Introspection", "" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" + "") +public: + OrgBluezGattDescriptor1Adaptor(QObject *parent); + virtual ~OrgBluezGattDescriptor1Adaptor(); + +public: // PROPERTIES + Q_PROPERTY(QDBusObjectPath Characteristic READ characteristic) + QDBusObjectPath characteristic() const; + + Q_PROPERTY(QString UUID READ uUID) + QString uUID() const; + + Q_PROPERTY(QByteArray Value READ value) + QByteArray value() const; + +public Q_SLOTS: // METHODS + QByteArray ReadValue(const QVariantMap &options, const QDBusMessage &msg); + void WriteValue(const QByteArray &value, const QVariantMap &options, const QDBusMessage& msg); +Q_SIGNALS: // SIGNALS +}; + +#endif diff --git a/src/bluetooth/bluez/gattmanager1.cpp b/src/bluetooth/bluez/gattmanager1.cpp new file mode 100644 index 0000000..66558b0 --- /dev/null +++ b/src/bluetooth/bluez/gattmanager1.cpp @@ -0,0 +1,28 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -I QtCore/private/qglobal_p.h -p gattmanager1_p.h:gattmanager1.cpp org.bluez.GattManager1.xml --moc + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "gattmanager1_p.h" + +/* + * Implementation of interface class OrgBluezGattManager1Interface + */ + +OrgBluezGattManager1Interface::OrgBluezGattManager1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +OrgBluezGattManager1Interface::~OrgBluezGattManager1Interface() +{ +} + + +#include "moc_gattmanager1_p.cpp" diff --git a/src/bluetooth/bluez/gattmanager1_p.h b/src/bluetooth/bluez/gattmanager1_p.h new file mode 100644 index 0000000..43f8127 --- /dev/null +++ b/src/bluetooth/bluez/gattmanager1_p.h @@ -0,0 +1,73 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -I QtCore/private/qglobal_p.h -p gattmanager1_p.h:gattmanager1.cpp org.bluez.GattManager1.xml --moc + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#ifndef GATTMANAGER1_P_H +#define GATTMANAGER1_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 + +/* + * Proxy class for interface org.bluez.GattManager1 + */ +class OrgBluezGattManager1Interface: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "org.bluez.GattManager1"; } + +public: + OrgBluezGattManager1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); + + ~OrgBluezGattManager1Interface(); + +public Q_SLOTS: // METHODS + inline QDBusPendingReply<> RegisterApplication(const QDBusObjectPath &application, const QVariantMap &options) + { + QList argumentList; + argumentList << QVariant::fromValue(application) << QVariant::fromValue(options); + return asyncCallWithArgumentList(QStringLiteral("RegisterApplication"), argumentList); + } + + inline QDBusPendingReply<> UnregisterApplication(const QDBusObjectPath &application) + { + QList argumentList; + argumentList << QVariant::fromValue(application); + return asyncCallWithArgumentList(QStringLiteral("UnregisterApplication"), argumentList); + } + +Q_SIGNALS: // SIGNALS +}; + +namespace org { + namespace bluez { + using GattManager1 = ::OrgBluezGattManager1Interface; + } +} +#endif diff --git a/src/bluetooth/bluez/gattservice1.cpp b/src/bluetooth/bluez/gattservice1.cpp new file mode 100644 index 0000000..4a490c5 --- /dev/null +++ b/src/bluetooth/bluez/gattservice1.cpp @@ -0,0 +1,28 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -I QtCore/private/qglobal_p.h -p gattservice1_p.h:gattservice1.cpp org.bluez.GattService1.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "gattservice1_p.h" + +/* + * Implementation of interface class OrgBluezGattService1Interface + */ + +OrgBluezGattService1Interface::OrgBluezGattService1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +OrgBluezGattService1Interface::~OrgBluezGattService1Interface() +{ +} + + +#include "moc_gattservice1_p.cpp" diff --git a/src/bluetooth/bluez/gattservice1_p.h b/src/bluetooth/bluez/gattservice1_p.h new file mode 100644 index 0000000..3b2e119 --- /dev/null +++ b/src/bluetooth/bluez/gattservice1_p.h @@ -0,0 +1,75 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -I QtCore/private/qglobal_p.h -p gattservice1_p.h:gattservice1.cpp org.bluez.GattService1.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#ifndef GATTSERVICE1_P_H +#define GATTSERVICE1_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 + +/* + * Proxy class for interface org.bluez.GattService1 + */ +class OrgBluezGattService1Interface: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "org.bluez.GattService1"; } + +public: + OrgBluezGattService1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); + + ~OrgBluezGattService1Interface(); + + Q_PROPERTY(QDBusObjectPath Device READ device) + inline QDBusObjectPath device() const + { return qvariant_cast< QDBusObjectPath >(property("Device")); } + + Q_PROPERTY(QList Includes READ includes) + inline QList includes() const + { return qvariant_cast< QList >(property("Includes")); } + + Q_PROPERTY(bool Primary READ primary) + inline bool primary() const + { return qvariant_cast< bool >(property("Primary")); } + + Q_PROPERTY(QString UUID READ uUID) + inline QString uUID() const + { return qvariant_cast< QString >(property("UUID")); } + +public Q_SLOTS: // METHODS +Q_SIGNALS: // SIGNALS +}; + +namespace org { + namespace bluez { + using GattService1 = ::OrgBluezGattService1Interface; + } +} +#endif diff --git a/src/bluetooth/bluez/gattservice1adaptor.cpp b/src/bluetooth/bluez/gattservice1adaptor.cpp new file mode 100644 index 0000000..365040c --- /dev/null +++ b/src/bluetooth/bluez/gattservice1adaptor.cpp @@ -0,0 +1,58 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -a gattservice1adaptor_p.h:gattservice1adaptor.cpp -c OrgBluezGattService1Adaptor -i bluez5_helper_p.h org.bluez.GattService1.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#include "gattservice1adaptor_p.h" +#include +#include +#include +#include +#include +#include +#include + +/* + * Implementation of adaptor class OrgBluezGattService1Adaptor + */ + +OrgBluezGattService1Adaptor::OrgBluezGattService1Adaptor(QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + // constructor + setAutoRelaySignals(true); +} + +OrgBluezGattService1Adaptor::~OrgBluezGattService1Adaptor() +{ + // destructor +} + +QDBusObjectPath OrgBluezGattService1Adaptor::device() const +{ + // get the value of property Device + return qvariant_cast< QDBusObjectPath >(parent()->property("Device")); +} + +QList OrgBluezGattService1Adaptor::includes() const +{ + // get the value of property Includes + return qvariant_cast< QList >(parent()->property("Includes")); +} + +bool OrgBluezGattService1Adaptor::primary() const +{ + // get the value of property Primary + return qvariant_cast< bool >(parent()->property("Primary")); +} + +QString OrgBluezGattService1Adaptor::uUID() const +{ + // get the value of property UUID + return qvariant_cast< QString >(parent()->property("UUID")); +} diff --git a/src/bluetooth/bluez/gattservice1adaptor_p.h b/src/bluetooth/bluez/gattservice1adaptor_p.h new file mode 100644 index 0000000..b9bd85a --- /dev/null +++ b/src/bluetooth/bluez/gattservice1adaptor_p.h @@ -0,0 +1,67 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -a gattservice1adaptor_p.h:gattservice1adaptor.cpp -c OrgBluezGattService1Adaptor -i bluez5_helper_p.h org.bluez.GattService1.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#ifndef GATTSERVICE1ADAPTOR_P_H +#define GATTSERVICE1ADAPTOR_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 "bluez5_helper_p.h" +#include + +/* + * Adaptor class for interface org.bluez.GattService1 + */ +class OrgBluezGattService1Adaptor: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.bluez.GattService1") + Q_CLASSINFO("D-Bus Introspection", "" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" + "") +public: + OrgBluezGattService1Adaptor(QObject *parent); + virtual ~OrgBluezGattService1Adaptor(); + +public: // PROPERTIES + Q_PROPERTY(QDBusObjectPath Device READ device) + QDBusObjectPath device() const; + + Q_PROPERTY(QList Includes READ includes) + QList includes() const; + + Q_PROPERTY(bool Primary READ primary) + bool primary() const; + + Q_PROPERTY(QString UUID READ uUID) + QString uUID() const; + +public Q_SLOTS: // METHODS +Q_SIGNALS: // SIGNALS +}; + +#endif diff --git a/src/bluetooth/bluez/generate b/src/bluetooth/bluez/generate new file mode 100755 index 0000000..f009f23 --- /dev/null +++ b/src/bluetooth/bluez/generate @@ -0,0 +1,31 @@ +#!/bin/sh + +QGLOBAL_P_H=QtCore/private/qglobal_p.h + +process() { + CPP_BASENAME=$1 + shift + XML_FILE="$1" + shift + + HEADER_FILE=${CPP_BASENAME}_p.h + CPP_FILE=${CPP_BASENAME}.cpp + qdbusxml2cpp "$@" -I "$QGLOBAL_P_H" -p $HEADER_FILE:$CPP_FILE "$XML_FILE" --moc +} + +#Bluez 5 +process adapter1_bluez5 org.bluez.Adapter1.xml +process device1_bluez5 org.bluez.Device1.xml -i bluez5_helper_p.h +process profilemanager1 org.bluez.ProfileManager1.xml +process profile1 org.bluez.Profile1.xml + +process objectmanager org.freedesktop.dbus.objectmanager.xml -i bluez5_helper_p.h +process properties org.freedesktop.dbus.properties.xml + +process gattchar1 org.bluez.GattCharacteristic1.xml +process gattdesc1 org.bluez.GattDescriptor1.xml +process gattservice1 org.bluez.GattService1.xml +process battery1 org.bluez.Battery1.xml + +process gattmanager1 org.bluez.GattManager1.xml +process leadvertisingmanager1 org.bluez.LEAdvertisingManager1.xml diff --git a/src/bluetooth/bluez/hcimanager.cpp b/src/bluetooth/bluez/hcimanager.cpp new file mode 100644 index 0000000..573d603 --- /dev/null +++ b/src/bluetooth/bluez/hcimanager.cpp @@ -0,0 +1,564 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2016 Javier S. Pedro +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "hcimanager_p.h" + +#include "qbluetoothsocketbase_p.h" +#include "qlowenergyconnectionparameters.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ) + +HciManager::HciManager(const QBluetoothAddress& deviceAdapter) : + QObject(nullptr), hciSocket(-1), hciDev(-1) +{ + hciSocket = ::socket(AF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC, BTPROTO_HCI); + if (hciSocket < 0) { + qCWarning(QT_BT_BLUEZ) << "Cannot open HCI socket"; + return; //TODO error report + } + + hciDev = hciForAddress(deviceAdapter); + if (hciDev < 0) { + qCWarning(QT_BT_BLUEZ) << "Cannot find hci dev for" << deviceAdapter.toString(); + close(hciSocket); + hciSocket = -1; + return; + } + + struct sockaddr_hci addr; + + memset(&addr, 0, sizeof(struct sockaddr_hci)); + addr.hci_dev = hciDev; + addr.hci_family = AF_BLUETOOTH; + + if (::bind(hciSocket, (struct sockaddr *) (&addr), sizeof(addr)) < 0) { + qCWarning(QT_BT_BLUEZ) << "HCI bind failed:" << strerror(errno); + close(hciSocket); + hciSocket = hciDev = -1; + return; + } + + notifier = new QSocketNotifier(hciSocket, QSocketNotifier::Read, this); + connect(notifier, SIGNAL(activated(QSocketDescriptor)), this, SLOT(_q_readNotify())); + +} + +HciManager::~HciManager() +{ + if (hciSocket >= 0) + ::close(hciSocket); + +} + +bool HciManager::isValid() const +{ + if (hciSocket && hciDev >= 0) + return true; + return false; +} + +int HciManager::hciForAddress(const QBluetoothAddress &deviceAdapter) +{ + if (hciSocket < 0) + return -1; + + bdaddr_t adapter; + convertAddress(deviceAdapter.toUInt64(), adapter.b); + + struct hci_dev_req *devRequest = nullptr; + struct hci_dev_list_req *devRequestList = nullptr; + struct hci_dev_info devInfo; + const int devListSize = sizeof(struct hci_dev_list_req) + + HCI_MAX_DEV * sizeof(struct hci_dev_req); + + devRequestList = (hci_dev_list_req *) malloc(devListSize); + if (!devRequestList) + return -1; + + QScopedPointer p(devRequestList); + + memset(p.data(), 0, devListSize); + p->dev_num = HCI_MAX_DEV; + devRequest = p->dev_req; + + if (ioctl(hciSocket, HCIGETDEVLIST, devRequestList) < 0) + return -1; + + for (int i = 0; i < devRequestList->dev_num; i++) { + devInfo.dev_id = (devRequest+i)->dev_id; + if (ioctl(hciSocket, HCIGETDEVINFO, &devInfo) < 0) { + continue; + } + + int result = memcmp(&adapter, &devInfo.bdaddr, sizeof(bdaddr_t)); + if (result == 0 || deviceAdapter.isNull()) // addresses match + return devInfo.dev_id; + } + + return -1; +} + +/* + * Returns true if \a event was successfully enabled + */ +bool HciManager::monitorEvent(HciManager::HciEvent event) +{ + if (!isValid()) + return false; + + // this event is already enabled + // TODO runningEvents does not seem to be used + if (runningEvents.contains(event)) + return true; + + hci_filter filter; + socklen_t length = sizeof(hci_filter); + if (getsockopt(hciSocket, SOL_HCI, HCI_FILTER, &filter, &length) < 0) { + qCWarning(QT_BT_BLUEZ) << "Cannot retrieve HCI filter settings"; + return false; + } + + hci_filter_set_ptype(HCI_EVENT_PKT, &filter); + hci_filter_set_event(static_cast(event), &filter); + //hci_filter_all_events(&filter); + + if (setsockopt(hciSocket, SOL_HCI, HCI_FILTER, &filter, sizeof(hci_filter)) < 0) { + qCWarning(QT_BT_BLUEZ) << "Could not set HCI socket options:" << strerror(errno); + return false; + } + + return true; +} + +bool HciManager::monitorAclPackets() +{ + if (!isValid()) + return false; + + hci_filter filter; + socklen_t length = sizeof(hci_filter); + if (getsockopt(hciSocket, SOL_HCI, HCI_FILTER, &filter, &length) < 0) { + qCWarning(QT_BT_BLUEZ) << "Cannot retrieve HCI filter settings"; + return false; + } + + hci_filter_set_ptype(HCI_ACL_PKT, &filter); + hci_filter_all_events(&filter); + + if (setsockopt(hciSocket, SOL_HCI, HCI_FILTER, &filter, sizeof(hci_filter)) < 0) { + qCWarning(QT_BT_BLUEZ) << "Could not set HCI socket options:" << strerror(errno); + return false; + } + + return true; +} + +bool HciManager::sendCommand(QBluezConst::OpCodeGroupField ogf, QBluezConst::OpCodeCommandField ocf, const QByteArray ¶meters) +{ + qCDebug(QT_BT_BLUEZ) << "sending command; ogf:" << ogf << "ocf:" << ocf; + quint8 packetType = HCI_COMMAND_PKT; + hci_command_hdr command = { + opCodePack(ogf, ocf), + static_cast(parameters.size()) + }; + static_assert(sizeof command == 3, "unexpected struct size"); + struct iovec iv[3]; + iv[0].iov_base = &packetType; + iv[0].iov_len = 1; + iv[1].iov_base = &command; + iv[1].iov_len = sizeof command; + int ivn = 2; + if (!parameters.isEmpty()) { + iv[2].iov_base = const_cast(parameters.constData()); // const_cast is safe, since iov_base will not get modified. + iv[2].iov_len = parameters.size(); + ++ivn; + } + while (writev(hciSocket, iv, ivn) < 0) { + if (errno == EAGAIN || errno == EINTR) + continue; + qCDebug(QT_BT_BLUEZ()) << "hci command failure:" << strerror(errno); + return false; + } + qCDebug(QT_BT_BLUEZ) << "command sent successfully"; + return true; +} + +/* + * Unsubscribe from all events + */ +void HciManager::stopEvents() +{ + if (!isValid()) + return; + + hci_filter filter; + hci_filter_clear(&filter); + + if (setsockopt(hciSocket, SOL_HCI, HCI_FILTER, &filter, sizeof(hci_filter)) < 0) { + qCWarning(QT_BT_BLUEZ) << "Could not clear HCI socket options:" << strerror(errno); + return; + } + + runningEvents.clear(); +} + +QBluetoothAddress HciManager::addressForConnectionHandle(quint16 handle) const +{ + if (!isValid()) + return QBluetoothAddress(); + + hci_conn_info *info; + hci_conn_list_req *infoList; + + const int maxNoOfConnections = 20; + infoList = (hci_conn_list_req *) + malloc(sizeof(hci_conn_list_req) + maxNoOfConnections * sizeof(hci_conn_info)); + + if (!infoList) + return QBluetoothAddress(); + + QScopedPointer p(infoList); + p->conn_num = maxNoOfConnections; + p->dev_id = hciDev; + info = p->conn_info; + + if (ioctl(hciSocket, HCIGETCONNLIST, (void *) infoList) < 0) { + qCWarning(QT_BT_BLUEZ) << "Cannot retrieve connection list"; + return QBluetoothAddress(); + } + + for (int i = 0; i < infoList->conn_num; i++) { + if (info[i].handle == handle) + return QBluetoothAddress(convertAddress(info[i].bdaddr.b)); + } + + return QBluetoothAddress(); +} + +QList HciManager::activeLowEnergyConnections() const +{ + if (!isValid()) + return QList(); + + hci_conn_info *info; + hci_conn_list_req *infoList; + + const int maxNoOfConnections = 20; + infoList = (hci_conn_list_req *) + malloc(sizeof(hci_conn_list_req) + maxNoOfConnections * sizeof(hci_conn_info)); + + if (!infoList) + return QList(); + + QScopedPointer p(infoList); + p->conn_num = maxNoOfConnections; + p->dev_id = hciDev; + info = p->conn_info; + + if (ioctl(hciSocket, HCIGETCONNLIST, (void *) infoList) < 0) { + qCWarning(QT_BT_BLUEZ) << "Cannot retrieve connection list"; + return QList(); + } + + QList activeLowEnergyHandles; + for (int i = 0; i < infoList->conn_num; i++) { + switch (info[i].type) { + case SCO_LINK: + case ACL_LINK: + case ESCO_LINK: + continue; + case LE_LINK: + activeLowEnergyHandles.append(info[i].handle); + break; + default: + qCWarning(QT_BT_BLUEZ) << "Unknown active connection type:" << Qt::hex << info[i].type; + break; + } + } + + return activeLowEnergyHandles; +} + +quint16 forceIntervalIntoRange(double connectionInterval) +{ + return qMin(qMax(7.5, connectionInterval), 4000) / 1.25; +} + +struct ConnectionUpdateData { + quint16 minInterval; + quint16 maxInterval; + quint16 slaveLatency; + quint16 timeout; +}; +ConnectionUpdateData connectionUpdateData(const QLowEnergyConnectionParameters ¶ms) +{ + ConnectionUpdateData data; + const quint16 minInterval = forceIntervalIntoRange(params.minimumInterval()); + const quint16 maxInterval = forceIntervalIntoRange(params.maximumInterval()); + data.minInterval = qToLittleEndian(minInterval); + data.maxInterval = qToLittleEndian(maxInterval); + const quint16 latency = qMax(0, qMin(params.latency(), 499)); + data.slaveLatency = qToLittleEndian(latency); + const quint16 timeout + = qMax(100, qMin(32000, params.supervisionTimeout())) / 10; + data.timeout = qToLittleEndian(timeout); + return data; +} + +bool HciManager::sendConnectionUpdateCommand(quint16 handle, + const QLowEnergyConnectionParameters ¶ms) +{ + struct CommandParams { + quint16 handle; + ConnectionUpdateData data; + quint16 minCeLength; + quint16 maxCeLength; + } commandParams; + commandParams.handle = qToLittleEndian(handle); + commandParams.data = connectionUpdateData(params); + commandParams.minCeLength = 0; + commandParams.maxCeLength = qToLittleEndian(quint16(0xffff)); + const QByteArray data = QByteArray::fromRawData(reinterpret_cast(&commandParams), + sizeof commandParams); + return sendCommand(QBluezConst::OgfLinkControl, QBluezConst::OcfLeConnectionUpdate, data); +} + +bool HciManager::sendConnectionParameterUpdateRequest(quint16 handle, + const QLowEnergyConnectionParameters ¶ms) +{ + ConnectionUpdateData connUpdateData = connectionUpdateData(params); + + // Vol 3, part A, 4 + struct SignalingPacket { + quint8 code; + quint8 identifier; + quint16 length; + } signalingPacket; + signalingPacket.code = 0x12; + signalingPacket.identifier = ++sigPacketIdentifier; + const quint16 sigPacketLen = sizeof connUpdateData; + signalingPacket.length = qToLittleEndian(sigPacketLen); + + L2CapHeader l2CapHeader; + const quint16 l2CapHeaderLen = sizeof signalingPacket + sigPacketLen; + l2CapHeader.length = qToLittleEndian(l2CapHeaderLen); + l2CapHeader.channelId = qToLittleEndian(quint16(SIGNALING_CHANNEL_ID)); + + // Vol 2, part E, 5.4.2 + AclData aclData; + aclData.handle = qToLittleEndian(handle); // Works because the next two values are zero. + aclData.pbFlag = 0; + aclData.bcFlag = 0; + aclData.dataLen = qToLittleEndian(quint16(sizeof l2CapHeader + l2CapHeaderLen)); + + struct iovec iv[5]; + quint8 packetType = HCI_ACL_PKT; + iv[0].iov_base = &packetType; + iv[0].iov_len = 1; + iv[1].iov_base = &aclData; + iv[1].iov_len = sizeof aclData; + iv[2].iov_base = &l2CapHeader; + iv[2].iov_len = sizeof l2CapHeader; + iv[3].iov_base = &signalingPacket; + iv[3].iov_len = sizeof signalingPacket; + iv[4].iov_base = &connUpdateData; + iv[4].iov_len = sizeof connUpdateData; + while (writev(hciSocket, iv, sizeof iv / sizeof *iv) < 0) { + if (errno == EAGAIN || errno == EINTR) + continue; + qCDebug(QT_BT_BLUEZ()) << "failure writing HCI ACL packet:" << strerror(errno); + return false; + } + qCDebug(QT_BT_BLUEZ) << "Connection Update Request packet sent successfully"; + return true; +} + +/*! + * Process all incoming HCI events. Function cannot process anything else but events. + */ +void HciManager::_q_readNotify() +{ + unsigned char buffer[qMax(HCI_MAX_EVENT_SIZE, sizeof(AclData))]; + + const auto size = ::read(hciSocket, buffer, sizeof(buffer)); + if (size < 0) { + if (errno != EAGAIN && errno != EINTR) + qCWarning(QT_BT_BLUEZ) << "Failed reading HCI events:" << qt_error_string(errno); + + return; + } + + switch (buffer[0]) { + case HCI_EVENT_PKT: + handleHciEventPacket(buffer + 1, size - 1); + break; + case HCI_ACL_PKT: + handleHciAclPacket(buffer + 1, size - 1); + break; + default: + qCWarning(QT_BT_BLUEZ) << "Ignoring unexpected HCI packet type" << buffer[0]; + } +} + +void HciManager::handleHciEventPacket(const quint8 *data, int size) +{ + if (size < HCI_EVENT_HDR_SIZE) { + qCWarning(QT_BT_BLUEZ) << "Unexpected HCI event packet size:" << size; + return; + } + + hci_event_hdr *header = (hci_event_hdr *) data; + + size -= HCI_EVENT_HDR_SIZE; + data += HCI_EVENT_HDR_SIZE; + + if (header->plen != size) { + qCWarning(QT_BT_BLUEZ) << "Invalid HCI event packet size"; + return; + } + + qCDebug(QT_BT_BLUEZ) << "HCI event triggered, type:" << (HciManager::HciEvent)header->evt + << "type code:" << Qt::hex << header->evt; + + switch ((HciManager::HciEvent)header->evt) { + case HciEvent::EVT_ENCRYPT_CHANGE: { + const evt_encrypt_change *event = (evt_encrypt_change *) data; + qCDebug(QT_BT_BLUEZ) << "HCI Encrypt change, status:" + << (event->status == 0 ? "Success" : "Failed") + << "handle:" << Qt::hex << event->handle + << "encrypt:" << event->encrypt; + + QBluetoothAddress remoteDevice = addressForConnectionHandle(event->handle); + if (!remoteDevice.isNull()) + emit encryptionChangedEvent(remoteDevice, event->status == 0); + } break; + case HciEvent::EVT_CMD_COMPLETE: { + auto * const event = reinterpret_cast(data); + static_assert(sizeof *event == 3, "unexpected struct size"); + + // There is always a status byte right after the generic structure. + Q_ASSERT(size > static_cast(sizeof *event)); + const quint8 status = data[sizeof *event]; + const auto additionalData = QByteArray(reinterpret_cast(data) + + sizeof *event + 1, size - sizeof *event - 1); + emit commandCompleted(event->opcode, status, additionalData); + } break; + case HciEvent::EVT_LE_META_EVENT: + handleLeMetaEvent(data); + break; + default: + break; + } + +} + +void HciManager::handleHciAclPacket(const quint8 *data, int size) +{ + if (size < int(sizeof(AclData))) { + qCWarning(QT_BT_BLUEZ) << "Unexpected HCI ACL packet size"; + return; + } + + quint16 rawAclData[sizeof(AclData) / sizeof(quint16)]; + rawAclData[0] = bt_get_le16(data); + rawAclData[1] = bt_get_le16(data + sizeof(quint16)); + const AclData *aclData = reinterpret_cast(rawAclData); + data += sizeof *aclData; + size -= sizeof *aclData; + + // Consider only directed, complete messages. + if ((aclData->pbFlag != 0 && aclData->pbFlag != 2) || aclData->bcFlag != 0) + return; + + if (size < aclData->dataLen) { + qCWarning(QT_BT_BLUEZ) << "HCI ACL packet data size" << size + << "is smaller than specified size" << aclData->dataLen; + return; + } + +// qCDebug(QT_BT_BLUEZ) << "handle:" << aclData->handle << "PB:" << aclData->pbFlag +// << "BC:" << aclData->bcFlag << "data len:" << aclData->dataLen; + + if (size < int(sizeof(L2CapHeader))) { + qCWarning(QT_BT_BLUEZ) << "Unexpected HCI ACL packet size"; + return; + } + L2CapHeader l2CapHeader = *reinterpret_cast(data); + l2CapHeader.channelId = qFromLittleEndian(l2CapHeader.channelId); + l2CapHeader.length = qFromLittleEndian(l2CapHeader.length); + data += sizeof l2CapHeader; + size -= sizeof l2CapHeader; + if (size < l2CapHeader.length) { + qCWarning(QT_BT_BLUEZ) << "L2Cap payload size" << size << "is smaller than specified size" + << l2CapHeader.length; + return; + } +// qCDebug(QT_BT_BLUEZ) << "l2cap channel id:" << l2CapHeader.channelId +// << "payload length:" << l2CapHeader.length; + if (l2CapHeader.channelId != SECURITY_CHANNEL_ID) + return; + if (*data != 0xa) // "Signing Information". Spec v4.2, Vol 3, Part H, 3.6.6 + return; + if (size != 17) { + qCWarning(QT_BT_BLUEZ) << "Unexpected key size" << size << "in Signing Information packet"; + return; + } + BluezUint128 csrk; + memcpy(&csrk, data + 1, sizeof csrk); + const bool isRemoteKey = aclData->pbFlag == 2; + emit signatureResolvingKeyReceived(aclData->handle, isRemoteKey, csrk); +} + +void HciManager::handleLeMetaEvent(const quint8 *data) +{ + // Spec v5.3, Vol 4, part E, 7.7.65.* + switch (*data) { + case 0x1: // HCI_LE_Connection_Complete + case 0xA: // HCI_LE_Enhanced_Connection_Complete + { + const quint16 handle = bt_get_le16(data + 2); + emit connectionComplete(handle); + break; + } + case 0x3: { + // TODO: From little endian! + struct ConnectionUpdateData { + quint8 status; + quint16 handle; + quint16 interval; + quint16 latency; + quint16 timeout; + } __attribute((packed)); + const auto * const updateData + = reinterpret_cast(data + 1); + if (updateData->status == 0) { + QLowEnergyConnectionParameters params; + const double interval = qFromLittleEndian(updateData->interval) * 1.25; + params.setIntervalRange(interval, interval); + params.setLatency(qFromLittleEndian(updateData->latency)); + params.setSupervisionTimeout(qFromLittleEndian(updateData->timeout) * 10); + emit connectionUpdate(qFromLittleEndian(updateData->handle), params); + } + break; + } + default: + break; + } +} + +QT_END_NAMESPACE + +#include "moc_hcimanager_p.cpp" diff --git a/src/bluetooth/bluez/hcimanager_p.h b/src/bluetooth/bluez/hcimanager_p.h new file mode 100644 index 0000000..67ed900 --- /dev/null +++ b/src/bluetooth/bluez/hcimanager_p.h @@ -0,0 +1,202 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef HCIMANAGER_P_H +#define HCIMANAGER_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 "bluez/bluez_data_p.h" + +QT_BEGIN_NAMESPACE + +class QLowEnergyConnectionParameters; + +class HciManager : public QObject +{ + Q_OBJECT +public: + enum class HciEvent { + EVT_INQUIRY_COMPLETE = 0x01, + EVT_INQUIRY_RESULT = 0x02, + EVT_CONN_COMPLETE = 0x03, + EVT_CONN_REQUEST = 0x04, + EVT_DISCONN_COMPLETE = 0x05, + EVT_AUTH_COMPLETE = 0x06, + EVT_REMOTE_NAME_REQ_COMPLETE = 0x07, + EVT_ENCRYPT_CHANGE = 0x08, + EVT_CHANGE_CONN_LINK_KEY_COMPLETE = 0x09, + EVT_MASTER_LINK_KEY_COMPLETE = 0x0A, + EVT_READ_REMOTE_FEATURES_COMPLETE = 0x0B, + EVT_READ_REMOTE_VERSION_COMPLETE = 0x0C, + EVT_QOS_SETUP_COMPLETE = 0x0D, + EVT_CMD_COMPLETE = 0x0E, + EVT_CMD_STATUS = 0x0F, + EVT_HARDWARE_ERROR = 0x10, + EVT_FLUSH_OCCURRED = 0x11, + EVT_ROLE_CHANGE = 0x12, + EVT_NUM_COMP_PKTS = 0x13, + EVT_MODE_CHANGE = 0x14, + EVT_RETURN_LINK_KEYS = 0x15, + EVT_PIN_CODE_REQ = 0x16, + EVT_LINK_KEY_REQ = 0x17, + EVT_LINK_KEY_NOTIFY = 0x18, + EVT_LOOPBACK_COMMAND = 0x19, + EVT_DATA_BUFFER_OVERFLOW = 0x1A, + EVT_MAX_SLOTS_CHANGE = 0x1B, + EVT_READ_CLOCK_OFFSET_COMPLETE = 0x1C, + EVT_CONN_PTYPE_CHANGED = 0x1D, + EVT_QOS_VIOLATION = 0x1E, + EVT_PSCAN_REP_MODE_CHANGE = 0x20, + EVT_FLOW_SPEC_COMPLETE = 0x21, + EVT_INQUIRY_RESULT_WITH_RSSI = 0x22, + EVT_READ_REMOTE_EXT_FEATURES_COMPLETE = 0x23, + EVT_SYNC_CONN_COMPLETE = 0x2C, + EVT_SYNC_CONN_CHANGED = 0x2D, + EVT_SNIFF_SUBRATING = 0x2E, + EVT_EXTENDED_INQUIRY_RESULT = 0x2F, + EVT_ENCRYPTION_KEY_REFRESH_COMPLETE = 0x30, + EVT_IO_CAPABILITY_REQUEST = 0x31, + EVT_IO_CAPABILITY_RESPONSE = 0x32, + EVT_USER_CONFIRM_REQUEST = 0x33, + EVT_USER_PASSKEY_REQUEST = 0x34, + EVT_REMOTE_OOB_DATA_REQUEST = 0x35, + EVT_SIMPLE_PAIRING_COMPLETE = 0x36, + EVT_LINK_SUPERVISION_TIMEOUT_CHANGED = 0x38, + EVT_ENHANCED_FLUSH_COMPLETE = 0x39, + EVT_USER_PASSKEY_NOTIFY = 0x3B, + EVT_KEYPRESS_NOTIFY = 0x3C, + EVT_REMOTE_HOST_FEATURES_NOTIFY = 0x3D, + EVT_LE_META_EVENT = 0x3E, + EVT_PHYSICAL_LINK_COMPLETE = 0x40, + EVT_CHANNEL_SELECTED = 0x41, + EVT_DISCONNECT_PHYSICAL_LINK_COMPLETE = 0x42, + EVT_PHYSICAL_LINK_LOSS_EARLY_WARNING = 0x43, + EVT_PHYSICAL_LINK_RECOVERY = 0x44, + EVT_LOGICAL_LINK_COMPLETE = 0x45, + EVT_DISCONNECT_LOGICAL_LINK_COMPLETE = 0x46, + EVT_FLOW_SPEC_MODIFY_COMPLETE = 0x47, + EVT_NUMBER_COMPLETED_BLOCKS = 0x48, + EVT_AMP_STATUS_CHANGE = 0x4D, + EVT_TESTING = 0xFE, + EVT_VENDOR = 0xFF, + EVT_STACK_INTERNAL = 0xFD + }; + Q_ENUM(HciEvent); + + enum class HciError { + HCI_SUCCESS = 0x00, // added for convenience, not in bluez code + HCI_UNKNOWN_COMMAND = 0x01, + HCI_NO_CONNECTION = 0x02, + HCI_HARDWARE_FAILURE = 0x03, + HCI_PAGE_TIMEOUT = 0x04, + HCI_AUTHENTICATION_FAILURE = 0x05, + HCI_PIN_OR_KEY_MISSING = 0x06, + HCI_MEMORY_FULL = 0x07, + HCI_CONNECTION_TIMEOUT = 0x08, + HCI_MAX_NUMBER_OF_CONNECTIONS = 0x09, + HCI_MAX_NUMBER_OF_SCO_CONNECTIONS = 0x0a, + HCI_ACL_CONNECTION_EXISTS = 0x0b, + HCI_COMMAND_DISALLOWED = 0x0c, + HCI_REJECTED_LIMITED_RESOURCES = 0x0d, + HCI_REJECTED_SECURITY = 0x0e, + HCI_REJECTED_PERSONAL = 0x0f, + HCI_HOST_TIMEOUT = 0x10, + HCI_UNSUPPORTED_FEATURE = 0x11, + HCI_INVALID_PARAMETERS = 0x12, + HCI_OE_USER_ENDED_CONNECTION = 0x13, + HCI_OE_LOW_RESOURCES = 0x14, + HCI_OE_POWER_OFF = 0x15, + HCI_CONNECTION_TERMINATED = 0x16, + HCI_REPEATED_ATTEMPTS = 0x17, + HCI_PAIRING_NOT_ALLOWED = 0x18, + HCI_UNKNOWN_LMP_PDU = 0x19, + HCI_UNSUPPORTED_REMOTE_FEATURE = 0x1a, + HCI_SCO_OFFSET_REJECTED = 0x1b, + HCI_SCO_INTERVAL_REJECTED = 0x1c, + HCI_AIR_MODE_REJECTED = 0x1d, + HCI_INVALID_LMP_PARAMETERS = 0x1e, + HCI_UNSPECIFIED_ERROR = 0x1f, + HCI_UNSUPPORTED_LMP_PARAMETER_VALUE = 0x20, + HCI_ROLE_CHANGE_NOT_ALLOWED = 0x21, + HCI_LMP_RESPONSE_TIMEOUT = 0x22, + HCI_LMP_ERROR_TRANSACTION_COLLISION = 0x23, + HCI_LMP_PDU_NOT_ALLOWED = 0x24, + HCI_ENCRYPTION_MODE_NOT_ACCEPTED = 0x25, + HCI_UNIT_LINK_KEY_USED = 0x26, + HCI_QOS_NOT_SUPPORTED = 0x27, + HCI_INSTANT_PASSED = 0x28, + HCI_PAIRING_NOT_SUPPORTED = 0x29, + HCI_TRANSACTION_COLLISION = 0x2a, + HCI_QOS_UNACCEPTABLE_PARAMETER = 0x2c, + HCI_QOS_REJECTED = 0x2d, + HCI_CLASSIFICATION_NOT_SUPPORTED = 0x2e, + HCI_INSUFFICIENT_SECURITY = 0x2f, + HCI_PARAMETER_OUT_OF_RANGE = 0x30, + HCI_ROLE_SWITCH_PENDING = 0x32, + HCI_SLOT_VIOLATION = 0x34, + HCI_ROLE_SWITCH_FAILED = 0x35, + HCI_EIR_TOO_LARGE = 0x36, + HCI_SIMPLE_PAIRING_NOT_SUPPORTED = 0x37, + HCI_HOST_BUSY_PAIRING = 0x38 + }; + Q_ENUM(HciError); + + explicit HciManager(const QBluetoothAddress &deviceAdapter); + ~HciManager(); + + bool isValid() const; + bool monitorEvent(HciManager::HciEvent event); + bool monitorAclPackets(); + bool sendCommand(QBluezConst::OpCodeGroupField ogf, QBluezConst::OpCodeCommandField ocf, const QByteArray ¶meters); + + void stopEvents(); + QBluetoothAddress addressForConnectionHandle(quint16 handle) const; + + // active connections + QList activeLowEnergyConnections() const; + + bool sendConnectionUpdateCommand(quint16 handle, const QLowEnergyConnectionParameters ¶ms); + bool sendConnectionParameterUpdateRequest(quint16 handle, + const QLowEnergyConnectionParameters ¶ms); + +signals: + void encryptionChangedEvent(const QBluetoothAddress &address, bool wasSuccess); + void commandCompleted(quint16 opCode, quint8 status, const QByteArray &data); + void connectionComplete(quint16 handle); + void connectionUpdate(quint16 handle, const QLowEnergyConnectionParameters ¶meters); + void signatureResolvingKeyReceived(quint16 connHandle, bool remoteKey, BluezUint128 csrk); + +private slots: + void _q_readNotify(); + +private: + int hciForAddress(const QBluetoothAddress &deviceAdapter); + void handleHciEventPacket(const quint8 *data, int size); + void handleHciAclPacket(const quint8 *data, int size); + void handleLeMetaEvent(const quint8 *data); + + int hciSocket; + int hciDev; + quint8 sigPacketIdentifier = 0; + QSocketNotifier *notifier = nullptr; + QSet runningEvents; +}; + +QT_END_NAMESPACE + +#endif // HCIMANAGER_P_H diff --git a/src/bluetooth/bluez/leadvertisement1.cpp b/src/bluetooth/bluez/leadvertisement1.cpp new file mode 100644 index 0000000..e1b91c4 --- /dev/null +++ b/src/bluetooth/bluez/leadvertisement1.cpp @@ -0,0 +1,136 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -a leadvertisement1_p.h:leadvertisement1.cpp -c OrgBluezLEAdvertisement1Adaptor -i bluez5_helper_p.h org.bluez.LEAdvertisement1.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#include "leadvertisement1_p.h" +#include +#include +#include +#include +#include +#include +#include + +/* + * Implementation of adaptor class OrgBluezLEAdvertisement1Adaptor + */ + +OrgBluezLEAdvertisement1Adaptor::OrgBluezLEAdvertisement1Adaptor(QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + // constructor + setAutoRelaySignals(true); +} + +OrgBluezLEAdvertisement1Adaptor::~OrgBluezLEAdvertisement1Adaptor() +{ + // destructor +} + +bool OrgBluezLEAdvertisement1Adaptor::discoverable() const +{ + // get the value of property Discoverable + return qvariant_cast< bool >(parent()->property("Discoverable")); +} + +void OrgBluezLEAdvertisement1Adaptor::setDiscoverable(bool value) +{ + // set the value of property Discoverable + parent()->setProperty("Discoverable", QVariant::fromValue(value)); +} + +QStringList OrgBluezLEAdvertisement1Adaptor::includes() const +{ + // get the value of property Includes + return qvariant_cast< QStringList >(parent()->property("Includes")); +} + +void OrgBluezLEAdvertisement1Adaptor::setIncludes(const QStringList &value) +{ + // set the value of property Includes + parent()->setProperty("Includes", QVariant::fromValue(value)); +} + +QString OrgBluezLEAdvertisement1Adaptor::localName() const +{ + // get the value of property LocalName + return qvariant_cast< QString >(parent()->property("LocalName")); +} + +void OrgBluezLEAdvertisement1Adaptor::setLocalName(const QString &value) +{ + // set the value of property LocalName + parent()->setProperty("LocalName", QVariant::fromValue(value)); +} + +ManufacturerDataList OrgBluezLEAdvertisement1Adaptor::manufacturerData() const +{ + // get the value of property ManufacturerData + return qvariant_cast< ManufacturerDataList >(parent()->property("ManufacturerData")); +} + +void OrgBluezLEAdvertisement1Adaptor::setManufacturerData(ManufacturerDataList value) +{ + // set the value of property ManufacturerData + parent()->setProperty("ManufacturerData", QVariant::fromValue(value)); +} + +uint OrgBluezLEAdvertisement1Adaptor::maxInterval() const +{ + // get the value of property MaxInterval + return qvariant_cast< uint >(parent()->property("MaxInterval")); +} + +void OrgBluezLEAdvertisement1Adaptor::setMaxInterval(uint value) +{ + // set the value of property MaxInterval + parent()->setProperty("MaxInterval", QVariant::fromValue(value)); +} + +uint OrgBluezLEAdvertisement1Adaptor::minInterval() const +{ + // get the value of property MinInterval + return qvariant_cast< uint >(parent()->property("MinInterval")); +} + +void OrgBluezLEAdvertisement1Adaptor::setMinInterval(uint value) +{ + // set the value of property MinInterval + parent()->setProperty("MinInterval", QVariant::fromValue(value)); +} + +QStringList OrgBluezLEAdvertisement1Adaptor::serviceUUIDs() const +{ + // get the value of property ServiceUUIDs + return qvariant_cast< QStringList >(parent()->property("ServiceUUIDs")); +} + +void OrgBluezLEAdvertisement1Adaptor::setServiceUUIDs(const QStringList &value) +{ + // set the value of property ServiceUUIDs + parent()->setProperty("ServiceUUIDs", QVariant::fromValue(value)); +} + +QString OrgBluezLEAdvertisement1Adaptor::type() const +{ + // get the value of property Type + return qvariant_cast< QString >(parent()->property("Type")); +} + +void OrgBluezLEAdvertisement1Adaptor::setType(const QString &value) +{ + // set the value of property Type + parent()->setProperty("Type", QVariant::fromValue(value)); +} + +void OrgBluezLEAdvertisement1Adaptor::Release() +{ + // handle method call org.bluez.LEAdvertisement1.Release + QMetaObject::invokeMethod(parent(), "Release"); +} diff --git a/src/bluetooth/bluez/leadvertisement1_p.h b/src/bluetooth/bluez/leadvertisement1_p.h new file mode 100644 index 0000000..8931e43 --- /dev/null +++ b/src/bluetooth/bluez/leadvertisement1_p.h @@ -0,0 +1,97 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -a leadvertisement1_p.h:leadvertisement1.cpp -c OrgBluezLEAdvertisement1Adaptor -i bluez5_helper_p.h org.bluez.LEAdvertisement1.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#ifndef LEADVERTISEMENT1_P_H +#define LEADVERTISEMENT1_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 "bluez5_helper_p.h" +#include + +/* + * Adaptor class for interface org.bluez.LEAdvertisement1 + */ +class OrgBluezLEAdvertisement1Adaptor: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.bluez.LEAdvertisement1") + Q_CLASSINFO("D-Bus Introspection", "" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" + "") +public: + OrgBluezLEAdvertisement1Adaptor(QObject *parent); + virtual ~OrgBluezLEAdvertisement1Adaptor(); + +public: // PROPERTIES + Q_PROPERTY(bool Discoverable READ discoverable WRITE setDiscoverable) + bool discoverable() const; + void setDiscoverable(bool value); + + Q_PROPERTY(QStringList Includes READ includes WRITE setIncludes) + QStringList includes() const; + void setIncludes(const QStringList &value); + + Q_PROPERTY(QString LocalName READ localName WRITE setLocalName) + QString localName() const; + void setLocalName(const QString &value); + + Q_PROPERTY(ManufacturerDataList ManufacturerData READ manufacturerData WRITE setManufacturerData) + ManufacturerDataList manufacturerData() const; + void setManufacturerData(ManufacturerDataList value); + + Q_PROPERTY(uint MaxInterval READ maxInterval WRITE setMaxInterval) + uint maxInterval() const; + void setMaxInterval(uint value); + + Q_PROPERTY(uint MinInterval READ minInterval WRITE setMinInterval) + uint minInterval() const; + void setMinInterval(uint value); + + Q_PROPERTY(QStringList ServiceUUIDs READ serviceUUIDs WRITE setServiceUUIDs) + QStringList serviceUUIDs() const; + void setServiceUUIDs(const QStringList &value); + + Q_PROPERTY(QString Type READ type WRITE setType) + QString type() const; + void setType(const QString &value); + +public Q_SLOTS: // METHODS + Q_NOREPLY void Release(); +Q_SIGNALS: // SIGNALS +}; + +#endif diff --git a/src/bluetooth/bluez/leadvertisingmanager1.cpp b/src/bluetooth/bluez/leadvertisingmanager1.cpp new file mode 100644 index 0000000..2969016 --- /dev/null +++ b/src/bluetooth/bluez/leadvertisingmanager1.cpp @@ -0,0 +1,28 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -I QtCore/private/qglobal_p.h -p leadvertisingmanager1_p.h:leadvertisingmanager1.cpp org.bluez.LEAdvertisingManager1.xml --moc + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "leadvertisingmanager1_p.h" + +/* + * Implementation of interface class OrgBluezLEAdvertisingManager1Interface + */ + +OrgBluezLEAdvertisingManager1Interface::OrgBluezLEAdvertisingManager1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +OrgBluezLEAdvertisingManager1Interface::~OrgBluezLEAdvertisingManager1Interface() +{ +} + + +#include "moc_leadvertisingmanager1_p.cpp" diff --git a/src/bluetooth/bluez/leadvertisingmanager1_p.h b/src/bluetooth/bluez/leadvertisingmanager1_p.h new file mode 100644 index 0000000..06a299b --- /dev/null +++ b/src/bluetooth/bluez/leadvertisingmanager1_p.h @@ -0,0 +1,85 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -I QtCore/private/qglobal_p.h -p leadvertisingmanager1_p.h:leadvertisingmanager1.cpp org.bluez.LEAdvertisingManager1.xml --moc + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#ifndef LEADVERTISINGMANAGER1_P_H +#define LEADVERTISINGMANAGER1_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 + +/* + * Proxy class for interface org.bluez.LEAdvertisingManager1 + */ +class OrgBluezLEAdvertisingManager1Interface: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "org.bluez.LEAdvertisingManager1"; } + +public: + OrgBluezLEAdvertisingManager1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); + + ~OrgBluezLEAdvertisingManager1Interface(); + + Q_PROPERTY(uchar ActiveInstances READ activeInstances) + inline uchar activeInstances() const + { return qvariant_cast< uchar >(property("ActiveInstances")); } + + Q_PROPERTY(QStringList SupportedIncludes READ supportedIncludes) + inline QStringList supportedIncludes() const + { return qvariant_cast< QStringList >(property("SupportedIncludes")); } + + Q_PROPERTY(uchar SupportedInstances READ supportedInstances) + inline uchar supportedInstances() const + { return qvariant_cast< uchar >(property("SupportedInstances")); } + +public Q_SLOTS: // METHODS + inline QDBusPendingReply<> RegisterAdvertisement(const QDBusObjectPath &advertisement, const QVariantMap &options) + { + QList argumentList; + argumentList << QVariant::fromValue(advertisement) << QVariant::fromValue(options); + return asyncCallWithArgumentList(QStringLiteral("RegisterAdvertisement"), argumentList); + } + + inline QDBusPendingReply<> UnregisterAdvertisement(const QDBusObjectPath &advertisement) + { + QList argumentList; + argumentList << QVariant::fromValue(advertisement); + return asyncCallWithArgumentList(QStringLiteral("UnregisterAdvertisement"), argumentList); + } + +Q_SIGNALS: // SIGNALS +}; + +namespace org { + namespace bluez { + using LEAdvertisingManager1 = ::OrgBluezLEAdvertisingManager1Interface; + } +} +#endif diff --git a/src/bluetooth/bluez/objectmanager.cpp b/src/bluetooth/bluez/objectmanager.cpp new file mode 100644 index 0000000..dd232c6 --- /dev/null +++ b/src/bluetooth/bluez/objectmanager.cpp @@ -0,0 +1,28 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -i bluez5_helper_p.h -I QtCore/private/qglobal_p.h -p objectmanager_p.h:objectmanager.cpp org.freedesktop.dbus.objectmanager.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "objectmanager_p.h" + +/* + * Implementation of interface class OrgFreedesktopDBusObjectManagerInterface + */ + +OrgFreedesktopDBusObjectManagerInterface::OrgFreedesktopDBusObjectManagerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +OrgFreedesktopDBusObjectManagerInterface::~OrgFreedesktopDBusObjectManagerInterface() +{ +} + + +#include "moc_objectmanager_p.cpp" diff --git a/src/bluetooth/bluez/objectmanager_p.h b/src/bluetooth/bluez/objectmanager_p.h new file mode 100644 index 0000000..d76eeb5 --- /dev/null +++ b/src/bluetooth/bluez/objectmanager_p.h @@ -0,0 +1,70 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -i bluez5_helper_p.h -I QtCore/private/qglobal_p.h -p objectmanager_p.h:objectmanager.cpp org.freedesktop.dbus.objectmanager.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#ifndef OBJECTMANAGER_P_H +#define OBJECTMANAGER_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 "bluez5_helper_p.h" +#include + +/* + * Proxy class for interface org.freedesktop.DBus.ObjectManager + */ +class OrgFreedesktopDBusObjectManagerInterface: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "org.freedesktop.DBus.ObjectManager"; } + +public: + OrgFreedesktopDBusObjectManagerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); + + ~OrgFreedesktopDBusObjectManagerInterface(); + +public Q_SLOTS: // METHODS + inline QDBusPendingReply GetManagedObjects() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("GetManagedObjects"), argumentList); + } + +Q_SIGNALS: // SIGNALS + void InterfacesAdded(const QDBusObjectPath &object_path, InterfaceList interfaces_and_properties); + void InterfacesRemoved(const QDBusObjectPath &object_path, const QStringList &interfaces); +}; + +namespace org { + namespace freedesktop { + namespace DBus { + using ObjectManager = ::OrgFreedesktopDBusObjectManagerInterface; + } + } +} +#endif diff --git a/src/bluetooth/bluez/objectmanageradaptor.cpp b/src/bluetooth/bluez/objectmanageradaptor.cpp new file mode 100644 index 0000000..575a7f2 --- /dev/null +++ b/src/bluetooth/bluez/objectmanageradaptor.cpp @@ -0,0 +1,42 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -a objectmanageradaptor_p.h:objectmanageradaptor.cpp -c OrgFreedesktopDBusObjectManagerAdaptor -i bluez5_helper_p.h org.freedesktop.dbus.objectmanager.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#include "objectmanageradaptor_p.h" +#include +#include +#include +#include +#include +#include +#include + +/* + * Implementation of adaptor class OrgFreedesktopDBusObjectManagerAdaptor + */ + +OrgFreedesktopDBusObjectManagerAdaptor::OrgFreedesktopDBusObjectManagerAdaptor(QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + // constructor + setAutoRelaySignals(true); +} + +OrgFreedesktopDBusObjectManagerAdaptor::~OrgFreedesktopDBusObjectManagerAdaptor() +{ + // destructor +} + +ManagedObjectList OrgFreedesktopDBusObjectManagerAdaptor::GetManagedObjects() +{ + // handle method call org.freedesktop.DBus.ObjectManager.GetManagedObjects + ManagedObjectList object_paths_interfaces_and_properties; + QMetaObject::invokeMethod(parent(), "GetManagedObjects", Q_RETURN_ARG(ManagedObjectList, object_paths_interfaces_and_properties)); + return object_paths_interfaces_and_properties; +} diff --git a/src/bluetooth/bluez/objectmanageradaptor_p.h b/src/bluetooth/bluez/objectmanageradaptor_p.h new file mode 100644 index 0000000..17579a2 --- /dev/null +++ b/src/bluetooth/bluez/objectmanageradaptor_p.h @@ -0,0 +1,67 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -a objectmanageradaptor_p.h:objectmanageradaptor.cpp -c OrgFreedesktopDBusObjectManagerAdaptor -i bluez5_helper_p.h org.freedesktop.dbus.objectmanager.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#ifndef OBJECTMANAGERADAPTOR_P_H +#define OBJECTMANAGERADAPTOR_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 "bluez5_helper_p.h" +#include + +/* + * Adaptor class for interface org.freedesktop.DBus.ObjectManager + */ +class OrgFreedesktopDBusObjectManagerAdaptor: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.freedesktop.DBus.ObjectManager") + Q_CLASSINFO("D-Bus Introspection", "" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" + "") +public: + OrgFreedesktopDBusObjectManagerAdaptor(QObject *parent); + virtual ~OrgFreedesktopDBusObjectManagerAdaptor(); + +public: // PROPERTIES +public Q_SLOTS: // METHODS + ManagedObjectList GetManagedObjects(); +Q_SIGNALS: // SIGNALS + void InterfacesAdded(const QDBusObjectPath &object_path, InterfaceList interfaces_and_properties); + void InterfacesRemoved(const QDBusObjectPath &object_path, const QStringList &interfaces); +}; + +#endif diff --git a/src/bluetooth/bluez/org.bluez.Adapter1.xml b/src/bluetooth/bluez/org.bluez.Adapter1.xml new file mode 100644 index 0000000..121c277 --- /dev/null +++ b/src/bluetooth/bluez/org.bluez.Adapter1.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/bluetooth/bluez/org.bluez.Battery1.xml b/src/bluetooth/bluez/org.bluez.Battery1.xml new file mode 100644 index 0000000..efa0309 --- /dev/null +++ b/src/bluetooth/bluez/org.bluez.Battery1.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/src/bluetooth/bluez/org.bluez.Device1.xml b/src/bluetooth/bluez/org.bluez.Device1.xml new file mode 100644 index 0000000..cd4cba7 --- /dev/null +++ b/src/bluetooth/bluez/org.bluez.Device1.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/bluetooth/bluez/org.bluez.GattCharacteristic1.xml b/src/bluetooth/bluez/org.bluez.GattCharacteristic1.xml new file mode 100644 index 0000000..f62014c --- /dev/null +++ b/src/bluetooth/bluez/org.bluez.GattCharacteristic1.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/bluetooth/bluez/org.bluez.GattDescriptor1.xml b/src/bluetooth/bluez/org.bluez.GattDescriptor1.xml new file mode 100644 index 0000000..fc7ebce --- /dev/null +++ b/src/bluetooth/bluez/org.bluez.GattDescriptor1.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/bluetooth/bluez/org.bluez.GattManager1.xml b/src/bluetooth/bluez/org.bluez.GattManager1.xml new file mode 100644 index 0000000..ca7819b --- /dev/null +++ b/src/bluetooth/bluez/org.bluez.GattManager1.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/src/bluetooth/bluez/org.bluez.GattService1.xml b/src/bluetooth/bluez/org.bluez.GattService1.xml new file mode 100644 index 0000000..e90eeda --- /dev/null +++ b/src/bluetooth/bluez/org.bluez.GattService1.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/bluetooth/bluez/org.bluez.LEAdvertisement1.xml b/src/bluetooth/bluez/org.bluez.LEAdvertisement1.xml new file mode 100644 index 0000000..845dbcc --- /dev/null +++ b/src/bluetooth/bluez/org.bluez.LEAdvertisement1.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/bluetooth/bluez/org.bluez.LEAdvertisingManager1.xml b/src/bluetooth/bluez/org.bluez.LEAdvertisingManager1.xml new file mode 100644 index 0000000..f8e1e49 --- /dev/null +++ b/src/bluetooth/bluez/org.bluez.LEAdvertisingManager1.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/bluetooth/bluez/org.bluez.Profile1.xml b/src/bluetooth/bluez/org.bluez.Profile1.xml new file mode 100644 index 0000000..2e5ec13 --- /dev/null +++ b/src/bluetooth/bluez/org.bluez.Profile1.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/src/bluetooth/bluez/org.bluez.ProfileManager1.xml b/src/bluetooth/bluez/org.bluez.ProfileManager1.xml new file mode 100644 index 0000000..54c9fd0 --- /dev/null +++ b/src/bluetooth/bluez/org.bluez.ProfileManager1.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + diff --git a/src/bluetooth/bluez/org.freedesktop.dbus.objectmanager.xml b/src/bluetooth/bluez/org.freedesktop.dbus.objectmanager.xml new file mode 100644 index 0000000..8ab2a6e --- /dev/null +++ b/src/bluetooth/bluez/org.freedesktop.dbus.objectmanager.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/bluetooth/bluez/org.freedesktop.dbus.properties.xml b/src/bluetooth/bluez/org.freedesktop.dbus.properties.xml new file mode 100644 index 0000000..5dc94f5 --- /dev/null +++ b/src/bluetooth/bluez/org.freedesktop.dbus.properties.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/bluetooth/bluez/profile1.cpp b/src/bluetooth/bluez/profile1.cpp new file mode 100644 index 0000000..7e67cf2 --- /dev/null +++ b/src/bluetooth/bluez/profile1.cpp @@ -0,0 +1,28 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -I QtCore/private/qglobal_p.h -p profile1_p.h:profile1.cpp org.bluez.Profile1.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "profile1_p.h" + +/* + * Implementation of interface class OrgBluezProfile1Interface + */ + +OrgBluezProfile1Interface::OrgBluezProfile1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +OrgBluezProfile1Interface::~OrgBluezProfile1Interface() +{ +} + + +#include "moc_profile1_p.cpp" diff --git a/src/bluetooth/bluez/profile1_p.h b/src/bluetooth/bluez/profile1_p.h new file mode 100644 index 0000000..bf26354 --- /dev/null +++ b/src/bluetooth/bluez/profile1_p.h @@ -0,0 +1,79 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -I QtCore/private/qglobal_p.h -p profile1_p.h:profile1.cpp org.bluez.Profile1.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#ifndef PROFILE1_P_H +#define PROFILE1_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 + +/* + * Proxy class for interface org.bluez.Profile1 + */ +class OrgBluezProfile1Interface: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "org.bluez.Profile1"; } + +public: + OrgBluezProfile1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); + + ~OrgBluezProfile1Interface(); + +public Q_SLOTS: // METHODS + inline QDBusPendingReply<> NewConnection(const QDBusObjectPath &in0, const QDBusUnixFileDescriptor &in1, const QVariantMap &in2) + { + QList argumentList; + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1) << QVariant::fromValue(in2); + return asyncCallWithArgumentList(QStringLiteral("NewConnection"), argumentList); + } + + inline Q_NOREPLY void Release() + { + QList argumentList; + callWithArgumentList(QDBus::NoBlock, QStringLiteral("Release"), argumentList); + } + + inline QDBusPendingReply<> RequestDisconnection(const QDBusObjectPath &in0) + { + QList argumentList; + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QStringLiteral("RequestDisconnection"), argumentList); + } + +Q_SIGNALS: // SIGNALS +}; + +namespace org { + namespace bluez { + using Profile1 = ::OrgBluezProfile1Interface; + } +} +#endif diff --git a/src/bluetooth/bluez/profile1context.cpp b/src/bluetooth/bluez/profile1context.cpp new file mode 100644 index 0000000..3bb7e1b --- /dev/null +++ b/src/bluetooth/bluez/profile1context.cpp @@ -0,0 +1,38 @@ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "profile1context_p.h" + +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ) + +OrgBluezProfile1ContextInterface::OrgBluezProfile1ContextInterface(QObject *parent) : QObject(parent) +{ +} + +void OrgBluezProfile1ContextInterface::NewConnection(const QDBusObjectPath &/*remotePath*/, + const QDBusUnixFileDescriptor &descriptor, + const QVariantMap &/*properties*/) +{ + qCDebug(QT_BT_BLUEZ) << "Profile Context: New Connection"; + emit newConnection(descriptor); + setDelayedReply(false); +} + +void OrgBluezProfile1ContextInterface::RequestDisconnection(const QDBusObjectPath &/*remotePath*/) +{ + qCDebug(QT_BT_BLUEZ) << "Profile Context: Request Disconnection"; + setDelayedReply(false); +} + +void OrgBluezProfile1ContextInterface::Release() +{ + qCDebug(QT_BT_BLUEZ) << "Profile Context: Release"; +} + +QT_END_NAMESPACE + +#include "moc_profile1context_p.cpp" diff --git a/src/bluetooth/bluez/profile1context_p.h b/src/bluetooth/bluez/profile1context_p.h new file mode 100644 index 0000000..99160bb --- /dev/null +++ b/src/bluetooth/bluez/profile1context_p.h @@ -0,0 +1,61 @@ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef PROFILECONTEXT_P_H +#define PROFILECONTEXT_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 OrgBluezProfile1ContextInterface : public QObject, protected QDBusContext +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.bluez.Profile1") + Q_CLASSINFO("D-Bus Introspection", "" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" + "") +public: + explicit OrgBluezProfile1ContextInterface(QObject *parent = nullptr); + +Q_SIGNALS: + void newConnection(const QDBusUnixFileDescriptor &fd); + +public Q_SLOTS: + void NewConnection(const QDBusObjectPath &, const QDBusUnixFileDescriptor &, + const QVariantMap &); + void RequestDisconnection(const QDBusObjectPath &); + Q_NOREPLY void Release(); +}; + +QT_END_NAMESPACE + +#endif // PROFILECONTEXT_P_H diff --git a/src/bluetooth/bluez/profilemanager1.cpp b/src/bluetooth/bluez/profilemanager1.cpp new file mode 100644 index 0000000..4366a96 --- /dev/null +++ b/src/bluetooth/bluez/profilemanager1.cpp @@ -0,0 +1,28 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -I QtCore/private/qglobal_p.h -p profilemanager1_p.h:profilemanager1.cpp org.bluez.ProfileManager1.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "profilemanager1_p.h" + +/* + * Implementation of interface class OrgBluezProfileManager1Interface + */ + +OrgBluezProfileManager1Interface::OrgBluezProfileManager1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +OrgBluezProfileManager1Interface::~OrgBluezProfileManager1Interface() +{ +} + + +#include "moc_profilemanager1_p.cpp" diff --git a/src/bluetooth/bluez/profilemanager1_p.h b/src/bluetooth/bluez/profilemanager1_p.h new file mode 100644 index 0000000..a02af3b --- /dev/null +++ b/src/bluetooth/bluez/profilemanager1_p.h @@ -0,0 +1,73 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -I QtCore/private/qglobal_p.h -p profilemanager1_p.h:profilemanager1.cpp org.bluez.ProfileManager1.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#ifndef PROFILEMANAGER1_P_H +#define PROFILEMANAGER1_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 + +/* + * Proxy class for interface org.bluez.ProfileManager1 + */ +class OrgBluezProfileManager1Interface: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "org.bluez.ProfileManager1"; } + +public: + OrgBluezProfileManager1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); + + ~OrgBluezProfileManager1Interface(); + +public Q_SLOTS: // METHODS + inline QDBusPendingReply<> RegisterProfile(const QDBusObjectPath &profile, const QString &UUID, const QVariantMap &options) + { + QList argumentList; + argumentList << QVariant::fromValue(profile) << QVariant::fromValue(UUID) << QVariant::fromValue(options); + return asyncCallWithArgumentList(QStringLiteral("RegisterProfile"), argumentList); + } + + inline QDBusPendingReply<> UnregisterProfile(const QDBusObjectPath &profile) + { + QList argumentList; + argumentList << QVariant::fromValue(profile); + return asyncCallWithArgumentList(QStringLiteral("UnregisterProfile"), argumentList); + } + +Q_SIGNALS: // SIGNALS +}; + +namespace org { + namespace bluez { + using ProfileManager1 = ::OrgBluezProfileManager1Interface; + } +} +#endif diff --git a/src/bluetooth/bluez/properties.cpp b/src/bluetooth/bluez/properties.cpp new file mode 100644 index 0000000..0725d58 --- /dev/null +++ b/src/bluetooth/bluez/properties.cpp @@ -0,0 +1,28 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -I QtCore/private/qglobal_p.h -p properties_p.h:properties.cpp org.freedesktop.dbus.properties.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "properties_p.h" + +/* + * Implementation of interface class OrgFreedesktopDBusPropertiesInterface + */ + +OrgFreedesktopDBusPropertiesInterface::OrgFreedesktopDBusPropertiesInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +OrgFreedesktopDBusPropertiesInterface::~OrgFreedesktopDBusPropertiesInterface() +{ +} + + +#include "moc_properties_p.cpp" diff --git a/src/bluetooth/bluez/properties_p.h b/src/bluetooth/bluez/properties_p.h new file mode 100644 index 0000000..8328652 --- /dev/null +++ b/src/bluetooth/bluez/properties_p.h @@ -0,0 +1,84 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -I QtCore/private/qglobal_p.h -p properties_p.h:properties.cpp org.freedesktop.dbus.properties.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#ifndef PROPERTIES_P_H +#define PROPERTIES_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 + +/* + * Proxy class for interface org.freedesktop.DBus.Properties + */ +class OrgFreedesktopDBusPropertiesInterface: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "org.freedesktop.DBus.Properties"; } + +public: + OrgFreedesktopDBusPropertiesInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); + + ~OrgFreedesktopDBusPropertiesInterface(); + +public Q_SLOTS: // METHODS + inline QDBusPendingReply Get(const QString &interface, const QString &name) + { + QList argumentList; + argumentList << QVariant::fromValue(interface) << QVariant::fromValue(name); + return asyncCallWithArgumentList(QStringLiteral("Get"), argumentList); + } + + inline QDBusPendingReply GetAll(const QString &interface) + { + QList argumentList; + argumentList << QVariant::fromValue(interface); + return asyncCallWithArgumentList(QStringLiteral("GetAll"), argumentList); + } + + inline QDBusPendingReply<> Set(const QString &interface, const QString &name, const QDBusVariant &value) + { + QList argumentList; + argumentList << QVariant::fromValue(interface) << QVariant::fromValue(name) << QVariant::fromValue(value); + return asyncCallWithArgumentList(QStringLiteral("Set"), argumentList); + } + +Q_SIGNALS: // SIGNALS + void PropertiesChanged(const QString &interface, const QVariantMap &changed_properties, const QStringList &invalidated_properties, + const QDBusMessage &msg); +}; + +namespace org { + namespace freedesktop { + namespace DBus { + using Properties = ::OrgFreedesktopDBusPropertiesInterface; + } + } +} +#endif diff --git a/src/bluetooth/bluez/propertiesadaptor.cpp b/src/bluetooth/bluez/propertiesadaptor.cpp new file mode 100644 index 0000000..177f839 --- /dev/null +++ b/src/bluetooth/bluez/propertiesadaptor.cpp @@ -0,0 +1,56 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -a propertiesadaptor_p.h:propertiesadaptor.cpp -c OrgFreedesktopDBusPropertiesAdaptor -i bluez5_helper_p.h org.freedesktop.dbus.properties.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#include "propertiesadaptor_p.h" +#include +#include +#include +#include +#include +#include +#include + +/* + * Implementation of adaptor class OrgFreedesktopDBusPropertiesAdaptor + */ + +OrgFreedesktopDBusPropertiesAdaptor::OrgFreedesktopDBusPropertiesAdaptor(QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + // constructor + setAutoRelaySignals(true); +} + +OrgFreedesktopDBusPropertiesAdaptor::~OrgFreedesktopDBusPropertiesAdaptor() +{ + // destructor +} + +QDBusVariant OrgFreedesktopDBusPropertiesAdaptor::Get(const QString &interface, const QString &name) +{ + // handle method call org.freedesktop.DBus.Properties.Get + QDBusVariant value; + QMetaObject::invokeMethod(parent(), "Get", Q_RETURN_ARG(QDBusVariant, value), Q_ARG(QString, interface), Q_ARG(QString, name)); + return value; +} + +QVariantMap OrgFreedesktopDBusPropertiesAdaptor::GetAll(const QString &interface) +{ + // handle method call org.freedesktop.DBus.Properties.GetAll + QVariantMap properties; + QMetaObject::invokeMethod(parent(), "GetAll", Q_RETURN_ARG(QVariantMap, properties), Q_ARG(QString, interface)); + return properties; +} + +void OrgFreedesktopDBusPropertiesAdaptor::Set(const QString &interface, const QString &name, const QDBusVariant &value) +{ + // handle method call org.freedesktop.DBus.Properties.Set + QMetaObject::invokeMethod(parent(), "Set", Q_ARG(QString, interface), Q_ARG(QString, name), Q_ARG(QDBusVariant, value)); +} diff --git a/src/bluetooth/bluez/propertiesadaptor_p.h b/src/bluetooth/bluez/propertiesadaptor_p.h new file mode 100644 index 0000000..1be0fd0 --- /dev/null +++ b/src/bluetooth/bluez/propertiesadaptor_p.h @@ -0,0 +1,76 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -a propertiesadaptor_p.h:propertiesadaptor.cpp -c OrgFreedesktopDBusPropertiesAdaptor -i bluez5_helper_p.h org.freedesktop.dbus.properties.xml + * + * qdbusxml2cpp is Copyright (C) 2022 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#ifndef PROPERTIESADAPTOR_P_H +#define PROPERTIESADAPTOR_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 "bluez5_helper_p.h" +#include + +/* + * Adaptor class for interface org.freedesktop.DBus.Properties + */ +class OrgFreedesktopDBusPropertiesAdaptor: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.freedesktop.DBus.Properties") + Q_CLASSINFO("D-Bus Introspection", "" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" + "") +public: + OrgFreedesktopDBusPropertiesAdaptor(QObject *parent); + virtual ~OrgFreedesktopDBusPropertiesAdaptor(); + +public: // PROPERTIES +public Q_SLOTS: // METHODS + QDBusVariant Get(const QString &interface, const QString &name); + QVariantMap GetAll(const QString &interface); + void Set(const QString &interface, const QString &name, const QDBusVariant &value); +Q_SIGNALS: // SIGNALS + void PropertiesChanged(const QString &interface, const QVariantMap &changed_properties, const QStringList &invalidated_properties); +}; + +#endif diff --git a/src/bluetooth/bluez/remotedevicemanager.cpp b/src/bluetooth/bluez/remotedevicemanager.cpp new file mode 100644 index 0000000..e8b13ce --- /dev/null +++ b/src/bluetooth/bluez/remotedevicemanager.cpp @@ -0,0 +1,137 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include + +#include "remotedevicemanager_p.h" +#include "bluez5_helper_p.h" +#include "device1_bluez5_p.h" +#include "objectmanager_p.h" + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ) + +/*! + * Convenience wrapper around org.bluez.Device1 management + * + * Very simple and not thread safe. + */ + +RemoteDeviceManager::RemoteDeviceManager( + const QBluetoothAddress &address, QObject *parent) + : QObject(parent), localAddress(address) +{ + initializeBluez5(); + + bool ok = false; + adapterPath = findAdapterForAddress(address, &ok); + if (!ok || adapterPath.isEmpty()) { + qCWarning(QT_BT_BLUEZ) << "Cannot initialize RemoteDeviceManager"; + } +} + +bool RemoteDeviceManager::scheduleJob(JobType job, const QList &remoteDevices) +{ + if (adapterPath.isEmpty()) + return false; + + for (const auto& remote : remoteDevices) + jobQueue.push_back(std::make_pair(job, remote)); + + QTimer::singleShot(0, this, [this](){ runQueue(); }); + return true; +} + +void RemoteDeviceManager::runQueue() +{ + if (jobInProgress || adapterPath.isEmpty()) + return; + + if (jobQueue.empty()) + return; + + jobInProgress = true; + switch (jobQueue.front().first) { + case JobType::JobDisconnectDevice: + disconnectDevice(jobQueue.front().second); + break; + default: + break; + } +} + +void RemoteDeviceManager::prepareNextJob() +{ + Q_ASSERT(!jobQueue.empty()); + + jobQueue.pop_front(); + jobInProgress = false; + + qCDebug(QT_BT_BLUEZ) << "RemoteDeviceManager job queue status:" << jobQueue.empty(); + if (jobQueue.empty()) + emit finished(); + else + runQueue(); +} + +void RemoteDeviceManager::disconnectDevice(const QBluetoothAddress &remote) +{ + // collect initial set of information + OrgFreedesktopDBusObjectManagerInterface managerBluez5( + QStringLiteral("org.bluez"), + QStringLiteral("/"), + QDBusConnection::systemBus(), this); + QDBusPendingReply reply = managerBluez5.GetManagedObjects(); + reply.waitForFinished(); + if (reply.isError()) { + QTimer::singleShot(0, this, [this](){ prepareNextJob(); }); + return; + } + + bool jobStarted = false; + ManagedObjectList managedObjectList = reply.value(); + for (auto it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) { + const QDBusObjectPath &path = it.key(); + const InterfaceList &ifaceList = it.value(); + + for (auto jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) { + const QString &iface = jt.key(); + + if (path.path().indexOf(adapterPath) != 0) + continue; //devices whose path doesn't start with same path we skip + + if (iface != QStringLiteral("org.bluez.Device1")) + continue; + + const QBluetoothAddress foundAddress(ifaceList.value(iface).value(QStringLiteral("Address")).toString()); + if (foundAddress != remote) + continue; + + // found the correct Device1 path + OrgBluezDevice1Interface* device1 = new OrgBluezDevice1Interface(QStringLiteral("org.bluez"), + path.path(), + QDBusConnection::systemBus(), + this); + QDBusPendingReply<> asyncReply = device1->Disconnect(); + QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(asyncReply, this); + const auto watcherFinished = [this, device1](QDBusPendingCallWatcher* call) { + call->deleteLater(); + device1->deleteLater(); + prepareNextJob(); + }; + connect(watcher, &QDBusPendingCallWatcher::finished, this, watcherFinished); + jobStarted = true; + break; + } + } + + if (!jobStarted) { + qCDebug(QT_BT_BLUEZ) << "RemoteDeviceManager JobDisconnectDevice failed"; + QTimer::singleShot(0, this, [this](){ prepareNextJob(); }); + } +} + +QT_END_NAMESPACE + +#include "moc_remotedevicemanager_p.cpp" diff --git a/src/bluetooth/bluez/remotedevicemanager_p.h b/src/bluetooth/bluez/remotedevicemanager_p.h new file mode 100644 index 0000000..a41b145 --- /dev/null +++ b/src/bluetooth/bluez/remotedevicemanager_p.h @@ -0,0 +1,64 @@ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef REMOTEDEVICEMANAGER_P_H +#define REMOTEDEVICEMANAGER_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 + + +QT_BEGIN_NAMESPACE + +// This API is kept a bit more generic in anticipation of further changes in the future. + +class RemoteDeviceManager : public QObject +{ + Q_OBJECT +public: + enum class JobType + { + JobDisconnectDevice, + }; + + explicit RemoteDeviceManager(const QBluetoothAddress& localAddress, QObject *parent = nullptr); + + bool isJobInProgress() const { return jobInProgress; } + bool scheduleJob(JobType job, const QList &remoteDevices); + +signals: + void finished(); + +private slots: + void runQueue(); + void prepareNextJob(); + +private: + void disconnectDevice(const QBluetoothAddress& remote); + + bool jobInProgress = false; + QBluetoothAddress localAddress; + std::deque> jobQueue; + QString adapterPath; +}; + +QT_END_NAMESPACE + +#endif // REMOTEDEVICEMANAGER_P_H diff --git a/src/bluetooth/bluez/servicemap.cpp b/src/bluetooth/bluez/servicemap.cpp new file mode 100644 index 0000000..8a8b6f4 --- /dev/null +++ b/src/bluetooth/bluez/servicemap.cpp @@ -0,0 +1,31 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "servicemap_p.h" + +QT_BEGIN_NAMESPACE + +QT_IMPL_METATYPE_EXTERN(ServiceMap) + +const QDBusArgument &operator>>(const QDBusArgument &argument, ServiceMap &serviceMap) +{ + argument.beginMap(); + + while (!argument.atEnd()) { + quint32 uuid; + QString service; + + argument.beginMapEntry(); + argument >> uuid; + argument >> service; + argument.endMapEntry(); + + serviceMap.insert(uuid, service); + } + + argument.endMap(); + + return argument; +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/bluez/servicemap_p.h b/src/bluetooth/bluez/servicemap_p.h new file mode 100644 index 0000000..773f9d0 --- /dev/null +++ b/src/bluetooth/bluez/servicemap_p.h @@ -0,0 +1,35 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef SERVICEMAP_P_H +#define SERVICEMAP_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 + +typedef QMap ServiceMap; + +const QDBusArgument &operator>>(const QDBusArgument &argument, ServiceMap &serviceMap); + +QT_END_NAMESPACE + +QT_DECL_METATYPE_EXTERN(ServiceMap, Q_BLUETOOTH_EXPORT) + +#endif // SERVICEMAP_P_H diff --git a/src/bluetooth/configure.cmake b/src/bluetooth/configure.cmake new file mode 100644 index 0000000..a3ae873 --- /dev/null +++ b/src/bluetooth/configure.cmake @@ -0,0 +1,76 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + + + +#### Inputs + + + +#### Libraries + +qt_find_package(BlueZ PROVIDED_TARGETS PkgConfig::BLUEZ) + + +#### Tests + +if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../../config.tests/bluez/CMakeLists.txt") + qt_config_compile_test("bluez" + LABEL "BlueZ" + PROJECT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../config.tests/bluez") +endif() + +if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../../config.tests/bluez_le/CMakeLists.txt") + qt_config_compile_test("bluez_le" + LABEL "BlueZ Low Energy" + PROJECT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../config.tests/bluez_le") +endif() + +if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../../config.tests/linux_crypto_api/CMakeLists.txt") + qt_config_compile_test("linux_crypto_api" + LABEL "Linux Crypto API" + PROJECT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../config.tests/linux_crypto_api") +endif() + +if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../../config.tests/winrt_bt/CMakeLists.txt") + qt_config_compile_test("winrt_bt" + LABEL "WinRT Bluetooth API" + PROJECT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../config.tests/winrt_bt") +endif() + + +#### Features + +qt_feature("bluez" PUBLIC + LABEL "BlueZ" + CONDITION BLUEZ_FOUND AND TEST_bluez AND QT_FEATURE_dbus +) +qt_feature("bluez_le" PRIVATE + LABEL "BlueZ Low Energy" + CONDITION QT_FEATURE_bluez AND TEST_bluez_le +) +qt_feature("linux_crypto_api" PRIVATE + LABEL "Linux Crypto API" + CONDITION QT_FEATURE_bluez_le AND TEST_linux_crypto_api +) +qt_feature("winrt_bt" PRIVATE + LABEL "WinRT Bluetooth API" + CONDITION WIN32 AND TEST_winrt_bt +) + +qt_configure_add_summary_section(NAME "Qt Bluetooth") +qt_configure_add_summary_entry(ARGS bluez) +qt_configure_add_summary_entry(ARGS bluez_le) +qt_configure_add_summary_entry(ARGS linux_crypto_api) +qt_configure_add_summary_entry(ARGS winrt_bt) +qt_configure_end_summary_section() +qt_configure_add_report_entry( + TYPE NOTE + MESSAGE "Bluez version is too old to support Bluetooth Low Energy. Only classic Bluetooth will be available." + CONDITION QT_FEATURE_bluez AND NOT QT_FEATURE_bluez_le +) +qt_configure_add_report_entry( + TYPE NOTE + MESSAGE "Linux crypto API not present. BTLE signed writes will not work." + CONDITION QT_FEATURE_bluez_le AND NOT QT_FEATURE_linux_crypto_api +) diff --git a/src/bluetooth/darwin/btcentralmanager.mm b/src/bluetooth/darwin/btcentralmanager.mm new file mode 100644 index 0000000..55eaf2a --- /dev/null +++ b/src/bluetooth/darwin/btcentralmanager.mm @@ -0,0 +1,1880 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qlowenergyserviceprivate_p.h" +#include "qlowenergycharacteristic.h" +#include "qlowenergycontroller.h" +#include "btcentralmanager_p.h" +#include "btnotifier_p.h" + +#include +#include +#include + +#include +#include +#include + +Q_DECLARE_METATYPE(QLowEnergyHandle) + +QT_BEGIN_NAMESPACE + +namespace DarwinBluetooth { + +NSUInteger qt_countGATTEntries(CBService *service) +{ + // Identify, how many characteristics/descriptors we have on a given service, + // +1 for the service itself. + // No checks if NSUInteger is big enough :) + // Let's assume such number of entries is not possible :) + + Q_ASSERT_X(service, Q_FUNC_INFO, "invalid service (nil)"); + + QT_BT_MAC_AUTORELEASEPOOL; + + NSArray *const cs = service.characteristics; + if (!cs || !cs.count) + return 1; + + NSUInteger n = 1 + cs.count; + for (CBCharacteristic *c in cs) { + NSArray *const ds = c.descriptors; + if (ds) + n += ds.count; + } + + return n; +} + +ObjCStrongReference qt_timeoutNSError(OperationTimeout type) +{ + // For now we do not provide details, since nobody is using this NSError + // after all (except callbacks checking if an operation was successful + // or not). + Q_ASSERT(type != OperationTimeout::none); + Q_UNUSED(type); + NSError *nsError = [[NSError alloc] initWithDomain:CBErrorDomain + code:CBErrorOperationCancelled + userInfo:nil]; + return ObjCStrongReference(nsError, RetainPolicy::noInitialRetain); +} + +auto qt_find_watchdog(const std::vector &watchdogs, id object, OperationTimeout type) +{ + return std::find_if(watchdogs.begin(), watchdogs.end(), [object, type](const GCDTimer &other){ + return [other objectUnderWatch] == object && [other timeoutType] == type;}); +} + +} // namespace DarwinBluetooth + +QT_END_NAMESPACE + +QT_USE_NAMESPACE + +@interface DarwinBTCentralManager (PrivateAPI) + +- (void)watchAfter:(id)object timeout:(DarwinBluetooth::OperationTimeout)type; +- (bool)objectIsUnderWatch:(id)object operation:(DarwinBluetooth::OperationTimeout)type; +- (void)stopWatchingAfter:(id)object operation:(DarwinBluetooth::OperationTimeout)type; +- (void)stopWatchers; +- (void)retrievePeripheralAndConnect; +- (void)connectToPeripheral; +- (void)discoverIncludedServices; +- (void)readCharacteristics:(CBService *)service; +- (void)serviceDetailsDiscoveryFinished:(CBService *)service; +- (void)performNextRequest; +- (void)performNextReadRequest; +- (void)performNextWriteRequest; + +// Aux. functions. +- (CBService *)serviceForUUID:(const QBluetoothUuid &)qtUuid; +- (CBCharacteristic *)nextCharacteristicForService:(CBService*)service + startingFrom:(CBCharacteristic *)from; +- (CBCharacteristic *)nextCharacteristicForService:(CBService*)service + startingFrom:(CBCharacteristic *)from + withProperties:(CBCharacteristicProperties)properties; +- (CBDescriptor *)nextDescriptorForCharacteristic:(CBCharacteristic *)characteristic + startingFrom:(CBDescriptor *)descriptor; +- (CBDescriptor *)descriptor:(const QBluetoothUuid &)dUuid + forCharacteristic:(CBCharacteristic *)ch; +- (bool)cacheWriteValue:(const QByteArray &)value for:(NSObject *)obj; +- (void)handleReadWriteError:(NSError *)error; +- (void)reset; + +@end + +using DiscoveryMode = QLowEnergyService::DiscoveryMode; + +@implementation DarwinBTCentralManager +{ +@private + CBCentralManager *manager; + DarwinBluetooth::CentralManagerState managerState; + bool disconnectPending; + + QBluetoothUuid deviceUuid; + + DarwinBluetooth::LECBManagerNotifier *notifier; + + // Quite a verbose service discovery machinery + // (a "graph traversal"). + DarwinBluetooth::ObjCStrongReference servicesToVisit; + // The service we're discovering now (included services discovery): + NSUInteger currentService; + // Included services, we'll iterate through at the end of 'servicesToVisit': + DarwinBluetooth::ObjCStrongReference servicesToVisitNext; + // We'd like to avoid loops in a services' topology: + DarwinBluetooth::ObjCStrongReference visitedServices; + + QMap servicesToDiscoverDetails; + + DarwinBluetooth::ServiceHash serviceMap; + DarwinBluetooth::CharHash charMap; + DarwinBluetooth::DescHash descMap; + + QLowEnergyHandle lastValidHandle; + + bool requestPending; + DarwinBluetooth::RequestQueue requests; + QLowEnergyHandle currentReadHandle; + + DarwinBluetooth::ValueHash valuesToWrite; + + qint64 timeoutMS; + std::vector timeoutWatchdogs; + + CBPeripheral *peripheral; + int lastKnownMtu; +} + +- (id)initWith:(DarwinBluetooth::LECBManagerNotifier *)aNotifier +{ + using namespace DarwinBluetooth; + + if (self = [super init]) { + manager = nil; + managerState = CentralManagerIdle; + disconnectPending = false; + peripheral = nil; + notifier = aNotifier; + currentService = 0; + lastValidHandle = 0; + requestPending = false; + currentReadHandle = 0; + + if (Q_UNLIKELY(!qEnvironmentVariableIsEmpty("BLUETOOTH_GATT_TIMEOUT"))) { + bool ok = false; + const int value = qEnvironmentVariableIntValue("BLUETOOTH_GATT_TIMEOUT", &ok); + if (ok && value >= 0) + timeoutMS = value; + } + + if (!timeoutMS) + timeoutMS = 20000; + + lastKnownMtu = defaultMtu; + } + + return self; +} + +- (void)dealloc +{ + // In the past I had a 'transient delegate': I've seen some crashes + // while deleting a manager _before_ its state updated. + // Strangely enough, I can not reproduce this anymore, so this + // part is simplified now. To be investigated though. + + visitedServices.reset(); + servicesToVisit.reset(); + servicesToVisitNext.reset(); + + [manager setDelegate:nil]; + [manager release]; + + [peripheral setDelegate:nil]; + [peripheral release]; + + if (notifier) + notifier->deleteLater(); + + [self stopWatchers]; + [super dealloc]; +} + +- (CBPeripheral *)peripheral +{ + return peripheral; +} + +- (void)watchAfter:(id)object timeout:(DarwinBluetooth::OperationTimeout)type +{ + using namespace DarwinBluetooth; + + GCDTimer newWatcher([[DarwinBTGCDTimer alloc] initWithDelegate:self], RetainPolicy::noInitialRetain); + [newWatcher watchAfter:object withTimeoutType:type]; + timeoutWatchdogs.push_back(newWatcher); + [newWatcher startWithTimeout:timeoutMS step:200]; +} + +- (bool)objectIsUnderWatch:(id)object operation:(DarwinBluetooth::OperationTimeout)type +{ + return DarwinBluetooth::qt_find_watchdog(timeoutWatchdogs, object, type) != timeoutWatchdogs.end(); +} + +- (void)stopWatchingAfter:(id)object operation:(DarwinBluetooth::OperationTimeout)type +{ + auto pos = DarwinBluetooth::qt_find_watchdog(timeoutWatchdogs, object, type); + if (pos != timeoutWatchdogs.end()) { + [*pos cancelTimer]; + timeoutWatchdogs.erase(pos); + } +} + +- (void)stopWatchers +{ + for (auto &watchdog : timeoutWatchdogs) + [watchdog cancelTimer]; + timeoutWatchdogs.clear(); +} + +- (void)timeout:(id)sender +{ + Q_UNUSED(sender); + + using namespace DarwinBluetooth; + + DarwinBTGCDTimer *watcher = static_cast(sender); + id cbObject = [watcher objectUnderWatch]; + const OperationTimeout type = [watcher timeoutType]; + + Q_ASSERT([self objectIsUnderWatch:cbObject operation:type]); + + NSLog(@"Timeout caused by: %@", cbObject); + + // Note that after this switch the 'watcher' is released (we don't + // own it anymore), though GCD is probably still holding a reference. + const ObjCStrongReference nsError(qt_timeoutNSError(type)); + switch (type) { + case OperationTimeout::serviceDiscovery: + qCWarning(QT_BT_DARWIN, "Timeout in services discovery"); + [self peripheral:peripheral didDiscoverServices:nsError]; + break; + case OperationTimeout::includedServicesDiscovery: + qCWarning(QT_BT_DARWIN, "Timeout in included services discovery"); + [self peripheral:peripheral didDiscoverIncludedServicesForService:cbObject error:nsError]; + break; + case OperationTimeout::characteristicsDiscovery: + qCWarning(QT_BT_DARWIN, "Timeout in characteristics discovery"); + [self peripheral:peripheral didDiscoverCharacteristicsForService:cbObject error:nsError]; + break; + case OperationTimeout::characteristicRead: + qCWarning(QT_BT_DARWIN, "Timeout while reading a characteristic"); + [self peripheral:peripheral didUpdateValueForCharacteristic:cbObject error:nsError]; + break; + case OperationTimeout::descriptorsDiscovery: + qCWarning(QT_BT_DARWIN, "Timeout in descriptors discovery"); + [self peripheral:peripheral didDiscoverDescriptorsForCharacteristic:cbObject error:nsError]; + break; + case OperationTimeout::descriptorRead: + qCWarning(QT_BT_DARWIN, "Timeout while reading a descriptor"); + [self peripheral:peripheral didUpdateValueForDescriptor:cbObject error:nsError]; + break; + case OperationTimeout::characteristicWrite: + qCWarning(QT_BT_DARWIN, "Timeout while writing a characteristic with response"); + [self peripheral:peripheral didWriteValueForCharacteristic:cbObject error:nsError]; + default:; + } +} + +- (void)connectToDevice:(const QBluetoothUuid &)aDeviceUuid +{ + disconnectPending = false; // Cancel the previous disconnect if any. + deviceUuid = aDeviceUuid; + + if (!manager) { + // The first time we try to connect, no manager created yet, + // no status update received. + if (const dispatch_queue_t leQueue = DarwinBluetooth::qt_LE_queue()) { + managerState = DarwinBluetooth::CentralManagerUpdating; + manager = [[CBCentralManager alloc] initWithDelegate:self queue:leQueue]; + } + + if (!manager) { + managerState = DarwinBluetooth::CentralManagerIdle; + qCWarning(QT_BT_DARWIN) << "failed to allocate a central manager"; + if (notifier) + emit notifier->CBManagerError(QLowEnergyController::ConnectionError); + } + } else if (managerState != DarwinBluetooth::CentralManagerUpdating) { + [self retrievePeripheralAndConnect]; + } +} + +- (void)retrievePeripheralAndConnect +{ + Q_ASSERT_X(manager, Q_FUNC_INFO, "invalid central manager (nil)"); + Q_ASSERT_X(managerState == DarwinBluetooth::CentralManagerIdle, + Q_FUNC_INFO, "invalid state"); + + if ([self isConnected]) { + qCDebug(QT_BT_DARWIN) << "already connected"; + if (notifier) + emit notifier->connected(); + return; + } else if (peripheral) { + // Was retrieved already, but not connected + // or disconnected. + [self connectToPeripheral]; + return; + } + + using namespace DarwinBluetooth; + + // Retrieve a peripheral first ... + const ObjCScopedPointer uuids([[NSMutableArray alloc] init], RetainPolicy::noInitialRetain); + if (!uuids) { + qCWarning(QT_BT_DARWIN) << "failed to allocate identifiers"; + if (notifier) + emit notifier->CBManagerError(QLowEnergyController::ConnectionError); + return; + } + + + const QUuid::Id128Bytes qtUuidData(deviceUuid.toBytes()); + uuid_t uuidData = {}; + std::copy(qtUuidData.data, qtUuidData.data + 16, uuidData); + const ObjCScopedPointer nsUuid([[NSUUID alloc] initWithUUIDBytes:uuidData], RetainPolicy::noInitialRetain); + if (!nsUuid) { + qCWarning(QT_BT_DARWIN) << "failed to allocate NSUUID identifier"; + if (notifier) + emit notifier->CBManagerError(QLowEnergyController::ConnectionError); + return; + } + + [uuids addObject:nsUuid]; + // With the latest CoreBluetooth, we can synchronously retrieve peripherals: + QT_BT_MAC_AUTORELEASEPOOL; + NSArray *const peripherals = [manager retrievePeripheralsWithIdentifiers:uuids]; + if (!peripherals || peripherals.count != 1) { + qCWarning(QT_BT_DARWIN) << "failed to retrieve a peripheral"; + if (notifier) + emit notifier->CBManagerError(QLowEnergyController::UnknownRemoteDeviceError); + return; + } + + peripheral = [static_cast([peripherals objectAtIndex:0]) retain]; + [self connectToPeripheral]; +} + +- (void)connectToPeripheral +{ + using namespace DarwinBluetooth; + + Q_ASSERT_X(manager, Q_FUNC_INFO, "invalid central manager (nil)"); + Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)"); + Q_ASSERT_X(managerState == CentralManagerIdle, Q_FUNC_INFO, "invalid state"); + + // The state is still the same - connecting. + if ([self isConnected]) { + qCDebug(QT_BT_DARWIN) << "already connected"; + if (notifier) + emit notifier->connected(); + } else { + [self setMtu:defaultMtu]; + qCDebug(QT_BT_DARWIN) << "trying to connect"; + managerState = CentralManagerConnecting; + [manager connectPeripheral:peripheral options:nil]; + } +} + +- (bool)isConnected +{ + if (!peripheral) + return false; + + return peripheral.state == CBPeripheralStateConnected; +} + +- (void)disconnectFromDevice +{ + [self reset]; + + if (managerState == DarwinBluetooth::CentralManagerUpdating) { + disconnectPending = true; // this is for 'didUpdate' method. + if (notifier) { + // We were waiting for the first update + // with 'PoweredOn' status, when suddenly got disconnected called. + // Since we have not attempted to connect yet, emit now. + // Note: we do not change the state, since we still maybe interested + // in the status update before the next connect attempt. + emit notifier->disconnected(); + } + } else { + disconnectPending = false; + if ([self isConnected]) + managerState = DarwinBluetooth::CentralManagerDisconnecting; + else + managerState = DarwinBluetooth::CentralManagerIdle; + + // We have to call -cancelPeripheralConnection: even + // if not connected (to cancel a pending connect attempt). + // Unfortunately, didDisconnect callback is not always called + // (despite of Apple's docs saying it _must_ be). + if (peripheral) + [manager cancelPeripheralConnection:peripheral]; + } +} + +- (void)discoverServices +{ + using namespace DarwinBluetooth; + + Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)"); + Q_ASSERT_X(managerState == CentralManagerIdle, Q_FUNC_INFO, "invalid state"); + + // From Apple's docs: + // + //"If the servicesUUIDs parameter is nil, all the available + //services of the peripheral are returned; setting the + //parameter to nil is considerably slower and is not recommended." + // + // ... but we'd like to have them all: + managerState = CentralManagerDiscovering; + [self watchAfter:peripheral timeout:OperationTimeout::serviceDiscovery]; + [peripheral discoverServices:nil]; +} + +- (void)discoverIncludedServices +{ + using namespace DarwinBluetooth; + + Q_ASSERT_X(managerState == CentralManagerIdle, Q_FUNC_INFO, "invalid state"); + Q_ASSERT_X(manager, Q_FUNC_INFO, "invalid manager (nil)"); + Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)"); + + QT_BT_MAC_AUTORELEASEPOOL; + + NSArray *const services = peripheral.services; + if (!services || !services.count) { + // A peripheral without any services at all. + if (notifier) + emit notifier->serviceDiscoveryFinished(); + } else { + // 'reset' also calls retain on a parameter. + servicesToVisitNext.reset(); + servicesToVisit.reset([NSMutableArray arrayWithArray:services], RetainPolicy::doInitialRetain); + currentService = 0; + visitedServices.reset([NSMutableSet setWithCapacity:peripheral.services.count], RetainPolicy::doInitialRetain); + + CBService *const s = [services objectAtIndex:currentService]; + [visitedServices addObject:s]; + managerState = CentralManagerDiscovering; + [self watchAfter:s timeout:OperationTimeout::includedServicesDiscovery]; + [peripheral discoverIncludedServices:nil forService:s]; + } +} + +- (void)discoverServiceDetails:(const QBluetoothUuid &)serviceUuid + readValues:(bool) read +{ + // This function does not change 'managerState', since it + // can be called concurrently (not waiting for the previous + // discovery to finish). + + using namespace DarwinBluetooth; + + Q_ASSERT_X(managerState != CentralManagerUpdating, Q_FUNC_INFO, "invalid state"); + Q_ASSERT_X(!serviceUuid.isNull(), Q_FUNC_INFO, "invalid service UUID"); + Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)"); + + if (servicesToDiscoverDetails.contains(serviceUuid)) { + qCWarning(QT_BT_DARWIN) << "already discovering for" + << serviceUuid; + return; + } + + QT_BT_MAC_AUTORELEASEPOOL; + + if (CBService *const service = [self serviceForUUID:serviceUuid]) { + const auto mode = read ? DiscoveryMode::FullDiscovery : DiscoveryMode::SkipValueDiscovery; + servicesToDiscoverDetails[serviceUuid] = mode; + [self watchAfter:service timeout:OperationTimeout::characteristicsDiscovery]; + [peripheral discoverCharacteristics:nil forService:service]; + return; + } + + qCWarning(QT_BT_DARWIN) << "unknown service uuid" + << serviceUuid; + + if (notifier) + emit notifier->CBManagerError(serviceUuid, QLowEnergyService::UnknownError); +} + +- (void)readCharacteristics:(CBService *)service +{ + // This method does not change 'managerState', we can + // have several 'detail discoveries' active. + Q_ASSERT_X(service, Q_FUNC_INFO, "invalid service (nil)"); + + using namespace DarwinBluetooth; + + QT_BT_MAC_AUTORELEASEPOOL; + + Q_ASSERT_X(managerState != CentralManagerUpdating, Q_FUNC_INFO, "invalid state"); + Q_ASSERT_X(manager, Q_FUNC_INFO, "invalid manager (nil)"); + Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)"); + + if (!service.characteristics || !service.characteristics.count) + return [self serviceDetailsDiscoveryFinished:service]; + + NSArray *const cs = service.characteristics; + for (CBCharacteristic *c in cs) { + if (c.properties & CBCharacteristicPropertyRead) { + [self watchAfter:c timeout:OperationTimeout::characteristicRead]; + return [peripheral readValueForCharacteristic:c]; + } + } + + // No readable properties? Discover descriptors then: + [self discoverDescriptors:service]; +} + +- (void)discoverDescriptors:(CBService *)service +{ + // This method does not change 'managerState', we can have + // several discoveries active. + Q_ASSERT_X(service, Q_FUNC_INFO, "invalid service (nil)"); + + using namespace DarwinBluetooth; + + QT_BT_MAC_AUTORELEASEPOOL; + + Q_ASSERT_X(managerState != CentralManagerUpdating, + Q_FUNC_INFO, "invalid state"); + Q_ASSERT_X(manager, Q_FUNC_INFO, "invalid manager (nil)"); + Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)"); + + if (!service.characteristics || !service.characteristics.count) { + [self serviceDetailsDiscoveryFinished:service]; + } else { + // Start from 0 and continue in the callback. + CBCharacteristic *ch = [service.characteristics objectAtIndex:0]; + [self watchAfter:ch timeout:OperationTimeout::descriptorsDiscovery]; + [peripheral discoverDescriptorsForCharacteristic:ch]; + } +} + +- (void)readDescriptors:(CBService *)service +{ + using namespace DarwinBluetooth; + + Q_ASSERT_X(service, Q_FUNC_INFO, "invalid service (nil)"); + Q_ASSERT_X(managerState != CentralManagerUpdating, Q_FUNC_INFO, "invalid state"); + Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)"); + + QT_BT_MAC_AUTORELEASEPOOL; + + NSArray *const cs = service.characteristics; + // We can never be here if we have no characteristics. + Q_ASSERT_X(cs && cs.count, Q_FUNC_INFO, "invalid service"); + for (CBCharacteristic *c in cs) { + if (c.descriptors && c.descriptors.count) { + CBDescriptor *desc = [c.descriptors objectAtIndex:0]; + [self watchAfter:desc timeout:OperationTimeout::descriptorRead]; + return [peripheral readValueForDescriptor:desc]; + } + } + + // No descriptors to read, done. + [self serviceDetailsDiscoveryFinished:service]; +} + +- (void)serviceDetailsDiscoveryFinished:(CBService *)service +{ + Q_ASSERT_X(service, Q_FUNC_INFO, "invalid service (nil)"); + + using namespace DarwinBluetooth; + + QT_BT_MAC_AUTORELEASEPOOL; + + const QBluetoothUuid serviceUuid(qt_uuid(service.UUID)); + const bool skipValues = servicesToDiscoverDetails[serviceUuid] == DiscoveryMode::SkipValueDiscovery; + servicesToDiscoverDetails.remove(serviceUuid); + + const NSUInteger nHandles = qt_countGATTEntries(service); + Q_ASSERT_X(nHandles, Q_FUNC_INFO, "unexpected number of GATT entires"); + + const QLowEnergyHandle maxHandle = std::numeric_limits::max(); + if (nHandles >= maxHandle || lastValidHandle > maxHandle - nHandles) { + // Well, that's unlikely :) But we must be sure. + qCWarning(QT_BT_DARWIN) << "can not allocate more handles"; + if (notifier) + notifier->CBManagerError(serviceUuid, QLowEnergyService::OperationError); + return; + } + + // A temporary service object to pass the details. + // Set only uuid, characteristics and descriptors (and probably values), + // nothing else is needed. + QSharedPointer qtService(new QLowEnergyServicePrivate); + qtService->uuid = serviceUuid; + // We 'register' handles/'CBentities' even if qlowenergycontroller (delegate) + // later fails to do this with some error. Otherwise, if we try to implement + // rollback/transaction logic interface is getting too ugly/complicated. + ++lastValidHandle; + serviceMap[lastValidHandle] = service; + qtService->startHandle = lastValidHandle; + + NSArray *const cs = service.characteristics; + // Now map chars/descriptors and handles. + if (cs && cs.count) { + QHash charList; + + for (CBCharacteristic *c in cs) { + ++lastValidHandle; + // Register this characteristic: + charMap[lastValidHandle] = c; + // Create a Qt's internal characteristic: + QLowEnergyServicePrivate::CharData newChar = {}; + newChar.uuid = qt_uuid(c.UUID); + const int cbProps = c.properties & 0xff; + newChar.properties = static_cast(cbProps); + if (!skipValues) + newChar.value = qt_bytearray(c.value); + newChar.valueHandle = lastValidHandle; + + NSArray *const ds = c.descriptors; + if (ds && ds.count) { + QHash descList; + for (CBDescriptor *d in ds) { + // Register this descriptor: + ++lastValidHandle; + descMap[lastValidHandle] = d; + // Create a Qt's internal descriptor: + QLowEnergyServicePrivate::DescData newDesc = {}; + newDesc.uuid = qt_uuid(d.UUID); + newDesc.value = qt_bytearray(static_cast(d.value)); + descList[lastValidHandle] = newDesc; + // Check, if it's client characteristic configuration descriptor: + if (newDesc.uuid == QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration) { + if (newDesc.value.size() && (newDesc.value[0] & 3)) + [peripheral setNotifyValue:YES forCharacteristic:c]; + } + } + + newChar.descriptorList = descList; + } + + charList[newChar.valueHandle] = newChar; + } + + qtService->characteristicList = charList; + } + + qtService->endHandle = lastValidHandle; + + if (notifier) + emit notifier->serviceDetailsDiscoveryFinished(qtService); +} + +- (void)performNextRequest +{ + using namespace DarwinBluetooth; + + if (requestPending || !requests.size()) + return; + + switch (requests.head().type) { + case LERequest::CharRead: + case LERequest::DescRead: + return [self performNextReadRequest]; + case LERequest::CharWrite: + case LERequest::DescWrite: + case LERequest::ClientConfiguration: + return [self performNextWriteRequest]; + default: + // Should never happen. + Q_ASSERT(0); + } +} + +- (void)performNextReadRequest +{ + using namespace DarwinBluetooth; + + Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)"); + Q_ASSERT_X(!requestPending, Q_FUNC_INFO, "processing another request"); + Q_ASSERT_X(requests.size(), Q_FUNC_INFO, "no requests to handle"); + Q_ASSERT_X(requests.head().type == LERequest::CharRead + || requests.head().type == LERequest::DescRead, + Q_FUNC_INFO, "not a read request"); + + const LERequest request(requests.dequeue()); + if (request.type == LERequest::CharRead) { + if (!charMap.contains(request.handle)) { + qCWarning(QT_BT_DARWIN) << "characteristic with handle" + << request.handle << "not found"; + return [self performNextRequest]; + } + + requestPending = true; + currentReadHandle = request.handle; + // Timeouts: for now, we do not alert timeoutWatchdog - never had such + // bug reports and after all a read timeout can be handled externally. + [peripheral readValueForCharacteristic:charMap[request.handle]]; + } else { + if (!descMap.contains(request.handle)) { + qCWarning(QT_BT_DARWIN) << "descriptor with handle" + << request.handle << "not found"; + return [self performNextRequest]; + } + + requestPending = true; + currentReadHandle = request.handle; + // Timeouts: see the comment above (CharRead). + [peripheral readValueForDescriptor:descMap[request.handle]]; + } +} + +- (void)performNextWriteRequest +{ + using namespace DarwinBluetooth; + + Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)"); + Q_ASSERT_X(!requestPending, Q_FUNC_INFO, "processing another request"); + Q_ASSERT_X(requests.size(), Q_FUNC_INFO, "no requests to handle"); + Q_ASSERT_X(requests.head().type == LERequest::CharWrite + || requests.head().type == LERequest::DescWrite + || requests.head().type == LERequest::ClientConfiguration, + Q_FUNC_INFO, "not a write request"); + + const LERequest request(requests.dequeue()); + + if (request.type == LERequest::DescWrite) { + if (!descMap.contains(request.handle)) { + qCWarning(QT_BT_DARWIN) << "handle:" << request.handle + << "not found"; + return [self performNextRequest]; + } + + CBDescriptor *const descriptor = descMap[request.handle]; + ObjCStrongReference data(data_from_bytearray(request.value)); + if (!data) { + // Even if qtData.size() == 0, we still need NSData object. + qCWarning(QT_BT_DARWIN) << "failed to allocate an NSData object"; + return [self performNextRequest]; + } + + if (![self cacheWriteValue:request.value for:descriptor]) + return [self performNextRequest]; + + requestPending = true; + return [peripheral writeValue:data.data() forDescriptor:descriptor]; + } else { + if (!charMap.contains(request.handle)) { + qCWarning(QT_BT_DARWIN) << "characteristic with handle:" + << request.handle << "not found"; + return [self performNextRequest]; + } + + CBCharacteristic *const characteristic = charMap[request.handle]; + + if (request.type == LERequest::ClientConfiguration) { + const QBluetoothUuid qtUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration); + CBDescriptor *const descriptor = [self descriptor:qtUuid forCharacteristic:characteristic]; + Q_ASSERT_X(descriptor, Q_FUNC_INFO, "no client characteristic " + "configuration descriptor found"); + + if (![self cacheWriteValue:request.value for:descriptor]) + return [self performNextRequest]; + + bool enable = false; + if (request.value.size()) + enable = request.value[0] & 3; + + requestPending = true; + [peripheral setNotifyValue:enable forCharacteristic:characteristic]; + } else { + ObjCStrongReference data(data_from_bytearray(request.value)); + if (!data) { + // Even if qtData.size() == 0, we still need NSData object. + qCWarning(QT_BT_DARWIN) << "failed to allocate NSData object"; + return [self performNextRequest]; + } + + // TODO: check what happens if I'm using NSData with length 0. + if (request.withResponse) { + if (![self cacheWriteValue:request.value for:characteristic]) + return [self performNextRequest]; + + requestPending = true; + [self watchAfter:characteristic timeout:OperationTimeout::characteristicWrite]; + [peripheral writeValue:data.data() forCharacteristic:characteristic + type:CBCharacteristicWriteWithResponse]; + } else { + [peripheral writeValue:data.data() forCharacteristic:characteristic + type:CBCharacteristicWriteWithoutResponse]; + [self performNextRequest]; + } + } + } +} + +- (void)setMtu:(int)newMtu +{ + if (lastKnownMtu == newMtu) + return; + lastKnownMtu = newMtu; + if (notifier) + emit notifier->mtuChanged(newMtu); +} + +- (int)mtu +{ + using namespace DarwinBluetooth; + + if (![self isConnected]) { + [self setMtu:defaultMtu]; + return defaultMtu; + } + + Q_ASSERT(peripheral); + const NSUInteger maxLen = [peripheral maximumWriteValueLengthForType: + CBCharacteristicWriteWithoutResponse]; + if (maxLen > std::numeric_limits::max() - 3) + [self setMtu:defaultMtu]; + else + [self setMtu:int(maxLen) + 3]; + + return lastKnownMtu; +} + +- (void)readRssi +{ + Q_ASSERT([self isConnected]); + [peripheral readRSSI]; +} + +- (void)setNotifyValue:(const QByteArray &)value + forCharacteristic:(QLowEnergyHandle)charHandle + onService:(const QBluetoothUuid &)serviceUuid +{ + using namespace DarwinBluetooth; + + Q_ASSERT_X(charHandle, Q_FUNC_INFO, "invalid characteristic handle (0)"); + + if (!charMap.contains(charHandle)) { + qCWarning(QT_BT_DARWIN) << "unknown characteristic handle" + << charHandle; + if (notifier) { + emit notifier->CBManagerError(serviceUuid, + QLowEnergyService::DescriptorWriteError); + } + return; + } + + // At the moment we call setNotifyValue _only_ from 'writeDescriptor'; + // from Qt's API POV it's a descriptor write operation and we must report + // it back, so check _now_ that we really have this descriptor. + const QBluetoothUuid qtUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration); + if (![self descriptor:qtUuid forCharacteristic:charMap[charHandle]]) { + qCWarning(QT_BT_DARWIN) << "no client characteristic configuration found"; + if (notifier) { + emit notifier->CBManagerError(serviceUuid, + QLowEnergyService::DescriptorWriteError); + } + return; + } + + LERequest request; + request.type = LERequest::ClientConfiguration; + request.handle = charHandle; + request.value = value; + + requests.enqueue(request); + [self performNextRequest]; +} + +- (void)readCharacteristic:(QLowEnergyHandle)charHandle + onService:(const QBluetoothUuid &)serviceUuid +{ + using namespace DarwinBluetooth; + + Q_ASSERT_X(charHandle, Q_FUNC_INFO, "invalid characteristic handle (0)"); + + QT_BT_MAC_AUTORELEASEPOOL; + + if (!charMap.contains(charHandle)) { + qCWarning(QT_BT_DARWIN) << "characteristic:" << charHandle << "not found"; + if (notifier) { + emit notifier->CBManagerError(serviceUuid, + QLowEnergyService::CharacteristicReadError); + + } + return; + } + + LERequest request; + request.type = LERequest::CharRead; + request.handle = charHandle; + + requests.enqueue(request); + [self performNextRequest]; +} + +- (void)write:(const QByteArray &)value + charHandle:(QLowEnergyHandle)charHandle + onService:(const QBluetoothUuid &)serviceUuid + withResponse:(bool)withResponse +{ + using namespace DarwinBluetooth; + + Q_ASSERT_X(charHandle, Q_FUNC_INFO, "invalid characteristic handle (0)"); + + QT_BT_MAC_AUTORELEASEPOOL; + + if (!charMap.contains(charHandle)) { + qCWarning(QT_BT_DARWIN) << "characteristic:" << charHandle << "not found"; + if (notifier) { + emit notifier->CBManagerError(serviceUuid, + QLowEnergyService::CharacteristicWriteError); + } + return; + } + + LERequest request; + request.type = LERequest::CharWrite; + request.withResponse = withResponse; + request.handle = charHandle; + request.value = value; + + requests.enqueue(request); + [self performNextRequest]; +} + +- (void)readDescriptor:(QLowEnergyHandle)descHandle + onService:(const QBluetoothUuid &)serviceUuid +{ + using namespace DarwinBluetooth; + + Q_ASSERT_X(descHandle, Q_FUNC_INFO, "invalid descriptor handle (0)"); + + if (!descMap.contains(descHandle)) { + qCWarning(QT_BT_DARWIN) << "handle:" << descHandle << "not found"; + if (notifier) { + emit notifier->CBManagerError(serviceUuid, + QLowEnergyService::DescriptorReadError); + } + return; + } + + LERequest request; + request.type = LERequest::DescRead; + request.handle = descHandle; + + requests.enqueue(request); + [self performNextRequest]; +} + +- (void)write:(const QByteArray &)value + descHandle:(QLowEnergyHandle)descHandle + onService:(const QBluetoothUuid &)serviceUuid +{ + using namespace DarwinBluetooth; + + Q_ASSERT_X(descHandle, Q_FUNC_INFO, "invalid descriptor handle (0)"); + + if (!descMap.contains(descHandle)) { + qCWarning(QT_BT_DARWIN) << "handle:" << descHandle << "not found"; + if (notifier) { + emit notifier->CBManagerError(serviceUuid, + QLowEnergyService::DescriptorWriteError); + } + return; + } + + LERequest request; + request.type = LERequest::DescWrite; + request.handle = descHandle; + request.value = value; + + requests.enqueue(request); + [self performNextRequest]; +} + +// Aux. methods: + +- (CBService *)serviceForUUID:(const QBluetoothUuid &)qtUuid +{ + using namespace DarwinBluetooth; + + Q_ASSERT_X(!qtUuid.isNull(), Q_FUNC_INFO, "invalid uuid"); + Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)"); + + ObjCStrongReference toVisit([NSMutableArray arrayWithArray:peripheral.services], RetainPolicy::doInitialRetain); + ObjCStrongReference toVisitNext([[NSMutableArray alloc] init], RetainPolicy::noInitialRetain); + ObjCStrongReference visitedNodes([[NSMutableSet alloc] init], RetainPolicy::noInitialRetain); + + while (true) { + for (NSUInteger i = 0, e = [toVisit count]; i < e; ++i) { + CBService *const s = [toVisit objectAtIndex:i]; + if (equal_uuids(s.UUID, qtUuid)) + return s; + if (![visitedNodes containsObject:s] && s.includedServices && s.includedServices.count) { + [visitedNodes addObject:s]; + [toVisitNext addObjectsFromArray:s.includedServices]; + } + } + + if (![toVisitNext count]) + return nil; + + toVisit.swap(toVisitNext); + toVisitNext.reset([[NSMutableArray alloc] init], RetainPolicy::noInitialRetain); + } + + return nil; +} + +- (CBCharacteristic *)nextCharacteristicForService:(CBService*)service + startingFrom:(CBCharacteristic *)characteristic +{ + Q_ASSERT_X(service, Q_FUNC_INFO, "invalid service (nil)"); + Q_ASSERT_X(characteristic, Q_FUNC_INFO, "invalid characteristic (nil)"); + Q_ASSERT_X(service.characteristics, Q_FUNC_INFO, "invalid service"); + Q_ASSERT_X(service.characteristics.count, Q_FUNC_INFO, "invalid service"); + + QT_BT_MAC_AUTORELEASEPOOL; + + // TODO: test that we NEVER have the same characteristic twice in array! + // At the moment I just protect against this by iterating in a reverse + // order (at least avoiding a potential inifite loop with '-indexOfObject:'). + NSArray *const cs = service.characteristics; + if (cs.count == 1) + return nil; + + for (NSUInteger index = cs.count - 1; index != 0; --index) { + if ([cs objectAtIndex:index] == characteristic) { + if (index + 1 == cs.count) + return nil; + else + return [cs objectAtIndex:index + 1]; + } + } + + Q_ASSERT_X([cs objectAtIndex:0] == characteristic, Q_FUNC_INFO, + "characteristic was not found in service.characteristics"); + + return [cs objectAtIndex:1]; +} + +- (CBCharacteristic *)nextCharacteristicForService:(CBService*)service + startingFrom:(CBCharacteristic *)characteristic + properties:(CBCharacteristicProperties)properties +{ + Q_ASSERT_X(service, Q_FUNC_INFO, "invalid service (nil)"); + Q_ASSERT_X(characteristic, Q_FUNC_INFO, "invalid characteristic (nil)"); + Q_ASSERT_X(service.characteristics, Q_FUNC_INFO, "invalid service"); + Q_ASSERT_X(service.characteristics.count, Q_FUNC_INFO, "invalid service"); + + QT_BT_MAC_AUTORELEASEPOOL; + + // TODO: test that we NEVER have the same characteristic twice in array! + // At the moment I just protect against this by iterating in a reverse + // order (at least avoiding a potential inifite loop with '-indexOfObject:'). + NSArray *const cs = service.characteristics; + if (cs.count == 1) + return nil; + + NSUInteger index = cs.count - 1; + for (; index != 0; --index) { + if ([cs objectAtIndex:index] == characteristic) { + if (index + 1 == cs.count) { + return nil; + } else { + index += 1; + break; + } + } + } + + if (!index) { + Q_ASSERT_X([cs objectAtIndex:0] == characteristic, Q_FUNC_INFO, + "characteristic not found in service.characteristics"); + index = 1; + } + + for (const NSUInteger e = cs.count; index < e; ++index) { + CBCharacteristic *const c = [cs objectAtIndex:index]; + if (c.properties & properties) + return c; + } + + return nil; +} + +- (CBDescriptor *)nextDescriptorForCharacteristic:(CBCharacteristic *)characteristic + startingFrom:(CBDescriptor *)descriptor +{ + Q_ASSERT_X(characteristic, Q_FUNC_INFO, "invalid characteristic (nil)"); + Q_ASSERT_X(descriptor, Q_FUNC_INFO, "invalid descriptor (nil)"); + Q_ASSERT_X(characteristic.descriptors, Q_FUNC_INFO, "invalid characteristic"); + Q_ASSERT_X(characteristic.descriptors.count, Q_FUNC_INFO, "invalid characteristic"); + + QT_BT_MAC_AUTORELEASEPOOL; + + NSArray *const ds = characteristic.descriptors; + if (ds.count == 1) + return nil; + + for (NSUInteger index = ds.count - 1; index != 0; --index) { + if ([ds objectAtIndex:index] == descriptor) { + if (index + 1 == ds.count) + return nil; + else + return [ds objectAtIndex:index + 1]; + } + } + + Q_ASSERT_X([ds objectAtIndex:0] == descriptor, Q_FUNC_INFO, + "descriptor was not found in characteristic.descriptors"); + + return [ds objectAtIndex:1]; +} + +- (CBDescriptor *)descriptor:(const QBluetoothUuid &)qtUuid + forCharacteristic:(CBCharacteristic *)ch +{ + if (qtUuid.isNull() || !ch) + return nil; + + QT_BT_MAC_AUTORELEASEPOOL; + + CBDescriptor *descriptor = nil; + NSArray *const ds = ch.descriptors; + if (ds && ds.count) { + for (CBDescriptor *d in ds) { + if (DarwinBluetooth::equal_uuids(d.UUID, qtUuid)) { + descriptor = d; + break; + } + } + } + + return descriptor; +} + +- (bool)cacheWriteValue:(const QByteArray &)value for:(NSObject *)obj +{ + Q_ASSERT_X(obj, Q_FUNC_INFO, "invalid object (nil)"); + + if ([obj isKindOfClass:[CBCharacteristic class]]) { + CBCharacteristic *const ch = static_cast(obj); + if (!charMap.key(ch)) { + qCWarning(QT_BT_DARWIN) << "unexpected characteristic, no handle found"; + return false; + } + } else if ([obj isKindOfClass:[CBDescriptor class]]) { + CBDescriptor *const d = static_cast(obj); + if (!descMap.key(d)) { + qCWarning(QT_BT_DARWIN) << "unexpected descriptor, no handle found"; + return false; + } + } else { + qCWarning(QT_BT_DARWIN) << "invalid object, characteristic " + "or descriptor required"; + return false; + } + + if (valuesToWrite.contains(obj)) { + // It can be a result of some previous errors - for example, + // we never got a callback from a previous write. + qCWarning(QT_BT_DARWIN) << "already has a cached value for this " + "object, the value will be replaced"; + } + + valuesToWrite[obj] = value; + return true; +} + +- (void)reset +{ + requestPending = false; + valuesToWrite.clear(); + requests.clear(); + servicesToDiscoverDetails.clear(); + lastValidHandle = 0; + serviceMap.clear(); + charMap.clear(); + descMap.clear(); + currentReadHandle = 0; + [self stopWatchers]; + // TODO: also serviceToVisit/VisitNext and visitedServices ? +} + +- (void)handleReadWriteError:(NSError *)error +{ + Q_ASSERT(notifier); + + switch (error.code) { + case 0x05: // GATT_INSUFFICIENT_AUTHORIZATION + case 0x0F: // GATT_INSUFFICIENT_ENCRYPTION + emit notifier->CBManagerError(QLowEnergyController::AuthorizationError); + [self detach]; + break; + default: + break; + } +} + +// CBCentralManagerDelegate (the real one). + +- (void)centralManagerDidUpdateState:(CBCentralManager *)central +{ + using namespace DarwinBluetooth; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability-new" + + const auto state = central.state; + if (state == CBManagerStateUnknown || state == CBManagerStateResetting) { + // We still have to wait, docs say: + // "The current state of the central manager is unknown; + // an update is imminent." or + // "The connection with the system service was momentarily + // lost; an update is imminent." + return; + } + + // Let's check some states we do not like first: + if (state == CBManagerStateUnsupported || state == CBManagerStateUnauthorized) { + managerState = CentralManagerIdle; + // The LE is not supported or its usage was not authorized + if (notifier) { + if (state == CBManagerStateUnsupported) + emit notifier->LEnotSupported(); + else + emit notifier->CBManagerError(QLowEnergyController::MissingPermissionsError); + } + [self stopWatchers]; + return; + } + + if (state == CBManagerStatePoweredOff) { + if (managerState == CentralManagerUpdating) { + managerState = CentralManagerIdle; + // I've seen this instead of Unsupported on OS X. + if (notifier) + emit notifier->LEnotSupported(); + } else { + managerState = CentralManagerIdle; + // TODO: we need a better error + + // what will happen if later the state changes to PoweredOn??? + if (notifier) + emit notifier->CBManagerError(QLowEnergyController::InvalidBluetoothAdapterError); + } + [self stopWatchers]; + return; + } + + if (state == CBManagerStatePoweredOn) { + if (managerState == CentralManagerUpdating && !disconnectPending) { + managerState = CentralManagerIdle; + [self retrievePeripheralAndConnect]; + } + } else { + // We actually handled all known states, but .. Core Bluetooth can change? + Q_ASSERT_X(0, Q_FUNC_INFO, "invalid central's state"); + } + +#pragma clang diagnostic pop +} + +- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)aPeripheral +{ + Q_UNUSED(central); + Q_UNUSED(aPeripheral); + + if (managerState != DarwinBluetooth::CentralManagerConnecting) { + // We called cancel but before disconnected, managed to connect? + return; + } + + void([self mtu]); + + [peripheral setDelegate:self]; + + managerState = DarwinBluetooth::CentralManagerIdle; + if (notifier) + emit notifier->connected(); +} + +- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)aPeripheral + error:(NSError *)error +{ + Q_UNUSED(central); + Q_UNUSED(aPeripheral); + Q_UNUSED(error); + + if (managerState != DarwinBluetooth::CentralManagerConnecting) { + // Canceled already. + return; + } + + managerState = DarwinBluetooth::CentralManagerIdle; + // TODO: better error mapping is required. + if (notifier) + notifier->CBManagerError(QLowEnergyController::UnknownRemoteDeviceError); +} + +- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)aPeripheral + error:(NSError *)error +{ + Q_UNUSED(central); + Q_UNUSED(aPeripheral); + + // Clear internal caches/data. + [self reset]; + + if (error && managerState == DarwinBluetooth::CentralManagerDisconnecting) { + managerState = DarwinBluetooth::CentralManagerIdle; + qCWarning(QT_BT_DARWIN) << "failed to disconnect"; + if (notifier) + emit notifier->CBManagerError(QLowEnergyController::UnknownRemoteDeviceError); + } else { + managerState = DarwinBluetooth::CentralManagerIdle; + if (notifier) + emit notifier->disconnected(); + } +} + +// CBPeripheralDelegate. + +- (void)peripheral:(CBPeripheral *)aPeripheral didDiscoverServices:(NSError *)error +{ + Q_UNUSED(aPeripheral); + + using namespace DarwinBluetooth; + + if (managerState != CentralManagerDiscovering) { + // Canceled by -disconnectFromDevice, or as a result of a timeout. + return; + } + + if (![self objectIsUnderWatch:aPeripheral operation:OperationTimeout::serviceDiscovery]) // Timed out already + return; + + QT_BT_MAC_AUTORELEASEPOOL; + + [self stopWatchingAfter:aPeripheral operation:OperationTimeout::serviceDiscovery]; + + managerState = CentralManagerIdle; + + if (error) { + NSLog(@"%s failed with error %@", Q_FUNC_INFO, error); + // TODO: better error mapping required. + // Emit an error which also causes the service discovery finished() signal + if (notifier) + emit notifier->CBManagerError(QLowEnergyController::UnknownError); + return; + } + + [self discoverIncludedServices]; +} + +- (void)peripheral:(CBPeripheral *)aPeripheral + didModifyServices:(NSArray *)invalidatedServices +{ + Q_UNUSED(aPeripheral); + Q_UNUSED(invalidatedServices); + + qCWarning(QT_BT_DARWIN) << "The peripheral has modified its services."; + // "This method is invoked whenever one or more services of a peripheral have changed. + // A peripheral’s services have changed if: + // * A service is removed from the peripheral’s database + // * A new service is added to the peripheral’s database + // * A service that was previously removed from the peripheral’s + // database is readded to the database at a different location" + + // In case new services were added - we have to discover them. + // In case some were removed - we can end up with dangling pointers + // (see our 'watchdogs', for example). To handle the situation + // we stop all current operations here, report to QLowEnergyController + // so that it can trigger re-discovery. + [self reset]; + managerState = DarwinBluetooth::CentralManagerIdle; + if (notifier) + emit notifier->servicesWereModified(); +} + +- (void)peripheral:(CBPeripheral *)aPeripheral didDiscoverIncludedServicesForService:(CBService *)service + error:(NSError *)error +{ + Q_UNUSED(aPeripheral); + + using namespace DarwinBluetooth; + + if (managerState != CentralManagerDiscovering) { + // Canceled by disconnectFromDevice or -peripheralDidDisconnect... + return; + } + + if (![self objectIsUnderWatch:service operation:OperationTimeout::includedServicesDiscovery]) + return; + + QT_BT_MAC_AUTORELEASEPOOL; + + Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)"); + + [self stopWatchingAfter:service operation:OperationTimeout::includedServicesDiscovery]; + managerState = CentralManagerIdle; + + if (error) { + NSLog(@"%s: finished with error %@ for service %@", + Q_FUNC_INFO, error, service.UUID); + } else if (service.includedServices && service.includedServices.count) { + // Now we have even more services to do included services discovery ... + if (!servicesToVisitNext) + servicesToVisitNext.reset([NSMutableArray arrayWithArray:service.includedServices], RetainPolicy::doInitialRetain); + else + [servicesToVisitNext addObjectsFromArray:service.includedServices]; + } + + // Do we have something else to discover on this 'level'? + ++currentService; + + for (const NSUInteger e = [servicesToVisit count]; currentService < e; ++currentService) { + CBService *const s = [servicesToVisit objectAtIndex:currentService]; + if (![visitedServices containsObject:s]) { + // Continue with discovery ... + [visitedServices addObject:s]; + managerState = CentralManagerDiscovering; + [self watchAfter:s timeout:OperationTimeout::includedServicesDiscovery]; + return [peripheral discoverIncludedServices:nil forService:s]; + } + } + + // No services to visit more on this 'level'. + + if (servicesToVisitNext && [servicesToVisitNext count]) { + servicesToVisit.swap(servicesToVisitNext); + servicesToVisitNext.reset(); + + currentService = 0; + for (const NSUInteger e = [servicesToVisit count]; currentService < e; ++currentService) { + CBService *const s = [servicesToVisit objectAtIndex:currentService]; + if (![visitedServices containsObject:s]) { + [visitedServices addObject:s]; + managerState = CentralManagerDiscovering; + [self watchAfter:s timeout:OperationTimeout::includedServicesDiscovery]; + return [peripheral discoverIncludedServices:nil forService:s]; + } + } + } + + // Finally, if we're here, the service discovery is done! + + // Release all these things now, no need to prolong their lifetime. + visitedServices.reset(); + servicesToVisit.reset(); + servicesToVisitNext.reset(); + + if (notifier) + emit notifier->serviceDiscoveryFinished(); +} + +- (void)peripheral:(CBPeripheral *)aPeripheral didDiscoverCharacteristicsForService:(CBService *)service + error:(NSError *)error +{ + // This method does not change 'managerState', we can have several + // discoveries active. + Q_UNUSED(aPeripheral); + + if (!notifier) { + // Detached. + return; + } + + using namespace DarwinBluetooth; + + if (![self objectIsUnderWatch:service operation:OperationTimeout::characteristicsDiscovery]) + return; + + QT_BT_MAC_AUTORELEASEPOOL; + + [self stopWatchingAfter:service operation:OperationTimeout::characteristicsDiscovery]; + + const auto qtUuid = qt_uuid(service.UUID); + const bool skipRead = servicesToDiscoverDetails[qtUuid] == DiscoveryMode::SkipValueDiscovery; + + Q_ASSERT_X(managerState != CentralManagerUpdating, Q_FUNC_INFO, "invalid state"); + + if (error) { + NSLog(@"%s failed with error: %@", Q_FUNC_INFO, error); + // We did not discover any characteristics and can not discover descriptors, + // inform our delegate (it will set a service state also). + emit notifier->CBManagerError(qtUuid, QLowEnergyController::UnknownError); + } + + if (skipRead) { + [self serviceDetailsDiscoveryFinished:service]; + return; + } + [self readCharacteristics:service]; +} + +- (void)peripheral:(CBPeripheral *)aPeripheral + didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic + error:(NSError *)error +{ + Q_UNUSED(aPeripheral); + + if (!notifier) // Detached. + return; + + using namespace DarwinBluetooth; + + QT_BT_MAC_AUTORELEASEPOOL; + + const bool readMatch = [self objectIsUnderWatch:characteristic operation:OperationTimeout::characteristicRead]; + if (readMatch) + [self stopWatchingAfter:characteristic operation:OperationTimeout::characteristicRead]; + + Q_ASSERT_X(managerState != CentralManagerUpdating, Q_FUNC_INFO, "invalid state"); + Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)"); + + + // First, let's check if we're discovering a service details now. + CBService *const service = characteristic.service; + const QBluetoothUuid qtUuid(qt_uuid(service.UUID)); + const bool isDetailsDiscovery = servicesToDiscoverDetails.contains(qtUuid); + const QLowEnergyHandle chHandle = charMap.key(characteristic); + + if (error) { + NSLog(@"%s failed with error %@", Q_FUNC_INFO, error); + if (!isDetailsDiscovery) { + if (chHandle && chHandle == currentReadHandle) { + currentReadHandle = 0; + requestPending = false; + emit notifier->CBManagerError(qtUuid, QLowEnergyService::CharacteristicReadError); + [self handleReadWriteError:error]; + [self performNextRequest]; + } + return; + } + } + + if (isDetailsDiscovery) { + if (readMatch) { + // Test if we have any other characteristic to read yet. + CBCharacteristic *const next = [self nextCharacteristicForService:characteristic.service + startingFrom:characteristic properties:CBCharacteristicPropertyRead]; + if (next) { + [self watchAfter:next timeout:OperationTimeout::characteristicRead]; + [peripheral readValueForCharacteristic:next]; + } else { + [self discoverDescriptors:characteristic.service]; + } + } + } else { + // This is (probably) the result of update notification. + // It's very possible we can have an invalid handle here (0) - + // if something esle is wrong (we subscribed for a notification), + // disconnected (but other application is connected) and still receiveing + // updated values ... + // TODO: this must be properly tested. + if (!chHandle) { + qCCritical(QT_BT_DARWIN) << "unexpected update notification, " + "no characteristic handle found"; + return; + } + + if (currentReadHandle == chHandle) { + // Even if it was not a reply to our read request (no way to test it) + // report it. + requestPending = false; + currentReadHandle = 0; + // + emit notifier->characteristicRead(chHandle, qt_bytearray(characteristic.value)); + [self performNextRequest]; + } else { + emit notifier->characteristicUpdated(chHandle, qt_bytearray(characteristic.value)); + } + } +} + +- (void)peripheral:(CBPeripheral *)aPeripheral + didDiscoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic + error:(NSError *)error +{ + // This method does not change 'managerState', we can + // have several discoveries active at the same time. + Q_UNUSED(aPeripheral); + + if (!notifier) { + // Detached, no need to continue ... + return; + } + + QT_BT_MAC_AUTORELEASEPOOL; + + using namespace DarwinBluetooth; + + if (![self objectIsUnderWatch:characteristic operation:OperationTimeout::descriptorsDiscovery]) + return; + + [self stopWatchingAfter:characteristic operation:OperationTimeout::descriptorsDiscovery]; + + if (error) { + NSLog(@"%s failed with error %@", Q_FUNC_INFO, error); + // We can continue though ... + } + + // Do we have more characteristics on this service to discover descriptors? + CBCharacteristic *const next = [self nextCharacteristicForService:characteristic.service + startingFrom:characteristic]; + if (next) { + [self watchAfter:next timeout:OperationTimeout::descriptorsDiscovery]; + [peripheral discoverDescriptorsForCharacteristic:next]; + } else { + [self readDescriptors:characteristic.service]; + } +} + +- (void)peripheral:(CBPeripheral *)aPeripheral + didUpdateValueForDescriptor:(CBDescriptor *)descriptor + error:(NSError *)error +{ + Q_UNUSED(aPeripheral); + + Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)"); + + if (!notifier) { + // Detached ... + return; + } + + QT_BT_MAC_AUTORELEASEPOOL; + + using namespace DarwinBluetooth; + + if (![self objectIsUnderWatch:descriptor operation:OperationTimeout::descriptorRead]) + return; + + [self stopWatchingAfter:descriptor operation:OperationTimeout::descriptorRead]; + + CBService *const service = descriptor.characteristic.service; + const QBluetoothUuid qtUuid(qt_uuid(service.UUID)); + const bool isDetailsDiscovery = servicesToDiscoverDetails.contains(qtUuid); + const QLowEnergyHandle dHandle = descMap.key(descriptor); + + if (error) { + NSLog(@"%s failed with error %@", Q_FUNC_INFO, error); + + if (!isDetailsDiscovery) { + if (dHandle && dHandle == currentReadHandle) { + currentReadHandle = 0; + requestPending = false; + emit notifier->CBManagerError(qtUuid, QLowEnergyService::DescriptorReadError); + [self handleReadWriteError:error]; + [self performNextRequest]; + } + return; + } + } + + if (isDetailsDiscovery) { + // Test if we have any other characteristic to read yet. + CBDescriptor *const next = [self nextDescriptorForCharacteristic:descriptor.characteristic + startingFrom:descriptor]; + if (next) { + [self watchAfter:next timeout:OperationTimeout::descriptorRead]; + [peripheral readValueForDescriptor:next]; + } else { + // We either have to read a value for a next descriptor + // on a given characteristic, or continue with the + // next characteristic in a given service (if any). + CBCharacteristic *const ch = descriptor.characteristic; + CBCharacteristic *nextCh = [self nextCharacteristicForService:ch.service + startingFrom:ch]; + while (nextCh) { + if (nextCh.descriptors && nextCh.descriptors.count) { + CBDescriptor *desc = [nextCh.descriptors objectAtIndex:0]; + [self watchAfter:desc timeout:OperationTimeout::descriptorRead]; + return [peripheral readValueForDescriptor:desc]; + } + + nextCh = [self nextCharacteristicForService:ch.service + startingFrom:nextCh]; + } + + [self serviceDetailsDiscoveryFinished:service]; + } + } else { + if (!dHandle) { + qCCritical(QT_BT_DARWIN) << "unexpected value update notification, " + "no descriptor handle found"; + return; + } + + if (dHandle == currentReadHandle) { + currentReadHandle = 0; + requestPending = false; + emit notifier->descriptorRead(dHandle, qt_bytearray(static_cast(descriptor.value))); + [self performNextRequest]; + } + } +} + +- (void)peripheral:(CBPeripheral *)aPeripheral + didWriteValueForCharacteristic:(CBCharacteristic *)characteristic + error:(NSError *)error +{ + Q_UNUSED(aPeripheral); + Q_UNUSED(characteristic); + + if (!notifier) { + // Detached. + return; + } + + // From docs: + // + // "This method is invoked only when your app calls the writeValue:forCharacteristic:type: + // method with the CBCharacteristicWriteWithResponse constant specified as the write type. + // If successful, the error parameter is nil. If unsuccessful, + // the error parameter returns the cause of the failure." + + using namespace DarwinBluetooth; + + QT_BT_MAC_AUTORELEASEPOOL; + + if (![self objectIsUnderWatch:characteristic operation:OperationTimeout::characteristicWrite]) + return; + + [self stopWatchingAfter:characteristic operation:OperationTimeout::characteristicWrite]; + requestPending = false; + + // Error or not, but the cached value has to be deleted ... + const QByteArray valueToReport(valuesToWrite.value(characteristic, QByteArray())); + if (!valuesToWrite.remove(characteristic)) { + qCWarning(QT_BT_DARWIN) << "no updated value found " + "for characteristic"; + } + + if (error) { + NSLog(@"%s failed with error %@", Q_FUNC_INFO, error); + emit notifier->CBManagerError(qt_uuid(characteristic.service.UUID), + QLowEnergyService::CharacteristicWriteError); + [self handleReadWriteError:error]; + } else { + const QLowEnergyHandle cHandle = charMap.key(characteristic); + emit notifier->characteristicWritten(cHandle, valueToReport); + } + + [self performNextRequest]; +} + +- (void)peripheral:(CBPeripheral *)aPeripheral + didWriteValueForDescriptor:(CBDescriptor *)descriptor + error:(NSError *)error +{ + Q_UNUSED(aPeripheral); + + if (!notifier) { + // Detached already. + return; + } + + using namespace DarwinBluetooth; + + QT_BT_MAC_AUTORELEASEPOOL; + + requestPending = false; + + // Error or not, a value (if any) must be removed. + const QByteArray valueToReport(valuesToWrite.value(descriptor, QByteArray())); + if (!valuesToWrite.remove(descriptor)) + qCWarning(QT_BT_DARWIN) << "no updated value found"; + + if (error) { + NSLog(@"%s failed with error %@", Q_FUNC_INFO, error); + emit notifier->CBManagerError(qt_uuid(descriptor.characteristic.service.UUID), + QLowEnergyService::DescriptorWriteError); + [self handleReadWriteError:error]; + } else { + const QLowEnergyHandle dHandle = descMap.key(descriptor); + Q_ASSERT_X(dHandle, Q_FUNC_INFO, "descriptor not found in the descriptors map"); + emit notifier->descriptorWritten(dHandle, valueToReport); + } + + [self performNextRequest]; +} + +- (void)peripheral:(CBPeripheral *)aPeripheral + didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic + error:(NSError *)error +{ + Q_UNUSED(aPeripheral); + + if (!notifier) + return; + + using namespace DarwinBluetooth; + + QT_BT_MAC_AUTORELEASEPOOL; + + requestPending = false; + + const QBluetoothUuid qtUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration); + CBDescriptor *const descriptor = [self descriptor:qtUuid forCharacteristic:characteristic]; + const QByteArray valueToReport(valuesToWrite.value(descriptor, QByteArray())); + const int nRemoved = valuesToWrite.remove(descriptor); + + if (error) { + NSLog(@"%s failed with error %@", Q_FUNC_INFO, error); + // In Qt's API it's a descriptor write actually. + emit notifier->CBManagerError(qt_uuid(characteristic.service.UUID), + QLowEnergyService::DescriptorWriteError); + } else if (nRemoved) { + const QLowEnergyHandle dHandle = descMap.key(descriptor); + emit notifier->descriptorWritten(dHandle, valueToReport); + } + + [self performNextRequest]; +} + +- (void)peripheral:(CBPeripheral *)aPeripheral didReadRSSI:(NSNumber *)RSSI error:(nullable NSError *)error +{ + Q_UNUSED(aPeripheral); + + if (!notifier) // This controller was detached. + return; + + if (error) { + NSLog(@"Reading RSSI finished with error: %@", error); + return emit notifier->CBManagerError(QLowEnergyController::RssiReadError); + } + + if (!RSSI) { + qCWarning(QT_BT_DARWIN, "Reading RSSI returned no value"); + return emit notifier->CBManagerError(QLowEnergyController::RssiReadError); + } + + emit notifier->rssiUpdated(qint16([RSSI shortValue])); +} + +- (void)detach +{ + if (notifier) { + notifier->disconnect(); + notifier->deleteLater(); + notifier = nullptr; + } + + [self stopWatchers]; + [self disconnectFromDevice]; +} + +@end diff --git a/src/bluetooth/darwin/btcentralmanager_p.h b/src/bluetooth/darwin/btcentralmanager_p.h new file mode 100644 index 0000000..3986228 --- /dev/null +++ b/src/bluetooth/darwin/btcentralmanager_p.h @@ -0,0 +1,144 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef BTCENTRALMANAGER_P_H +#define BTCENTRALMANAGER_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 "qlowenergycontroller.h" +#include "qbluetoothuuid.h" +#include "btgcdtimer_p.h" +#include "btutility_p.h" + +#include + +#include +#include +#include +#include + +#include + +#include + +QT_BEGIN_NAMESPACE + +namespace DarwinBluetooth { + +class LECBManagerNotifier; + +enum CentralManagerState +{ + // QLowEnergyController already has some of these states, + // but it's not enough and we need more special states here. + CentralManagerIdle, + // Required by CBCentralManager to avoid problems with dangled pointers. + CentralManagerUpdating, + CentralManagerConnecting, + CentralManagerDiscovering, + CentralManagerDisconnecting +}; + +// In Qt we work with handles and UUIDs. Core Bluetooth +// has NSArrays (and nested NSArrays inside servces/characteristics). +// To simplify a navigation, I need a simple way to map from a handle +// to a Core Bluetooth object. These are weak pointers, +// will probably require '__weak' with ARC. +typedef QHash ServiceHash; +typedef QHash CharHash; +typedef QHash DescHash; + +// Descriptor/charactesirstic read/write requests +// - we have to serialize 'concurrent' requests. +struct LERequest { + enum RequestType { + CharRead, + CharWrite, + DescRead, + DescWrite, + ClientConfiguration, + Invalid + }; + + LERequest() : type(Invalid), + withResponse(false), + handle(0) + {} + + RequestType type; + bool withResponse; + QLowEnergyHandle handle; + QByteArray value; +}; + +typedef QQueue RequestQueue; + +// Core Bluetooth's write confirmation does not provide +// the updated value (characteristic or descriptor). +// But the Qt's Bluetooth API ('write with response') +// expects this updated value as a response, so we have +// to cache this write value and report it back. +// 'NSObject *' will require '__weak' with ARC. +typedef QHash ValueHash; + +} // namespace DarwinBluetooth + +QT_END_NAMESPACE + +@interface QT_MANGLE_NAMESPACE(DarwinBTCentralManager) : NSObject +- (id)initWith:(QT_PREPEND_NAMESPACE(DarwinBluetooth)::LECBManagerNotifier *)notifier; +- (void)dealloc; + +- (CBPeripheral *)peripheral; + +// IMPORTANT: _all_ these methods are to be executed on qt_LE_queue, +// when passing parameters - C++ objects _must_ be copied (see the controller's code). +- (void)connectToDevice:(const QT_PREPEND_NAMESPACE(QBluetoothUuid) &)aDeviceUuid; + +- (void)disconnectFromDevice; + +- (void)discoverServices; +- (void)discoverServiceDetails:(const QT_PREPEND_NAMESPACE(QBluetoothUuid) &)serviceUuid + readValues:(bool)read; + +- (int)mtu; +- (void)readRssi; + +- (void)setNotifyValue:(const QT_PREPEND_NAMESPACE(QByteArray) &)value + forCharacteristic:(QT_PREPEND_NAMESPACE(QLowEnergyHandle))charHandle + onService:(const QT_PREPEND_NAMESPACE(QBluetoothUuid) &)serviceUuid; + +- (void)readCharacteristic:(QT_PREPEND_NAMESPACE(QLowEnergyHandle))charHandle + onService:(const QT_PREPEND_NAMESPACE(QBluetoothUuid) &)serviceUuid; + +- (void)write:(const QT_PREPEND_NAMESPACE(QByteArray) &)value + charHandle:(QT_PREPEND_NAMESPACE(QLowEnergyHandle))charHandle + onService:(const QT_PREPEND_NAMESPACE(QBluetoothUuid) &)serviceUuid + withResponse:(bool)writeWithResponse; + +- (void)readDescriptor:(QT_PREPEND_NAMESPACE(QLowEnergyHandle))descHandle + onService:(const QT_PREPEND_NAMESPACE(QBluetoothUuid) &)serviceUuid; + +- (void)write:(const QT_PREPEND_NAMESPACE(QByteArray) &)value + descHandle:(QT_PREPEND_NAMESPACE(QLowEnergyHandle))descHandle + onService:(const QT_PREPEND_NAMESPACE(QBluetoothUuid) &)serviceUuid; + +- (void)detach; + +@end + +QT_NAMESPACE_ALIAS_OBJC_CLASS(DarwinBTCentralManager); + +#endif diff --git a/src/bluetooth/darwin/btconnectionmonitor.mm b/src/bluetooth/darwin/btconnectionmonitor.mm new file mode 100644 index 0000000..12dd788 --- /dev/null +++ b/src/bluetooth/darwin/btconnectionmonitor.mm @@ -0,0 +1,109 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "btconnectionmonitor_p.h" +#include "btutility_p.h" + +#include "qbluetoothaddress.h" + +#include + +QT_USE_NAMESPACE + +@implementation DarwinBTConnectionMonitor +{ + QT_PREPEND_NAMESPACE(DarwinBluetooth::ConnectionMonitor) *monitor; + IOBluetoothUserNotification *discoveryNotification; + NSMutableArray *foundConnections; +} + +- (id)initWithMonitor:(DarwinBluetooth::ConnectionMonitor *)aMonitor +{ + Q_ASSERT_X(aMonitor, "-initWithMonitor:", "invalid monitor (null)"); + + if (self = [super init]) { + monitor = aMonitor; + discoveryNotification = [[IOBluetoothDevice registerForConnectNotifications:self + selector:@selector(connectionNotification:withDevice:)] retain]; + foundConnections = [[NSMutableArray alloc] init]; + } + + return self; +} + +- (void)dealloc +{ + Q_ASSERT_X(!monitor, "-dealloc", + "Connection monitor was not stopped, calling -stopMonitoring is required"); + [super dealloc]; +} + +- (void)connectionNotification:(IOBluetoothUserNotification *)aNotification + withDevice:(IOBluetoothDevice *)device +{ + Q_UNUSED(aNotification); + + typedef IOBluetoothUserNotification Notification; + + if (!device) + return; + + if (!monitor) { + // Rather surprising: monitor == nullptr means we stopped monitoring. + // So apparently this thingie is still alive and keeps receiving + // notifications. + qCWarning(QT_BT_DARWIN, + "Connection notification received in a monitor that was cancelled"); + return; + } + + QT_BT_MAC_AUTORELEASEPOOL; + + // All Obj-C objects are autoreleased. + + const QBluetoothAddress deviceAddress(DarwinBluetooth::qt_address([device getAddress])); + if (deviceAddress.isNull()) + return; + + if (foundConnections) { + Notification *const notification = [device registerForDisconnectNotification:self + selector: @selector(connectionClosedNotification:withDevice:)]; + if (notification) + [foundConnections addObject:notification]; + } + + Q_ASSERT_X(monitor, "-connectionNotification:withDevice:", "invalid monitor (null)"); + monitor->deviceConnected(deviceAddress); +} + +- (void)connectionClosedNotification:(IOBluetoothUserNotification *)notification + withDevice:(IOBluetoothDevice *)device +{ + QT_BT_MAC_AUTORELEASEPOOL; + + [notification unregister];//? + [foundConnections removeObject:notification]; + + const QBluetoothAddress deviceAddress(DarwinBluetooth::qt_address([device getAddress])); + if (deviceAddress.isNull()) + return; + + Q_ASSERT_X(monitor, "-connectionClosedNotification:withDevice:", "invalid monitor (null)"); + monitor->deviceDisconnected(deviceAddress); +} + +-(void)stopMonitoring +{ + monitor = nullptr; + [discoveryNotification unregister]; + [discoveryNotification release]; + discoveryNotification = nil; + + for (IOBluetoothUserNotification *n in foundConnections) + [n unregister]; + + [foundConnections release]; + foundConnections = nil; +} + +@end diff --git a/src/bluetooth/darwin/btconnectionmonitor_p.h b/src/bluetooth/darwin/btconnectionmonitor_p.h new file mode 100644 index 0000000..f4f5c7e --- /dev/null +++ b/src/bluetooth/darwin/btconnectionmonitor_p.h @@ -0,0 +1,39 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef BTCONNECTIONMONITOR_P_H +#define BTCONNECTIONMONITOR_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 "btdelegates_p.h" + +#include + +#include + +#include + +#include + +@interface QT_MANGLE_NAMESPACE(DarwinBTConnectionMonitor) : NSObject + +- (id)initWithMonitor:(QT_PREPEND_NAMESPACE(DarwinBluetooth::ConnectionMonitor) *)monitor; +- (void)connectionNotification:(id)notification withDevice:(IOBluetoothDevice *)device; +- (void)connectionClosedNotification:(id)notification withDevice:(IOBluetoothDevice *)device; + +- (void)stopMonitoring; +@end + +QT_NAMESPACE_ALIAS_OBJC_CLASS(DarwinBTConnectionMonitor); + +#endif diff --git a/src/bluetooth/darwin/btdelegates.cpp b/src/bluetooth/darwin/btdelegates.cpp new file mode 100644 index 0000000..fc86778 --- /dev/null +++ b/src/bluetooth/darwin/btdelegates.cpp @@ -0,0 +1,40 @@ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "btdelegates_p.h" + +#if defined(Q_OS_MACOS) + +QT_BEGIN_NAMESPACE + +namespace DarwinBluetooth { + +DeviceInquiryDelegate::~DeviceInquiryDelegate() +{ +} + +PairingDelegate::~PairingDelegate() +{ +} + +SDPInquiryDelegate::~SDPInquiryDelegate() +{ +} + +ChannelDelegate::~ChannelDelegate() +{ +} + +ConnectionMonitor::~ConnectionMonitor() +{ +} + +SocketListener::~SocketListener() +{ +} + +} // namespace DarwinBluetooth + +QT_END_NAMESPACE + +#endif diff --git a/src/bluetooth/darwin/btdelegates_p.h b/src/bluetooth/darwin/btdelegates_p.h new file mode 100644 index 0000000..7dd9fde --- /dev/null +++ b/src/bluetooth/darwin/btdelegates_p.h @@ -0,0 +1,107 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef BTDELEGATES_P_H +#define BTDELEGATES_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 + +#if defined(Q_OS_MACOS) + +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +class QBluetoothAddress; + +namespace DarwinBluetooth { + +class DeviceInquiryDelegate +{ +public: + virtual ~DeviceInquiryDelegate(); + + virtual void inquiryFinished() = 0; + virtual void error(IOReturn error) = 0; + virtual void classicDeviceFound(void *ioBluetoothDevice) = 0; +}; + +class PairingDelegate +{ +public: + using BluetoothNumericValue = uint32_t; + using BluetoothPasskey = BluetoothNumericValue; + + virtual ~PairingDelegate(); + + virtual void connecting(void *pair) = 0; + virtual void requestPIN(void *pair) = 0; + virtual void requestUserConfirmation(void *pair, + BluetoothNumericValue) = 0; + virtual void passkeyNotification(void *pair, + BluetoothPasskey passkey) = 0; + virtual void error(void *pair, IOReturn errorCode) = 0; + virtual void pairingFinished(void *pair) = 0; +}; + +class SDPInquiryDelegate { +public: + virtual ~SDPInquiryDelegate(); + + virtual void SDPInquiryFinished(void *ioBluetoothDevice) = 0; + virtual void SDPInquiryError(void *ioBluetoothDevice, IOReturn errorCode) = 0; +}; + +// L2CAP and RFCOMM. +class ChannelDelegate +{ +public: + virtual ~ChannelDelegate(); + + virtual void setChannelError(IOReturn errorCode) = 0; + virtual void channelOpenComplete() = 0; + virtual void channelClosed() = 0; + + virtual void readChannelData(void *data, std::size_t size) = 0; + virtual void writeComplete() = 0; +}; + +class ConnectionMonitor { +public: + virtual ~ConnectionMonitor(); + + virtual void deviceConnected(const QBluetoothAddress &address) = 0; + virtual void deviceDisconnected(const QBluetoothAddress &address) = 0; +}; + +class SocketListener +{ +public: + virtual ~SocketListener(); + + virtual void openNotifyRFCOMM(void *rfcommChannel) = 0; + virtual void openNotifyL2CAP(void *l2capChannel) = 0; +}; + + +} // namespace DarwinBluetooth + +QT_END_NAMESPACE + +#endif // Q_OS_MACOS + +#endif // DARWINBTDELEGATES_P_H diff --git a/src/bluetooth/darwin/btdeviceinquiry.mm b/src/bluetooth/darwin/btdeviceinquiry.mm new file mode 100644 index 0000000..19401ee --- /dev/null +++ b/src/bluetooth/darwin/btdeviceinquiry.mm @@ -0,0 +1,167 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "btdeviceinquiry_p.h" +#include "btutility_p.h" + +#include +#include +#include + +#include + +QT_USE_NAMESPACE + +const uint8_t IOBlueoothInquiryLengthS = 15; + +@implementation DarwinBTClassicDeviceInquiry +{ + IOBluetoothDeviceInquiry *m_inquiry; + bool m_active; + DarwinBluetooth::DeviceInquiryDelegate *m_delegate;//C++ "delegate" + + std::unique_ptr watchDog; +} + +- (id)initWithDelegate:(DarwinBluetooth::DeviceInquiryDelegate *)delegate +{ + if (self = [super init]) { + Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid device inquiry delegate (null)"); + + m_inquiry = [[IOBluetoothDeviceInquiry inquiryWithDelegate:self] retain]; + + if (m_inquiry) { + // Inquiry length is 15 seconds. Starting from macOS 10.15.7 + // (the lowest version I was able to test on, though initially + // the problem was found on macOS 11, arm64 machine and then + // confirmed on macOS 12 Beta 4), it seems to be ignored, + // thus scan never stops. See -start for how we try to prevent + // this. + [m_inquiry setInquiryLength:IOBlueoothInquiryLengthS]; + [m_inquiry setUpdateNewDeviceNames:NO];//Useless, disable! + m_delegate = delegate; + } else { + qCCritical(QT_BT_DARWIN) << "failed to create a device inquiry"; + } + + m_active = false; + } + + return self; +} + +- (void)dealloc +{ + // Noop if m_inquiry is nil. + [m_inquiry setDelegate:nil]; + if (m_active) + [m_inquiry stop]; + [m_inquiry release]; + + [super dealloc]; +} + +- (bool)isActive +{ + return m_active; +} + +- (IOReturn)start +{ + if (!m_inquiry) + return kIOReturnNoPower; + + if (m_active) + return kIOReturnBusy; + + m_active = true; + [m_inquiry clearFoundDevices]; + + qCDebug(QT_BT_DARWIN) << "Starting device inquiry with" + << IOBlueoothInquiryLengthS << "second timeout limit."; + const IOReturn result = [m_inquiry start]; + if (result != kIOReturnSuccess) { + // QtBluetooth will probably convert an error into UnknownError, + // losing the actual information. + qCWarning(QT_BT_DARWIN) << "device inquiry start failed with IOKit error code:" << result; + m_active = false; + } else { + // Docs say it's 10 s. by default, we set it to 15 s. (see -initWithDelegate:), + // and it may fail to finish. + watchDog.reset(new QTimer); + watchDog->connect(watchDog.get(), &QTimer::timeout, watchDog.get(), [self]{ + qCWarning(QT_BT_DARWIN, "Manually interrupting IOBluetoothDeviceInquiry"); + qCDebug(QT_BT_DARWIN) << "Found devices:" << [m_inquiry foundDevices]; + [self stop]; + }); + + watchDog->setSingleShot(true); + // +2 to give IOBluetooth a chance to stop it first: + watchDog->setInterval((IOBlueoothInquiryLengthS + 2) * 1000); + watchDog->start(); + } + + return result; +} + +- (IOReturn)stop +{ + if (!m_active) + return kIOReturnSuccess; + + Q_ASSERT_X(m_inquiry, Q_FUNC_INFO, "active but nil inquiry"); + + return [m_inquiry stop]; +} + +- (void)deviceInquiryComplete:(IOBluetoothDeviceInquiry *)sender + error:(IOReturn)error aborted:(BOOL)aborted +{ + qCDebug(QT_BT_DARWIN) << "deviceInquiryComplete, error:" << error + << "user-stopped:" << aborted; + if (!m_active) + return; + + if (sender != m_inquiry) // Can never happen in the current version. + return; + + Q_ASSERT_X(m_delegate, Q_FUNC_INFO, "invalid device inquiry delegate (null)"); + + if (error != kIOReturnSuccess && !aborted) { + // QtBluetooth has not too many error codes, 'UnknownError' is not really + // useful, log the actual error code here: + qCWarning(QT_BT_DARWIN) << "IOKit error code: " << error; + // Let watchDog to stop it, calling -stop at timeout, otherwise, + // it looks like inquiry continues even after this error and + // keeps reporting new devices found. + } else { + // Either a normal completion or from a timer slot. + watchDog.reset(); + m_active = false; + m_delegate->inquiryFinished(); + } +} + +- (void)deviceInquiryDeviceFound:(IOBluetoothDeviceInquiry *)sender + device:(IOBluetoothDevice *)device +{ + qCDebug(QT_BT_DARWIN) << "deviceInquiryDeviceFound:" << [device nameOrAddress]; + if (sender != m_inquiry) // Can never happen in the current version. + return; + + if (!m_active) { + // We are not expecting new device(s) to be found after we reported 'finished'. + qCWarning(QT_BT_DARWIN, "IOBluetooth device found after inquiry complete/interrupted"); + return; + } + + Q_ASSERT_X(m_delegate, Q_FUNC_INFO, "invalid device inquiry delegate (null)"); + m_delegate->classicDeviceFound(device); +} + +- (void)deviceInquiryStarted:(IOBluetoothDeviceInquiry *)sender +{ + Q_UNUSED(sender); +} + +@end diff --git a/src/bluetooth/darwin/btdeviceinquiry_p.h b/src/bluetooth/darwin/btdeviceinquiry_p.h new file mode 100644 index 0000000..66a91d5 --- /dev/null +++ b/src/bluetooth/darwin/btdeviceinquiry_p.h @@ -0,0 +1,51 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef BTDEVICEINQUIRY_P_H +#define BTDEVICEINQUIRY_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 "btdelegates_p.h" + +#include + +#include + +#include +#include + +#include + +@interface QT_MANGLE_NAMESPACE(DarwinBTClassicDeviceInquiry) : NSObject + +- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(DarwinBluetooth::DeviceInquiryDelegate) *)delegate; +- (void)dealloc; + +- (bool)isActive; +- (IOReturn)start; +- (IOReturn)stop; + +//Obj-C delegate: +- (void)deviceInquiryComplete:(IOBluetoothDeviceInquiry *)sender + error:(IOReturn)error aborted:(BOOL)aborted; + +- (void)deviceInquiryDeviceFound:(IOBluetoothDeviceInquiry *)sender + device:(IOBluetoothDevice *)device; + +- (void)deviceInquiryStarted:(IOBluetoothDeviceInquiry *)sender; + +@end + +QT_NAMESPACE_ALIAS_OBJC_CLASS(DarwinBTClassicDeviceInquiry); + +#endif diff --git a/src/bluetooth/darwin/btdevicepair.mm b/src/bluetooth/darwin/btdevicepair.mm new file mode 100644 index 0000000..e76516f --- /dev/null +++ b/src/bluetooth/darwin/btdevicepair.mm @@ -0,0 +1,179 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "btdevicepair_p.h" +#include "btutility_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +namespace DarwinBluetooth { + +ObjCStrongReference device_with_address(const QBluetoothAddress &address) +{ + if (address.isNull()) + return {}; + + const BluetoothDeviceAddress &iobtAddress = iobluetooth_address(address); + ObjCStrongReference res([IOBluetoothDevice deviceWithAddress:&iobtAddress], RetainPolicy::doInitialRetain); + return res; +} + +} // namespace DarwinBluetooth + +QT_END_NAMESPACE + +QT_USE_NAMESPACE + +@implementation DarwinBTClassicPairing +{ + QT_PREPEND_NAMESPACE(QBluetoothAddress) m_targetAddress; + + bool m_active; + IOBluetoothDevicePair *m_pairing; // The real pairing request + QT_PREPEND_NAMESPACE(DarwinBluetooth)::PairingDelegate *m_object; +} + +- (id)initWithTarget:(const QBluetoothAddress &)address + delegate:(DarwinBluetooth::PairingDelegate *)object +{ + if (self = [super init]) { + Q_ASSERT_X(!address.isNull(), Q_FUNC_INFO, "invalid target address"); + Q_ASSERT_X(object, Q_FUNC_INFO, "invalid delegate (null)"); + + m_targetAddress = address; + m_object = object; + m_active = false; + } + + return self; +} + +- (void)dealloc +{ + [m_pairing stop]; + [m_pairing release]; + [super dealloc]; +} + +- (IOReturn) start +{ + if (m_active) + return kIOReturnBusy; + + Q_ASSERT_X(!m_targetAddress.isNull(), Q_FUNC_INFO, "invalid target address"); + + QT_BT_MAC_AUTORELEASEPOOL; + + const BluetoothDeviceAddress &iobtAddress = DarwinBluetooth::iobluetooth_address(m_targetAddress); + // Device is autoreleased. + IOBluetoothDevice *const device = [IOBluetoothDevice deviceWithAddress:&iobtAddress]; + if (!device) { + qCCritical(QT_BT_DARWIN) << "failed to create a device to pair with"; + return kIOReturnError; + } + + m_pairing = [[IOBluetoothDevicePair pairWithDevice:device] retain]; + if (!m_pairing) { + qCCritical(QT_BT_DARWIN) << "failed to create a device pair"; + return kIOReturnError; + } + + [m_pairing setDelegate:self]; + const IOReturn result = [m_pairing start]; + if (result != kIOReturnSuccess) { + [m_pairing release]; + m_pairing = nil; + } else + m_active = true; + + return result; +} + +- (bool)isActive +{ + return m_active; +} + +- (void)stop +{ + // stop: stops pairing, removes the delegate + // and disconnects if device was connected. + if (m_pairing) + [m_pairing stop]; +} + +- (const QBluetoothAddress &)targetAddress +{ + return m_targetAddress; +} + +- (IOBluetoothDevicePair *)pairingRequest +{ + return [[m_pairing retain] autorelease]; +} + +- (IOBluetoothDevice *)targetDevice +{ + return [m_pairing device];//It's retained/autoreleased by pair. +} + +// IOBluetoothDevicePairDelegate: + +- (void)devicePairingStarted:(id)sender +{ + Q_UNUSED(sender); +} + +- (void)devicePairingConnecting:(id)sender +{ + Q_UNUSED(sender); +} + +- (void)deviceParingPINCodeRequest:(id)sender +{ + Q_UNUSED(sender); +} + +- (void)devicePairingUserConfirmationRequest:(id)sender + numericValue:(BluetoothNumericValue)numericValue +{ + if (sender != m_pairing) // Can never happen. + return; + + Q_ASSERT_X(m_object, Q_FUNC_INFO, "invalid delegate (null)"); + + m_object->requestUserConfirmation(self, numericValue); +} + +- (void)devicePairingUserPasskeyNotification:(id)sender + passkey:(BluetoothPasskey)passkey +{ + Q_UNUSED(sender); + Q_UNUSED(passkey); +} + +- (void)devicePairingFinished:(id)sender error:(IOReturn)error +{ + Q_ASSERT_X(m_object, Q_FUNC_INFO, "invalid delegate (null)"); + + if (sender != m_pairing) // Can never happen though. + return; + + m_active = false; + if (error != kIOReturnSuccess) + m_object->error(self, error); + else + m_object->pairingFinished(self); +} + +- (void)deviceSimplePairingComplete:(id)sender + status:(BluetoothHCIEventStatus)status +{ + Q_UNUSED(sender); + Q_UNUSED(status); +} + +@end diff --git a/src/bluetooth/darwin/btdevicepair_p.h b/src/bluetooth/darwin/btdevicepair_p.h new file mode 100644 index 0000000..1b2f9ab --- /dev/null +++ b/src/bluetooth/darwin/btdevicepair_p.h @@ -0,0 +1,77 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef BTDEVICEPAIR_P_H +#define BTDEVICEPAIR_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 "qbluetoothaddress.h" +#include "btdelegates_p.h" +#include "btutility_p.h" + +#include + +#include + +#include + +#include + +QT_BEGIN_NAMESPACE + +namespace DarwinBluetooth { + +ObjCStrongReference device_with_address(const QBluetoothAddress &address); + +} // Namespace DarwinBluetooth. + +QT_END_NAMESPACE + +@interface QT_MANGLE_NAMESPACE(DarwinBTClassicPairing) : NSObject + +- (id)initWithTarget:(const QBluetoothAddress &)address + delegate:(QT_PREPEND_NAMESPACE(DarwinBluetooth::PairingDelegate) *)object; + +- (void)dealloc; + +- (IOReturn)start; +- (bool)isActive; +- (void)stop; + +- (const QBluetoothAddress &)targetAddress; +- (IOBluetoothDevicePair *)pairingRequest; +- (IOBluetoothDevice *)targetDevice; + +// IOBluetoothDevicePairDelegate: + +- (void)devicePairingStarted:(id)sender; +- (void)devicePairingConnecting:(id)sender; +- (void)deviceParingPINCodeRequest:(id)sender; + +- (void)devicePairingUserConfirmationRequest:(id)sender + numericValue:(BluetoothNumericValue)numericValue; + +- (void)devicePairingUserPasskeyNotification:(id)sender + passkey:(BluetoothPasskey)passkey; + +- (void)devicePairingFinished:(id)sender + error:(IOReturn)error; + +- (void)deviceSimplePairingComplete:(id)sender + status:(BluetoothHCIEventStatus)status; + +@end + +QT_NAMESPACE_ALIAS_OBJC_CLASS(DarwinBTClassicPairing); + +#endif diff --git a/src/bluetooth/darwin/btgcdtimer.mm b/src/bluetooth/darwin/btgcdtimer.mm new file mode 100644 index 0000000..6b8633a --- /dev/null +++ b/src/bluetooth/darwin/btgcdtimer.mm @@ -0,0 +1,111 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "btgcdtimer_p.h" +#include "btutility_p.h" + +#include +#include + +#include + +QT_USE_NAMESPACE +using namespace DarwinBluetooth; + +@implementation DarwinBTGCDTimer { +@private + qint64 timeoutMS; + qint64 timeoutStepMS; + + // Optional: + id objectUnderWatch; + OperationTimeout timeoutType; + + QElapsedTimer timer; + id timeoutHandler; + + bool cancelled; +} + +- (instancetype)initWithDelegate:(id)delegate +{ + if (self = [super init]) { + timeoutHandler = delegate; + timeoutMS = 0; + timeoutStepMS = 0; + objectUnderWatch = nil; + timeoutType = OperationTimeout::none; + cancelled = false; + } + return self; +} + +- (void)watchAfter:(id)object withTimeoutType:(OperationTimeout)type +{ + objectUnderWatch = object; + timeoutType = type; +} + +- (void)startWithTimeout:(qint64)ms step:(qint64)stepMS +{ + Q_ASSERT(!timeoutMS && !timeoutStepMS); + Q_ASSERT(!cancelled); + + if (!timeoutHandler) { + // Nobody to report timeout to, no need to start any task then. + return; + } + + if (ms <= 0 || stepMS <= 0) { + qCWarning(QT_BT_DARWIN, "Invalid timeout/step parameters"); + return; + } + + timeoutMS = ms; + timeoutStepMS = stepMS; + timer.start(); + + [self handleTimeout]; +} + +- (void)handleTimeout +{ + if (cancelled) + return; + + const qint64 elapsed = timer.elapsed(); + if (elapsed >= timeoutMS) { + [timeoutHandler timeout:self]; + } else { + // Re-schedule: + dispatch_queue_t leQueue(qt_LE_queue()); + Q_ASSERT(leQueue); + const qint64 timeChunkMS = std::min(timeoutMS - elapsed, timeoutStepMS); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, + int64_t(timeChunkMS / 1000. * NSEC_PER_SEC)), + leQueue, + ^{ + [self handleTimeout]; + }); + } +} + +- (void)cancelTimer +{ + cancelled = true; + timeoutHandler = nil; + objectUnderWatch = nil; + timeoutType = OperationTimeout::none; +} + +- (id)objectUnderWatch +{ + return objectUnderWatch; +} + +- (OperationTimeout)timeoutType +{ + return timeoutType; +} + +@end diff --git a/src/bluetooth/darwin/btgcdtimer_p.h b/src/bluetooth/darwin/btgcdtimer_p.h new file mode 100644 index 0000000..b927336 --- /dev/null +++ b/src/bluetooth/darwin/btgcdtimer_p.h @@ -0,0 +1,74 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef BTGCDTIMER_P_H +#define BTGCDTIMER_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 "btutility_p.h" + +#include + +#include + +#include + +QT_BEGIN_NAMESPACE + +namespace DarwinBluetooth { + +enum class OperationTimeout +{ + none, + serviceDiscovery, + includedServicesDiscovery, + characteristicsDiscovery, + characteristicRead, + descriptorsDiscovery, + descriptorRead, + characteristicWrite +}; + +} // namespace DarwinBluetooth + +QT_END_NAMESPACE + +@protocol QT_MANGLE_NAMESPACE(GCDTimerDelegate) +@required +- (void)timeout:(id)sender; +@end + +@interface QT_MANGLE_NAMESPACE(DarwinBTGCDTimer) : NSObject +- (instancetype)initWithDelegate:(id)delegate; +- (void)watchAfter:(id)object withTimeoutType:(QT_PREPEND_NAMESPACE(DarwinBluetooth)::OperationTimeout)type; +- (void)startWithTimeout:(qint64)ms step:(qint64)stepMS; +- (void)handleTimeout; +- (void)cancelTimer; +- (id)objectUnderWatch; +- (QT_PREPEND_NAMESPACE(DarwinBluetooth)::OperationTimeout)timeoutType; +@end + +QT_NAMESPACE_ALIAS_OBJC_CLASS(DarwinBTGCDTimer); + +QT_BEGIN_NAMESPACE + +namespace DarwinBluetooth { + +using GCDTimer = ObjCStrongReference; + +} // namespace DarwinBluetooth + +QT_END_NAMESPACE + +#endif // BTGCDTIMER_P_H + diff --git a/src/bluetooth/darwin/btl2capchannel.mm b/src/bluetooth/darwin/btl2capchannel.mm new file mode 100644 index 0000000..17c1d16 --- /dev/null +++ b/src/bluetooth/darwin/btl2capchannel.mm @@ -0,0 +1,222 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothaddress.h" +#include "btl2capchannel_p.h" +#include "btdelegates_p.h" +#include "btutility_p.h" + +#include +#include + +QT_USE_NAMESPACE + +@implementation DarwinBTL2CAPChannel +{ + QT_PREPEND_NAMESPACE(DarwinBluetooth)::ChannelDelegate *delegate; + IOBluetoothDevice *device; + IOBluetoothL2CAPChannel *channel; + bool connected; +} + +- (id)initWithDelegate:(DarwinBluetooth::ChannelDelegate *)aDelegate +{ + Q_ASSERT_X(aDelegate, Q_FUNC_INFO, "invalid delegate (null)"); + + if (self = [super init]) { + delegate = aDelegate; + device = nil; + channel = nil; + connected = false; + } + + return self; +} + +- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(DarwinBluetooth::ChannelDelegate) *)aDelegate + channel:(IOBluetoothL2CAPChannel *)aChannel +{ + // This type of channel does not require connect, it's created with + // already open channel. + Q_ASSERT_X(aDelegate, Q_FUNC_INFO, "invalid delegate (null)"); + Q_ASSERT_X(channel, Q_FUNC_INFO, "invalid channel (nil)"); + + if (self = [super init]) { + delegate = aDelegate; + channel = [aChannel retain]; + [channel setDelegate:self]; + device = [channel.device retain]; + connected = true; + } + + return self; +} + +- (void)dealloc +{ + // TODO: test if this implementation works at all! + if (channel) { + [channel setDelegate:nil]; + // From Apple's docs: + // "This method may only be called by the client that opened the channel + // in the first place. In the future asynchronous and synchronous versions + // will be provided that let the client know when the close process has been finished." + [channel closeChannel]; + [channel release]; + } + + [device release]; + + [super dealloc]; +} + +- (IOReturn)connectAsyncToDevice:(const QBluetoothAddress &)address + withPSM:(BluetoothL2CAPChannelID)psm +{ + if (address.isNull()) { + qCCritical(QT_BT_DARWIN) << "invalid peer address"; + return kIOReturnNoDevice; + } + + // Can never be called twice. + if (connected || device || channel) { + qCCritical(QT_BT_DARWIN) << "connection is already active"; + return kIOReturnStillOpen; + } + + QT_BT_MAC_AUTORELEASEPOOL; + + const BluetoothDeviceAddress iobtAddress = DarwinBluetooth::iobluetooth_address(address); + device = [IOBluetoothDevice deviceWithAddress:&iobtAddress]; + if (!device) { + qCCritical(QT_BT_DARWIN) << "failed to create a device"; + return kIOReturnNoDevice; + } + + const IOReturn status = [device openL2CAPChannelAsync:&channel withPSM:psm delegate:self]; + if (status != kIOReturnSuccess) { + qCCritical(QT_BT_DARWIN) << "failed to open L2CAP channel"; + // device is still autoreleased. + device = nil; + return status; + } + + [channel retain];// What if we're closed already? + [device retain]; + + return kIOReturnSuccess; +} + +// IOBluetoothL2CAPChannelDelegate: + +- (void)l2capChannelData:(IOBluetoothL2CAPChannel*)l2capChannel + data:(void *)dataPointer length:(size_t)dataLength +{ + Q_UNUSED(l2capChannel); + + Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)"); + + if (dataPointer && dataLength) + delegate->readChannelData(dataPointer, dataLength); +} + +- (void)l2capChannelOpenComplete:(IOBluetoothL2CAPChannel*) + l2capChannel status:(IOReturn)error +{ + Q_UNUSED(l2capChannel); + + Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)"); + + if (error != kIOReturnSuccess) { + delegate->setChannelError(error); + } else { + connected = true; + delegate->channelOpenComplete(); + } +} + +- (void)l2capChannelClosed:(IOBluetoothL2CAPChannel*)l2capChannel +{ + Q_UNUSED(l2capChannel); + + Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)"); + delegate->channelClosed(); + connected = false; +} + +- (void)l2capChannelReconfigured:(IOBluetoothL2CAPChannel*)l2capChannel +{ + Q_UNUSED(l2capChannel); +} + +- (void)l2capChannelWriteComplete:(IOBluetoothL2CAPChannel*)l2capChannel + refcon:(void*)refcon status:(IOReturn)error +{ + Q_UNUSED(l2capChannel); + Q_UNUSED(refcon); + + Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)"); + + if (error != kIOReturnSuccess) + delegate->setChannelError(error); + else + delegate->writeComplete(); +} + +- (void)l2capChannelQueueSpaceAvailable:(IOBluetoothL2CAPChannel*)l2capChannel +{ + Q_UNUSED(l2capChannel); +} + +// Aux. methods. +- (BluetoothL2CAPPSM)getPSM +{ + if (channel) + return channel.PSM; + + return 0; +} + +- (BluetoothDeviceAddress)peerAddress +{ + const BluetoothDeviceAddress *const addr = device ? [device getAddress] + : nullptr; + if (addr) + return *addr; + + return BluetoothDeviceAddress(); +} + +- (NSString *)peerName +{ + if (device) + return device.name; + + return nil; +} + +- (bool)isConnected +{ + return connected; +} + +- (IOReturn) writeSync:(void*)data length:(UInt16)length +{ + Q_ASSERT_X(data, Q_FUNC_INFO, "invalid data (null)"); + Q_ASSERT_X(length, Q_FUNC_INFO, "invalid data size"); + Q_ASSERT_X(connected && channel, Q_FUNC_INFO, "invalid L2CAP channel"); + + return [channel writeSync:data length:length]; +} + +- (IOReturn) writeAsync:(void*)data length:(UInt16)length +{ + Q_ASSERT_X(data, Q_FUNC_INFO, "invalid data (null)"); + Q_ASSERT_X(length, Q_FUNC_INFO, "invalid data size"); + Q_ASSERT_X(connected && channel, Q_FUNC_INFO, "invalid L2CAP channel"); + + return [channel writeAsync:data length:length refcon:nullptr]; +} + + +@end diff --git a/src/bluetooth/darwin/btl2capchannel_p.h b/src/bluetooth/darwin/btl2capchannel_p.h new file mode 100644 index 0000000..68d24ab --- /dev/null +++ b/src/bluetooth/darwin/btl2capchannel_p.h @@ -0,0 +1,85 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef BTL2CAPCHANNEL_P_H +#define BTL2CAPCHANNEL_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 QBluetoothAddress; + +namespace DarwinBluetooth { + +class ChannelDelegate; + +} + +QT_END_NAMESPACE + +@interface QT_MANGLE_NAMESPACE(DarwinBTL2CAPChannel) : NSObject + +- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(DarwinBluetooth)::ChannelDelegate *)aDelegate; +- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(DarwinBluetooth)::ChannelDelegate *)aDelegate + channel:(IOBluetoothL2CAPChannel *)aChannel; + +- (void)dealloc; + +// Async. connection (connect can be called only once). +- (IOReturn)connectAsyncToDevice:(const QT_PREPEND_NAMESPACE(QBluetoothAddress) &)address + withPSM:(BluetoothL2CAPChannelID)psm; + +// IOBluetoothL2CAPChannelDelegate: +- (void)l2capChannelData:(IOBluetoothL2CAPChannel*)l2capChannel + data:(void *)dataPointer length:(size_t)dataLength; +- (void)l2capChannelOpenComplete:(IOBluetoothL2CAPChannel*) + l2capChannel status:(IOReturn)error; +- (void)l2capChannelClosed:(IOBluetoothL2CAPChannel*)l2capChannel; +- (void)l2capChannelReconfigured:(IOBluetoothL2CAPChannel*)l2capChannel; +- (void)l2capChannelWriteComplete:(IOBluetoothL2CAPChannel*)l2capChannel + refcon:(void*)refcon status:(IOReturn)error; +- (void)l2capChannelQueueSpaceAvailable:(IOBluetoothL2CAPChannel*)l2capChannel; + +// +- (BluetoothL2CAPPSM)getPSM; +- (BluetoothDeviceAddress)peerAddress; +- (NSString *)peerName; +- (bool)isConnected; + +// Writes the given data synchronously over the target L2CAP channel to the remote +// device. +// The length of the data may not exceed the L2CAP channel's outgoing MTU. +// This method will block until the data has been successfully sent to the +// hardware for transmission (or an error occurs). +- (IOReturn) writeSync:(void*)data length:(UInt16)length; + +// The length of the data may not exceed the L2CAP channel's outgoing MTU. +// When the data has been successfully passed to the hardware to be transmitted, +// the delegate method -l2capChannelWriteComplete:refcon:status: will be called. +// Returns kIOReturnSuccess if the data was buffered successfully. +- (IOReturn) writeAsync:(void*)data length:(UInt16)length; + +@end + +QT_NAMESPACE_ALIAS_OBJC_CLASS(DarwinBTL2CAPChannel); + +#endif diff --git a/src/bluetooth/darwin/btledeviceinquiry.mm b/src/bluetooth/darwin/btledeviceinquiry.mm new file mode 100644 index 0000000..2611aae --- /dev/null +++ b/src/bluetooth/darwin/btledeviceinquiry.mm @@ -0,0 +1,353 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothdeviceinfo.h" +#include "btledeviceinquiry_p.h" +#include "qbluetoothuuid.h" +#include "btnotifier_p.h" +#include "btutility_p.h" + +#include +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +namespace DarwinBluetooth { + +QBluetoothUuid qt_uuid(NSUUID *nsUuid) +{ + if (!nsUuid) + return QBluetoothUuid(); + + uuid_t uuidData = {}; + [nsUuid getUUIDBytes:uuidData]; + QUuid::Id128Bytes qtUuidData = {}; + std::copy(uuidData, uuidData + 16, qtUuidData.data); + return QBluetoothUuid(qtUuidData); +} + +const int timeStepMS = 100; +const int powerOffTimeoutMS = 30000; + +struct AdvertisementData { + // That's what CoreBluetooth has: + // CBAdvertisementDataLocalNameKey + // CBAdvertisementDataTxPowerLevelKey + // CBAdvertisementDataServiceUUIDsKey + // CBAdvertisementDataServiceDataKey + // CBAdvertisementDataManufacturerDataKey + // CBAdvertisementDataOverflowServiceUUIDsKey + // CBAdvertisementDataIsConnectable + // CBAdvertisementDataSolicitedServiceUUIDsKey + + // For now, we "parse": + QString localName; + QList serviceUuids; + QHash manufacturerData; + QHash serviceData; + // TODO: other keys probably? + AdvertisementData(NSDictionary *AdvertisementData); +}; + +AdvertisementData::AdvertisementData(NSDictionary *advertisementData) +{ + if (!advertisementData) + return; + + // ... constant CBAdvertisementDataLocalNameKey ... + // NSString containing the local name of a peripheral. + NSObject *value = [advertisementData objectForKey:CBAdvertisementDataLocalNameKey]; + if (value && [value isKindOfClass:[NSString class]]) + localName = QString::fromNSString(static_cast(value)); + + // ... constant CBAdvertisementDataServiceUUIDsKey ... + // A list of one or more CBUUID objects, representing CBService UUIDs. + + value = [advertisementData objectForKey:CBAdvertisementDataServiceUUIDsKey]; + if (value && [value isKindOfClass:[NSArray class]]) { + NSArray *uuids = static_cast(value); + for (CBUUID *cbUuid in uuids) + serviceUuids << qt_uuid(cbUuid); + } + + NSDictionary *advdict = [advertisementData objectForKey:CBAdvertisementDataServiceDataKey]; + if (advdict) { + [advdict enumerateKeysAndObjectsUsingBlock:^(CBUUID *key, NSData *val, BOOL *) { + serviceData.insert(qt_uuid(key), QByteArray::fromNSData(static_cast(val))); + }]; + } + + value = [advertisementData objectForKey:CBAdvertisementDataManufacturerDataKey]; + if (value && [value isKindOfClass:[NSData class]]) { + QByteArray data = QByteArray::fromNSData(static_cast(value)); + manufacturerData.insert(qFromLittleEndian(data.constData()), data.mid(2)); + } +} + +} + +QT_END_NAMESPACE + +QT_USE_NAMESPACE + +@interface DarwinBTLEDeviceInquiry (PrivateAPI) +- (void)stopScanSafe; +- (void)stopNotifier; +@end + +@implementation DarwinBTLEDeviceInquiry +{ + LECBManagerNotifier *notifier; + ObjCScopedPointer manager; + + QList devices; + LEInquiryState internalState; + int inquiryTimeoutMS; + + QT_PREPEND_NAMESPACE(DarwinBluetooth)::GCDTimer elapsedTimer; +} + +-(id)initWithNotifier:(LECBManagerNotifier *)aNotifier +{ + if (self = [super init]) { + Q_ASSERT(aNotifier); + notifier = aNotifier; + internalState = InquiryStarting; + inquiryTimeoutMS = DarwinBluetooth::defaultLEScanTimeoutMS; + } + + return self; +} + +- (void)dealloc +{ + [self stopScanSafe]; + [manager setDelegate:nil]; + [elapsedTimer cancelTimer]; + [self stopNotifier]; + [super dealloc]; +} + +- (void)timeout:(id)sender +{ + Q_UNUSED(sender); + + if (internalState == InquiryActive) { + [self stopScanSafe]; + [manager setDelegate:nil]; + internalState = InquiryFinished; + Q_ASSERT(notifier); + emit notifier->discoveryFinished(); + } else if (internalState == InquiryStarting) { + // This is interesting on iOS only, where the system shows an alert + // asking to enable Bluetooth in the 'Settings' app. If not done yet + // (after 30 seconds) - we consider this as an error. + [manager setDelegate:nil]; + internalState = ErrorPoweredOff; + Q_ASSERT(notifier); + emit notifier->CBManagerError(QBluetoothDeviceDiscoveryAgent::PoweredOffError); + } +} + +- (void)startWithTimeout:(int)timeout +{ + dispatch_queue_t leQueue(DarwinBluetooth::qt_LE_queue()); + Q_ASSERT(leQueue); + inquiryTimeoutMS = timeout; + manager.reset([[CBCentralManager alloc] initWithDelegate:self queue:leQueue], + DarwinBluetooth::RetainPolicy::noInitialRetain); +} + +- (void)centralManagerDidUpdateState:(CBCentralManager *)central +{ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability-new" + + if (central != manager) + return; + + if (internalState != InquiryActive && internalState != InquiryStarting) + return; + + Q_ASSERT(notifier); + + using namespace DarwinBluetooth; + + const auto state = central.state; + if (state == CBManagerStatePoweredOn) { + if (internalState == InquiryStarting) { + internalState = InquiryActive; + + if (inquiryTimeoutMS > 0) { + [elapsedTimer cancelTimer]; + elapsedTimer.reset([[DarwinBTGCDTimer alloc] initWithDelegate:self], RetainPolicy::noInitialRetain); + [elapsedTimer startWithTimeout:inquiryTimeoutMS step:timeStepMS]; + } + + // ### Qt 6.x: remove the use of env. variable, as soon as a proper public API is in place. + bool envOk = false; + const int env = qEnvironmentVariableIntValue("QT_BLUETOOTH_SCAN_ENABLE_DUPLICATES", &envOk); + if (envOk && env) { + [manager scanForPeripheralsWithServices:nil + options:@{CBCentralManagerScanOptionAllowDuplicatesKey : @YES}]; + } else { + [manager scanForPeripheralsWithServices:nil options:nil]; + } + } // Else we ignore. + } else if (state == CBManagerStateUnsupported) { + if (internalState == InquiryActive) { + [self stopScanSafe]; + // Not sure how this is possible at all, + // probably, can never happen. + internalState = ErrorPoweredOff; + emit notifier->CBManagerError(QBluetoothDeviceDiscoveryAgent::PoweredOffError); + } else { + internalState = ErrorLENotSupported; + emit notifier->LEnotSupported(); + } + [manager setDelegate:nil]; + } else if (state == CBManagerStateUnauthorized) { + if (internalState == InquiryActive) + [self stopScanSafe]; + internalState = ErrorNotAuthorized; + emit notifier->CBManagerError(QBluetoothDeviceDiscoveryAgent::MissingPermissionsError); + [manager setDelegate:nil]; + } else if (state == CBManagerStatePoweredOff) { + +#ifndef Q_OS_MACOS + if (internalState == InquiryStarting) { + // On iOS a user can see at this point an alert asking to + // enable Bluetooth in the "Settings" app. If a user does so, + // we'll receive 'PoweredOn' state update later. + // No change in internalState. Wait for 30 seconds. + [elapsedTimer cancelTimer]; + elapsedTimer.reset([[DarwinBTGCDTimer alloc] initWithDelegate:self], RetainPolicy::noInitialRetain); + [elapsedTimer startWithTimeout:powerOffTimeoutMS step:300]; + return; + } +#else + Q_UNUSED(powerOffTimeoutMS); +#endif // Q_OS_MACOS + [elapsedTimer cancelTimer]; + [self stopScanSafe]; + [manager setDelegate:nil]; + internalState = ErrorPoweredOff; + // On macOS we report PoweredOffError and our C++ owner will delete us + // (here we're kwnon as 'self'). Connection is Qt::QueuedConnection so we + // are apparently safe to call -stopNotifier after the signal. + emit notifier->CBManagerError(QBluetoothDeviceDiscoveryAgent::PoweredOffError); + [self stopNotifier]; + } else { + // The following two states we ignore (from Apple's docs): + //" + // -CBCentralManagerStateUnknown + // The current state of the central manager is unknown; + // an update is imminent. + // + // -CBCentralManagerStateResetting + // The connection with the system service was momentarily + // lost; an update is imminent. " + // Wait for this imminent update. + } + +#pragma clang diagnostic pop +} + +- (void)stopScanSafe +{ + // CoreBluetooth warns about API misused if we call stopScan in a state + // other than powered on. Hence this 'Safe' ... + if (!manager) + return; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability-new" + + if (internalState == InquiryActive) { + const auto state = manager.get().state; + if (state == CBManagerStatePoweredOn) + [manager stopScan]; + } + +#pragma clang diagnostic pop +} + +- (void)stopNotifier +{ + if (notifier) { + notifier->disconnect(); + notifier->deleteLater(); + notifier = nullptr; + } +} + +- (void)stop +{ + [self stopScanSafe]; + [manager setDelegate:nil]; + [elapsedTimer cancelTimer]; + [self stopNotifier]; + internalState = InquiryCancelled; +} + +- (void)centralManager:(CBCentralManager *)central + didDiscoverPeripheral:(CBPeripheral *)peripheral + advertisementData:(NSDictionary *)advertisementData + RSSI:(NSNumber *)RSSI +{ + using namespace DarwinBluetooth; + + if (central != manager) + return; + + if (internalState != InquiryActive) + return; + + if (!notifier) + return; + + QBluetoothUuid deviceUuid; + + if (!peripheral.identifier) { + qCWarning(QT_BT_DARWIN) << "peripheral without NSUUID"; + return; + } + + deviceUuid = DarwinBluetooth::qt_uuid(peripheral.identifier); + + if (deviceUuid.isNull()) { + qCWarning(QT_BT_DARWIN) << "no way to address peripheral, QBluetoothUuid is null"; + return; + } + + const AdvertisementData qtAdvData(advertisementData); + QString name(qtAdvData.localName); + if (!name.size() && peripheral.name) + name = QString::fromNSString(peripheral.name); + + // TODO: fix 'classOfDevice' (0 for now). + QBluetoothDeviceInfo newDeviceInfo(deviceUuid, name, 0); + if (RSSI) + newDeviceInfo.setRssi([RSSI shortValue]); + + if (qtAdvData.serviceUuids.size()) + newDeviceInfo.setServiceUuids(qtAdvData.serviceUuids); + + const QList keysManufacturer = qtAdvData.manufacturerData.keys(); + for (quint16 key : keysManufacturer) + newDeviceInfo.setManufacturerData(key, qtAdvData.manufacturerData.value(key)); + + const QList keysService = qtAdvData.serviceData.keys(); + for (QBluetoothUuid key : keysService) + newDeviceInfo.setServiceData(key, qtAdvData.serviceData.value(key)); + + // CoreBluetooth scans only for LE devices. + newDeviceInfo.setCoreConfigurations(QBluetoothDeviceInfo::LowEnergyCoreConfiguration); + emit notifier->deviceDiscovered(newDeviceInfo); +} + +@end diff --git a/src/bluetooth/darwin/btledeviceinquiry_p.h b/src/bluetooth/darwin/btledeviceinquiry_p.h new file mode 100644 index 0000000..edc393d --- /dev/null +++ b/src/bluetooth/darwin/btledeviceinquiry_p.h @@ -0,0 +1,71 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef BTLEDEVICEINQUIRY_P_H +#define BTLEDEVICEINQUIRY_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 "qbluetoothdevicediscoveryagent.h" +#include "qbluetoothdeviceinfo.h" +#include "btgcdtimer_p.h" +#include "btutility_p.h" + +#include + +#include + +#include + +#include + +QT_BEGIN_NAMESPACE + +class QBluetoothUuid; + +namespace DarwinBluetooth +{ + +class LECBManagerNotifier; + +} // namespace DarwinBluetooth + +QT_END_NAMESPACE + +using QT_PREPEND_NAMESPACE(DarwinBluetooth)::LECBManagerNotifier; +using QT_PREPEND_NAMESPACE(DarwinBluetooth)::ObjCScopedPointer; + +enum LEInquiryState +{ + InquiryStarting, + InquiryActive, + InquiryFinished, + InquiryCancelled, + ErrorPoweredOff, + ErrorLENotSupported, + ErrorNotAuthorized +}; + +@interface QT_MANGLE_NAMESPACE(DarwinBTLEDeviceInquiry) : NSObject +- (id)initWithNotifier:(LECBManagerNotifier *)aNotifier; +- (void)dealloc; + +// IMPORTANT: both 'startWithTimeout' and 'stop' MUST be executed on the "Qt's +// LE queue". +- (void)startWithTimeout:(int)timeout; +- (void)stop; + +@end + +QT_NAMESPACE_ALIAS_OBJC_CLASS(DarwinBTLEDeviceInquiry); + +#endif diff --git a/src/bluetooth/darwin/btnotifier.cpp b/src/bluetooth/darwin/btnotifier.cpp new file mode 100644 index 0000000..6ab7e47 --- /dev/null +++ b/src/bluetooth/darwin/btnotifier.cpp @@ -0,0 +1,4 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "btnotifier_p.h" diff --git a/src/bluetooth/darwin/btnotifier_p.h b/src/bluetooth/darwin/btnotifier_p.h new file mode 100644 index 0000000..64a285e --- /dev/null +++ b/src/bluetooth/darwin/btnotifier_p.h @@ -0,0 +1,71 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef BTNOTIFIER_P_H +#define BTNOTIFIER_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 "qbluetoothdevicediscoveryagent.h" +#include "qlowenergycontroller.h" +#include "qbluetoothdeviceinfo.h" +#include "qbluetoothuuid.h" +#include "qbluetooth.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QLowEnergyServicePrivate; + +namespace DarwinBluetooth +{ + +class LECBManagerNotifier : public QObject +{ + Q_OBJECT + +Q_SIGNALS: + void deviceDiscovered(QBluetoothDeviceInfo deviceInfo); + void discoveryFinished(); + + void connected(); + void disconnected(); + + void mtuChanged(int newValue); + + void serviceDiscoveryFinished(); + void serviceDetailsDiscoveryFinished(QSharedPointer service); + void characteristicRead(QLowEnergyHandle charHandle, const QByteArray &value); + void characteristicWritten(QLowEnergyHandle charHandle, const QByteArray &value); + void characteristicUpdated(QLowEnergyHandle charHandle, const QByteArray &value); + void descriptorRead(QLowEnergyHandle descHandle, const QByteArray &value); + void descriptorWritten(QLowEnergyHandle descHandle, const QByteArray &value); + void notificationEnabled(QLowEnergyHandle charHandle, bool enabled); + void servicesWereModified(); + void rssiUpdated(qint16 newValue); + + void LEnotSupported(); + void CBManagerError(QBluetoothDeviceDiscoveryAgent::Error error); + void CBManagerError(QLowEnergyController::Error error); + void CBManagerError(const QBluetoothUuid &serviceUuid, QLowEnergyController::Error error); + void CBManagerError(const QBluetoothUuid &serviceUuid, QLowEnergyService::ServiceError error); +}; + +} // namespace DarwinBluetooth + +QT_END_NAMESPACE + +#endif diff --git a/src/bluetooth/darwin/btperipheralmanager.mm b/src/bluetooth/darwin/btperipheralmanager.mm new file mode 100644 index 0000000..78a328c --- /dev/null +++ b/src/bluetooth/darwin/btperipheralmanager.mm @@ -0,0 +1,834 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qlowenergyadvertisingparameters.h" +#include "qlowenergycharacteristicdata.h" +#include "qlowenergydescriptordata.h" +#include "btperipheralmanager_p.h" +#include "qlowenergyservicedata.h" +#include "btnotifier_p.h" +#include "qbluetooth.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace +{ + +CBCharacteristicProperties cb_properties(const QLowEnergyCharacteristicData &data) +{ + // Direct 'mapping' is ok. + return CBCharacteristicProperties(int(data.properties())); +} + +CBAttributePermissions cb_permissions(const QLowEnergyCharacteristicData &data) +{ + using QLEC = QLowEnergyCharacteristic; + + const auto props = data.properties(); + CBAttributePermissions cbFlags = {}; + + if ((props & QLEC::Write) || (props & QLEC::WriteNoResponse) + || (props & QLEC::WriteSigned)) { + cbFlags = CBAttributePermissions(cbFlags | CBAttributePermissionsWriteable); + } + + if (props & QLEC::Read) + cbFlags = CBAttributePermissions(cbFlags | CBAttributePermissionsReadable); + + if (data.writeConstraints() & QBluetooth::AttAccessConstraint::AttEncryptionRequired) + cbFlags = CBAttributePermissions(cbFlags | CBAttributePermissionsWriteEncryptionRequired); + + if (data.readConstraints() & QBluetooth::AttAccessConstraint::AttEncryptionRequired) + cbFlags = CBAttributePermissions(cbFlags | CBAttributePermissionsReadEncryptionRequired); + + return cbFlags; +} + +ObjCStrongReference create_characteristic(const QLowEnergyCharacteristicData &data) +{ + const ObjCStrongReference ch([[CBMutableCharacteristic alloc] initWithType:cb_uuid(data.uuid()) + properties:cb_properties(data) + value:nil + permissions:cb_permissions(data)], + RetainPolicy::noInitialRetain); + return ch; +} + +ObjCStrongReference create_descriptor(const QLowEnergyDescriptorData &data) +{ + // CoreBluetooth supports only: + /* + "That said, only two of these are currently supported when creating local, + mutable descriptors: the characteristic user description descriptor and + the characteristic format descriptor, represented by the CBUUID constants + CBUUIDCharacteristicUserDescriptionString and CBUUIDCharacteristicFormatString" + */ + + if (data.uuid() != QBluetoothUuid::DescriptorType::CharacteristicUserDescription && + data.uuid() != QBluetoothUuid::DescriptorType::CharacteristicPresentationFormat) { + qCWarning(QT_BT_DARWIN) << "unsupported descriptor" << data.uuid(); + return {}; + } + + QT_BT_MAC_AUTORELEASEPOOL + + // Descriptors are immutable with CoreBluetooth, that's why we + // have to provide a value here and not able to change it later. + ObjCStrongReference value; + if (data.uuid() == QBluetoothUuid::DescriptorType::CharacteristicUserDescription) { + const QString asQString(QString::fromUtf8(data.value())); + value.reset(asQString.toNSString(), RetainPolicy::doInitialRetain); // toNSString is auto-released, we have to retain. + } else { + const auto nsData = data_from_bytearray(data.value()); + value.reset(nsData.data(), RetainPolicy::doInitialRetain); + } + + const ObjCStrongReference d([[CBMutableDescriptor alloc] + initWithType:cb_uuid(data.uuid()) + value:value], RetainPolicy::noInitialRetain); + return d; +} + +quint32 qt_countGATTEntries(const QLowEnergyServiceData &data) +{ + const auto maxu32 = std::numeric_limits::max(); + // + 1 for a service itself. + quint32 nEntries = 1 + quint32(data.includedServices().size()); + for (const auto &ch : data.characteristics()) { + if (maxu32 - 2 < nEntries) + return {}; + nEntries += 2; + if (maxu32 - ch.descriptors().size() < nEntries) + return {}; + nEntries += ch.descriptors().size(); + } + + return nEntries; +} + +bool qt_validate_value_range(const QLowEnergyCharacteristicData &data) +{ + if (data.minimumValueLength() > data.maximumValueLength() + || data.minimumValueLength() < 0) { + return false; + } + + return data.value().size() <= data.maximumValueLength(); +} + +} + +@interface DarwinBTPeripheralManager (PrivateAPI) + +- (void)addConnectedCentral:(CBCentral *)central; +- (CBService *)findIncludedService:(const QBluetoothUuid &)qtUUID; + +- (void)addIncludedServices:(const QLowEnergyServiceData &)data + to:(CBMutableService *)cbService + qtService:(QLowEnergyServicePrivate *)qtService; + +- (void)addCharacteristicsAndDescriptors:(const QLowEnergyServiceData &)data + to:(CBMutableService *)cbService + qtService:(QLowEnergyServicePrivate *)qtService; + +- (CBATTError)validateWriteRequest:(CBATTRequest *)request; + +@end + +@implementation DarwinBTPeripheralManager +{ + ObjCScopedPointer manager; + LECBManagerNotifier *notifier; + + QLowEnergyHandle lastHandle; + // Services in this vector are placed in such order: + // the one that has included services, must + // follow its included services to avoid exceptions from CBPeripheralManager. + std::vector> services; + decltype(services.size()) nextServiceToAdd; + + // Lookup map for included services: + std::map serviceIndex; + ObjCScopedPointer advertisementData; + + GenericLEMap charMap; + GenericLEMap> charValues; + + QMap valueRanges; + + std::deque updateQueue; + + PeripheralState state; + NSUInteger maxNotificationValueLength; + decltype(services.size()) nOfFailedAds; +} + +- (id)initWith:(LECBManagerNotifier *)aNotifier +{ + if (self = [super init]) { + Q_ASSERT(aNotifier); + notifier = aNotifier; + state = PeripheralState::idle; + nextServiceToAdd = {}; + maxNotificationValueLength = std::numeric_limits::max(); + } + + return self; +} + +- (void)dealloc +{ + [self detach]; + [super dealloc]; +} + +- (QSharedPointer)addService:(const QLowEnergyServiceData &)data +{ + using QLES = QLowEnergyService; + using namespace DarwinBluetooth; + + const auto nEntries = qt_countGATTEntries(data); + if (!nEntries || nEntries > std::numeric_limits::max() - lastHandle) { + qCCritical(QT_BT_DARWIN) << "addService: not enough handles"; + return {}; + } + + QT_BT_MAC_AUTORELEASEPOOL + + const BOOL primary = data.type() == QLowEnergyServiceData::ServiceTypePrimary; + const auto cbUUID = cb_uuid(data.uuid()); + + const ObjCStrongReference + newCBService([[CBMutableService alloc] initWithType:cbUUID primary:primary], + RetainPolicy::noInitialRetain); + + if (!newCBService) { + qCCritical(QT_BT_DARWIN) << "addService: failed to create CBMutableService"; + return {}; + } + + auto newQtService = QSharedPointer::create(); + newQtService->state = QLowEnergyService::LocalService; + newQtService->uuid = data.uuid(); + newQtService->type = primary ? QLES::PrimaryService : QLES::IncludedService; + newQtService->startHandle = ++lastHandle; + // Controller will be set by ... controller :) + + [self addIncludedServices:data to:newCBService qtService:newQtService.data()]; + [self addCharacteristicsAndDescriptors:data to:newCBService qtService:newQtService.data()]; + + services.push_back(newCBService); + serviceIndex[data.uuid()] = newCBService; + + newQtService->endHandle = lastHandle; + + return newQtService; +} + +- (void) setParameters:(const QLowEnergyAdvertisingParameters &)parameters + data:(const QLowEnergyAdvertisingData &)data + scanResponse:(const QLowEnergyAdvertisingData &)scanResponse +{ + Q_UNUSED(parameters); + + // This is the last method we call on the controller's thread + // before starting advertising on the Qt's LE queue. + // From Apple's docs: + /* + - (void)startAdvertising:(NSDictionary *)advertisementData + + Advertises peripheral manager data. + + * advertisementData + + - An optional dictionary containing the data you want to advertise. + The possible keys of an advertisementData dictionary are detailed in CBCentralManagerDelegate + Protocol Reference. That said, only two of the keys are supported for peripheral manager objects: + CBAdvertisementDataLocalNameKey and CBAdvertisementDataServiceUUIDsKey. + */ + + QT_BT_MAC_AUTORELEASEPOOL + + advertisementData.reset([[NSMutableDictionary alloc] init], + DarwinBluetooth::RetainPolicy::noInitialRetain); + if (!advertisementData) { + qCWarning(QT_BT_DARWIN) << "setParameters: failed to allocate " + "NSMutableDictonary (advertisementData)"; + return; + } + + auto localName = scanResponse.localName(); + if (!localName.size()) + localName = data.localName(); + + if (localName.size()) { + [advertisementData setObject:localName.toNSString() + forKey:CBAdvertisementDataLocalNameKey]; + } + + if (data.services().isEmpty() && scanResponse.services().isEmpty()) + return; + + const ObjCScopedPointer uuids([[NSMutableArray alloc] init], + DarwinBluetooth::RetainPolicy::noInitialRetain); + if (!uuids) { + qCWarning(QT_BT_DARWIN) << "setParameters: failed to allocate " + "NSMutableArray (services uuids)"; + return; + } + + + for (const auto &qtUUID : data.services()) { + const auto cbUUID = cb_uuid(qtUUID); + if (cbUUID) + [uuids addObject:cbUUID]; + } + + for (const auto &qtUUID : scanResponse.services()) { + const auto cbUUID = cb_uuid(qtUUID); + if (cbUUID) + [uuids addObject:cbUUID]; + } + + if ([uuids count]) { + [advertisementData setObject:uuids + forKey:CBAdvertisementDataServiceUUIDsKey]; + } +} + +- (void)startAdvertising +{ + state = PeripheralState::waitingForPowerOn; + if (manager) + [manager setDelegate:nil]; + manager.reset([[CBPeripheralManager alloc] initWithDelegate:self + queue:DarwinBluetooth::qt_LE_queue()], + DarwinBluetooth::RetainPolicy::noInitialRetain); +} + +- (void)stopAdvertising +{ + [manager stopAdvertising]; + state = PeripheralState::idle; +} + +- (void)detach +{ + if (notifier) { + notifier->disconnect(); + notifier->deleteLater(); + notifier = nullptr; + } + + if (state == PeripheralState::advertising) { + [manager stopAdvertising]; + [manager setDelegate:nil]; + state = PeripheralState::idle; + } +} + +- (void)write:(const QByteArray &)value + charHandle:(QLowEnergyHandle)charHandle +{ + using namespace DarwinBluetooth; + + if (!notifier) + return; + + QT_BT_MAC_AUTORELEASEPOOL + + if (!charMap.contains(charHandle) || !valueRanges.contains(charHandle)) { + emit notifier->CBManagerError(QLowEnergyController::UnknownError); + return; + } + + const auto & range = valueRanges[charHandle]; + if (value.size() < qsizetype(range.first) || value.size() > qsizetype(range.second) +#ifdef Q_OS_IOS + || value.size() > DarwinBluetooth::maxValueLength) { +#else + ) { +#endif + qCWarning(QT_BT_DARWIN) << "ignoring value of invalid length" << value.size(); + return; + } + + emit notifier->characteristicWritten(charHandle, value); + + const auto nsData = mutable_data_from_bytearray(value); + charValues[charHandle] = nsData; + // We copy data here: sending update requests is async (see sendUpdateRequests), + // by the time we're allowed to actually send them, the data can change again + // and we'll send an 'out of order' value. + const ObjCStrongReference copy([NSData dataWithData:nsData], RetainPolicy::doInitialRetain); + updateQueue.push_back(UpdateRequest{charHandle, copy}); + [self sendUpdateRequests]; +} + +- (void) addServicesToPeripheral +{ + Q_ASSERT(manager); + + if (nextServiceToAdd < services.size()) + [manager addService:services[nextServiceToAdd++]]; +} + +// CBPeripheralManagerDelegate: + +- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral +{ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability-new" + + if (peripheral != manager || !notifier) + return; + + if (peripheral.state == CBManagerStatePoweredOn) { + // "Bluetooth is currently powered on and is available to use." + if (state == PeripheralState::waitingForPowerOn) { + [manager removeAllServices]; + nextServiceToAdd = {}; + state = PeripheralState::advertising; + nOfFailedAds = 0; + [self addServicesToPeripheral]; + } + return; + } + + /* + "A state with a value lower than CBPeripheralManagerStatePoweredOn implies that + advertising has stopped and that any connected centrals have been disconnected." + */ + + maxNotificationValueLength = std::numeric_limits::max(); + + if (state == PeripheralState::advertising) { + state = PeripheralState::waitingForPowerOn; + } else if (state == PeripheralState::connected) { + state = PeripheralState::idle; + emit notifier->disconnected(); + } + + // The next four states are _below_ "powered off"; according to the docs: + /* + "In addition, the local database is cleared and all services must be + explicitly added again." + */ + + if (peripheral.state == CBManagerStateUnsupported) { + state = PeripheralState::idle; + emit notifier->LEnotSupported(); + } else if (peripheral.state == CBManagerStateUnauthorized) { + state = PeripheralState::idle; + emit notifier->CBManagerError(QLowEnergyController::MissingPermissionsError); + } + +#pragma clang diagnostic pop +} + +- (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral + error:(NSError *)error +{ + if (peripheral != manager || !notifier) + return; + + if (error) { + NSLog(@"failed to start advertising, error: %@", error); + state = PeripheralState::idle; + emit notifier->CBManagerError(QLowEnergyController::AdvertisingError); + } +} + +- (void)peripheralManager:(CBPeripheralManager *)peripheral + didAddService:(CBService *)service error:(NSError *)error +{ + Q_UNUSED(service); + + if (peripheral != manager || !notifier) + return; + + if (error) { + NSLog(@"failed to add a service, error: %@", error); + if (++nOfFailedAds == services.size()) { + emit notifier->CBManagerError(QLowEnergyController::AdvertisingError); + state = PeripheralState::idle; + return; + } + } + + if (nextServiceToAdd == services.size()) { + nOfFailedAds = 0; // Discard any failed, some services made it into advertising. + [manager startAdvertising:[advertisementData count] ? advertisementData.get() : nil]; + } else { + [self addServicesToPeripheral]; + } +} + +- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central + didSubscribeToCharacteristic:(CBCharacteristic *)characteristic +{ + Q_UNUSED(characteristic); + + if (peripheral != manager || !notifier) + return; + + [self addConnectedCentral:central]; + + if (const auto handle = charMap.key(characteristic)) + emit notifier->notificationEnabled(handle, true); +} + +- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central + didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic +{ + Q_UNUSED(characteristic); + + if (peripheral != manager || !notifier) + return; + + const auto handle = charMap.key(characteristic); + if (![static_cast(characteristic).subscribedCentrals count] + && handle) + emit notifier->notificationEnabled(handle, false); +} + +- (void)peripheralManager:(CBPeripheralManager *)peripheral + didReceiveReadRequest:(CBATTRequest *)request +{ + if (peripheral != manager || !notifier) + return; + + QT_BT_MAC_AUTORELEASEPOOL + + const auto handle = charMap.key(request.characteristic); + if (!handle || !charValues.contains(handle)) { + qCWarning(QT_BT_DARWIN) << "invalid read request, unknown characteristic"; + [manager respondToRequest:request withResult:CBATTErrorInvalidHandle]; + return; + } + + const auto &value = charValues[handle]; + if (request.offset > [value length]) { + qCWarning(QT_BT_DARWIN) << "invalid offset in a read request"; + [manager respondToRequest:request withResult:CBATTErrorInvalidOffset]; + return; + } + + [self addConnectedCentral:request.central]; + + NSData *dataToSend = nil; + if (!request.offset) { + dataToSend = value; + } else { + dataToSend = [value subdataWithRange: + NSMakeRange(request.offset, [value length] - request.offset)]; + } + + request.value = dataToSend; + [manager respondToRequest:request withResult:CBATTErrorSuccess]; +} + + +- (void)writeValueForCharacteristic:(QLowEnergyHandle) charHandle + withWriteRequest:(CBATTRequest *)request +{ + Q_ASSERT(charHandle); + Q_ASSERT(request); + + Q_ASSERT(valueRanges.contains(charHandle)); + const auto &range = valueRanges[charHandle]; + Q_ASSERT(request.offset <= range.second + && request.value.length <= range.second - request.offset); + + Q_ASSERT(charValues.contains(charHandle)); + NSMutableData *const value = charValues[charHandle]; + if (request.offset + request.value.length > value.length) + [value increaseLengthBy:request.offset + request.value.length - value.length]; + + [value replaceBytesInRange:NSMakeRange(request.offset, request.value.length) + withBytes:request.value.bytes]; +} + +- (void)peripheralManager:(CBPeripheralManager *)peripheral + didReceiveWriteRequests:(NSArray *)requests +{ + using namespace DarwinBluetooth; + + QT_BT_MAC_AUTORELEASEPOOL + + if (peripheral != manager || !notifier) { + // Detached already. + return; + } + + // We first test if all requests are valid + // since CoreBluetooth requires "all or none" + // and respond only _once_ to the first one. + for (CBATTRequest *request in requests) { + const auto status = [self validateWriteRequest:request]; + if (status != CBATTErrorSuccess) { + [manager respondToRequest:[requests objectAtIndex:0] + withResult:status]; + return; + } + } + + std::map updated; + + for (CBATTRequest *request in requests) { + // Transition to 'connected' if needed. + [self addConnectedCentral:request.central]; + const auto charHandle = charMap.key(request.characteristic); + const auto prevLen = updated[charHandle]; + updated[charHandle] = std::max(request.offset + request.value.length, + prevLen); + [self writeValueForCharacteristic:charHandle withWriteRequest:request]; + } + + for (const auto &pair : updated) { + const auto handle = pair.first; + NSMutableData *value = charValues[handle]; + value.length = pair.second; + emit notifier->characteristicUpdated(handle, qt_bytearray(value)); + const ObjCStrongReference copy([NSData dataWithData:value], + RetainPolicy::doInitialRetain); + updateQueue.push_back(UpdateRequest{handle, copy}); + } + + if (requests.count) { + [manager respondToRequest:[requests objectAtIndex:0] + withResult:CBATTErrorSuccess]; + } + + [self sendUpdateRequests]; +} + +- (void)peripheralManagerIsReadyToUpdateSubscribers:(CBPeripheralManager *)peripheral +{ + if (peripheral != manager || !notifier) { + // Detached. + return; + } + + [self sendUpdateRequests]; +} + +- (void)sendUpdateRequests +{ + QT_BT_MAC_AUTORELEASEPOOL + + while (updateQueue.size()) { + const auto &request = updateQueue.front(); + if (charMap.contains(request.charHandle)) { + if (maxNotificationValueLength < [request.value length]) { + qCWarning(QT_BT_DARWIN) << "value of length" << [request.value length] + << "will possibly be truncated to" + << maxNotificationValueLength; + } + const BOOL res = [manager updateValue:request.value + forCharacteristic:static_cast(charMap[request.charHandle]) + onSubscribedCentrals:nil]; + if (!res) { + // Have to wait for the 'ManagerIsReadyToUpdate'. + break; + } + } + + updateQueue.pop_front(); + } +} + +// Private API: + +- (void)addConnectedCentral:(CBCentral *)central +{ + if (!central) + return; + + if (!notifier) { + // We were detached. + return; + } + + maxNotificationValueLength = std::min(maxNotificationValueLength, + central.maximumUpdateValueLength); + + QT_BT_MAC_AUTORELEASEPOOL + + if (state == PeripheralState::advertising) { + state = PeripheralState::connected; + emit notifier->connected(); + } +} + +- (CBService *)findIncludedService:(const QBluetoothUuid &)qtUUID +{ + const auto it = serviceIndex.find(qtUUID); + if (it == serviceIndex.end()) + return nil; + + return it->second; +} + +- (void)addIncludedServices:(const QLowEnergyServiceData &)data + to:(CBMutableService *)cbService + qtService:(QLowEnergyServicePrivate *)qtService +{ + Q_ASSERT(cbService); + Q_ASSERT(qtService); + + QT_BT_MAC_AUTORELEASEPOOL + + ObjCScopedPointer included([[NSMutableArray alloc] init], + DarwinBluetooth::RetainPolicy::noInitialRetain); + if (!included) { + qCWarning(QT_BT_DARWIN) << "addIncludedSerivces: failed " + "to allocate NSMutableArray"; + return; + } + + for (auto includedService : data.includedServices()) { + if (CBService *cbs = [self findIncludedService:includedService->serviceUuid()]) { + [included addObject:cbs]; + qtService->includedServices << includedService->serviceUuid(); + ++lastHandle; + } else { + qCWarning(QT_BT_DARWIN) << "can not use" << includedService->serviceUuid() + << "as included, it has to be added first"; + } + } + + if ([included count]) + cbService.includedServices = included; +} + +- (void)addCharacteristicsAndDescriptors:(const QLowEnergyServiceData &)data + to:(CBMutableService *)cbService + qtService:(QLowEnergyServicePrivate *)qtService +{ + Q_ASSERT(cbService); + Q_ASSERT(qtService); + + QT_BT_MAC_AUTORELEASEPOOL + + ObjCScopedPointer newCBChars([[NSMutableArray alloc] init], + DarwinBluetooth::RetainPolicy::noInitialRetain); + if (!newCBChars) { + qCWarning(QT_BT_DARWIN) << "addCharacteristicsAndDescritptors: " + "failed to allocate NSMutableArray " + "(characteristics)"; + return; + } + + for (const auto &ch : data.characteristics()) { + if (!qt_validate_value_range(ch)) { + qCWarning(QT_BT_DARWIN) << "addCharacteristicsAndDescritptors: " + "invalid value size/min-max length"; + continue; + } + +#ifdef Q_OS_IOS + if (ch.value().size() > DarwinBluetooth::maxValueLength) { + qCWarning(QT_BT_DARWIN) << "addCharacteristicsAndDescritptors: " + "value exceeds the maximal permitted " + "value length (" + << DarwinBluetooth::maxValueLength + << "octets) on the platform"; + continue; + } +#endif + + const auto cbChar(create_characteristic(ch)); + if (!cbChar) { + qCWarning(QT_BT_DARWIN) << "addCharacteristicsAndDescritptors: " + "failed to allocate a characteristic"; + continue; + } + + const auto nsData(mutable_data_from_bytearray(ch.value())); + if (!nsData) { + qCWarning(QT_BT_DARWIN) << "addCharacteristicsAndDescritptors: " + "addService: failed to allocate NSData (char value)"; + continue; + } + + [newCBChars addObject:cbChar]; + + const auto declHandle = ++lastHandle; + // CB part: + charMap[declHandle] = cbChar; + charValues[declHandle] = nsData; + valueRanges[declHandle] = ValueRange(ch.minimumValueLength(), ch.maximumValueLength()); + // QT part: + QLowEnergyServicePrivate::CharData charData; + charData.valueHandle = declHandle; + charData.uuid = ch.uuid(); + charData.properties = ch.properties(); + charData.value = ch.value(); + + const ObjCScopedPointer newCBDescs([[NSMutableArray alloc] init], + DarwinBluetooth::RetainPolicy::noInitialRetain); + if (!newCBDescs) { + qCWarning(QT_BT_DARWIN) << "addCharacteristicsAndDescritptors: " + "failed to allocate NSMutableArray " + "(descriptors)"; + continue; + } + + for (const auto &desc : ch.descriptors()) { + // CB part: + const auto cbDesc(create_descriptor(desc)); + const auto descHandle = ++lastHandle; + if (cbDesc) { + // See comments in create_descriptor on + // why cbDesc can be nil. + [newCBDescs addObject:cbDesc]; + } + // QT part: + QLowEnergyServicePrivate::DescData descData; + descData.uuid = desc.uuid(); + descData.value = desc.value(); + charData.descriptorList.insert(descHandle, descData); + } + + if ([newCBDescs count]) + cbChar.data().descriptors = newCBDescs.get(); + + qtService->characteristicList.insert(declHandle, charData); + } + + if ([newCBChars count]) + cbService.characteristics = newCBChars.get(); +} + +- (CBATTError)validateWriteRequest:(CBATTRequest *)request +{ + Q_ASSERT(request); + + QT_BT_MAC_AUTORELEASEPOOL + + const auto handle = charMap.key(request.characteristic); + if (!handle || !charValues.contains(handle)) + return CBATTErrorInvalidHandle; + + Q_ASSERT(valueRanges.contains(handle)); + + const auto &range = valueRanges[handle]; + if (request.offset > range.second) + return CBATTErrorInvalidOffset; + + if (request.value.length > range.second - request.offset) + return CBATTErrorInvalidAttributeValueLength; + + return CBATTErrorSuccess; +} + +@end diff --git a/src/bluetooth/darwin/btperipheralmanager_p.h b/src/bluetooth/darwin/btperipheralmanager_p.h new file mode 100644 index 0000000..3bd7ceb --- /dev/null +++ b/src/bluetooth/darwin/btperipheralmanager_p.h @@ -0,0 +1,128 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef BTPERIPHERALMANAGER_P_H +#define BTPERIPHERALMANAGER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of internal files. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. +// + +#include "btutility_p.h" + +#include "qlowenergyserviceprivate_p.h" +#include "qbluetooth.h" + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include + +#include + +QT_BEGIN_NAMESPACE + +class QLowEnergyAdvertisingParameters; +class QLowEnergyAdvertisingData; +class QLowEnergyServiceData; + +namespace DarwinBluetooth +{ + +class LECBManagerNotifier; + +} // namespace DarwinBluetooth + +QT_END_NAMESPACE + + +// Exposing names in a header is ugly, but constant QT_PREPEND_NAMESPACE is even worse ... +// After all, this header is to be included only in its own and controller's *.mm files. + +QT_USE_NAMESPACE + +using namespace DarwinBluetooth; + + +template +using GenericLEMap = QMap; + +enum class PeripheralState +{ + idle, + waitingForPowerOn, + advertising, + connected +}; + +struct UpdateRequest +{ + UpdateRequest() = default; + UpdateRequest(QLowEnergyHandle handle, const ObjCStrongReference &val) + : charHandle(handle), + value(val) + { + } + + QLowEnergyHandle charHandle = {}; + ObjCStrongReference value; +}; + +using ValueRange = QPair; + +@interface QT_MANGLE_NAMESPACE(DarwinBTPeripheralManager) : NSObject + +- (id)initWith:(LECBManagerNotifier *)notifier; +- (void)dealloc; + +- (QSharedPointer)addService:(const QLowEnergyServiceData &)data; +- (void) setParameters:(const QLowEnergyAdvertisingParameters &)parameters + data:(const QLowEnergyAdvertisingData &)data + scanResponse:(const QLowEnergyAdvertisingData &)scanResponse; + +// To be executed on the Qt's special BTLE dispatch queue. +- (void)startAdvertising; +- (void)stopAdvertising; +- (void)detach; + +- (void)write:(const QByteArray &)value + charHandle:(QLowEnergyHandle)charHandle; + + +// CBPeripheralManagerDelegate's callbacks (BTLE queue). +- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral; +- (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral + error:(NSError *)error; +- (void)peripheralManager:(CBPeripheralManager *)peripheral + didAddService:(CBService *)service error:(NSError *)error; +- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central + didSubscribeToCharacteristic:(CBCharacteristic *)characteristic; +- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central + didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic; +- (void)peripheralManager:(CBPeripheralManager *)peripheral + didReceiveReadRequest:(CBATTRequest *)request; +- (void)peripheralManager:(CBPeripheralManager *)peripheral + didReceiveWriteRequests:(NSArray *)requests; +- (void)peripheralManagerIsReadyToUpdateSubscribers:(CBPeripheralManager *)peripheral; + +@end + +QT_NAMESPACE_ALIAS_OBJC_CLASS(DarwinBTPeripheralManager); + +#endif diff --git a/src/bluetooth/darwin/btraii.mm b/src/bluetooth/darwin/btraii.mm new file mode 100644 index 0000000..acf95ae --- /dev/null +++ b/src/bluetooth/darwin/btraii.mm @@ -0,0 +1,81 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "btraii_p.h" + +#include + +#include + +#include + +QT_BEGIN_NAMESPACE + +namespace DarwinBluetooth { + +StrongReference::StrongReference(void *object, RetainPolicy policy) + : objCInstance(object) +{ + if (objCInstance && policy == RetainPolicy::doInitialRetain) + objCInstance = [getAs() retain]; +} + +StrongReference::StrongReference(const StrongReference &other) +{ + if ((objCInstance = other.getAs())) + objCInstance = [other.getAs() retain]; +} + +StrongReference::StrongReference(StrongReference &&other) +{ + std::swap(objCInstance, other.objCInstance); +} + +StrongReference::~StrongReference() +{ + [getAs() release]; +} + +StrongReference &StrongReference::operator = (const StrongReference &other) noexcept +{ + if (this != &other) { + [getAs() release]; + objCInstance = [other.getAs() retain]; + } + + return *this; +} + +StrongReference &StrongReference::operator = (StrongReference &&other) noexcept +{ + swap(other); + + return *this; +} + +void *StrongReference::release() +{ + void *released = objCInstance; + objCInstance = nullptr; + + return released; +} + +void StrongReference::reset() +{ + [getAs() release]; + objCInstance = nullptr; +} + +void StrongReference::reset(void *obj, RetainPolicy policy) +{ + [getAs() release]; + objCInstance = obj; + + if (objCInstance && policy == RetainPolicy::doInitialRetain) + objCInstance = [getAs() retain]; +} + +} // namespace DarwinBluetooth + +QT_END_NAMESPACE diff --git a/src/bluetooth/darwin/btraii_p.h b/src/bluetooth/darwin/btraii_p.h new file mode 100644 index 0000000..1ba5d35 --- /dev/null +++ b/src/bluetooth/darwin/btraii_p.h @@ -0,0 +1,98 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef BTRAII_P_H +#define BTRAII_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 + +namespace DarwinBluetooth { + +enum class RetainPolicy +{ + noInitialRetain, + doInitialRetain +}; + +// The class StrongReference and its descendant ScopedGuard +// are RAII classes dealing with raw pointers to NSObject class +// and its descendants (and thus hiding Objective-C's retain/ +// release semantics). The header itself is meant to be included +// into *.cpp files so it's a pure C++ code without any Objective-C +// syntax. Thus it's a bit clunky - the type information is 'erased' +// and has to be enforced by the code using these smart pointers. +// That's because these types are Objective-C classes - thus require +// Objective-C compiler to work. Member-function template 'getAs' is +// a convenience shortcut giving the desired pointer type in +// Objective-C++ files (*.mm). +class StrongReference +{ +public: + StrongReference() = default; + StrongReference(void *object, RetainPolicy policy); + StrongReference(const StrongReference &other); + StrongReference(StrongReference &&other); + + ~StrongReference(); + + StrongReference &operator = (const StrongReference &other) noexcept; + StrongReference &operator = (StrongReference &&other) noexcept; + + void swap(StrongReference &other) noexcept + { + std::swap(objCInstance, other.objCInstance); + } + + void *release(); + + void reset(); + void reset(void *newInstance, RetainPolicy policy); + + template + ObjCType *getAs() const + { + return static_cast(objCInstance); + } + + operator bool() const + { + return !!objCInstance; + } + +private: + void *objCInstance = nullptr; +}; + +class ScopedPointer final : public StrongReference +{ +public: + ScopedPointer() = default; + ScopedPointer(void *instance, RetainPolicy policy) + : StrongReference(instance, policy) + { + } + +private: + Q_DISABLE_COPY_MOVE(ScopedPointer) +}; + +} // namespace DarwinBluetooth + +QT_END_NAMESPACE + +#endif // BTRAII_P_H diff --git a/src/bluetooth/darwin/btrfcommchannel.mm b/src/bluetooth/darwin/btrfcommchannel.mm new file mode 100644 index 0000000..821944e --- /dev/null +++ b/src/bluetooth/darwin/btrfcommchannel.mm @@ -0,0 +1,225 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "btrfcommchannel_p.h" +#include "qbluetoothaddress.h" +#include "btdelegates_p.h" +#include "btutility_p.h" + +QT_USE_NAMESPACE + +@implementation DarwinBTRFCOMMChannel +{ + QT_PREPEND_NAMESPACE(DarwinBluetooth)::ChannelDelegate *delegate; + IOBluetoothDevice *device; + IOBluetoothRFCOMMChannel *channel; + bool connected; +} + +- (id)initWithDelegate:(DarwinBluetooth::ChannelDelegate *)aDelegate +{ + Q_ASSERT_X(aDelegate, Q_FUNC_INFO, "invalid delegate (null)"); + + if (self = [super init]) { + delegate = aDelegate; + device = nil; + channel = nil; + connected = false; + } + + return self; +} + +- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(DarwinBluetooth::ChannelDelegate) *)aDelegate + channel:(IOBluetoothRFCOMMChannel *)aChannel +{ + // This type of channel does not require connect, it's created with + // already open channel. + Q_ASSERT_X(aDelegate, Q_FUNC_INFO, "invalid delegate (null)"); + Q_ASSERT_X(aChannel, Q_FUNC_INFO, "invalid channel (nil)"); + + if (self = [super init]) { + delegate = aDelegate; + channel = [aChannel retain]; + [channel setDelegate:self]; + device = [[channel getDevice] retain]; + connected = true; + } + + return self; +} + +- (void)dealloc +{ + if (channel) { + [channel setDelegate:nil]; + [channel closeChannel]; + [channel release]; + } + + [device release]; + + [super dealloc]; +} + +// A single async connection (you can not reuse this object). +- (IOReturn)connectAsyncToDevice:(const QBluetoothAddress &)address + withChannelID:(BluetoothRFCOMMChannelID)channelID +{ + if (address.isNull()) { + qCCritical(QT_BT_DARWIN) << "invalid peer address"; + return kIOReturnNoDevice; + } + + // Can never be called twice. + if (connected || device || channel) { + qCCritical(QT_BT_DARWIN) << "connection is already active"; + return kIOReturnStillOpen; + } + + QT_BT_MAC_AUTORELEASEPOOL; + + const BluetoothDeviceAddress iobtAddress = DarwinBluetooth::iobluetooth_address(address); + device = [IOBluetoothDevice deviceWithAddress:&iobtAddress]; + if (!device) { // TODO: do I always check this BTW??? Apple's docs say nothing about nil. + qCCritical(QT_BT_DARWIN) << "failed to create a device"; + return kIOReturnNoDevice; + } + + const IOReturn status = [device openRFCOMMChannelAsync:&channel + withChannelID:channelID delegate:self]; + if (status != kIOReturnSuccess) { + qCCritical(QT_BT_DARWIN) << "failed to open L2CAP channel"; + // device is still autoreleased. + device = nil; + return status; + } + + [channel retain];// What if we're closed already? + [device retain]; + + return kIOReturnSuccess; +} + +- (void)rfcommChannelData:(IOBluetoothRFCOMMChannel*)rfcommChannel + data:(void *)dataPointer length:(size_t)dataLength +{ + Q_UNUSED(rfcommChannel); + + Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)"); + + // Not sure if it can ever happen and if + // assert is better. + if (!dataPointer || !dataLength) + return; + + delegate->readChannelData(dataPointer, dataLength); +} + +- (void)rfcommChannelOpenComplete:(IOBluetoothRFCOMMChannel*)rfcommChannel + status:(IOReturn)error +{ + Q_UNUSED(rfcommChannel); + + Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)"); + + if (error != kIOReturnSuccess) { + delegate->setChannelError(error); + } else { + connected = true; + delegate->channelOpenComplete(); + } +} + +- (void)rfcommChannelClosed:(IOBluetoothRFCOMMChannel*)rfcommChannel +{ + Q_UNUSED(rfcommChannel); + + Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)"); + delegate->channelClosed(); + connected = false; +} + +- (void)rfcommChannelControlSignalsChanged:(IOBluetoothRFCOMMChannel*)rfcommChannel +{ + Q_UNUSED(rfcommChannel); +} + +- (void)rfcommChannelFlowControlChanged:(IOBluetoothRFCOMMChannel*)rfcommChannel +{ + Q_UNUSED(rfcommChannel); +} + +- (void)rfcommChannelWriteComplete:(IOBluetoothRFCOMMChannel*)rfcommChannel + refcon:(void*)refcon status:(IOReturn)error +{ + Q_UNUSED(rfcommChannel); + Q_UNUSED(refcon); + + Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)"); + + if (error != kIOReturnSuccess) + delegate->setChannelError(error); + else + delegate->writeComplete(); +} + +- (void)rfcommChannelQueueSpaceAvailable:(IOBluetoothRFCOMMChannel*)rfcommChannel +{ + Q_UNUSED(rfcommChannel); +} + +- (BluetoothRFCOMMChannelID)getChannelID +{ + if (channel) + return [channel getChannelID]; + + return 0; +} + +- (BluetoothDeviceAddress)peerAddress +{ + const BluetoothDeviceAddress *const addr = device ? [device getAddress] + : nullptr; + if (addr) + return *addr; + + return BluetoothDeviceAddress(); +} + +- (NSString *)peerName +{ + if (device) + return device.name; + + return nil; +} + +- (BluetoothRFCOMMMTU)getMTU +{ + if (channel) + return [channel getMTU]; + + return 0; +} + +- (IOReturn) writeSync:(void*)data length:(UInt16)length +{ + Q_ASSERT_X(data, Q_FUNC_INFO, "invalid data (null)"); + Q_ASSERT_X(length, Q_FUNC_INFO, "invalid data size"); + Q_ASSERT_X(connected && channel, Q_FUNC_INFO, "invalid RFCOMM channel"); + + return [channel writeSync:data length:length]; +} + +- (IOReturn) writeAsync:(void*)data length:(UInt16)length +{ + Q_ASSERT_X(data, Q_FUNC_INFO, "invalid data (null)"); + Q_ASSERT_X(length, Q_FUNC_INFO, "invalid data size"); + Q_ASSERT_X(connected && channel, Q_FUNC_INFO, "invalid RFCOMM channel"); + + return [channel writeAsync:data length:length refcon:nullptr]; +} + + +@end diff --git a/src/bluetooth/darwin/btrfcommchannel_p.h b/src/bluetooth/darwin/btrfcommchannel_p.h new file mode 100644 index 0000000..dd32c49 --- /dev/null +++ b/src/bluetooth/darwin/btrfcommchannel_p.h @@ -0,0 +1,74 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef BTRFCOMMCHANNEL_P_H +#define BTRFCOMMCHANNEL_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 QBluetoothAddress; + +namespace DarwinBluetooth { + +class ChannelDelegate; + +} + +QT_END_NAMESPACE + +@interface QT_MANGLE_NAMESPACE(DarwinBTRFCOMMChannel) : NSObject + +- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(DarwinBluetooth)::ChannelDelegate *)aDelegate; +- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(DarwinBluetooth)::ChannelDelegate *)aDelegate + channel:(IOBluetoothRFCOMMChannel *)aChannel; + +- (void)dealloc; + +// A single async connection (can connect only once). +- (IOReturn)connectAsyncToDevice:(const QT_PREPEND_NAMESPACE(QBluetoothAddress) &)address + withChannelID:(BluetoothRFCOMMChannelID)channelID; + +- (void)rfcommChannelData:(IOBluetoothRFCOMMChannel*)rfcommChannel + data:(void *)dataPointer length:(size_t)dataLength; +- (void)rfcommChannelOpenComplete:(IOBluetoothRFCOMMChannel*)rfcommChannel + status:(IOReturn)error; +- (void)rfcommChannelClosed:(IOBluetoothRFCOMMChannel*)rfcommChannel; +- (void)rfcommChannelControlSignalsChanged:(IOBluetoothRFCOMMChannel*)rfcommChannel; +- (void)rfcommChannelFlowControlChanged:(IOBluetoothRFCOMMChannel*)rfcommChannel; +- (void)rfcommChannelWriteComplete:(IOBluetoothRFCOMMChannel*)rfcommChannel + refcon:(void*)refcon status:(IOReturn)error; +- (void)rfcommChannelQueueSpaceAvailable:(IOBluetoothRFCOMMChannel*)rfcommChannel; + +// +- (BluetoothRFCOMMChannelID)getChannelID; +- (BluetoothDeviceAddress)peerAddress; +- (NSString *)peerName; + +- (BluetoothRFCOMMMTU)getMTU; + +- (IOReturn) writeSync:(void*)data length:(UInt16)length; +- (IOReturn) writeAsync:(void*)data length:(UInt16)length; + +@end + +QT_NAMESPACE_ALIAS_OBJC_CLASS(DarwinBTRFCOMMChannel); + +#endif diff --git a/src/bluetooth/darwin/btsdpinquiry.mm b/src/bluetooth/darwin/btsdpinquiry.mm new file mode 100644 index 0000000..f3a235a --- /dev/null +++ b/src/bluetooth/darwin/btsdpinquiry.mm @@ -0,0 +1,422 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothserviceinfo.h" +#include "btsdpinquiry_p.h" +#include "qbluetoothuuid.h" +#include "btdelegates_p.h" +#include "btutility_p.h" + +#include +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +namespace DarwinBluetooth { + +namespace { + +const int basebandConnectTimeoutMS = 20000; + +QBluetoothUuid sdp_element_to_uuid(IOBluetoothSDPDataElement *element) +{ + QT_BT_MAC_AUTORELEASEPOOL; + + if (!element || [element getTypeDescriptor] != kBluetoothSDPDataElementTypeUUID) + return {}; + + return qt_uuid([[element getUUIDValue] getUUIDWithLength:16]); +} + +QBluetoothUuid extract_service_ID(IOBluetoothSDPServiceRecord *record) +{ + Q_ASSERT(record); + + QT_BT_MAC_AUTORELEASEPOOL; + + return sdp_element_to_uuid([record getAttributeDataElement:kBluetoothSDPAttributeIdentifierServiceID]); +} + +QList extract_service_class_ID_list(IOBluetoothSDPServiceRecord *record) +{ + Q_ASSERT(record); + + QT_BT_MAC_AUTORELEASEPOOL; + + IOBluetoothSDPDataElement *const idList = [record getAttributeDataElement:kBluetoothSDPAttributeIdentifierServiceClassIDList]; + + QList uuids; + if (!idList) + return uuids; + + NSArray *arr = nil; + if ([idList getTypeDescriptor] == kBluetoothSDPDataElementTypeDataElementSequence) + arr = [idList getArrayValue]; + else if ([idList getTypeDescriptor] == kBluetoothSDPDataElementTypeUUID) + arr = @[idList]; + + if (!arr) + return uuids; + + for (IOBluetoothSDPDataElement *dataElement in arr) { + const auto qtUuid = sdp_element_to_uuid(dataElement); + if (!qtUuid.isNull()) + uuids.push_back(qtUuid); + } + + return uuids; +} + +QBluetoothServiceInfo::Sequence service_class_ID_list_to_sequence(const QList &uuids) +{ + if (uuids.isEmpty()) + return {}; + + QBluetoothServiceInfo::Sequence sequence; + for (const auto &uuid : uuids) { + Q_ASSERT(!uuid.isNull()); + sequence.append(QVariant::fromValue(uuid)); + } + + return sequence; +} + +} // unnamed namespace + +QVariant extract_attribute_value(IOBluetoothSDPDataElement *dataElement) +{ + Q_ASSERT_X(dataElement, Q_FUNC_INFO, "invalid data element (nil)"); + + // TODO: error handling and diagnostic messages. + + // All "temporary" obj-c objects are autoreleased. + QT_BT_MAC_AUTORELEASEPOOL; + + const BluetoothSDPDataElementTypeDescriptor typeDescriptor = [dataElement getTypeDescriptor]; + + switch (typeDescriptor) { + case kBluetoothSDPDataElementTypeNil: + break; + case kBluetoothSDPDataElementTypeUnsignedInt: + return [[dataElement getNumberValue] unsignedIntValue]; + case kBluetoothSDPDataElementTypeSignedInt: + return [[dataElement getNumberValue] intValue]; + case kBluetoothSDPDataElementTypeUUID: + return QVariant::fromValue(sdp_element_to_uuid(dataElement)); + case kBluetoothSDPDataElementTypeString: + case kBluetoothSDPDataElementTypeURL: + return QString::fromNSString([dataElement getStringValue]); + case kBluetoothSDPDataElementTypeBoolean: + return [[dataElement getNumberValue] boolValue]; + case kBluetoothSDPDataElementTypeDataElementSequence: + case kBluetoothSDPDataElementTypeDataElementAlternative: // TODO: check this! + { + QBluetoothServiceInfo::Sequence sequence; + NSArray *const arr = [dataElement getArrayValue]; + for (IOBluetoothSDPDataElement *element in arr) + sequence.append(extract_attribute_value(element)); + + return QVariant::fromValue(sequence); + } + break;// Coding style. + default:; + } + + return QVariant(); +} + +void extract_service_record(IOBluetoothSDPServiceRecord *record, QBluetoothServiceInfo &serviceInfo) +{ + QT_BT_MAC_AUTORELEASEPOOL; + + if (!record) + return; + + NSDictionary *const attributes = record.attributes; + NSEnumerator *const keys = attributes.keyEnumerator; + for (NSNumber *key in keys) { + const quint16 attributeID = [key unsignedShortValue]; + IOBluetoothSDPDataElement *const element = [attributes objectForKey:key]; + const QVariant attributeValue = DarwinBluetooth::extract_attribute_value(element); + serviceInfo.setAttribute(attributeID, attributeValue); + } + + const QBluetoothUuid serviceUuid = extract_service_ID(record); + if (!serviceUuid.isNull()) + serviceInfo.setServiceUuid(serviceUuid); + + const QList uuids(extract_service_class_ID_list(record)); + const auto sequence = service_class_ID_list_to_sequence(uuids); + if (!sequence.isEmpty()) + serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, sequence); +} + +QList extract_services_uuids(IOBluetoothDevice *device) +{ + QList uuids; + + // All "temporary" obj-c objects are autoreleased. + QT_BT_MAC_AUTORELEASEPOOL; + + if (!device || !device.services) + return uuids; + + NSArray * const records = device.services; + for (IOBluetoothSDPServiceRecord *record in records) { + const QBluetoothUuid serviceID = extract_service_ID(record); + if (!serviceID.isNull()) + uuids.push_back(serviceID); + + const QList idList(extract_service_class_ID_list(record)); + if (idList.size()) + uuids.append(idList); + } + + return uuids; +} + +} // namespace DarwinBluetooth + +QT_END_NAMESPACE + +QT_USE_NAMESPACE + +using namespace DarwinBluetooth; + +@implementation DarwinBTSDPInquiry +{ + QT_PREPEND_NAMESPACE(DarwinBluetooth::SDPInquiryDelegate) *delegate; + ObjCScopedPointer device; + bool isActive; + + // Needed to workaround a broken SDP on Monterey: + std::unique_ptr connectionWatchdog; +} + +- (id)initWithDelegate:(DarwinBluetooth::SDPInquiryDelegate *)aDelegate +{ + Q_ASSERT_X(aDelegate, Q_FUNC_INFO, "invalid delegate (null)"); + + if (self = [super init]) { + delegate = aDelegate; + isActive = false; + } + + return self; +} + +- (void)dealloc +{ + //[device closeConnection]; //??? - synchronous, "In the future this API will be changed to allow asynchronous operation." + [super dealloc]; +} + +- (IOReturn)performSDPQueryWithDevice:(const QBluetoothAddress &)address +{ + Q_ASSERT_X(!isActive, Q_FUNC_INFO, "SDP query in progress"); + + QList emptyFilter; + return [self performSDPQueryWithDevice:address filters:emptyFilter]; +} + +- (void)interruptSDPQuery +{ + // To be only executed on timer. + Q_ASSERT(connectionWatchdog.get()); + // If device was reset, so the timer should be, we can never be here then. + Q_ASSERT(device.get()); + + Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)"); + qCDebug(QT_BT_DARWIN) << "couldn't connect to device" << [device nameOrAddress] + << ", ending SDP inquiry."; + + // Stop the watchdog and close the connection as otherwise there could be + // later "connectionComplete" callbacks + connectionWatchdog->stop(); + [device closeConnection]; + + delegate->SDPInquiryError(device, kIOReturnTimeout); + device.reset(); + isActive = false; +} + +- (IOReturn)performSDPQueryWithDevice:(const QBluetoothAddress &)address + filters:(const QList &)qtFilters +{ + Q_ASSERT_X(!isActive, Q_FUNC_INFO, "SDP query in progress"); + Q_ASSERT_X(!address.isNull(), Q_FUNC_INFO, "invalid target device address"); + qCDebug(QT_BT_DARWIN) << "Starting and SDP inquiry for address:" << address; + + QT_BT_MAC_AUTORELEASEPOOL; + + // We first try to allocate "filters": + ObjCScopedPointer array; + if (QOperatingSystemVersion::current() <= QOperatingSystemVersion::MacOSBigSur + && qtFilters.size()) { // See the comment about filters on Monterey below. + array.reset([[NSMutableArray alloc] init], RetainPolicy::noInitialRetain); + if (!array) { + qCCritical(QT_BT_DARWIN) << "failed to allocate an uuid filter"; + return kIOReturnError; + } + + for (const QBluetoothUuid &qUuid : qtFilters) { + ObjCStrongReference uuid(iobluetooth_uuid(qUuid)); + if (uuid) + [array addObject:uuid]; + } + + if (qsizetype([array count]) != qtFilters.size()) { + qCCritical(QT_BT_DARWIN) << "failed to create an uuid filter"; + return kIOReturnError; + } + } + + const BluetoothDeviceAddress iobtAddress(iobluetooth_address(address)); + device.reset([IOBluetoothDevice deviceWithAddress:&iobtAddress], RetainPolicy::doInitialRetain); + if (!device) { + qCCritical(QT_BT_DARWIN) << "failed to create an IOBluetoothDevice object"; + return kIOReturnError; + } + qCDebug(QT_BT_DARWIN) << "Device" << [device nameOrAddress] << "connected:" + << bool([device isConnected]) << "paired:" << bool([device isPaired]); + + IOReturn result = kIOReturnSuccess; + + if (QOperatingSystemVersion::current() > QOperatingSystemVersion::MacOSBigSur) { + // SDP query on Monterey does not follow its own documented/expected behavior: + // - a simple performSDPQuery was previously ensuring baseband connection + // to be opened, now it does not do so, instead logs a warning and returns + // immediately. + // - a version with UUID filters simply does nothing except it immediately + // returns kIOReturnSuccess. + + // If the device was not yet connected, connect it first + if (![device isConnected]) { + qCDebug(QT_BT_DARWIN) << "Device" << [device nameOrAddress] + << "is not connected, connecting it first"; + result = [device openConnection:self]; + // The connection may succeed immediately. But if it didn't, start a connection timer + // which has two guardian roles: + // 1. Guard against connect attempt taking too long time + // 2. Sometimes on Monterey the callback indicating "connection completion" is + // not received even though the connection has in fact succeeded + if (![device isConnected]) { + qCDebug(QT_BT_DARWIN) << "Starting connection monitor for device" + << [device nameOrAddress] << "with timeout limit of" + << basebandConnectTimeoutMS/1000 << "seconds."; + connectionWatchdog.reset(new QTimer); + connectionWatchdog->setSingleShot(false); + QObject::connect(connectionWatchdog.get(), &QTimer::timeout, + connectionWatchdog.get(), + [self] () { + qCDebug(QT_BT_DARWIN) << "Connection monitor timeout for device:" + << [device nameOrAddress] + << ", connected:" << bool([device isConnected]); + // Device can sometimes get properly connected without IOBluetooth + // calling the connectionComplete callback, so we check the status here + if ([device isConnected]) + [self connectionComplete:device status:kIOReturnSuccess]; + else + [self interruptSDPQuery]; + }); + connectionWatchdog->start(basebandConnectTimeoutMS); + } + } + + if ([device isConnected]) + result = [device performSDPQuery:self]; + + if (result != kIOReturnSuccess) { + qCCritical(QT_BT_DARWIN, "failed to start an SDP query"); + device.reset(); + } else { + isActive = true; + } + + return result; + } // Monterey's code path. + + if (qtFilters.size()) + result = [device performSDPQuery:self uuids:array]; + else + result = [device performSDPQuery:self]; + + if (result != kIOReturnSuccess) { + qCCritical(QT_BT_DARWIN) << "failed to start an SDP query"; + device.reset(); + } else { + isActive = true; + } + + return result; +} + +- (void)connectionComplete:(IOBluetoothDevice *)aDevice status:(IOReturn)status +{ + qCDebug(QT_BT_DARWIN) << "connectionComplete for device" << [aDevice nameOrAddress] + << "with status:" << status; + if (aDevice != device) { + // Connection was previously cancelled, probably, due to the timeout. + return; + } + + // The connectionComplete may be invoked by either the IOBluetooth callback or our + // connection watchdog. In either case stop the watchdog if it exists + if (connectionWatchdog) + connectionWatchdog->stop(); + + if (status == kIOReturnSuccess) + status = [aDevice performSDPQuery:self]; + + if (status != kIOReturnSuccess) { + isActive = false; + qCWarning(QT_BT_DARWIN, "failed to open connection or start an SDP query"); + Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)"); + delegate->SDPInquiryError(aDevice, status); + } +} + +- (void)stopSDPQuery +{ + // There is no API to stop it SDP on device, but there is a 'stop' + // member-function in Qt and after it's called sdpQueryComplete + // must be somehow ignored (device != aDevice in a callback). + device.reset(); + isActive = false; + connectionWatchdog.reset(); +} + +- (void)sdpQueryComplete:(IOBluetoothDevice *)aDevice status:(IOReturn)status +{ + qCDebug(QT_BT_DARWIN) << "sdpQueryComplete for device:" << [aDevice nameOrAddress] + << "with status:" << status; + // Can happen - there is no legal way to cancel an SDP query, + // after the 'reset' device can never be + // the same as the cancelled one. + if (device != aDevice) + return; + + Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)"); + + isActive = false; + + // If we used the manual connection establishment, close the + // connection here. Otherwise the IOBluetooth may call stray + // connectionComplete or sdpQueryCompletes + if (connectionWatchdog) { + qCDebug(QT_BT_DARWIN) << "Closing the connection established for SDP inquiry."; + connectionWatchdog.reset(); + [device closeConnection]; + } + + if (status != kIOReturnSuccess) + delegate->SDPInquiryError(aDevice, status); + else + delegate->SDPInquiryFinished(aDevice); +} + +@end diff --git a/src/bluetooth/darwin/btsdpinquiry_p.h b/src/bluetooth/darwin/btsdpinquiry_p.h new file mode 100644 index 0000000..74d7c85 --- /dev/null +++ b/src/bluetooth/darwin/btsdpinquiry_p.h @@ -0,0 +1,65 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef BTSDPINQUIRY_H +#define BTSDPINQUIRY_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 "qbluetoothaddress.h" +#include "qbluetoothuuid.h" + +#include +#include +#include + +#include + +#include + +@class QT_MANGLE_NAMESPACE(DarwinBTSDPInquiry); + +QT_BEGIN_NAMESPACE + +class QBluetoothServiceInfo; +class QVariant; + +namespace DarwinBluetooth { + +class SDPInquiryDelegate; + +void extract_service_record(IOBluetoothSDPServiceRecord *record, QBluetoothServiceInfo &serviceInfo); +QVariant extract_attribute_value(IOBluetoothSDPDataElement *dataElement); +QList extract_services_uuids(IOBluetoothDevice *device); + +} // namespace DarwinBluetooth + +QT_END_NAMESPACE + +@interface QT_MANGLE_NAMESPACE(DarwinBTSDPInquiry) : NSObject + +- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(DarwinBluetooth::SDPInquiryDelegate) *)aDelegate; +- (void)dealloc; + +- (IOReturn)performSDPQueryWithDevice:(const QBluetoothAddress &)address; +- (IOReturn)performSDPQueryWithDevice:(const QBluetoothAddress &)address + filters:(const QList &)filters; + +- (void)stopSDPQuery; + +- (void)sdpQueryComplete:(IOBluetoothDevice *)aDevice status:(IOReturn)status; + +@end + +QT_NAMESPACE_ALIAS_OBJC_CLASS(DarwinBTSDPInquiry); + +#endif diff --git a/src/bluetooth/darwin/btservicerecord.mm b/src/bluetooth/darwin/btservicerecord.mm new file mode 100644 index 0000000..5c2e518 --- /dev/null +++ b/src/bluetooth/darwin/btservicerecord.mm @@ -0,0 +1,443 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothserviceinfo.h" +#include "btservicerecord_p.h" + +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +namespace DarwinBluetooth { + +// +// Returns a dictionary containing the Bluetooth RFCOMM service definition +// corresponding to the provided |uuid| and |options|. +namespace { + +typedef ObjCStrongReference Dictionary; +typedef ObjCStrongReference SDPUUid; +typedef ObjCStrongReference Number; +typedef QBluetoothServiceInfo QSInfo; +typedef QSInfo::Sequence Sequence; +typedef QSInfo::AttributeId AttributeId; + +} + +#if 0 +QBluetoothUuid profile_uuid(const QBluetoothServiceInfo &serviceInfo) +{ + // Strategy to pick service uuid: + // 1.) use serviceUuid() + // 2.) use first custom uuid if available + // 3.) use first service class uuid + QBluetoothUuid serviceUuid(serviceInfo.serviceUuid()); + + if (serviceUuid.isNull()) { + const QVariant var(serviceInfo.attribute(QBluetoothServiceInfo::ServiceClassIds)); + if (var.isValid()) { + const Sequence seq(var.value()); + + for (qsizetype i = 0; i < seq.size(); ++i) { + QBluetoothUuid uuid(seq.at(i).value()); + if (uuid.isNull()) + continue; + + const int size = uuid.minimumSize(); + if (size == 2 || size == 4) { // Base UUID derived + if (serviceUuid.isNull()) + serviceUuid = uuid; + } else { + return uuid; + } + } + } + } + + return serviceUuid; +} +#endif + +template +Number variant_to_nsnumber(const QVariant &); + +template<> +Number variant_to_nsnumber(const QVariant &var) +{ + return Number([NSNumber numberWithUnsignedChar:var.value()], RetainPolicy::doInitialRetain); +} + +template<> +Number variant_to_nsnumber(const QVariant &var) +{ + return Number([NSNumber numberWithUnsignedShort:var.value()], RetainPolicy::doInitialRetain); +} + +template<> +Number variant_to_nsnumber(const QVariant &var) +{ + return Number([NSNumber numberWithUnsignedInt:var.value()], RetainPolicy::doInitialRetain); +} + +template<> +Number variant_to_nsnumber(const QVariant &var) +{ + return Number([NSNumber numberWithChar:var.value()], RetainPolicy::doInitialRetain); +} + +template<> +Number variant_to_nsnumber(const QVariant &var) +{ + return Number([NSNumber numberWithShort:var.value()], RetainPolicy::doInitialRetain); +} + +template<> +Number variant_to_nsnumber(const QVariant &var) +{ + return Number([NSNumber numberWithInt:var.value()], RetainPolicy::doInitialRetain); +} + +template +void add_attribute(const QVariant &var, AttributeId key, Dictionary dict) +{ + Q_ASSERT_X(dict, Q_FUNC_INFO, "invalid dictionary (nil)"); + + if (!var.canConvert()) + return; + + const Number num(variant_to_nsnumber(var)); + [dict setObject:num forKey:[NSString stringWithFormat:@"%x", int(key)]]; +} + +template<> +void add_attribute(const QVariant &var, AttributeId key, Dictionary dict) +{ + Q_ASSERT_X(dict, Q_FUNC_INFO, "invalid dictionary (nil)"); + + if (!var.canConvert()) + return; + + const QString string(var.value()); + if (!string.isEmpty()) { + if (NSString *const nsString = string.toNSString()) + [dict setObject:nsString forKey:[NSString stringWithFormat:@"%x", int(key)]]; + } +} + +template<> +void add_attribute(const QVariant &var, AttributeId key, Dictionary dict) +{ + Q_ASSERT_X(dict, Q_FUNC_INFO, "invalid dictionary (nil)"); + + if (!var.canConvert()) + return; + + SDPUUid ioUUID(iobluetooth_uuid(var.value())); + [dict setObject:ioUUID forKey:[NSString stringWithFormat:@"%x", int(key)]]; +} + +template<> +void add_attribute(const QVariant &var, AttributeId key, Dictionary dict) +{ + Q_ASSERT_X(dict, Q_FUNC_INFO, "invalid dictionary (nil)"); + + if (!var.canConvert()) + return; + + Q_UNUSED(var); + Q_UNUSED(key); + Q_UNUSED(dict); + + // TODO: not clear how should I pass an url in a dictionary, NSURL does not work. +} + +template +void add_attribute(const QVariant &var, NSMutableArray *list); + +template +void add_attribute(const QVariant &var, NSMutableArray *list) +{ + Q_ASSERT_X(list, Q_FUNC_INFO, "invalid list (nil)"); + + if (!var.canConvert()) + return; + + const Number num(variant_to_nsnumber(var)); + [list addObject:num]; +} + +template<> +void add_attribute(const QVariant &var, NSMutableArray *list) +{ + Q_ASSERT_X(list, Q_FUNC_INFO, "invalid list (nil)"); + + if (!var.canConvert()) + return; + + const Number num(variant_to_nsnumber(var)); + + NSDictionary* dict = @{ + @"DataElementType" : [NSNumber numberWithInt:1], + @"DataElementSize" : [NSNumber numberWithInt:2], + @"DataElementValue" : num + }; + + [list addObject: dict]; +} + +template<> +void add_attribute(const QVariant &var, NSMutableArray *list) +{ + Q_ASSERT_X(list, Q_FUNC_INFO, "invalid list (nil)"); + + if (!var.canConvert()) + return; + + const QString string(var.value()); + if (!string.isEmpty()) { + if (NSString *const nsString = string.toNSString()) + [list addObject:nsString]; + } +} + +template<> +void add_attribute(const QVariant &var, NSMutableArray *list) +{ + Q_ASSERT_X(list, Q_FUNC_INFO, "invalid list (nil)"); + + if (!var.canConvert()) + return; + + SDPUUid ioUUID(iobluetooth_uuid(var.value())); + [list addObject:ioUUID]; +} + +template<> +void add_attribute(const QVariant &var, NSMutableArray *list) +{ + Q_ASSERT_X(list, Q_FUNC_INFO, "invalid list (nil)"); + + if (!var.canConvert()) + return; + + Q_UNUSED(var); + Q_UNUSED(list); + // TODO: not clear how should I pass an url in a dictionary, NSURL does not work. +} + +void add_rfcomm_protocol_descriptor_list(uint16 channelID, Dictionary dict) +{ + Q_ASSERT_X(dict, Q_FUNC_INFO, "invalid dictionary (nil)"); + + QT_BT_MAC_AUTORELEASEPOOL; + + // Objective-C has literals (for arrays and dictionaries), but it will not compile + // on 10.7 or below, so quite a lot of code here. + + NSMutableArray *const descriptorList = [NSMutableArray array]; + + IOBluetoothSDPUUID *const l2capUUID = [IOBluetoothSDPUUID uuid16:kBluetoothSDPUUID16L2CAP]; + NSArray *const l2capList = [NSArray arrayWithObject:l2capUUID]; + + [descriptorList addObject:l2capList]; + // + IOBluetoothSDPUUID *const rfcommUUID = [IOBluetoothSDPUUID uuid16:kBluetoothSDPUUID16RFCOMM]; + NSMutableDictionary *const rfcommDict = [NSMutableDictionary dictionary]; + [rfcommDict setObject:[NSNumber numberWithInt:1] forKey:@"DataElementType"]; + [rfcommDict setObject:[NSNumber numberWithInt:1] forKey:@"DataElementSize"]; + [rfcommDict setObject:[NSNumber numberWithInt:channelID] forKey:@"DataElementValue"]; + // + NSMutableArray *const rfcommList = [NSMutableArray array]; + [rfcommList addObject:rfcommUUID]; + [rfcommList addObject:rfcommDict]; + + [descriptorList addObject:rfcommList]; + [dict setObject:descriptorList forKey:[NSString stringWithFormat:@"%x", + kBluetoothSDPAttributeIdentifierProtocolDescriptorList]]; +} + +void add_l2cap_protocol_descriptor_list(uint16 psm, Dictionary dict) +{ + Q_ASSERT_X(dict, Q_FUNC_INFO, "invalid dictionary (nil)"); + + QT_BT_MAC_AUTORELEASEPOOL; + + // Objective-C has literals (for arrays and dictionaries), but it will not compile + // on 10.7 or below, so quite a lot of code here. + + NSMutableArray *const descriptorList = [NSMutableArray array]; + NSMutableArray *const l2capList = [NSMutableArray array]; + + IOBluetoothSDPUUID *const l2capUUID = [IOBluetoothSDPUUID uuid16:kBluetoothSDPUUID16L2CAP]; + [l2capList addObject:l2capUUID]; + + NSMutableDictionary *const l2capDict = [NSMutableDictionary dictionary]; + [l2capDict setObject:[NSNumber numberWithInt:1] forKey:@"DataElementType"]; + [l2capDict setObject:[NSNumber numberWithInt:2] forKey:@"DataElementSize"]; + [l2capDict setObject:[NSNumber numberWithInt:psm] forKey:@"DataElementValue"]; + [l2capList addObject:l2capDict]; + + [descriptorList addObject:l2capList]; + [dict setObject:descriptorList forKey:[NSString stringWithFormat:@"%x", + kBluetoothSDPAttributeIdentifierProtocolDescriptorList]]; +} + +bool add_attribute(const QVariant &var, AttributeId key, NSMutableArray *list) +{ + Q_ASSERT_X(list, Q_FUNC_INFO, "invalid list (nil)"); + + if (var.canConvert()) + return false; + + if (var.typeId() == QMetaType::QString) { + //ServiceName, ServiceDescription, ServiceProvider. + add_attribute(var, list); + } else if (var.userType() == qMetaTypeId()) { + add_attribute(var, list); + } else { + // Here we need 'key' to understand the type. + // We can have different integer types actually, so I have to check + // the 'key' to be sure the conversion is reasonable. + switch (key) { + case QSInfo::ServiceRecordHandle: + case QSInfo::ServiceRecordState: + case QSInfo::ServiceInfoTimeToLive: + add_attribute(var, list); + break; + case QSInfo::BluetoothProfileDescriptorList: + add_attribute(var, list); + break; + case QSInfo::ServiceAvailability: + add_attribute(var, list); + break; + case QSInfo::IconUrl: + case QSInfo::DocumentationUrl: + case QSInfo::ClientExecutableUrl: + add_attribute(var, list); + break; + default:; + } + } + + return true; +} + +bool add_attribute(const QBluetoothServiceInfo &serviceInfo, AttributeId key, Dictionary dict) +{ + Q_ASSERT_X(dict, Q_FUNC_INFO, "invalid dict (nil)"); + + const QVariant var(serviceInfo.attribute(key)); + if (var.canConvert()) + return false; + + if (var.typeId() == QMetaType::QString) { + //ServiceName, ServiceDescription, ServiceProvider. + add_attribute(var, key, dict); + } else if (var.userType() == qMetaTypeId()) { + add_attribute(serviceInfo.attribute(key), key, dict); + } else { + // We can have different integer types actually, so I have to check + // the 'key' to be sure the conversion is reasonable. + switch (key) { + case QSInfo::ServiceRecordHandle: + case QSInfo::ServiceRecordState: + case QSInfo::ServiceInfoTimeToLive: + add_attribute(serviceInfo.attribute(key), key, dict); + break; + case QSInfo::ServiceAvailability: + add_attribute(serviceInfo.attribute(key), key, dict); + break; + case QSInfo::IconUrl: + case QSInfo::DocumentationUrl: + case QSInfo::ClientExecutableUrl: + add_attribute(serviceInfo.attribute(key), key, dict); + break; + default:; + } + } + + return true; +} + +bool add_sequence_attribute(const QVariant &var, AttributeId key, NSMutableArray *list) +{ + // Add a "nested" sequence. + Q_ASSERT_X(list, Q_FUNC_INFO, "invalid list (nil)"); + + if (var.isNull() || !var.canConvert()) + return false; + + NSMutableArray *const nested = [NSMutableArray array]; + [list addObject:nested]; + + const Sequence sequence(var.value()); + for (const QVariant &var : sequence) { + if (var.canConvert()) { + add_sequence_attribute(var, key, nested); + } else { + add_attribute(var, key, nested); + } + } + + return true; +} + +bool add_sequence_attribute(const QBluetoothServiceInfo &serviceInfo, AttributeId key, Dictionary dict) +{ + Q_ASSERT_X(dict, Q_FUNC_INFO, "invalid dictionary (nil)"); + + const QVariant &var(serviceInfo.attribute(key)); + if (var.isNull() || !var.canConvert()) + return false; + + QT_BT_MAC_AUTORELEASEPOOL; + + NSMutableArray *const list = [NSMutableArray array]; + const Sequence sequence(var.value()); + for (const QVariant &element : sequence) { + if (!add_sequence_attribute(element, key, list)) + add_attribute(element, key, list); + } + [dict setObject:list forKey:[NSString stringWithFormat:@"%x", int(key)]]; + return true; +} + +Dictionary iobluetooth_service_dictionary(const QBluetoothServiceInfo &serviceInfo) +{ + Dictionary dict; + + if (serviceInfo.socketProtocol() == QBluetoothServiceInfo::UnknownProtocol) + return dict; + + const QList attributeIds(serviceInfo.attributes()); + if (!attributeIds.size()) + return dict; + + dict.reset([[NSMutableDictionary alloc] init], RetainPolicy::noInitialRetain); + + for (quint16 key : attributeIds) { + if (key == QSInfo::ProtocolDescriptorList) // We handle it in a special way. + continue; + // TODO: check if non-sequence QVariant still must be + // converted into NSArray for some attribute ID. + if (!add_sequence_attribute(serviceInfo, AttributeId(key), dict)) + add_attribute(serviceInfo, AttributeId(key), dict); + } + + if (serviceInfo.socketProtocol() == QBluetoothServiceInfo::L2capProtocol) { + add_l2cap_protocol_descriptor_list(serviceInfo.protocolServiceMultiplexer(), + dict); + } else { + add_rfcomm_protocol_descriptor_list(serviceInfo.serverChannel(), dict); + } + + return dict; +} + +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/darwin/btservicerecord_p.h b/src/bluetooth/darwin/btservicerecord_p.h new file mode 100644 index 0000000..fc882d9 --- /dev/null +++ b/src/bluetooth/darwin/btservicerecord_p.h @@ -0,0 +1,36 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef BTSERVICERECORD_P_H +#define BTSERVICERECORD_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 "btutility_p.h" + +#include + +#include + +QT_BEGIN_NAMESPACE + +class QBluetoothServiceInfo; + +namespace DarwinBluetooth { + +ObjCStrongReference iobluetooth_service_dictionary(const QBluetoothServiceInfo &serviceInfo); + +} // namespace DarwinBluetooth + +QT_END_NAMESPACE + +#endif diff --git a/src/bluetooth/darwin/btsocketlistener.mm b/src/bluetooth/darwin/btsocketlistener.mm new file mode 100644 index 0000000..073e894 --- /dev/null +++ b/src/bluetooth/darwin/btsocketlistener.mm @@ -0,0 +1,92 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "btsocketlistener_p.h" +#include "btdelegates_p.h" +#include "btutility_p.h" + +#include + +QT_USE_NAMESPACE + +@implementation DarwinBTSocketListener +{ + IOBluetoothUserNotification *connectionNotification; + QT_PREPEND_NAMESPACE(DarwinBluetooth::SocketListener) *delegate; + quint16 port; +} + +- (id)initWithListener:(DarwinBluetooth::SocketListener *)aDelegate +{ + Q_ASSERT_X(aDelegate, Q_FUNC_INFO, "invalid delegate (null)"); + if (self = [super init]) { + connectionNotification = nil; + delegate = aDelegate; + port = 0; + } + + return self; +} + +- (void)dealloc +{ + [connectionNotification unregister]; + [connectionNotification release]; + + [super dealloc]; +} + +- (bool)listenRFCOMMConnectionsWithChannelID:(BluetoothRFCOMMChannelID)channelID +{ + Q_ASSERT_X(!connectionNotification, Q_FUNC_INFO, "already listening"); + + connectionNotification = [IOBluetoothRFCOMMChannel registerForChannelOpenNotifications:self + selector:@selector(rfcommOpenNotification:channel:) + withChannelID:channelID + direction:kIOBluetoothUserNotificationChannelDirectionIncoming]; + connectionNotification = [connectionNotification retain]; + if (connectionNotification) + port = channelID; + + return connectionNotification; +} + +- (bool)listenL2CAPConnectionsWithPSM:(BluetoothL2CAPPSM)psm +{ + Q_ASSERT_X(!connectionNotification, Q_FUNC_INFO, "already listening"); + + connectionNotification = [IOBluetoothL2CAPChannel registerForChannelOpenNotifications:self + selector:@selector(l2capOpenNotification:channel:) + withPSM:psm + direction:kIOBluetoothUserNotificationChannelDirectionIncoming]; + connectionNotification = [connectionNotification retain]; + if (connectionNotification) + port = psm; + + return connectionNotification; +} + +- (void)rfcommOpenNotification:(IOBluetoothUserNotification *)notification + channel:(IOBluetoothRFCOMMChannel *)newChannel +{ + Q_UNUSED(notification); + + Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)"); + delegate->openNotifyRFCOMM(newChannel); +} + +- (void)l2capOpenNotification:(IOBluetoothUserNotification *)notification + channel:(IOBluetoothL2CAPChannel *)newChannel +{ + Q_UNUSED(notification); + + Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)"); + delegate->openNotifyL2CAP(newChannel); +} + +- (quint16)port +{ + return port; +} + +@end diff --git a/src/bluetooth/darwin/btsocketlistener_p.h b/src/bluetooth/darwin/btsocketlistener_p.h new file mode 100644 index 0000000..82950ec --- /dev/null +++ b/src/bluetooth/darwin/btsocketlistener_p.h @@ -0,0 +1,58 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef BTSOCKETLISTENER_P_H +#define BTSOCKETLISTENER_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 + +namespace DarwinBluetooth { + +class SocketListener; + +} + +QT_END_NAMESPACE + +// A single DarwinBTSocketListener can be started only once with +// RFCOMM or L2CAP protocol. It must be deleted to stop listening. + +@interface QT_MANGLE_NAMESPACE(DarwinBTSocketListener) : NSObject + +- (id)initWithListener:(QT_PREPEND_NAMESPACE(DarwinBluetooth::SocketListener) *)aDelegate; +- (void)dealloc; + +- (bool)listenRFCOMMConnectionsWithChannelID:(BluetoothRFCOMMChannelID)channelID; +- (bool)listenL2CAPConnectionsWithPSM:(BluetoothL2CAPPSM)psm; + +- (void)rfcommOpenNotification:(IOBluetoothUserNotification *)notification + channel:(IOBluetoothRFCOMMChannel *)newChannel; + +- (void)l2capOpenNotification:(IOBluetoothUserNotification *)notification + channel:(IOBluetoothL2CAPChannel *)newChannel; + +- (quint16)port; + +@end + +QT_NAMESPACE_ALIAS_OBJC_CLASS(DarwinBTSocketListener); + +#endif diff --git a/src/bluetooth/darwin/btutility.mm b/src/bluetooth/darwin/btutility.mm new file mode 100644 index 0000000..e9f2156 --- /dev/null +++ b/src/bluetooth/darwin/btutility.mm @@ -0,0 +1,332 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qlowenergycharacteristicdata.h" +#include "qbluetoothaddress.h" +#include "qbluetoothuuid.h" +#include "btutility_p.h" + +#include +#include +#include + +#ifndef QT_IOS_BLUETOOTH + +#import +#import +#import + +#endif + +#include +#include + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(QT_BT_DARWIN, "qt.bluetooth.darwin") + +namespace DarwinBluetooth { + +const int defaultLEScanTimeoutMS = 40000; +// We use it only on iOS for now: +const int maxValueLength = 512; + +const int defaultMtu = 23; + +QString qt_address(NSString *address) +{ + if (address && address.length) { + NSString *const fixed = [address stringByReplacingOccurrencesOfString:@"-" withString:@":"]; + return QString::fromNSString(fixed); + } + + return QString(); +} + +#ifndef QT_IOS_BLUETOOTH + + +QBluetoothAddress qt_address(const BluetoothDeviceAddress *a) +{ + if (a) { + // TODO: can a byte order be different in BluetoothDeviceAddress? + const quint64 qAddress = a->data[5] | + qint64(a->data[4]) << 8 | + qint64(a->data[3]) << 16 | + qint64(a->data[2]) << 24 | + qint64(a->data[1]) << 32 | + qint64(a->data[0]) << 40; + return QBluetoothAddress(qAddress); + } + + return QBluetoothAddress(); +} + +BluetoothDeviceAddress iobluetooth_address(const QBluetoothAddress &qAddress) +{ + BluetoothDeviceAddress a = {}; + if (!qAddress.isNull()) { + const quint64 val = qAddress.toUInt64(); + a.data[0] = (val >> 40) & 0xff; + a.data[1] = (val >> 32) & 0xff; + a.data[2] = (val >> 24) & 0xff; + a.data[3] = (val >> 16) & 0xff; + a.data[4] = (val >> 8) & 0xff; + a.data[5] = val & 0xff; + } + + return a; +} + +ObjCStrongReference iobluetooth_uuid(const QBluetoothUuid &uuid) +{ + const unsigned nBytes = 128 / std::numeric_limits::digits; + const QUuid::Id128Bytes intVal(uuid.toBytes()); + + const ObjCStrongReference iobtUUID([IOBluetoothSDPUUID uuidWithBytes:intVal.data + length:nBytes], RetainPolicy::doInitialRetain); + return iobtUUID; +} + +QBluetoothUuid qt_uuid(IOBluetoothSDPUUID *uuid) +{ + QBluetoothUuid qtUuid; + if (!uuid || [uuid length] != 16) // TODO: issue any diagnostic? + return qtUuid; + + // TODO: ensure the correct byte-order!!! + QUuid::Id128Bytes uuidVal = {}; + const quint8 *const source = static_cast([uuid bytes]); + std::copy(source, source + 16, uuidVal.data); + return QBluetoothUuid(uuidVal); +} + +QString qt_error_string(IOReturn errorCode) +{ + switch (errorCode) { + case kIOReturnSuccess: + // NoError in many classes == an empty string description. + return QString(); + case kIOReturnNoMemory: + return QString::fromLatin1("memory allocation failed"); + case kIOReturnNoResources: + return QString::fromLatin1("failed to obtain a resource"); + case kIOReturnBusy: + return QString::fromLatin1("device is busy"); + case kIOReturnStillOpen: + return QString::fromLatin1("device(s) still open"); + // Others later ... + case kIOReturnError: // "general error" (IOReturn.h) + default: + return QString::fromLatin1("unknown error"); + } +} + +void qt_test_iobluetooth_runloop() +{ + // IOBluetooth heavily relies on a CFRunLoop machinery in a way it dispatches + // its callbacks. Technically, having a QThread with CFRunLoop-based event + // dispatcher would suffice. At the moment of writing we do not have such + // event dispatcher, so we only can work on the main thread. + if (CFRunLoopGetMain() != CFRunLoopGetCurrent()) { + qCWarning(QT_BT_DARWIN) << "IOBluetooth works only on the main thread or a" + << "thread with a running CFRunLoop"; + } +} + +#endif // !QT_IOS_BLUETOOTH + +// Apple has: CBUUID, NSUUID, CFUUID, IOBluetoothSDPUUID +// and it's handy to have several converters: + +QBluetoothUuid qt_uuid(CBUUID *uuid) +{ + // Apples' docs say "128 bit" and "16-bit UUIDs are implicitly + // pre-filled with the Bluetooth Base UUID." + // But Core Bluetooth can return CBUUID objects of length 2, 4, and 16. + + if (!uuid) + return QBluetoothUuid(); + + QT_BT_MAC_AUTORELEASEPOOL; + + if (uuid.data.length == 2) { + // CBUUID's docs say nothing about byte-order. + // Seems to be in big-endian. + const uchar *const src = static_cast(uuid.data.bytes); + return QBluetoothUuid(qFromBigEndian(src)); + } else if (uuid.data.length == 4) { + const uchar *const src = static_cast(uuid.data.bytes); + return QBluetoothUuid(qFromBigEndian(src)); + } else if (uuid.data.length == 16) { + QUuid::Id128Bytes qtUuidData = {}; + const quint8 *const source = static_cast(uuid.data.bytes); + std::copy(source, source + 16, qtUuidData.data); + + return QBluetoothUuid(qtUuidData); + } + + qCDebug(QT_BT_DARWIN) << "qt_uuid, invalid CBUUID, 2, 4, or 16 bytes expected, but got " + << uuid.data.length << " bytes length"; + return QBluetoothUuid(); +} + +ObjCStrongReference cb_uuid(const QBluetoothUuid &qtUuid) +{ + bool ok = false; + const auto asUInt16 = qToBigEndian(qtUuid.toUInt16(&ok)); + const auto asUInt128 = qtUuid.toBytes(); + + const NSUInteger length = ok ? sizeof asUInt16 : sizeof asUInt128; + const void *bytes = &asUInt128; + if (ok) + bytes = &asUInt16; + + NSData *uuidData = [NSData dataWithBytes:bytes length:length]; + ObjCStrongReference cbUuid([CBUUID UUIDWithData:uuidData], RetainPolicy::doInitialRetain); + return cbUuid; +} + +bool equal_uuids(const QBluetoothUuid &qtUuid, CBUUID *cbUuid) +{ + const QBluetoothUuid qtUuid2(qt_uuid(cbUuid)); + return qtUuid == qtUuid2; +} + +bool equal_uuids(CBUUID *cbUuid, const QBluetoothUuid &qtUuid) +{ + return equal_uuids(qtUuid, cbUuid); +} + +QByteArray qt_bytearray(NSData *data) +{ + QByteArray value; + if (!data || !data.length) + return value; + + value.resize(data.length); + const char *const src = static_cast(data.bytes); + std::copy(src, src + data.length, value.data()); + + return value; +} + +template +QByteArray qt_bytearray(Integer n) +{ + QByteArray value; + value.resize(sizeof n); + const char *const src = reinterpret_cast(&n); + std::copy(src, src + sizeof n, value.data()); + + return value; +} + +QByteArray qt_bytearray(NSString *string) +{ + if (!string) + return QByteArray(); + + QT_BT_MAC_AUTORELEASEPOOL; + NSData *const utf8Data = [string dataUsingEncoding:NSUTF8StringEncoding]; + + return qt_bytearray(utf8Data); +} + +QByteArray qt_bytearray(NSObject *obj) +{ + // descriptor.value has type 'id'. + // While the Apple's docs say this about descriptors: + // + // - CBUUIDCharacteristicExtendedPropertiesString + // The string representation of the UUID for the extended properties descriptor. + // The corresponding value for this descriptor is an NSNumber object. + // + // - CBUUIDCharacteristicUserDescriptionString + // The string representation of the UUID for the user description descriptor. + // The corresponding value for this descriptor is an NSString object. + // + // ... etc. + // + // This is not true. On OS X, they all seem to be NSData (or derived from NSData), + // and they can be something else on iOS (NSNumber, NSString, etc.) + if (!obj) + return QByteArray(); + + QT_BT_MAC_AUTORELEASEPOOL; + + if ([obj isKindOfClass:[NSData class]]) { + return qt_bytearray(static_cast(obj)); + } else if ([obj isKindOfClass:[NSString class]]) { + return qt_bytearray(static_cast(obj)); + } else if ([obj isKindOfClass:[NSNumber class]]) { + NSNumber *const nsNumber = static_cast(obj); + return qt_bytearray([nsNumber unsignedShortValue]); + } + // TODO: Where can be more types, but Core Bluetooth does not support them, + // or at least it's not documented. + + return QByteArray(); +} + +ObjCStrongReference data_from_bytearray(const QByteArray & qtData) +{ + if (!qtData.size()) + return ObjCStrongReference([[NSData alloc] init], RetainPolicy::noInitialRetain); + + ObjCStrongReference result([NSData dataWithBytes:qtData.constData() length:qtData.size()], RetainPolicy::doInitialRetain); + return result; +} + +ObjCStrongReference mutable_data_from_bytearray(const QByteArray &qtData) +{ + using MutableData = ObjCStrongReference; + + if (!qtData.size()) + return MutableData([[NSMutableData alloc] init], RetainPolicy::noInitialRetain); + + MutableData result([[NSMutableData alloc] initWithLength:qtData.size()], RetainPolicy::noInitialRetain); + [result replaceBytesInRange:NSMakeRange(0, qtData.size()) + withBytes:qtData.constData()]; + return result; +} + +// A small RAII class for a dispatch queue. +class SerialDispatchQueue +{ +public: + explicit SerialDispatchQueue(const char *label) + { + Q_ASSERT(label); + + queue = dispatch_queue_create(label, DISPATCH_QUEUE_SERIAL); + if (!queue) { + qCCritical(QT_BT_DARWIN) << "failed to create dispatch queue with label" + << label; + } + } + ~SerialDispatchQueue() + { + if (queue) + dispatch_release(queue); + } + + dispatch_queue_t data() const + { + return queue; + } +private: + dispatch_queue_t queue; + + Q_DISABLE_COPY(SerialDispatchQueue) +}; + +dispatch_queue_t qt_LE_queue() +{ + static const SerialDispatchQueue leQueue("qt-bluetooth-LE-queue"); + return leQueue.data(); +} + +} // namespace DarwinBluetooth + +QT_END_NAMESPACE diff --git a/src/bluetooth/darwin/btutility_p.h b/src/bluetooth/darwin/btutility_p.h new file mode 100644 index 0000000..87f4a71 --- /dev/null +++ b/src/bluetooth/darwin/btutility_p.h @@ -0,0 +1,132 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef BTUTILITY_P_H +#define BTUTILITY_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 "btraii_p.h" + +#include +#include + +#include + +#include + +#include + +#ifdef Q_OS_MACOS +#include +#endif // Q_OS_MACOS + +QT_BEGIN_NAMESPACE + +class QLowEnergyCharacteristicData; +class QBluetoothAddress; +class QBluetoothUuid; +class QString; + +namespace DarwinBluetooth { + +template +class ObjCScopedPointer +{ +public: + ObjCScopedPointer() = default; + ObjCScopedPointer(T *ptr, RetainPolicy policy) + : m_ptr(ptr, policy) + { + } + void swap(ObjCScopedPointer &other) + { + m_ptr.swap(other.m_ptr); + } + void reset() + { + m_ptr.reset(); + } + void reset(T *ptr, RetainPolicy policy) + { + m_ptr.reset(ptr, policy); + } + operator T*() const + { + return m_ptr.getAs(); + } + T *get() const + { + // operator T * above does not work when accessing + // properties using '.' syntax. + return m_ptr.getAs(); + } +private: + // Copy and move disabled by m_ptr: + ScopedPointer m_ptr; +}; + +#define QT_BT_MAC_AUTORELEASEPOOL const QMacAutoReleasePool pool; + +template +class ObjCStrongReference final : public StrongReference { +public: + using StrongReference::StrongReference; + + operator T *() const + { + return this->getAs(); + } + + T *data() const + { + return this->getAs(); + } +}; + +QString qt_address(NSString *address); + +#ifndef QT_IOS_BLUETOOTH + +QBluetoothAddress qt_address(const BluetoothDeviceAddress *address); +BluetoothDeviceAddress iobluetooth_address(const QBluetoothAddress &address); + +ObjCStrongReference iobluetooth_uuid(const QBluetoothUuid &uuid); +QBluetoothUuid qt_uuid(IOBluetoothSDPUUID *uuid); +QString qt_error_string(IOReturn errorCode); +void qt_test_iobluetooth_runloop(); + +#endif // !QT_IOS_BLUETOOTH + +QBluetoothUuid qt_uuid(CBUUID *uuid); +ObjCStrongReference cb_uuid(const QBluetoothUuid &qtUuid); +bool equal_uuids(const QBluetoothUuid &qtUuid, CBUUID *cbUuid); +bool equal_uuids(CBUUID *cbUuid, const QBluetoothUuid &qtUuid); +QByteArray qt_bytearray(NSData *data); +QByteArray qt_bytearray(NSObject *data); + +ObjCStrongReference data_from_bytearray(const QByteArray &qtData); +ObjCStrongReference mutable_data_from_bytearray(const QByteArray &qtData); + +dispatch_queue_t qt_LE_queue(); + +extern const int defaultLEScanTimeoutMS; +extern const int maxValueLength; +extern const int defaultMtu; + +} // namespace DarwinBluetooth + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_DARWIN) + +QT_END_NAMESPACE + +#endif // BTUTILITY_P_H diff --git a/src/bluetooth/darwin/uistrings.cpp b/src/bluetooth/darwin/uistrings.cpp new file mode 100644 index 0000000..9f93b23 --- /dev/null +++ b/src/bluetooth/darwin/uistrings.cpp @@ -0,0 +1,56 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "uistrings_p.h" + +#include + +// Translatable messages should go into this .cpp file for them to +// be picked up by lupdate. + +QT_BEGIN_NAMESPACE + +const char DEV_DISCOVERY[] = "QBluetoothDeviceDiscoveryAgent"; +const char DD_POWERED_OFF[] = QT_TRANSLATE_NOOP("QBluetoothDeviceDiscoveryAgent", "Device is powered off"); +const char DD_INVALID_ADAPTER[] = QT_TRANSLATE_NOOP("QBluetoothDeviceDiscoveryAgent", "Cannot find valid Bluetooth adapter."); +const char DD_IO[] = QT_TRANSLATE_NOOP("QBluetoothDeviceDiscoveryAgent", "Input Output Error"); +const char DD_NOTSUPPORTED[] = QT_TRANSLATE_NOOP("QBluetoothDeviceDiscoveryAgent", "Bluetooth LE is not supported"); +const char DD_UNKNOWN_ERROR[] = QT_TRANSLATE_NOOP("QBluetoothDeviceDiscoveryAgent", "Unknown error"); +const char DD_MISSING_PERMISSION[] = QT_TRANSLATE_NOOP("QBluetoothDeviceDiscoveryAgent", "Missing permission"); +const char DD_NOT_STARTED[] = QT_TRANSLATE_NOOP("QBluetoothDeviceDiscoveryAgent", "Cannot start device inquiry"); +const char DD_NOT_STARTED_LE[] = QT_TRANSLATE_NOOP("QBluetoothDeviceDiscoveryAgent", "Cannot start low energy device inquiry"); +const char DD_NOT_STOPPED[] = QT_TRANSLATE_NOOP("QBluetoothDeviceDiscoveryAgent", "Discovery cannot be stopped"); + +const char SERVICE_DISCOVERY[] = "QBluetoothServiceDiscoveryAgent"; +const char SD_LOCAL_DEV_OFF[] = QT_TRANSLATE_NOOP("QBluetoothServiceDiscoveryAgent", "Local device is powered off"); +const char SD_MINIMAL_FAILED[] = QT_TRANSLATE_NOOP("QBluetoothServiceDiscoveryAgent", "Minimal service discovery failed"); +const char SD_INVALID_ADDRESS[] = QT_TRANSLATE_NOOP("QBluetoothServiceDiscoveryAgent", "Invalid Bluetooth adapter address"); + +const char SOCKET[] = "QBluetoothSocket"; +const char SOC_NETWORK_ERROR[] = QT_TRANSLATE_NOOP("QBluetoothSocket", "Network Error"); +const char SOC_NOWRITE[] = QT_TRANSLATE_NOOP("QBluetoothSocket", "Cannot write while not connected"); +const char SOC_CONNECT_IN_PROGRESS[] = QT_TRANSLATE_NOOP("QBluetoothSocket", "Trying to connect while connection is in progress"); +const char SOC_SERVICE_NOT_FOUND[] = QT_TRANSLATE_NOOP("QBluetoothSocket", "Service cannot be found"); +const char SOC_INVAL_DATASIZE[] = QT_TRANSLATE_NOOP("QBluetoothSocket", "Invalid data/data size"); +const char SOC_NOREAD[] = QT_TRANSLATE_NOOP("QBluetoothSocket", "Cannot read while not connected"); + +const char TRANSFER_REPLY[] = "QBluetoothTransferReply"; +const char TR_INVAL_TARGET[] = QT_TRANSLATE_NOOP("QBluetoothTransferReply", "Invalid target address"); +const char TR_SESSION_NO_START[] = QT_TRANSLATE_NOOP("QBluetoothTransferReply", "Push session cannot be started"); +const char TR_CONNECT_FAILED[] = QT_TRANSLATE_NOOP("QBluetoothTransferReply", "Push session cannot connect"); +const char TR_FILE_NOT_EXIST[] = QT_TRANSLATE_NOOP("QBluetoothTransferReply", "Source file does not exist"); +const char TR_NOT_READ_IODEVICE[] = QT_TRANSLATE_NOOP("QBluetoothTransferReply", "QIODevice cannot be read. Make sure it is open for reading."); +const char TR_SESSION_FAILED[] = QT_TRANSLATE_NOOP("QBluetoothTransferReply", "Push session failed"); +const char TR_INVALID_DEVICE[] = QT_TRANSLATE_NOOP("QBluetoothTransferReply", "Invalid input device (null)"); +const char TR_OP_CANCEL[] = QT_TRANSLATE_NOOP("QBluetoothTransferReply", "Operation canceled"); +const char TR_IN_PROGRESS[] = QT_TRANSLATE_NOOP("QBluetoothTransferReply", "Transfer already started"); +const char TR_SERVICE_NO_FOUND[] = QT_TRANSLATE_NOOP("QBluetoothTransferReply", "Push service not found"); + +const char LE_CONTROLLER[] = "QLowEnergyController"; +const char LEC_RDEV_NO_FOUND[] = QT_TRANSLATE_NOOP("QLowEnergyController", "Remote device cannot be found"); +const char LEC_NO_LOCAL_DEV[] = QT_TRANSLATE_NOOP("QLowEnergyController", "Cannot find local adapter"); +const char LEC_IO_ERROR[] = QT_TRANSLATE_NOOP("QLowEnergyController", "Error occurred during connection I/O"); +const char LEC_UNKNOWN_ERROR[] = QT_TRANSLATE_NOOP("QLowEnergyController", "Unknown Error"); +const char LEC_MISSING_PERMISSION[] = QT_TRANSLATE_NOOP("QLowEnergyController", "Missing permission"); + +QT_END_NAMESPACE diff --git a/src/bluetooth/darwin/uistrings_p.h b/src/bluetooth/darwin/uistrings_p.h new file mode 100644 index 0000000..11cfb24 --- /dev/null +++ b/src/bluetooth/darwin/uistrings_p.h @@ -0,0 +1,75 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef TRANSLATIONS_H +#define TRANSLATIONS_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 + +// QBluetoothDeviceDiscoveryAgent related strings +extern const char DEV_DISCOVERY[]; +extern const char DD_POWERED_OFF[]; +extern const char DD_INVALID_ADAPTER[]; +extern const char DD_IO[]; +extern const char DD_NOTSUPPORTED[]; +extern const char DD_UNKNOWN_ERROR[]; +extern const char DD_MISSING_PERMISSION[]; +extern const char DD_NOT_STARTED[]; +extern const char DD_NOT_STARTED_LE[]; +extern const char DD_NOT_STOPPED[]; + +// QBluetoothServiceDiscoveryAgent related strings +extern const char SERVICE_DISCOVERY[]; +extern const char SD_LOCAL_DEV_OFF[]; +extern const char SD_MINIMAL_FAILED[]; +extern const char SD_INVALID_ADDRESS[]; + +// QBluetoothSocket related strings +extern const char SOCKET[]; +extern const char SOC_NETWORK_ERROR[]; +extern const char SOC_NOWRITE[]; +extern const char SOC_CONNECT_IN_PROGRESS[]; +extern const char SOC_SERVICE_NOT_FOUND[]; +extern const char SOC_INVAL_DATASIZE[]; +extern const char SOC_NOREAD[]; + +// QBluetoothTransferReply related strings +extern const char TRANSFER_REPLY[]; +extern const char TR_INVAL_TARGET[]; +extern const char TR_SESSION_NO_START[]; +extern const char TR_CONNECT_FAILED[]; +extern const char TR_FILE_NOT_EXIST[]; +extern const char TR_NOT_READ_IODEVICE[]; +extern const char TR_SESSION_FAILED[]; +extern const char TR_INVALID_DEVICE[]; +extern const char TR_OP_CANCEL[]; +extern const char TR_IN_PROGRESS[]; +extern const char TR_SERVICE_NO_FOUND[]; + +// QLowEnergyController related strings +extern const char LE_CONTROLLER[]; +extern const char LEC_RDEV_NO_FOUND[]; +extern const char LEC_NO_LOCAL_DEV[]; +extern const char LEC_IO_ERROR[]; +extern const char LEC_UNKNOWN_ERROR[]; +extern const char LEC_MISSING_PERMISSION[]; + +QT_END_NAMESPACE + +#endif // TRANSLATIONS_H + diff --git a/src/bluetooth/doc/images/peripheral-structure.png b/src/bluetooth/doc/images/peripheral-structure.png new file mode 100644 index 0000000..55cdf16 Binary files /dev/null and b/src/bluetooth/doc/images/peripheral-structure.png differ diff --git a/src/bluetooth/doc/qt6-changes.qdoc b/src/bluetooth/doc/qt6-changes.qdoc new file mode 100644 index 0000000..c22105e --- /dev/null +++ b/src/bluetooth/doc/qt6-changes.qdoc @@ -0,0 +1,141 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \page qtbluetooth-changes-qt6.html + \title Changes to Qt Bluetooth + \ingroup changes-qt-5-to-6 + \brief Migrate QtBluetooth to Qt 6. + + Qt 6 is a result of the conscious effort to make the framework more + efficient and easy to use. + + We try to maintain binary and source compatibility for all the public + APIs in each release. But some changes were inevitable in an effort to + make Qt a better framework. + + In this topic we summarize those changes in QtBluetooth, and provide guidance + to handle them. + + \section1 General + + \list + \li qbluetoothglobal.h was removed. qtbluetoothglobal.h is the official header with the same purpose. + + \li Every usage of QVector has been replaced by QList. + + \li Win32 backend has been removed. There will not be a working Bluetooth backend when Qt is built with mingw. + + \li Since there is now only one Windows backend, the logging category qt.bluetooth.winrt was removed. + The corresponding log messages are now in qt.bluetooth.windows. + \endlist + + \section1 QBluetooth namespace + + The enums QBluetooth::Security and QBluetooth::AttAccessConstraint have been changed + to a scoped enums for improved type safety. + + \section1 QBluetoothDeviceDiscoveryAgent + + QBluetoothDeviceDiscoveryAgent::inquiryType property and related setter/getter & enum were removed. + The API element was never implemented and/or supported. + + \section1 QBluetoothDeviceInfo + + \list + \li manufacturerData() returns a QMultiHash rather than QHash. Since Qt 6 + QMultiHash is no longer derived from QHash. + + \li DataCompleteness was removed without replacement as the related API elements + no longer served a purpose + + \li setServiceUuids(const QList, DataCompleteness) was replaced by + setServiceUuids(const QList &uuids) + + \li DataCompleteness serviceUuidsCompleteness() const was removed without replacement. + + \li QList serviceUuids(DataCompleteness *completeness = nullptr) const was replaced by + QList serviceUuids() const. + \endlist + + \section1 QBluetoothLocalDevice + + The pairing agent related API was removed without replacement. This includes pairingConfirmation(bool), + pairingDisplayPinCode(..) & pairingDisplayConfirmation(..). Except for Android and BlueZ 4 there was + never an implementation for it. Bluez 4 support was removed in Qt 6 and Android's implementation + required unobtainable BLUETOOTH_PRIVILEGED for at least parts of the code. + + \section1 QLowEnergyService + + Renamed ServiceState enum values: + \list + \li \l{QLowEnergyService::DiscoveryRequired}{DiscoveryRequired} becomes \l{QLowEnergyService::RemoteService}{RemoteService} + \li \l{QLowEnergyService::DiscoveringService}{DiscoveringService} becomes \l{QLowEnergyService::RemoteServiceDiscovering}{RemoteServiceDiscovering} + \li \l{QLowEnergyService::ServiceDiscovered}{ServiceDiscovered} becomes \l{QLowEnergyService::RemoteServiceDiscovered}{RemoteServiceDiscovered} + \endlist + This change happens in anticipation that service discovery might become an optional + step in the future. + + \section1 QBluetoothUuid + + enums \l{QBluetoothUuid::ProtocolUuid}{ProtocolUuid}, + \l{QBluetoothUuid::ServiceClassUuid}{ServiceClassUuid}, + \l{QBluetoothUuid::CharacteristicType}{CharacteristicType}, and + \l{QBluetoothUuid::DescriptorType}{DescriptorType} are now scoped enums. + The usage of enum items has to be adapted in user code. + + \section1 QLowEnergyController + + \list + \li Existing ctors and create*() functions with remote QBluetoothAddress parameters have been removed. QBluetoothAddress + is not sufficient to indicate remote devices on Apple systems. It requires UUIDs to "name" devices. This can only + be satisfied by QBluetoothDeviceInfo. + + \li Remaining QLowEnergyController ctors have been made private. The createPeripheral() and createCentral() functions + should be used to obtain QLowEnergyController instances. + \endlist + + \section1 QLowEnergyCharacteristic + + \list + \li The new method clientCharacteristicConfiguration() has been introduced to conveniently obtain the + Client Characteristic Configuration Descriptor. + \li The constants + \l{QLowEnergyCharacteristic::CCCDDisable}{CCCDDisable}, + \l{QLowEnergyCharacteristic::CCCDEnableNotification}{CCCDEnableNotification}, and + \l{QLowEnergyCharacteristic::CCCDEnableIndication}{CCCDEnableIndication} have been introduced + which hold the possible values for the Client Characteristic Configuration Descriptor. + \li The handle() method is no longer part of the public Bluetooth LE interfaces. It's purpose as identifier + for characteristics was replaced. The QLowEnergyCharacteristic instances itself serve as identifier. + \endlist + + \section1 QLowEnergyDescriptor + + The handle() method is no longer part of the public Bluetooth LE interfaces. It's purpose as identifier + for descriptors was replaced. The QLowEnergyDescriptor instances itself serve as identifier. + + \section1 QBluetoothTransferManager + + QBluetoothTransferManager, QBluetoothTransferRequest, and QBluetoothTransferReply have been removed + without replacement. + + \section1 QBluetoothSocket + + QBluetoothSocket::SocketState and QBluetoothSocket::SocketError are now scoped enums. The usage of enum + items has to be adapted in user code. + + \section1 QML Interface + + The QML interface has been removed because socket programming via QML is not advisable. + QDeclarativeBluetoothService, QDeclarativeBluetoothSocket, and QDeclarativeBluetoothDiscoveryModel + (in QML: BluetoothService, BluetoothSocket, and BluetoothDiscoveryModel) + have been removed without replacement. + + \section1 "error" signals + + The "error" signals in QBluetoothDeviceDiscoveryAgent, QBluetoothLocalDevice, QBluetoothServer, + QBluetoothServiceDiscoveryAgent, QBluetoothSocket, QLowEnergyController, and QLowEnergyService + have been renamed to "errorOccurred" to remove ambiguities between the "error" signal and the + "error" getter. + +*/ diff --git a/src/bluetooth/doc/qtbluetooth.qdocconf b/src/bluetooth/doc/qtbluetooth.qdocconf new file mode 100644 index 0000000..325897c --- /dev/null +++ b/src/bluetooth/doc/qtbluetooth.qdocconf @@ -0,0 +1,54 @@ +include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf) +include($QT_INSTALL_DOCS/config/exampleurl-qtconnectivity.qdocconf) + +project = QtBluetooth +description = Qt Bluetooth Reference Documentation +version = $QT_VERSION + +examplesinstallpath = bluetooth + +qhp.projects = QtBluetooth + +qhp.QtBluetooth.file = qtbluetooth.qhp +qhp.QtBluetooth.namespace = org.qt-project.qtbluetooth.$QT_VERSION_TAG +qhp.QtBluetooth.virtualFolder = qtbluetooth +qhp.QtBluetooth.indexTitle = Qt Bluetooth +qhp.QtBluetooth.indexRoot = + +qhp.QtBluetooth.subprojects = overviews classes examples +qhp.QtBluetooth.subprojects.classes.title = C++ Classes +qhp.QtBluetooth.subprojects.classes.indexTitle = Qt Bluetooth C++ Classes +qhp.QtBluetooth.subprojects.classes.selectors = class fake:headerfile +qhp.QtBluetooth.subprojects.classes.sortPages = true +qhp.QtBluetooth.subprojects.overviews.title = Overviews +qhp.QtBluetooth.subprojects.overviews.indexTitle = Qt Bluetooth Overview +qhp.QtBluetooth.subprojects.overviews.selectors = fake:page,group,module +qhp.QtBluetooth.subprojects.examples.title = Qt Bluetooth Examples +qhp.QtBluetooth.subprojects.examples.indexTitle = Qt Bluetooth Examples +qhp.QtBluetooth.subprojects.examples.selectors = fake:example + +tagfile = ../../../doc/qtbluetooth/qtbluetooth.tags + +depends += qtcore qtgui qtwidgets qtdoc qtquick qtcmake qmake + +headerdirs += .. + +sourcedirs += .. + +exampledirs += ../../../examples/bluetooth \ + snippets/ \ + ../ + +manifestmeta.thumbnail.names = "QtBluetooth/Bluetooth Low Energy Heart Rate Server" + +manifestmeta.highlighted.names = \ + "QtBluetooth/Bluetooth Low Energy Heart Rate Game" \ + "QtBluetooth/Bluetooth Low Energy Scanner" + +imagedirs += images + +navigation.landingpage = "Qt Bluetooth" +navigation.cppclassespage = "Qt Bluetooth C++ Classes" + +# Enforce zero documentation warnings +warninglimit = 0 diff --git a/src/bluetooth/doc/snippets/CMakeLists.txt b/src/bluetooth/doc/snippets/CMakeLists.txt new file mode 100644 index 0000000..50fd10c --- /dev/null +++ b/src/bluetooth/doc/snippets/CMakeLists.txt @@ -0,0 +1,7 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +# ![0] +find_package(Qt6 REQUIRED COMPONENTS Bluetooth) +target_link_libraries(mytarget PRIVATE Qt6::Bluetooth) +# ![0] diff --git a/src/bluetooth/doc/snippets/doc_src_qtbluetooth.cpp b/src/bluetooth/doc/snippets/doc_src_qtbluetooth.cpp new file mode 100644 index 0000000..fa57b0c --- /dev/null +++ b/src/bluetooth/doc/snippets/doc_src_qtbluetooth.cpp @@ -0,0 +1,191 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +//! [include] +#include +//! [include] +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +//! [namespace] +QT_USE_NAMESPACE +//! [namespace] + +class MyClass : public QObject +{ + Q_OBJECT +public: + MyClass() : QObject() {} + void localDevice(); + void startDeviceDiscovery(); + void startServiceDiscovery(); + void objectPush(); + void btleSharedData(); + void enableCharNotifications(); + +public slots: + void deviceDiscovered(const QBluetoothDeviceInfo &device); + void serviceDiscovered(const QBluetoothServiceInfo &service); + void characteristicChanged(const QLowEnergyCharacteristic& ,const QByteArray&); +}; + +void MyClass::localDevice() { +//! [turningon] +QBluetoothLocalDevice localDevice; +QString localDeviceName; + +// Check if Bluetooth is available on this device +if (localDevice.isValid()) { + + // Turn Bluetooth on + localDevice.powerOn(); + + // Read local device name + localDeviceName = localDevice.name(); + + // Make it visible to others + localDevice.setHostMode(QBluetoothLocalDevice::HostDiscoverable); + + // Get connected devices + QList remotes; + remotes = localDevice.connectedDevices(); +} +//! [turningon] + + +} + +//! [device_discovery] +void MyClass::startDeviceDiscovery() +{ + + // Create a discovery agent and connect to its signals + QBluetoothDeviceDiscoveryAgent *discoveryAgent = new QBluetoothDeviceDiscoveryAgent(this); + connect(discoveryAgent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)), + this, SLOT(deviceDiscovered(QBluetoothDeviceInfo))); + + // Start a discovery + discoveryAgent->start(); + + //... +} + +// In your local slot, read information about the found devices +void MyClass::deviceDiscovered(const QBluetoothDeviceInfo &device) +{ + qDebug() << "Found new device:" << device.name() << '(' << device.address().toString() << ')'; +} +//! [device_discovery] + +//! [service_discovery] +void MyClass::startServiceDiscovery() +{ + + // Create a discovery agent and connect to its signals + QBluetoothServiceDiscoveryAgent *discoveryAgent = new QBluetoothServiceDiscoveryAgent(this); + connect(discoveryAgent, SIGNAL(serviceDiscovered(QBluetoothServiceInfo)), + this, SLOT(serviceDiscovered(QBluetoothServiceInfo))); + + // Start a discovery + discoveryAgent->start(); + + //... +} + +// In your local slot, read information about the found devices +void MyClass::serviceDiscovered(const QBluetoothServiceInfo &service) +{ + qDebug() << "Found new service:" << service.serviceName() + << '(' << service.device().address().toString() << ')'; +} +//! [service_discovery] + +void MyClass::characteristicChanged(const QLowEnergyCharacteristic &, const QByteArray &) +{ +} + +void MyClass::btleSharedData() +{ + QBluetoothDeviceInfo remoteDevice; + +//! [data_share_qlowenergyservice] + QLowEnergyService *first, *second; + QLowEnergyController control(remoteDevice); + control.connectToDevice(); + + // waiting for connection + + first = control.createServiceObject(QBluetoothUuid::ServiceClassUuid::BatteryService); + second = control.createServiceObject(QBluetoothUuid::ServiceClassUuid::BatteryService); + Q_ASSERT(first->state() == QLowEnergyService::RemoteService); + Q_ASSERT(first->state() == second->state()); + + first->discoverDetails(); + + Q_ASSERT(first->state() == QLowEnergyService::RemoteServiceDiscovering); + Q_ASSERT(first->state() == second->state()); +//! [data_share_qlowenergyservice] +} + +void MyClass::enableCharNotifications() +{ + QBluetoothDeviceInfo remoteDevice; + QLowEnergyService *service; + QLowEnergyController *control = QLowEnergyController::createCentral(remoteDevice, this); + control->connectToDevice(); + + + service = control->createServiceObject(QBluetoothUuid::ServiceClassUuid::BatteryService, this); + if (!service) + return; + + service->discoverDetails(); + + //... wait until discovered + +//! [enable_btle_notifications] + //PreCondition: service details already discovered + QLowEnergyCharacteristic batteryLevel = service->characteristic( + QBluetoothUuid::CharacteristicType::BatteryLevel); + if (!batteryLevel.isValid()) + return; + + QLowEnergyDescriptor notification = batteryLevel.descriptor( + QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration); + if (!notification.isValid()) + return; + + // establish hook into notifications + connect(service, SIGNAL(characteristicChanged(QLowEnergyCharacteristic,QByteArray)), + this, SLOT(characteristicChanged(QLowEnergyCharacteristic,QByteArray))); + + // enable notification + service->writeDescriptor(notification, QByteArray::fromHex("0100")); + + // disable notification + //service->writeDescriptor(notification, QByteArray::fromHex("0000")); + + // wait until descriptorWritten() signal is emitted + // to confirm successful write +//! [enable_btle_notifications] +} + + + +int main(int argc, char** argv) +{ + QCoreApplication app(argc, argv); + MyClass cl; + + return app.exec(); +} + +#include "doc_src_qtbluetooth.moc" diff --git a/src/bluetooth/doc/snippets/snippets.pro b/src/bluetooth/doc/snippets/snippets.pro new file mode 100644 index 0000000..7ad0c44 --- /dev/null +++ b/src/bluetooth/doc/snippets/snippets.pro @@ -0,0 +1,3 @@ +#! [contacts project modification] +QT += bluetooth +#! [contacts project modification] diff --git a/src/bluetooth/doc/src/bluetooth-cpp.qdoc b/src/bluetooth/doc/src/bluetooth-cpp.qdoc new file mode 100644 index 0000000..958609b --- /dev/null +++ b/src/bluetooth/doc/src/bluetooth-cpp.qdoc @@ -0,0 +1,22 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only +/*! + +\module QtBluetooth + +\title Qt Bluetooth C++ Classes +\brief Enables basic Bluetooth operations like scanning for devices and connecting them. +\ingroup modules +\qtvariable bluetooth +\since 5.2 + + + The \l{Qt Bluetooth} C++ API enables an application to scan for devices and + connect and interact with them in a more flexible way. + + To use the C++ library in your application, add the following configuration + option to your \c .pro file: + + \snippet snippets.pro contacts project modification +*/ + diff --git a/src/bluetooth/doc/src/bluetooth-index.qdoc b/src/bluetooth/doc/src/bluetooth-index.qdoc new file mode 100644 index 0000000..ff6bf03 --- /dev/null +++ b/src/bluetooth/doc/src/bluetooth-index.qdoc @@ -0,0 +1,204 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! +\page qtbluetooth-index.html +\title Qt Bluetooth +\brief Qt Bluetooth enables connectivity between Bluetooth enabled devices. +\ingroup technology-apis + +The Bluetooth API provides connectivity between Bluetooth enabled devices. + +Currently, the API is supported on the following platforms: + +\table +\header + \li API Feature + \li \l {Qt for Android}{Android} + \li \l {Qt for iOS}{iOS} + \li \l {Qt for Linux/X11}{Linux (BlueZ 5.x)} + \li \l \macos + \li \l {Qt for Windows}{Windows} +\row + \li Classic Bluetooth + \li x + \li + \li x + \li x + \li x +\row + \li Bluetooth LE Central + \li x + \li x + \li x + \li x + \li x +\row + \li Bluetooth LE Peripheral + \li x + \li x + \li x + \li x + \li +\endtable + +\section1 Overview + +Bluetooth is a short-range (less than 100 meters) wireless technology. It +has a data transfer rate of 2.1 Mbps, which makes it ideal +for transferring data between devices. Bluetooth connectivity is based on +basic device management, such as scanning for devices, gathering information +about them, and exchanging data between them. + +Qt Bluetooth supports Bluetooth Low Energy development for client/central role +use cases. Further details can be found in the +\l {Bluetooth Low Energy Overview}{Bluetooth Low Energy Overview} section. + +\section1 Using the Module + +\include {module-use.qdocinc} {using the c++ api} + +\section2 Building with CMake + +\include {module-use.qdocinc} {building with cmake} {Bluetooth} + +\section2 Building with qmake + +\include {module-use.qdocinc} {building_with_qmake} {bluetooth} + +\section1 Permissions + +Starting from Qt 6.6, the Qt Bluetooth module uses new \l QPermission API +to handle \l {QBluetoothPermission}{Bluetooth} permissions. This means that Qt +itself no longer queries for these permissions, so this needs to be done +directly from the client application. + +Please refer to the \l {Application Permissions} page for an example of how +to integrate the new \l QPermission API into the application. + +\section1 Related Information + +\section2 Building Qt Bluetooth + +Even though the module can be built for all Qt platforms, the module is not +ported to all of them. Non-supported platforms employ a dummy backend that is +automatically selected when the platform is not supported. The dummy backend +reports appropriate error messages and values, which enables you to detect at +runtime that the current platform is not supported. The dummy backend is also +selected on Linux if BlueZ development headers are not found during build time +or Qt was built without Qt D-Bus support. + +The usage of the dummy backend is highlighted via an appropriate warning while building and running. + +\section3 Linux Specific + +Since Qt 6.5 the Linux peripheral support has two backend alternatives: +BlueZ DBus and Bluetooth Kernel API. The DBus backend is the default +backend since Qt 6.7. + +BlueZ DBus is the newer BlueZ stack and possibly the eventual successor of the +older Kernel API. It is a bit more limited in terms of features, but in a +typical usage this should not matter. One notable benefit of using the DBus +backend is that the user process no longer needs to have the +\e CAP_NET_ADMIN capability (for example by running as \c root user). + +The DBus backend requires BlueZ version 5.56 or higher, and that it provides +the needed DBus APIs. If these requirements are not met, Qt automatically +falls back to the Bluetooth Kernel API backend. + +The older kernel backend can also be selected manually by setting the +\e QT_BLUETOOTH_USE_KERNEL_PERIPHERAL environment variable. + +\section3 \macos Specific +The Bluetooth API on \macos requires a certain type of event dispatcher +that in Qt causes a dependency to \l QGuiApplication. However, you can set the +environment variable \c {QT_EVENT_DISPATCHER_CORE_FOUNDATION=1} to circumvent +this issue. + +Applications that don't use Classic Bluetooth will find a subset of QtBluetooth +is available, as CoreBluetooth (Bluetooth LE) don't require \l QApplication or +\l QGuiApplication. + +\section2 Articles and Guides +\list + \li \l {Qt Bluetooth Overview}{Classic Bluetooth Overview} + \li \l {Bluetooth Low Energy Overview} +\endlist + +\section2 Reference +\list + \li \l {Qt Bluetooth C++ Classes}{C++ Classes} +\endlist + +\section2 Logging Categories + +The \l QtBluetooth module exports the following +\l {Configuring Categories}{logging categories}: + +\table +\header + \li Logging Category + \li Description +\row + \li qt.bluetooth + \li Enables logging of cross platform code path in QtBluetooth +\row + \li qt.bluetooth.android + \li Enables logging of the \l {Qt for Android} {Android} implementation +\row + \li qt.bluetooth.bluez + \li Enables logging of the BLuez/Linux implementation +\row + \li qt.bluetooth.ios + \li Enables logging of the \l {Qt for iOS} {iOS} implementation +\row + \li qt.bluetooth.osx + \li Enables logging of the \l {Qt for macOS} {macOS} implementation +\row + \li qt.bluetooth.windows + \li Enables logging of the \l {Qt for Windows} {Windows} implementation +\endtable + +Logging categories enable additional warning and debug output for QtBluetooth. +More detailed information about logging is found in \l QLoggingCategory. A +quick way to enable all QtBluetooth logging is to add the following line to the +\c main() function: + +\code + QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true")); +\endcode + +\section2 Examples +\list + \li QML + \list + \li \l {heartrate-game}{Bluetooth Low Energy Heart Rate Game} + \li \l {heartrate-server}{Bluetooth Low Energy Heart Rate Server} + \li \l {lowenergyscanner}{Bluetooth Low Energy Scanner} + \endlist + \li C++ + \list + \li \l {btchat}{Bluetooth Chat} + \endlist +\endlist + +\section1 Module Evolution + +\l{Changes to Qt Bluetooth} lists important changes in the module +API and functionality that were done for the Qt 6 series of Qt. + +\section1 Licenses and Attributions + +Qt Bluetooth is available under commercial licenses from \l{The Qt Company}. +In addition, it is available under the +\l{GNU Lesser General Public License, version 3}, or +the \l{GNU General Public License, version 2}. +See \l{Qt Licensing} for further details. + +On Linux, Qt Bluetooth uses a separate executable, \c sdpscanner, +to integrate with the official Linux bluetooth protocol stack +BlueZ. BlueZ is available under the \l{GNU General Public License, +version 2}. + +\generatelist{groupsbymodule attributions-qtbluetooth} +*/ diff --git a/src/bluetooth/doc/src/bluetooth-le-overview.qdoc b/src/bluetooth/doc/src/bluetooth-le-overview.qdoc new file mode 100644 index 0000000..cc94308 --- /dev/null +++ b/src/bluetooth/doc/src/bluetooth-le-overview.qdoc @@ -0,0 +1,273 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! +\ingroup technology-apis +\title Bluetooth Low Energy Overview +\page qtbluetooth-le-overview.html +\brief The Qt Bluetooth Low Energy API enables communication between Bluetooth +Low Energy devices. + +\tableofcontents + + The Qt Bluetooth Low Energy API supports the peripheral/server and central/client roles. + It is supported on all major Qt platforms. The only exception is the missing peripheral role + support on Windows. + + \section1 What Is Bluetooth Low Energy + + Bluetooth Low Energy, also known as Bluetooth Smart, is a wireless computer + network technology, which was officially introduced in 2011. It works on the same + 2.4 GHz frequency as ”classic” Bluetooth. The main difference is, as stated by its technology name, + low energy consumption. It provides an opportunity for Bluetooth Low Energy devices to + operate for months, even years, on coin-cell batteries. The technology was introduced by + \l {https://www.bluetooth.org/en-us/specification/adopted-specifications}{Bluetooth v4.0}. + Devices which support this technology are called Bluetooth Smart Ready Devices. + The key features of the technology are: + + \list + \li Ultra-low peak, average and idle mode power consumption + \li Ability to run for years on standard, coin-cell batteries + \li Low cost + \li Multi-vendor interoperability + \li Enhanced range + \endlist + + Bluetooth Low Energy uses a client-server architecture. The server (also + known as peripheral) offers services such as temperature or heart rate + and advertises them. The client (known as central + device) connects to the server and reads the values advertised by the server. + An example might be an apartment with Bluetooth Smart Ready sensors such + as a thermostat, humidity or pressure sensor. Those sensors are peripheral + devices advertising the environment values of the apartment. At the same time + a mobile phone or computer might connect to those sensors, retrieve their + values and present them as part of a larger environment control application + to the user. + + \section1 Basic Service Structure + + Bluetooth Low Energy is based on two protocols: ATT (Attribute Protocol) + and GATT (Generic Attribute Profile). They specify the communication layers + used by every Bluetooth Smart Ready device. + + \section2 ATT Protocol + + The basic building block of ATT is an \e attribute. Each attribute consists of + three elements: + + \list + \li a value - the payload or desirable piece of information + \li a UUID - the type of attribute (used by GATT) + \li a 16-bit handle - a unique identifier for the attribute + \endlist + + The server stores the attributes and the client uses the ATT protocol to + read and write values on the server. + + \section2 GATT Profile + + GATT defines grouping for a set of attributes by applying a meaning to predefined + UUIDs. The table below shows an example service exposing a heart rate + on a particular day. The actual values are stored inside the two characteristics: + + \table + \header + \li Handle + \li UUID + \li Value + \li Description + \row + \li 0x0001 + \li 0x2800 + \li UUID 0x180D + \li Begin Heart Rate service + \row + \li 0x0002 + \li 0x2803 + \li UUID 0x2A37, Value handle: 0x0003 + \li Characteristic of type \e {Heart Rate Measurement (HRM)} + \row + \li 0x0003 + \li 0x2A37 + \li 65 bpm + \li Heart rate value + \row + \li 0x0004 + \li 0x2803 + \li UUID 0x2A08, Value handle: 0x0005 + \li Characteristic of type Date Time + \row + \li 0x0005 + \li 0x2A08 + \li 18/08/2014 11:00 + \li Date and Time of the measurement + \row + \li 0x0006 + \li 0x2800 + \li UUID xxxxxx + \li Begin next service + \row + \li ... + \li ... + \li ... + \li ... + \endtable + + GATT specifies that the above used UUID \c 0x2800 marks the begin of a service definition. + Every attribute following \c 0x2800 is part of the service until the next \c 0x2800 or the + end is encountered. In similar ways the well known UUID \c 0x2803 states that a characteristic + is to be found and each of the characteristics has a type defining the nature of the value. + The example above uses the UUIDs \c 0x2A08 (Date Time) and \c 0x2A37 (Heart Rate Measurement). + Each of the above UUIDs is defined by the \l {https://bluetooth.org}{Bluetooth Special Interest Group}. + and can be found in the + \l{https://www.bluetooth.com/specifications/assigned-numbers}{GATT specifications}. While it + is advisable to use pre-defined UUIDs where available it is entirely possible to use new and not + yet used UUIDs for characteristic and service types. + + In general, each service may consist of one or more characteristics. A characteristic + contains data and can be further described by descriptors, which provide additional + information or means of manipulating the characteristic. All services, characteristics and + descriptors are recognized by their 128-bit UUID. Finally, it is possible to include + services inside of services (see picture below). + + \image peripheral-structure.png + + \section1 Using Qt Bluetooth Low Energy API + + This section describes how to use the Bluetooth Low Energy API provided by Qt. + On the client side, the API permits creating connections to peripheral devices, discovering + their services, as well as reading and writing data stored on the device. + On the server side, it allows to set up services, advertise them, and get notified when the + client writes characteristics. + The example code below is taken from the \l {heartrate-game}{Heart Rate Game} and + \l {heartrate-server}{Heart Rate Server} examples. + + \section2 Establishing a Connection + + To be able to read and write the characteristics of the Bluetooth Low Energy peripheral device, + it is necessary to find and connect the device. This requires the peripheral device to advertise + its presence and services. We start the device discovery with the help of the + \l QBluetoothDeviceDiscoveryAgent class. We connect to its \l {QBluetoothDeviceDiscoveryAgent::deviceDiscovered()} + signal and start the search with \l {QBluetoothDeviceDiscoveryAgent::start()}{start()}: + + \snippet heartrate-game/devicefinder.cpp devicediscovery-1 + \snippet heartrate-game/devicefinder.cpp devicediscovery-2 + + Since we are only interested in Low Energy devices we filter the device type within the + receiving slot. The device type can be ascertained using the \l QBluetoothDeviceInfo::coreConfigurations() + flag. The \l {QBluetoothDeviceDiscoveryAgent::}{deviceDiscovered()} signal + may be emitted multiple times for the same device as more details are + discovered. Here we match these device discoveries so that the user only + sees the individual devices: + + \snippet heartrate-game/devicefinder.cpp devicediscovery-3 + \snippet heartrate-game/devicefinder.cpp devicediscovery-4 + + Once the address of the peripheral device is known we use the \l QLowEnergyController class. + This class is the entry point for all Bluetooth Low Energy development. The constructor of the class + accepts the remote device's \l QBluetoothAddress. Finally we set up the customary slots and + directly connect to the device using + \l {QLowEnergyController::connectToDevice()}{connectToDevice()}: + + \snippet heartrate-game/devicehandler.cpp Connect-Signals-1 + \snippet heartrate-game/devicehandler.cpp Connect-Signals-2 + + \section2 Service Search + + The above code snippet shows how the application initiates the service discovery once the + connection has been established. + + The \c serviceDiscovered() slot below is triggered as a result of the + \l {QLowEnergyController::serviceDiscovered()} signal and provides an intermittent progress report. + Since we are talking about the heart listener app which monitors HeartRate devices in the vicinity + we ignore any service that is not of type \l QBluetoothUuid::ServiceClassUuid::HeartRate. + + \snippet heartrate-game/devicehandler.cpp Filter HeartRate service 1 + + Eventually the \l {QLowEnergyController::discoveryFinished()} signal is emitted to indicate + the successful completion of the service discovery. Provided a HeartRate service was found, + a \l QLowEnergyService instance is created to represent the service. The returned service object + provides the required signals for update notifications and the discovery of service details + is triggered using \l QLowEnergyService::discoverDetails(): + + \snippet heartrate-game/devicehandler.cpp Filter HeartRate service 2 + + During the detail search the service's \l {QLowEnergyService::state()}{state()} transitions + from \l {QLowEnergyService::RemoteService}{RemoteService} to + \l {QLowEnergyService::RemoteServiceDiscovering}{RemoteServiceDiscovering} and eventually ends with + \l {QLowEnergyService::RemoteServiceDiscovered}{RemoteServiceDiscovered}: + + \snippet heartrate-game/devicehandler.cpp Find HRM characteristic + + \section2 Interaction with the Peripheral Device + + In the code example above, the desired characteristic is of type + \l {QBluetoothUuid::CharacteristicType::HeartRateMeasurement}{HeartRateMeasurement}. Since the application measures + the heart rate changes, it must enable change notifications for the characteristic. + Note that not all characteristics provide change notifications. Since the HeartRate characteristic + has been standardized it is possible to assume that notifications can be received. Ultimately + \l QLowEnergyCharacteristic::properties() must have the \l {QLowEnergyCharacteristic::Notify} flag + set and a descriptor of type \l {QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration} must exist to confirm + the availability of an appropriate notification. + + Finally, we process the value of the HeartRate characteristic, as per Bluetooth Low Energy standard: + + \snippet heartrate-game/devicehandler.cpp Reading value + + In general a characteristic value is a series of bytes. The precise interpretation of + those bytes depends on the characteristic type and value structure. + A significant number has been standardized by the + \l {https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx}{Bluetooth SIG} whereas others + may follow a custom protocol. The above code snippet demonstrates how to the read the standardized + HeartRate value. + + \section2 Advertising Services + + If we are implementing a GATT server application on a peripheral device, we need to define the + services we want to offer to central devices and advertise them: + + \snippet heartrate-server/main.cpp Advertising Data + \snippet heartrate-server/main.cpp Start Advertising + + Now potential clients can connect to our device, discover the provided service and + register themselves to get notified of changes to the characteristic value. + This part of the API was already covered by the above sections. + + \section2 Implementing a Service on the Peripheral Device + + The first step is to define the service, its characteristics and descriptors. This is achieved + using the \l QLowEnergyServiceData, \l QLowEnergyCharacteristicData and + \l QLowEnergyDescriptorData classes. These classes act as containers or building blocks for the + essential information that comprises the to-be-defined Bluetooth Low Energy service. + The code snippet below defines a simple HeartRate service which publishes + the measured beats per minute. An example where such a service could be used is a wrist watch. + + \snippet heartrate-server/main.cpp Service Data + + The resulting \c serviceData object can be published as described in the + \l {Advertising Services} section above. Despite the partial information overlap between the + information wrapped by \l QLowEnergyServiceData and \l QLowEnergyAdvertisingData the two classes + serve two very different tasks. The advertising data is published to nearby devices and often + limited in scope due to its size restriction of 29 bytes. Therefore they are not always 100% + complete. By comparison the service data contained inside of \l QLowEnergyServiceData provides + the complete set of service data and only becomes visible to the connecting client when a + connection with an active service discovery has been performed. + + The next section demonstrates how the service can update the heart rate value. Depending on the + nature of the service it may have to comply with the official service definition + as defined on \l {https://www.bluetooth.org}. Other services may be completely custom. The + heart rate service was adopted and its specification can be found under + \l {https://www.bluetooth.com/specifications/adopted-specifications}. + + \snippet heartrate-server/main.cpp Provide Heartbeat + + In general characteristic and descriptor value updates on the peripheral device use the same + methods as connecting Bluetooth Low Energy devices. + + \note To use \l{Qt Bluetooth} (in both central and peripheral roles) on iOS, you have to provide + an Info.plist file containing the usage description. According to the CoreBluetooth's + documentation: \e {Your app will crash if its Info.plist doesn’t include usage description + keys for the types of data it needs to access. To access Core Bluetooth APIs on apps linked + on or after iOS 13, include the NSBluetoothAlwaysUsageDescription key. In iOS 12 and earlier, + include NSBluetoothPeripheralUsageDescription to access Bluetooth peripheral data.} +*/ diff --git a/src/bluetooth/doc/src/bluetooth-overview.qdoc b/src/bluetooth/doc/src/bluetooth-overview.qdoc new file mode 100644 index 0000000..54a429d --- /dev/null +++ b/src/bluetooth/doc/src/bluetooth-overview.qdoc @@ -0,0 +1,90 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! +\ingroup technology-apis +\title Qt Bluetooth Overview +\page qtbluetooth-overview.html +\brief The Qt Bluetooth API enables connectivity with other regular Bluetooth + and Bluetooth Low Energy enabled devices. + +\tableofcontents + + With the Qt Bluetooth API typical use cases are: + + \list + \li Retrieve information about the local Bluetooth device. + \li Scan for other Bluetooth devices in range and retrieve information about them. + \li Push files to remote devices using the OBEX Object Push Profile (OPP) + \li Connect to remote devices through a RFCOMM channel using the Serial Port Profile (SPP). + \li Create a RFCOMM server that allows incoming connections using SPP. + \li Retrieve specification about Bluetooth Low Energy device. + \li Connect to Bluetooth Low Energy device. + \li Receive advertisement from Bluetooth Low Energy device. + \endlist + + Note that the Object Push Profile is not supported on Android and Windows. + + \note Parts of RFCOMM functionality cannot be configured by Qt on + Windows. A service's \l {QBluetoothServiceInfo::}{ServiceClassIds} and + \l {QBluetoothServiceInfo::}{ProtocolDescriptorList} are filled + automatically. Therefore, registering a service with custom values for + these fields might not yield the expected result on Windows. + + \note The Received Signal Strength Indicator (RSSI), as well as + the Manufacturer Specific Data advertised by Bluetooth LE devices are + not supported by the Win32 backend. Also, it is only possible to find + devices that have been previously paired through Windows Settings. + + The following sections describe how to use the Qt Bluetooth C++ API classes + for the above use cases. + + \section1 Retrieving Local Device Information + + The Qt Bluetooth API has three main purposes. The first one is to + obtain local and remote device information. The first steps in retrieving device information are + to check if Bluetooth is available on the device and read the local device address and name. + QBluetoothLocalDevice is the class that provides all of this information. Additionally you can use it + to turn Bluetooth on/off, set the visibility of the device and determine the current connections. + + \snippet doc_src_qtbluetooth.cpp turningon + + \section1 Scanning for Bluetooth Devices + + Similar to the QBluetoothLocalDevice, the API offers QBluetoothDeviceInfo which provides + similar information for remote devices. Although you can just create QBluetoothDeviceInfo objects on + your own and fill them with data, the easier way is to use the QBluetoothDeviceDiscoveryAgent to + start an automated search for visible Bluetooth devices within the connectable range. + + \snippet doc_src_qtbluetooth.cpp device_discovery + + \section1 Exchanging Data Between Devices + + The more flexible approach for communication between two Bluetooth enabled devices, is to + create a virtual serial port connection and freely exchange data over that connection. This can + be done by the Serial Port Profile (SPP). The Serial Port Profile emulates a serial connection + over the Bluetooth transport protocol RFCOMM. + + To be able to receive incoming SPP connections, you need to listen to incoming connections using + \l QBluetoothServer. + + \snippet btchat/chatserver.cpp Create the server + + Connect to this server from another device playing the client role by using a + QBluetoothSocket: + + \snippet btchat/chatclient.cpp startClient + + Using such a connection allows to exchange any form of data in both directions. + It is perfectly suited for gaming or for syncing the state between two instances of + an application on two devices. For more detailed descriptions on how to configure the server + and client, please refer to the detailed description sections in the \l QBluetoothServer and + \l QBluetoothSocket classes. A good example to start with SPP is the \l{btchat}{Bluetooth Chat} + example. + + \section1 Bluetooth Low Energy + + Bluetooth Low Energy, also known as Bluetooth Smart, is a new technology enabling + devices with low energy consumption to communicate with each other. More details about + this technology and the related Qt APIs can be found in the \l {Bluetooth Low Energy Overview}. +*/ diff --git a/src/bluetooth/doc/src/examples.qdoc b/src/bluetooth/doc/src/examples.qdoc new file mode 100644 index 0000000..46425cf --- /dev/null +++ b/src/bluetooth/doc/src/examples.qdoc @@ -0,0 +1,42 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \page bluetooth-examples.html + \title Qt Bluetooth Examples + \brief Examples for the Qt Bluetooth module. + + This is a variety of examples that cover the entire range of the Qt + Bluetooth API. You will find them in their own documentation but they are also + accessible from here. + + \section2 C++ Tutorial + The \l{btchat}{Bluetooth Chat} example contains a tutorial on how to use the + C++ API to create a RFCOMM server and client, and exchange data between them. + + \section2 C++ Examples + \table 80% + \header + \li Example + \li Description + \row + \li \l{btchat}{Bluetooth Chat} + \li Simple chat server and client via Bluetooth. + \endtable + + \section2 QML Examples + \table 80% + \header + \li Example + \li Description + \row + \li \l{heartrate-game}{QML Bluetooth Low Energy Heart Rate Game} + \li Connect to Bluetooth Low Energy heart rate belts and receive + measurements such as the current pulse. + \row + \li \l{lowenergyscanner}{QML Bluetooth Low Energy Scanner} + \li Scan for Bluetooth Low Energy devices and show their services and characteristics. + \endtable + +*/ + diff --git a/src/bluetooth/dummy/dummy_helper.cpp b/src/bluetooth/dummy/dummy_helper.cpp new file mode 100644 index 0000000..a925703 --- /dev/null +++ b/src/bluetooth/dummy/dummy_helper.cpp @@ -0,0 +1,23 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include +#include + +#include "dummy_helper_p.h" + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT) + +Q_GLOBAL_STATIC_WITH_ARGS(bool, dummyWarningPrinted, (false)) + +void printDummyWarning() +{ + if (!*dummyWarningPrinted()) { + qCWarning(QT_BT) << "Dummy backend running. Qt Bluetooth module is non-functional."; + *dummyWarningPrinted() = true; + } +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/dummy/dummy_helper_p.h b/src/bluetooth/dummy/dummy_helper_p.h new file mode 100644 index 0000000..c51fa91 --- /dev/null +++ b/src/bluetooth/dummy/dummy_helper_p.h @@ -0,0 +1,26 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef DUMMY_HELPER_H +#define DUMMY_HELPER_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 "QtCore/private/qglobal_p.h" + +QT_BEGIN_NAMESPACE + +void printDummyWarning(); + +QT_END_NAMESPACE + +#endif // DUMMY_HELPER_H diff --git a/src/bluetooth/lecmaccalculator.cpp b/src/bluetooth/lecmaccalculator.cpp new file mode 100644 index 0000000..92b9c35 --- /dev/null +++ b/src/bluetooth/lecmaccalculator.cpp @@ -0,0 +1,150 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +#include "lecmaccalculator_p.h" + +#include "bluez/bluez_data_p.h" + +#include +#include +#include + +#include +#include +#include +#include + +#ifdef CONFIG_LINUX_CRYPTO_API +#include +#endif + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ) + +LeCmacCalculator::LeCmacCalculator() +{ +#ifdef CONFIG_LINUX_CRYPTO_API + m_baseSocket = socket(AF_ALG, SOCK_SEQPACKET, 0); + if (m_baseSocket == -1) { + qCWarning(QT_BT_BLUEZ) << "failed to create first level crypto socket:" + << strerror(errno); + return; + } + sockaddr_alg sa; + using namespace std; + memset(&sa, 0, sizeof sa); + sa.salg_family = AF_ALG; + strcpy(reinterpret_cast(sa.salg_type), "hash"); + strcpy(reinterpret_cast(sa.salg_name), "cmac(aes)"); + if (::bind(m_baseSocket, reinterpret_cast(&sa), sizeof sa) == -1) { + qCWarning(QT_BT_BLUEZ) << "bind() failed for crypto socket:" << strerror(errno); + return; + } +#else // CONFIG_LINUX_CRYPTO_API + qCWarning(QT_BT_BLUEZ) << "Linux crypto API not present, CMAC verification will fail."; +#endif +} + +LeCmacCalculator::~LeCmacCalculator() +{ + if (m_baseSocket != -1) + close(m_baseSocket); +} + +QByteArray LeCmacCalculator::createFullMessage(const QByteArray &message, quint32 signCounter) +{ + // Spec v4.2, Vol 3, Part H, 2.4.5 + QByteArray fullMessage = message; + fullMessage.resize(fullMessage.size() + sizeof signCounter); + putBtData(signCounter, fullMessage.data() + message.size()); + return fullMessage; +} + +quint64 LeCmacCalculator::calculateMac(const QByteArray &message, QUuid::Id128Bytes csrk) const +{ +#ifdef CONFIG_LINUX_CRYPTO_API + if (m_baseSocket == -1) + return false; + QUuid::Id128Bytes csrkMsb; + std::reverse_copy(std::begin(csrk.data), std::end(csrk.data), std::begin(csrkMsb.data)); + qCDebug(QT_BT_BLUEZ) << "CSRK (MSB):" << QByteArray(reinterpret_cast(csrkMsb.data), + sizeof csrkMsb).toHex(); + if (setsockopt(m_baseSocket, 279 /* SOL_ALG */, ALG_SET_KEY, csrkMsb.data, sizeof csrkMsb) == -1) { + qCWarning(QT_BT_BLUEZ) << "setsockopt() failed for crypto socket:" << strerror(errno); + return 0; + } + + class SocketWrapper + { + public: + SocketWrapper(int socket) : m_socket(socket) {} + ~SocketWrapper() { + if (m_socket != -1) + close(m_socket); + } + + int value() const { return m_socket; } + private: + int m_socket; + }; + SocketWrapper cryptoSocket(accept(m_baseSocket, nullptr, nullptr)); + if (cryptoSocket.value() == -1) { + qCWarning(QT_BT_BLUEZ) << "accept() failed for crypto socket:" << strerror(errno); + return 0; + } + + QByteArray messageSwapped(message.size(), Qt::Uninitialized); + std::reverse_copy(message.begin(), message.end(), messageSwapped.begin()); + qint64 totalBytesWritten = 0; + do { + const qint64 bytesWritten = qt_safe_write(cryptoSocket.value(), + messageSwapped.constData() + totalBytesWritten, + messageSwapped.size() - totalBytesWritten); + if (bytesWritten == -1) { + qCWarning(QT_BT_BLUEZ) << "writing to crypto socket failed:" << strerror(errno); + return 0; + } + totalBytesWritten += bytesWritten; + } while (totalBytesWritten < messageSwapped.size()); + quint64 mac; + quint8 * const macPtr = reinterpret_cast(&mac); + qint64 totalBytesRead = 0; + do { + const qint64 bytesRead = qt_safe_read(cryptoSocket.value(), macPtr + totalBytesRead, + sizeof mac - totalBytesRead); + if (bytesRead == -1) { + qCWarning(QT_BT_BLUEZ) << "reading from crypto socket failed:" << strerror(errno); + return 0; + } + totalBytesRead += bytesRead; + } while (totalBytesRead < qint64(sizeof mac)); + return qFromBigEndian(mac); +#else // CONFIG_LINUX_CRYPTO_API + Q_UNUSED(message); + Q_UNUSED(csrk); + qCWarning(QT_BT_BLUEZ) << "CMAC calculation failed due to missing Linux crypto API."; + return 0; +#endif +} + +bool LeCmacCalculator::verify(const QByteArray &message, QUuid::Id128Bytes csrk, + quint64 expectedMac) const +{ +#ifdef CONFIG_LINUX_CRYPTO_API + const quint64 actualMac = calculateMac(message, csrk); + if (actualMac != expectedMac) { + qCWarning(QT_BT_BLUEZ) << Qt::hex << "signature verification failed: calculated mac:" + << actualMac << "expected mac:" << expectedMac; + return false; + } + return true; +#else // CONFIG_LINUX_CRYPTO_API + Q_UNUSED(message); + Q_UNUSED(csrk); + Q_UNUSED(expectedMac); + qCWarning(QT_BT_BLUEZ) << "CMAC verification failed due to missing Linux crypto API."; + return false; +#endif +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/lecmaccalculator_p.h b/src/bluetooth/lecmaccalculator_p.h new file mode 100644 index 0000000..b79c544 --- /dev/null +++ b/src/bluetooth/lecmaccalculator_p.h @@ -0,0 +1,42 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +#ifndef LECMACCALCULATOR_H +#define LECMACCALCULATOR_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_AUTOTEST_EXPORT LeCmacCalculator +{ +public: + LeCmacCalculator(); + ~LeCmacCalculator(); + + static QByteArray createFullMessage(const QByteArray &message, quint32 signCounter); + + quint64 calculateMac(const QByteArray &message, QUuid::Id128Bytes csrk) const; + + // Convenience function. + bool verify(const QByteArray &message, QUuid::Id128Bytes csrk, quint64 expectedMac) const; + +private: + int m_baseSocket = -1; +}; + + +QT_END_NAMESPACE + +#endif // Header guard diff --git a/src/bluetooth/qbluetooth.cpp b/src/bluetooth/qbluetooth.cpp new file mode 100644 index 0000000..0a8efb4 --- /dev/null +++ b/src/bluetooth/qbluetooth.cpp @@ -0,0 +1,74 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2014 Denis Shienkov +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include +#include + +QT_BEGIN_NAMESPACE + +namespace QBluetooth { +/*! + \namespace QBluetooth + \inmodule QtBluetooth + \brief The QBluetooth namespace provides classes and functions related to + Bluetooth. + + \since 5.2 +*/ + +/*! + \enum QBluetooth::Security + + This enum describe the security requirements of a Bluetooth service. + + \value NoSecurity The service does not require any security. + + \value Authorization The service requires authorization by the user, + unless the device is Authorized-Paired. + + \value Authentication The service requires authentication. Device must + be paired, and the user is prompted on connection unless the device is + Authorized-Paired. + + \value Encryption The service requires the communication link to be + encrypted. This requires the device to be paired. + + \value Secure The service requires the communication link to be secure. + Simple Pairing from Bluetooth 2.1 or greater is required. + Legacy pairing is not permitted. +*/ + +/*! + \enum QBluetooth::AttAccessConstraint + \since 5.7 + + This enum describes the possible requirements for reading or writing an ATT attribute. + + \value AttAuthorizationRequired + The client needs authorization from the ATT server to access the attribute. + \value AttAuthenticationRequired + The client needs to be authenticated to access the attribute. + \value AttEncryptionRequired + The attribute can only be accessed if the connection is encrypted. +*/ + +} + +/*! + \typedef QLowEnergyHandle + \relates QBluetooth + \since 5.4 + + Typedef for Bluetooth Low Energy ATT attribute handles. +*/ + +Q_LOGGING_CATEGORY(QT_BT, "qt.bluetooth") +Q_LOGGING_CATEGORY(QT_BT_ANDROID, "qt.bluetooth.android") +Q_LOGGING_CATEGORY(QT_BT_BLUEZ, "qt.bluetooth.bluez") +Q_LOGGING_CATEGORY(QT_BT_WINDOWS, "qt.bluetooth.windows") +Q_LOGGING_CATEGORY(QT_BT_WINDOWS_SERVICE_THREAD, "qt.bluetooth.winrt.service.thread") + +QT_END_NAMESPACE + +#include "moc_qbluetooth.cpp" diff --git a/src/bluetooth/qbluetooth.h b/src/bluetooth/qbluetooth.h new file mode 100644 index 0000000..5484b85 --- /dev/null +++ b/src/bluetooth/qbluetooth.h @@ -0,0 +1,46 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QBLUETOOTH_H +#define QBLUETOOTH_H + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace QBluetooth { +Q_NAMESPACE_EXPORT(Q_BLUETOOTH_EXPORT) +// TODO Qt 6: Merge these two enums? But note that ATT Authorization has no equivalent +// on the socket security level. + +enum class Security { + NoSecurity = 0x00, + Authorization = 0x01, + Authentication = 0x02, + Encryption = 0x04, + Secure = 0x08 +}; +Q_ENUM_NS(Security) +Q_DECLARE_FLAGS(SecurityFlags, Security) +Q_DECLARE_OPERATORS_FOR_FLAGS(SecurityFlags) + +enum class AttAccessConstraint { + AttAuthorizationRequired = 0x1, + AttAuthenticationRequired = 0x2, + AttEncryptionRequired = 0x4, +}; +Q_ENUM_NS(AttAccessConstraint) + +Q_DECLARE_FLAGS(AttAccessConstraints, AttAccessConstraint) +Q_DECLARE_OPERATORS_FOR_FLAGS(AttAccessConstraints) + +} + +typedef quint16 QLowEnergyHandle; + +QT_END_NAMESPACE + +#endif // QBLUETOOTH_H diff --git a/src/bluetooth/qbluetoothaddress.cpp b/src/bluetooth/qbluetoothaddress.cpp new file mode 100644 index 0000000..9919b89 --- /dev/null +++ b/src/bluetooth/qbluetoothaddress.cpp @@ -0,0 +1,138 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothaddress.h" + +#ifndef QT_NO_DEBUG_STREAM +#include +#endif + +QT_BEGIN_NAMESPACE + +static_assert(QT6_ONLY(!)std::is_trivially_copyable_v, + "Must stay this way until Qt 7 because of BC reasons."); + +QT_IMPL_METATYPE_EXTERN(QBluetoothAddress) + +/*! + \class QBluetoothAddress + \inmodule QtBluetooth + \brief The QBluetoothAddress class assigns an address to the Bluetooth + device. + \since 5.2 + + This class holds a Bluetooth address in a platform- and protocol-independent manner. +*/ + +void registerQBluetoothAddress() +{ + qRegisterMetaType(); +} +Q_CONSTRUCTOR_FUNCTION(registerQBluetoothAddress) + +/*! + \fn QBluetoothAddress::QBluetoothAddress() + + Constructs a null Bluetooth Address. +*/ + +/*! + \fn QBluetoothAddress::QBluetoothAddress(quint64 address) + + Constructs a new Bluetooth address and assigns \a address to it. +*/ + +/*! + Constructs a new Bluetooth address and assigns \a address to it. + + The format of \a address can be either XX:XX:XX:XX:XX:XX or XXXXXXXXXXXX, + where X is a hexadecimal digit. Case is not important. +*/ +QBluetoothAddress::QBluetoothAddress(const QString &address) +{ + QString a = address; + + if (a.size() == 17) + a.remove(QLatin1Char(':')); + + if (a.size() == 12) { + bool ok; + m_address = a.toULongLong(&ok, 16); + if (!ok) + clear(); + } else { + m_address = 0; + } +} + +/*! + \fn QBluetoothAddress::qHash(const QBluetoothAddress &key, size_t seed) + \since 6.6 + + Returns the hash value for the \a key, using \a seed to seed the + calculation. +*/ + +/*! + \fn void QBluetoothAddress::clear() + + Sets the Bluetooth address to 00:00:00:00:00:00. +*/ + +/*! + \fn bool QBluetoothAddress::isNull() const + + Returns true if the Bluetooth address is null, otherwise returns false. +*/ + +/*! + \fn quint64 QBluetoothAddress::toUInt64() const + + Returns this Bluetooth address as a quint64. +*/ + +/*! + Returns the Bluetooth address as a string of the form, XX:XX:XX:XX:XX:XX. +*/ +QString QBluetoothAddress::toString() const +{ + QString s(QStringLiteral("%1:%2:%3:%4:%5:%6")); + + for (int i = 5; i >= 0; --i) { + const quint8 a = (m_address >> (i*8)) & 0xff; + s = s.arg(a, 2, 16, QLatin1Char('0')); + } + + return s.toUpper(); +} + +/*! + \fn bool QBluetoothAddress::operator<(const QBluetoothAddress &a, + const QBluetoothAddress &b) + \brief Returns true if the Bluetooth address \a a is less than \a b, otherwise + returns false. +*/ + +/*! + \fn bool QBluetoothAddress::operator==(const QBluetoothAddress &a, + const QBluetoothAddress &b) + \brief Returns \c true if the two Bluetooth addresses \a a and \a b are equal, + otherwise returns \c false. +*/ + +/*! + \fn bool QBluetoothAddress::operator!=(const QBluetoothAddress &a, + const QBluetoothAddress &b) + \brief Returns \c true if the two Bluetooth addresses \a a and \a b are not equal, + otherwise returns \c false. +*/ + +#ifndef QT_NO_DEBUG_STREAM +QDebug QBluetoothAddress::streamingOperator(QDebug debug, const QBluetoothAddress &address) +{ + debug << address.toString(); + return debug; +} +#endif + +QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothaddress.h b/src/bluetooth/qbluetoothaddress.h new file mode 100644 index 0000000..a7a2daa --- /dev/null +++ b/src/bluetooth/qbluetoothaddress.h @@ -0,0 +1,101 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QBLUETOOTHADDRESS_H +#define QBLUETOOTHADDRESS_H + +#include + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QT6_ONLY(Q_BLUETOOTH_EXPORT) QBluetoothAddress +{ +public: + constexpr QBluetoothAddress() noexcept {}; + constexpr explicit QBluetoothAddress(quint64 address) noexcept : m_address(address) {}; + QT7_ONLY(Q_BLUETOOTH_EXPORT) + explicit QBluetoothAddress(const QString &address); +#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) + QT_BLUETOOTH_INLINE_SINCE(6, 6) + QBluetoothAddress(const QBluetoothAddress &other) noexcept; + QT_BLUETOOTH_INLINE_SINCE(6, 6) + ~QBluetoothAddress(); + + QT_BLUETOOTH_INLINE_SINCE(6, 6) + QBluetoothAddress &operator=(const QBluetoothAddress &other) noexcept; + QBluetoothAddress(QBluetoothAddress &&) noexcept = default; + QBluetoothAddress &operator=(QBluetoothAddress &&) noexcept = default; +#endif // Qt 6 + + QT_BLUETOOTH_INLINE_SINCE(6, 6) + bool isNull() const noexcept; + + QT_BLUETOOTH_INLINE_SINCE(6, 6) + void clear() noexcept; + + friend bool operator<(const QBluetoothAddress &a, const QBluetoothAddress &b) + { + return a.m_address < b.m_address; + } + friend bool operator==(const QBluetoothAddress &a, const QBluetoothAddress &b) + { + return a.m_address == b.m_address; + } + inline friend bool operator!=(const QBluetoothAddress &a, const QBluetoothAddress &b) + { + return a.m_address != b.m_address; + } + + QT_BLUETOOTH_INLINE_SINCE(6, 6) + quint64 toUInt64() const noexcept; + QT7_ONLY(Q_BLUETOOTH_EXPORT) + QString toString() const; + +private: + quint64 m_address = { 0 }; + friend QT7_ONLY(constexpr) size_t qHash(const QBluetoothAddress &key, size_t seed = 0) noexcept + { return qHash(key.m_address, seed); } +#ifndef QT_NO_DEBUG_STREAM + friend QDebug operator<<(QDebug d, const QBluetoothAddress &a) + { + return streamingOperator(d, a); + } + QT7_ONLY(Q_BLUETOOTH_EXPORT) + static QDebug streamingOperator(QDebug, const QBluetoothAddress &address); +#endif +}; + +#if QT_BLUETOOTH_INLINE_IMPL_SINCE(6, 6) +#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) +QBluetoothAddress::QBluetoothAddress(const QBluetoothAddress &) noexcept = default; +QBluetoothAddress &QBluetoothAddress::operator=(const QBluetoothAddress &) noexcept = default; +QBluetoothAddress::~QBluetoothAddress() = default; +#endif + +void QBluetoothAddress::clear() noexcept +{ + m_address = 0; +} + +bool QBluetoothAddress::isNull() const noexcept +{ + return m_address == 0; +} + +quint64 QBluetoothAddress::toUInt64() const noexcept +{ + return m_address; +} +#endif // QT_BLUETOOTH_INLINE_IMPL_SINCE(6, 6) + +QT_END_NAMESPACE + +QT_DECL_METATYPE_EXTERN(QBluetoothAddress, Q_BLUETOOTH_EXPORT) + +#endif diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent.cpp new file mode 100644 index 0000000..da88f4a --- /dev/null +++ b/src/bluetooth/qbluetoothdevicediscoveryagent.cpp @@ -0,0 +1,375 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +#include "qbluetoothhostinfo.h" + +#include "qbluetoothdevicediscoveryagent.h" +#include "qbluetoothdevicediscoveryagent_p.h" +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT) + +/*! + \class QBluetoothDeviceDiscoveryAgent + \inmodule QtBluetooth + \brief The QBluetoothDeviceDiscoveryAgent class discovers the Bluetooth + devices nearby. + + \since 5.2 + + To discover the nearby Bluetooth devices: + \list + \li create an instance of QBluetoothDeviceDiscoveryAgent, + \li connect to either the deviceDiscovered() or finished() signals, + \li and call start(). + \endlist + + \snippet doc_src_qtbluetooth.cpp device_discovery + + To retrieve results asynchronously, connect to the deviceDiscovered() signal. To get a list of + all discovered devices, call discoveredDevices() after the finished() signal. + + This class can be used to discover Classic and Low Energy Bluetooth devices. + The individual device type can be determined via the + \l QBluetoothDeviceInfo::coreConfigurations() attribute. + In most cases the list returned by \l discoveredDevices() contains both types + of devices. However not every platform can detect both types of devices. + On platforms with this limitation (for example iOS only suports Low Energy discovery), + the discovery process will limit the search to the type which is supported. + + \note Since Android 6.0 the ability to detect devices requires ACCESS_COARSE_LOCATION. + + \note The Win32 backend currently does not support the Received Signal Strength + Indicator (RSSI), as well as the Manufacturer Specific Data, or other data + updates advertised by Bluetooth LE devices after discovery. +*/ + +/*! + \enum QBluetoothDeviceDiscoveryAgent::Error + + Indicates all possible error conditions found during Bluetooth device discovery. + + \value NoError No error has occurred. + \value PoweredOffError The Bluetooth adaptor is powered off, power it on before doing discovery. + \value InputOutputError Writing or reading from the device resulted in an error. + \value InvalidBluetoothAdapterError The passed local adapter address does not match the physical + adapter address of any local Bluetooth device. + \value [since 5.5] UnsupportedPlatformError Device discovery is not possible or implemented + on the current platform. The error is set in + response to a call to \l start(). An example for + such cases are iOS versions below 5.0 which do + not support Bluetooth device search at all. + \value [since 5.8] UnsupportedDiscoveryMethod One of the requested discovery methods is not + supported by the current platform. + \value [since 6.2] LocationServiceTurnedOffError The location service is turned off. + Usage of Bluetooth APIs is not possible + when location service is turned off. + \value [since 6.4] MissingPermissionsError The operating system requests + permissions which were not + granted by the user. + \value UnknownError An unknown error has occurred. +*/ + +/*! + \enum QBluetoothDeviceDiscoveryAgent::DiscoveryMethod + + This enum descibes the type of discovery method employed by the QBluetoothDeviceDiscoveryAgent. + + \value NoMethod The discovery is not possible. None of the available + methods are supported. + \value ClassicMethod The discovery process searches for Bluetooth Classic + (BaseRate) devices. + \value LowEnergyMethod The discovery process searches for Bluetooth Low Energy + devices. + + \sa supportedDiscoveryMethods() + \since 5.8 +*/ + +/*! + \fn void QBluetoothDeviceDiscoveryAgent::deviceDiscovered(const QBluetoothDeviceInfo &info) + + This signal is emitted when the Bluetooth device described by \a info is discovered. + + The signal is emitted as soon as the most important device information + has been collected. However, as long as the \l finished() signal has not + been emitted the information collection continues even for already discovered + devices. This is particularly true for signal strength information (RSSI) and + manufacturer data updates. If the use case requires continuous manufacturer data + or RSSI updates it is advisable to retrieve the device information via + \l discoveredDevices() once the discovery has finished or listen to the + \l deviceUpdated() signal. + + If \l lowEnergyDiscoveryTimeout() is larger than 0 the signal is only ever + emitted when at least one attribute of \a info changes. This reflects the desire to + receive updates as more precise information becomes available. The exception to this + behavior is the case when \l lowEnergyDiscoveryTimeout is set to \c 0. A timeout of \c 0 + expresses the desire to monitor the appearance and disappearance of Low Energy devices + over time. Under this condition the \l deviceDiscovered() signal is emitted even if + \a info has not changed since the last signal emission. + + \sa QBluetoothDeviceInfo::rssi(), lowEnergyDiscoveryTimeout() +*/ + +/*! + \fn void QBluetoothDeviceDiscoveryAgent::deviceUpdated(const QBluetoothDeviceInfo &info, QBluetoothDeviceInfo::Fields updatedFields) + + This signal is emitted when the agent receives additional information about + the Bluetooth device described by \a info. The \a updatedFields flags tell + which information has been updated. + + During discovery, some information can change dynamically, such as + \l {QBluetoothDeviceInfo::rssi()}{signal strength} and + \l {QBluetoothDeviceInfo::manufacturerData()}{manufacturerData}. + This signal informs you that if your application is displaying this data, it + can be updated, rather than waiting until the discovery has finished. + + \sa QBluetoothDeviceInfo::rssi(), lowEnergyDiscoveryTimeout() +*/ + +/*! + \fn void QBluetoothDeviceDiscoveryAgent::finished() + + This signal is emitted when Bluetooth device discovery completes. + The signal is not going to be emitted if the device discovery finishes with an error. +*/ + +/*! + \fn void QBluetoothDeviceDiscoveryAgent::errorOccurred(QBluetoothDeviceDiscoveryAgent::Error + error) + + This signal is emitted when an \a error occurs during Bluetooth device discovery. + The \a error parameter describes the error that occurred. + + \sa error(), errorString() + \since 6.2 +*/ + +/*! + \fn void QBluetoothDeviceDiscoveryAgent::canceled() + + This signal is emitted when device discovery is aborted by a call to stop(). +*/ + +/*! + \fn bool QBluetoothDeviceDiscoveryAgent::isActive() const + + Returns true if the agent is currently discovering Bluetooth devices, otherwise returns false. +*/ + +/*! + Constructs a new Bluetooth device discovery agent with parent \a parent. +*/ +QBluetoothDeviceDiscoveryAgent::QBluetoothDeviceDiscoveryAgent(QObject *parent) : + QObject(parent), + d_ptr(new QBluetoothDeviceDiscoveryAgentPrivate(QBluetoothAddress(), this)) +{ +} + +/*! + Constructs a new Bluetooth device discovery agent with \a parent. + + It uses \a deviceAdapter for the device search. If \a deviceAdapter is default constructed the resulting + QBluetoothDeviceDiscoveryAgent object will use the local default Bluetooth adapter. + + If a \a deviceAdapter is specified that is not a local adapter \l error() will be set to + \l InvalidBluetoothAdapterError. Therefore it is recommended to test the error flag immediately after + using this constructor. + + \sa error() +*/ +QBluetoothDeviceDiscoveryAgent::QBluetoothDeviceDiscoveryAgent( + const QBluetoothAddress &deviceAdapter, QObject *parent) : + QObject(parent), + d_ptr(new QBluetoothDeviceDiscoveryAgentPrivate(deviceAdapter, this)) +{ + if (!deviceAdapter.isNull()) { + const QList localDevices = QBluetoothLocalDevice::allDevices(); + for (const QBluetoothHostInfo &hostInfo : localDevices) { + if (hostInfo.address() == deviceAdapter) + return; + } + d_ptr->lastError = InvalidBluetoothAdapterError; + d_ptr->errorString = tr("Invalid Bluetooth adapter address"); + } +} + +/*! + Destructor for ~QBluetoothDeviceDiscoveryAgent() +*/ +QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent() +{ + delete d_ptr; +} + +/*! + Returns a list of all discovered Bluetooth devices. +*/ +QList QBluetoothDeviceDiscoveryAgent::discoveredDevices() const +{ + Q_D(const QBluetoothDeviceDiscoveryAgent); + return d->discoveredDevices; +} + +/*! + Sets the maximum search time for Bluetooth Low Energy device search to + \a timeout in milliseconds. If \a timeout is \c 0 the discovery runs + until \l stop() is called. + + This reflects the fact that the discovery process for Bluetooth Low Energy devices + is mostly open ended. The platform continues to look for more devices until the search is + manually stopped. The timeout ensures that the search is aborted after \a timeout milliseconds. + Of course, it is still possible to manually abort the discovery by calling \l stop(). + + The new timeout value does not take effect until the device search is restarted. + In addition the timeout does not affect the classic Bluetooth device search. Depending on + the platform the classic search may add more time to the total discovery process + beyond \a timeout. + + For a reliable Bluetooth Low Energy discovery, use at least 40000 milliseconds. + + \sa lowEnergyDiscoveryTimeout() + \since 5.8 + */ +void QBluetoothDeviceDiscoveryAgent::setLowEnergyDiscoveryTimeout(int timeout) +{ + Q_D(QBluetoothDeviceDiscoveryAgent); + + // cannot deliberately turn it off + if (timeout < 0) { + qCDebug(QT_BT) << "The Bluetooth Low Energy device discovery timeout cannot be negative."; + return; + } + + if (d->lowEnergySearchTimeout < 0) { + qCDebug(QT_BT) << "The Bluetooth Low Energy device discovery timeout cannot be " + "set on a backend which does not support this feature."; + return; + } + + d->lowEnergySearchTimeout = timeout; +} + +/*! + Returns a timeout in milliseconds that is applied to the Bluetooth Low Energy device search. + A value of \c -1 implies that the platform does not support this property and the timeout for + the device search cannot be adjusted. A return value of \c 0 + implies a never-ending search which must be manually stopped via \l stop(). + + \sa setLowEnergyDiscoveryTimeout() + \since 5.8 + */ +int QBluetoothDeviceDiscoveryAgent::lowEnergyDiscoveryTimeout() const +{ + Q_D(const QBluetoothDeviceDiscoveryAgent); + return d->lowEnergySearchTimeout; +} + +/*! + \fn QBluetoothDeviceDiscoveryAgent::DiscoveryMethods QBluetoothDeviceDiscoveryAgent::supportedDiscoveryMethods() + + This function returns the discovery methods supported by the current platform. + It can be used to limit the scope of the device discovery. + + \since 5.8 +*/ + +/*! + Starts Bluetooth device discovery, if it is not already started. + + The deviceDiscovered() signal is emitted as each device is discovered. The finished() signal + is emitted once device discovery is complete. The discovery utilizes the maximum set of + supported discovery methods on the platform. + + \sa supportedDiscoveryMethods() +*/ +void QBluetoothDeviceDiscoveryAgent::start() +{ + Q_D(QBluetoothDeviceDiscoveryAgent); + if (!isActive()) + d->start(supportedDiscoveryMethods()); +} + +/*! + Starts Bluetooth device discovery, if it is not already started and the provided + \a methods are supported. + The discovery \a methods limit the scope of the device search. + For example, if the target service or device is a Bluetooth Low Energy device, + this function could be used to limit the search to Bluetooth Low Energy devices and + thereby reduces the discovery time significantly. + + \note \a methods only determines the type of discovery and does not imply + the filtering of the results. For example, the search may still contain classic bluetooth devices + despite \a methods being set to \l {QBluetoothDeviceDiscoveryAgent::LowEnergyMethod} + {LowEnergyMethod} only. This may happen due to previously cached search results + which may be incorporated into the search results. + + \since 5.8 +*/ +void QBluetoothDeviceDiscoveryAgent::start(DiscoveryMethods methods) +{ + if (methods == NoMethod) + return; + + DiscoveryMethods supported = + QBluetoothDeviceDiscoveryAgent::supportedDiscoveryMethods(); + + Q_D(QBluetoothDeviceDiscoveryAgent); + if (!((supported & methods) == methods)) { + d->lastError = UnsupportedDiscoveryMethod; + d->errorString = QBluetoothDeviceDiscoveryAgent::tr("One or more device discovery methods " + "are not supported on this platform"); + emit errorOccurred(d->lastError); + return; + } + + if (!isActive()) + d->start(methods); +} + +/*! + Stops Bluetooth device discovery. The cancel() signal is emitted once the + device discovery is canceled. start() maybe called before the cancel signal is + received. Once start() has been called the cancel signal from the prior + discovery will be discarded. +*/ +void QBluetoothDeviceDiscoveryAgent::stop() +{ + Q_D(QBluetoothDeviceDiscoveryAgent); + if (isActive() && d->lastError != InvalidBluetoothAdapterError) + d->stop(); +} + +bool QBluetoothDeviceDiscoveryAgent::isActive() const +{ + Q_D(const QBluetoothDeviceDiscoveryAgent); + return d->isActive(); +} + +/*! + Returns the last error. + + Any possible previous errors are cleared upon restarting the discovery. +*/ +QBluetoothDeviceDiscoveryAgent::Error QBluetoothDeviceDiscoveryAgent::error() const +{ + Q_D(const QBluetoothDeviceDiscoveryAgent); + + return d->lastError; +} + +/*! + Returns a human-readable description of the last error. + + \sa error(), errorOccurred() +*/ +QString QBluetoothDeviceDiscoveryAgent::errorString() const +{ + Q_D(const QBluetoothDeviceDiscoveryAgent); + return d->errorString; +} + +QT_END_NAMESPACE + +#include "moc_qbluetoothdevicediscoveryagent.cpp" diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent.h b/src/bluetooth/qbluetoothdevicediscoveryagent.h new file mode 100644 index 0000000..923dbb9 --- /dev/null +++ b/src/bluetooth/qbluetoothdevicediscoveryagent.h @@ -0,0 +1,84 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2014 Denis Shienkov +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QBLUETOOTHDEVICEDISCOVERYAGENT_H +#define QBLUETOOTHDEVICEDISCOVERYAGENT_H + +#include + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QBluetoothDeviceDiscoveryAgentPrivate; + +class Q_BLUETOOTH_EXPORT QBluetoothDeviceDiscoveryAgent : public QObject +{ + Q_OBJECT + +public: + // FIXME: add more errors + // FIXME: add bluez error handling + enum Error { + NoError, + InputOutputError, + PoweredOffError, + InvalidBluetoothAdapterError, + UnsupportedPlatformError, + UnsupportedDiscoveryMethod, + LocationServiceTurnedOffError, + MissingPermissionsError, + UnknownError = 100 // New errors must be added before Unknown error + }; + Q_ENUM(Error) + + enum DiscoveryMethod + { + NoMethod = 0x0, + ClassicMethod = 0x01, + LowEnergyMethod = 0x02, + }; + Q_DECLARE_FLAGS(DiscoveryMethods, DiscoveryMethod) + Q_FLAG(DiscoveryMethods) + + explicit QBluetoothDeviceDiscoveryAgent(QObject *parent = nullptr); + explicit QBluetoothDeviceDiscoveryAgent(const QBluetoothAddress &deviceAdapter, + QObject *parent = nullptr); + ~QBluetoothDeviceDiscoveryAgent(); + + bool isActive() const; + + Error error() const; + QString errorString() const; + + QList discoveredDevices() const; + + void setLowEnergyDiscoveryTimeout(int msTimeout); + int lowEnergyDiscoveryTimeout() const; + + static DiscoveryMethods supportedDiscoveryMethods(); +public Q_SLOTS: + void start(); + void start(DiscoveryMethods method); + void stop(); + +Q_SIGNALS: + void deviceDiscovered(const QBluetoothDeviceInfo &info); + void deviceUpdated(const QBluetoothDeviceInfo &info, QBluetoothDeviceInfo::Fields updatedFields); + void finished(); + void errorOccurred(QBluetoothDeviceDiscoveryAgent::Error error); + void canceled(); + +private: + Q_DECLARE_PRIVATE(QBluetoothDeviceDiscoveryAgent) + QBluetoothDeviceDiscoveryAgentPrivate *d_ptr; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods) + +QT_END_NAMESPACE + +#endif diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp new file mode 100644 index 0000000..109fcb3 --- /dev/null +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp @@ -0,0 +1,463 @@ +// Copyright (C) 2016 Lauri Laanmets (Proekspert AS) +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "android/devicediscoverybroadcastreceiver_p.h" +#include "android/androidutils_p.h" +#include "android/jni_android_p.h" +#include "qbluetoothdevicediscoveryagent_p.h" +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID) + +enum { + NoScanActive = 0, + SDPScanActive = 1, + BtleScanActive = 2 +}; + +static constexpr auto deviceDiscoveryStartTimeLimit = std::chrono::seconds{5}; +static constexpr short deviceDiscoveryStartMaxAttempts = 6; + +QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate( + const QBluetoothAddress &deviceAdapter, QBluetoothDeviceDiscoveryAgent *parent) : + adapterAddress(deviceAdapter), + m_active(NoScanActive), + deviceDiscoveryStartAttemptsLeft(deviceDiscoveryStartMaxAttempts), + q_ptr(parent) +{ + adapter = getDefaultBluetoothAdapter(); + + if (!adapter.isValid()) + qCWarning(QT_BT_ANDROID) << "Device does not support Bluetooth"; +} + +QBluetoothDeviceDiscoveryAgentPrivate::~QBluetoothDeviceDiscoveryAgentPrivate() +{ + if (m_active != NoScanActive) + stop(); + + if (leScanner.isValid()) + leScanner.setField("qtObject", reinterpret_cast(nullptr)); + + if (receiver) { + receiver->unregisterReceiver(); + delete receiver; + } +} + +bool QBluetoothDeviceDiscoveryAgentPrivate::isActive() const +{ + if (pendingStart) + return true; + if (pendingCancel) + return false; + return m_active != NoScanActive; +} + +QBluetoothDeviceDiscoveryAgent::DiscoveryMethods QBluetoothDeviceDiscoveryAgent::supportedDiscoveryMethods() +{ + return (LowEnergyMethod | ClassicMethod); +} + +void QBluetoothDeviceDiscoveryAgentPrivate::classicDiscoveryStartFail() +{ + Q_Q(QBluetoothDeviceDiscoveryAgent); + lastError = QBluetoothDeviceDiscoveryAgent::InputOutputError; + errorString = QBluetoothDeviceDiscoveryAgent::tr("Classic Discovery cannot be started"); + emit q->errorOccurred(lastError); +} + +// Sets & emits an error and returns true if bluetooth is off +bool QBluetoothDeviceDiscoveryAgentPrivate::setErrorIfPowerOff() +{ + Q_Q(QBluetoothDeviceDiscoveryAgent); + + const int state = adapter.callMethod("getState"); + if (state != 12) { // BluetoothAdapter.STATE_ON + lastError = QBluetoothDeviceDiscoveryAgent::PoweredOffError; + m_active = NoScanActive; + errorString = QBluetoothDeviceDiscoveryAgent::tr("Device is powered off"); + emit q->errorOccurred(lastError); + return true; + } + return false; +} + +/* +The Classic/LE discovery method precedence is handled as follows: + +If only classic method is set => only classic method is used +If only LE method is set => only LE method is used +If both classic and LE methods are set, start classic scan first + If classic scan fails to start, start LE scan immediately in the start function + Otherwise start LE scan when classic scan completes +*/ + +void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods) +{ + requestedMethods = methods; + + if (pendingCancel) { + pendingStart = true; + return; + } + + Q_Q(QBluetoothDeviceDiscoveryAgent); + + if (!adapter.isValid()) { + qCWarning(QT_BT_ANDROID) << "Device does not support Bluetooth"; + lastError = QBluetoothDeviceDiscoveryAgent::InputOutputError; + errorString = QBluetoothDeviceDiscoveryAgent::tr("Device does not support Bluetooth"); + emit q->errorOccurred(lastError); + return; + } + + if (!adapterAddress.isNull() + && adapter.callMethod("getAddress").toString() + != adapterAddress.toString()) { + qCWarning(QT_BT_ANDROID) << "Incorrect local adapter passed."; + lastError = QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError; + errorString = QBluetoothDeviceDiscoveryAgent::tr("Passed address is not a local device."); + emit q->errorOccurred(lastError); + return; + } + + if (setErrorIfPowerOff()) + return; + + if (!ensureAndroidPermission(QBluetoothPermission::Access)) { + qCWarning(QT_BT_ANDROID) + << "Search not possible due to missing QBluetoothPermission::Access permission"; + errorString = QBluetoothDeviceDiscoveryAgent::tr( + "Failed to start device discovery due to missing permissions."); + lastError = QBluetoothDeviceDiscoveryAgent::MissingPermissionsError; + emit q->errorOccurred(lastError); + return; + } + qCDebug(QT_BT_ANDROID) << "QBluetoothPermission::Access permission available"; + + // Double check Location service is turned on + bool locationTurnedOn = true; // backwards compatible behavior to previous Qt versions + const QJniObject locString = QJniObject::getStaticObjectField( + "android/content/Context", "LOCATION_SERVICE", "Ljava/lang/String;"); + + const QJniObject locService = + QJniObject(QNativeInterface::QAndroidApplication::context()).callMethod( + "getSystemService", + locString.object()); + + if (locService.isValid()) { + if (QNativeInterface::QAndroidApplication::sdkVersion() >= 28) { + locationTurnedOn = bool(locService.callMethod("isLocationEnabled")); + } else { + // check whether there is any enabled provider + QJniObject listOfEnabledProviders = + locService.callMethod("getProviders", true); + + if (listOfEnabledProviders.isValid()) { + int size = listOfEnabledProviders.callMethod("size"); + locationTurnedOn = size > 0; + qCDebug(QT_BT_ANDROID) << size << "enabled location providers detected."; + } + } + } + + if (!locationTurnedOn) { + qCWarning(QT_BT_ANDROID) << "Search not possible due to turned off Location service"; + lastError = QBluetoothDeviceDiscoveryAgent::LocationServiceTurnedOffError; + errorString = QBluetoothDeviceDiscoveryAgent::tr("Location service turned off. Search is not possible."); + emit q->errorOccurred(lastError); + return; + } + + qCDebug(QT_BT_ANDROID) << "Location turned on"; + + // install Java BroadcastReceiver + if (!receiver) { + // SDP based device discovery + receiver = new DeviceDiscoveryBroadcastReceiver(); + qRegisterMetaType(); + QObject::connect(receiver, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo,bool)), + this, SLOT(processDiscoveredDevices(QBluetoothDeviceInfo,bool))); + QObject::connect(receiver, SIGNAL(finished()), this, SLOT(processSdpDiscoveryFinished())); + } + + lastError = QBluetoothDeviceDiscoveryAgent::NoError; + errorString.clear(); + discoveredDevices.clear(); + + // by arbitrary definition we run classic search first + if (requestedMethods & QBluetoothDeviceDiscoveryAgent::ClassicMethod) { + const bool success = adapter.callMethod("startDiscovery"); + if (!success) { + qCDebug(QT_BT_ANDROID) << "Classic Discovery cannot be started"; + // Check if only classic discovery requested -> error out and return. + // Otherwise since LE was also requested => don't return but allow the + // function to continue to LE scanning + if (requestedMethods == QBluetoothDeviceDiscoveryAgent::ClassicMethod) { + classicDiscoveryStartFail(); + return; + } + } else { + m_active = SDPScanActive; + if (!deviceDiscoveryStartTimeout) { + // In some bluetooth environments device discovery does not start properly + // if it is done shortly after (up to 20 seconds) a full service discovery. + // In that case we never get DISOVERY_STARTED action and device discovery never + // finishes. Here we use a small timeout to guard it; if we don't get the + // 'started' action in time, we restart the query. In the normal case the action + // is received in < 1 second. See QTBUG-101066 + deviceDiscoveryStartTimeout = new QTimer(this); + deviceDiscoveryStartTimeout->setInterval(deviceDiscoveryStartTimeLimit); + deviceDiscoveryStartTimeout->setSingleShot(true); + QObject::connect(receiver, &DeviceDiscoveryBroadcastReceiver::discoveryStarted, + deviceDiscoveryStartTimeout, &QTimer::stop); + QObject::connect(deviceDiscoveryStartTimeout, &QTimer::timeout, this, [this]() { + deviceDiscoveryStartAttemptsLeft -= 1; + qCWarning(QT_BT_ANDROID) << "Discovery start not received, attempts left:" + << deviceDiscoveryStartAttemptsLeft; + // Check that bluetooth is not switched off + if (setErrorIfPowerOff()) + return; + // If this was the last retry attempt, cancel the discovery just in case + // as a good cleanup practice + if (deviceDiscoveryStartAttemptsLeft <= 0) { + qCWarning(QT_BT_ANDROID) << "Classic device discovery failed to start"; + (void)adapter.callMethod("cancelDiscovery"); + } + // Restart the discovery and retry timer. + // The logic below is similar as in the start() + if (deviceDiscoveryStartAttemptsLeft > 0 && + adapter.callMethod("startDiscovery")) + deviceDiscoveryStartTimeout->start(); + else if (requestedMethods == QBluetoothDeviceDiscoveryAgent::ClassicMethod) + classicDiscoveryStartFail(); // No LE scan requested, scan is done + else + startLowEnergyScan(); // Continue to LE scan + }); + } + deviceDiscoveryStartAttemptsLeft = deviceDiscoveryStartMaxAttempts; + deviceDiscoveryStartTimeout->start(); + + qCDebug(QT_BT_ANDROID) + << "QBluetoothDeviceDiscoveryAgentPrivate::start() - Classic search successfully started."; + return; + } + } + + if (requestedMethods & QBluetoothDeviceDiscoveryAgent::LowEnergyMethod) { + // LE search only requested or classic discovery failed but lets try LE scan anyway + startLowEnergyScan(); + } +} + +void QBluetoothDeviceDiscoveryAgentPrivate::stop() +{ + Q_Q(QBluetoothDeviceDiscoveryAgent); + + pendingStart = false; + + if (deviceDiscoveryStartTimeout) + deviceDiscoveryStartTimeout->stop(); + + if (m_active == NoScanActive) + return; + + if (m_active == SDPScanActive) { + if (pendingCancel) { + // If we had both a pending cancel and a pending start, + // we now have only a pending cancel. + // The pending start was canceled above. + return; + } + + pendingCancel = true; + bool success = adapter.callMethod("cancelDiscovery"); + if (!success) { + lastError = QBluetoothDeviceDiscoveryAgent::InputOutputError; + errorString = QBluetoothDeviceDiscoveryAgent::tr("Discovery cannot be stopped"); + emit q->errorOccurred(lastError); + return; + } + } else if (m_active == BtleScanActive) { + stopLowEnergyScan(); + } +} + +void QBluetoothDeviceDiscoveryAgentPrivate::processSdpDiscoveryFinished() +{ + // We need to guard because Android sends two DISCOVERY_FINISHED when cancelling + // Also if we have two active agents both receive the same signal. + // If this one is not active ignore the device information + if (m_active != SDPScanActive) + return; + + Q_Q(QBluetoothDeviceDiscoveryAgent); + + if (pendingCancel && !pendingStart) { + m_active = NoScanActive; + pendingCancel = false; + emit q->canceled(); + } else if (pendingStart) { + pendingStart = pendingCancel = false; + start(requestedMethods); + } else { + // check that it didn't finish due to turned off Bluetooth Device + if (setErrorIfPowerOff()) + return; + // Since no BTLE scan requested and classic scan is done => finished() + if (!(requestedMethods & QBluetoothDeviceDiscoveryAgent::LowEnergyMethod)) { + m_active = NoScanActive; + emit q->finished(); + return; + } + + startLowEnergyScan(); + } +} + +void QBluetoothDeviceDiscoveryAgentPrivate::processDiscoveredDevices( + const QBluetoothDeviceInfo &info, bool isLeResult) +{ + // If we have two active agents both receive the same signal. + // If this one is not active ignore the device information + if (m_active != SDPScanActive && !isLeResult) + return; + if (m_active != BtleScanActive && isLeResult) + return; + + Q_Q(QBluetoothDeviceDiscoveryAgent); + + // Android Classic scan and LE scan can find the same device under different names + // The classic name finds the SDP based device name, the LE scan finds the name in + // the advertisement package. + // If address is same but name different then we keep both entries. + + for (qsizetype i = 0; i < discoveredDevices.size(); ++i) { + if (discoveredDevices[i].address() == info.address()) { + QBluetoothDeviceInfo::Fields updatedFields = QBluetoothDeviceInfo::Field::None; + if (discoveredDevices[i].rssi() != info.rssi()) { + qCDebug(QT_BT_ANDROID) << "Updating RSSI for" << info.address() + << info.rssi(); + discoveredDevices[i].setRssi(info.rssi()); + updatedFields.setFlag(QBluetoothDeviceInfo::Field::RSSI); + } + if (discoveredDevices[i].manufacturerData() != info.manufacturerData()) { + qCDebug(QT_BT_ANDROID) << "Updating manufacturer data for" << info.address(); + const QList keys = info.manufacturerIds(); + for (auto key: keys) + discoveredDevices[i].setManufacturerData(key, info.manufacturerData(key)); + updatedFields.setFlag(QBluetoothDeviceInfo::Field::ManufacturerData); + } + if (discoveredDevices[i].serviceData() != info.serviceData()) { + qCDebug(QT_BT_ANDROID) << "Updating service data for" << info.address(); + const QList keys = info.serviceIds(); + for (auto key : keys) + discoveredDevices[i].setServiceData(key, info.serviceData(key)); + updatedFields.setFlag(QBluetoothDeviceInfo::Field::ServiceData); + } + + if (lowEnergySearchTimeout > 0) { + if (discoveredDevices[i] != info) { + if (discoveredDevices.at(i).name() == info.name()) { + qCDebug(QT_BT_ANDROID) << "Almost Duplicate " << info.address() + << info.name() << "- replacing in place"; + discoveredDevices.replace(i, info); + emit q->deviceDiscovered(info); + } + } else { + if (!updatedFields.testFlag(QBluetoothDeviceInfo::Field::None)) + emit q->deviceUpdated(discoveredDevices[i], updatedFields); + } + + return; + } + + discoveredDevices.replace(i, info); + emit q->deviceDiscovered(info); + + if (!updatedFields.testFlag(QBluetoothDeviceInfo::Field::None)) + emit q->deviceUpdated(discoveredDevices[i], updatedFields); + + return; + } + } + + discoveredDevices.append(info); + qCDebug(QT_BT_ANDROID) << "Device found: " << info.name() << info.address().toString() + << "isLeScanResult:" << isLeResult + << "Manufacturer data size:" << info.manufacturerData().size(); + emit q->deviceDiscovered(info); +} + +void QBluetoothDeviceDiscoveryAgentPrivate::startLowEnergyScan() +{ + Q_Q(QBluetoothDeviceDiscoveryAgent); + + m_active = BtleScanActive; + + if (!leScanner.isValid()) { + leScanner = QJniObject::construct( + QNativeInterface::QAndroidApplication::context()); + if (!leScanner.isValid()) { + qCWarning(QT_BT_ANDROID) << "Cannot load BTLE device scan class"; + m_active = NoScanActive; + emit q->finished(); + return; + } + + leScanner.setField("qtObject", reinterpret_cast(receiver)); + } + + jboolean result = leScanner.callMethod("scanForLeDevice", true); + if (!result) { + qCWarning(QT_BT_ANDROID) << "Cannot start BTLE device scanner"; + m_active = NoScanActive; + emit q->finished(); + return; + } + + // wait interval and sum up what was found + if (!leScanTimeout) { + leScanTimeout = new QTimer(this); + leScanTimeout->setSingleShot(true); + connect(leScanTimeout, &QTimer::timeout, + this, &QBluetoothDeviceDiscoveryAgentPrivate::stopLowEnergyScan); + } + + if (lowEnergySearchTimeout > 0) { // otherwise no timeout and stop() required + leScanTimeout->setInterval(lowEnergySearchTimeout); + leScanTimeout->start(); + } + + qCDebug(QT_BT_ANDROID) + << "QBluetoothDeviceDiscoveryAgentPrivate::start() - Low Energy search successfully started."; +} + +void QBluetoothDeviceDiscoveryAgentPrivate::stopLowEnergyScan() +{ + jboolean result = leScanner.callMethod("scanForLeDevice", false); + if (!result) + qCWarning(QT_BT_ANDROID) << "Cannot stop BTLE device scanner"; + + m_active = NoScanActive; + + Q_Q(QBluetoothDeviceDiscoveryAgent); + if (leScanTimeout->isActive()) { + // still active if this function was called from stop() + leScanTimeout->stop(); + emit q->canceled(); + } else { + // timeout -> regular stop + emit q->finished(); + } +} +QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp new file mode 100644 index 0000000..24ae251 --- /dev/null +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp @@ -0,0 +1,460 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include + +#include + +#include "qbluetoothdevicediscoveryagent.h" +#include "qbluetoothdevicediscoveryagent_p.h" +#include "qbluetoothaddress.h" +#include "qbluetoothuuid.h" + +#include "bluez/bluez5_helper_p.h" +#include "bluez/objectmanager_p.h" +#include "bluez/adapter1_bluez5_p.h" +#include "bluez/device1_bluez5_p.h" +#include "bluez/properties_p.h" +#include "bluez/bluetoothmanagement_p.h" + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ) + +QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate( + const QBluetoothAddress &deviceAdapter, QBluetoothDeviceDiscoveryAgent *parent) : + adapterAddress(deviceAdapter), + q_ptr(parent) +{ + initializeBluez5(); + manager = new OrgFreedesktopDBusObjectManagerInterface( + QStringLiteral("org.bluez"), + QStringLiteral("/"), + QDBusConnection::systemBus(), parent); + QObject::connect(manager, + &OrgFreedesktopDBusObjectManagerInterface::InterfacesAdded, + q_ptr, + [this](const QDBusObjectPath &objectPath, InterfaceList interfacesAndProperties) { + this->_q_InterfacesAdded(objectPath, interfacesAndProperties); + }); + + // start private address monitoring + BluetoothManagement::instance(); +} + +QBluetoothDeviceDiscoveryAgentPrivate::~QBluetoothDeviceDiscoveryAgentPrivate() +{ + delete adapter; +} + +//TODO: Qt6 remove the pendingCancel/pendingStart logic as it is cumbersome. +// It is a behavior change across all platforms and was initially done +// for Bluez. The behavior should be similar to QBluetoothServiceDiscoveryAgent +// PendingCancel creates issues whereby the agent is still shutting down +// but isActive() below already returns false. This means the isActive() is +// out of sync with the finished() and cancel() signal. + +bool QBluetoothDeviceDiscoveryAgentPrivate::isActive() const +{ + if (pendingStart) + return true; + if (pendingCancel) + return false; //TODO Qt6: remove pending[Cancel|Start] logic (see comment above) + + return adapter; +} + +QBluetoothDeviceDiscoveryAgent::DiscoveryMethods QBluetoothDeviceDiscoveryAgent::supportedDiscoveryMethods() +{ + return (ClassicMethod | LowEnergyMethod); +} + +void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods) +{ + if (pendingCancel == true) { + pendingStart = true; + return; + } + + lastError = QBluetoothDeviceDiscoveryAgent::NoError; + errorString.clear(); + discoveredDevices.clear(); + devicesProperties.clear(); + + Q_Q(QBluetoothDeviceDiscoveryAgent); + + bool ok = false; + const QString adapterPath = findAdapterForAddress(adapterAddress, &ok); + if (!ok || adapterPath.isEmpty()) { + qCWarning(QT_BT_BLUEZ) << "Cannot find Bluez 5 adapter for device search" << ok; + lastError = QBluetoothDeviceDiscoveryAgent::InputOutputError; + errorString = QBluetoothDeviceDiscoveryAgent::tr("Cannot find valid Bluetooth adapter."); + q->errorOccurred(lastError); + return; + } + + adapter = new OrgBluezAdapter1Interface(QStringLiteral("org.bluez"), adapterPath, + QDBusConnection::systemBus()); + + if (!adapter->powered()) { + qCDebug(QT_BT_BLUEZ) << "Aborting device discovery due to offline Bluetooth Adapter"; + lastError = QBluetoothDeviceDiscoveryAgent::PoweredOffError; + errorString = QBluetoothDeviceDiscoveryAgent::tr("Device is powered off"); + delete adapter; + adapter = nullptr; + emit q->errorOccurred(lastError); + return; + } + + QVariantMap map; + if (methods == (QBluetoothDeviceDiscoveryAgent::LowEnergyMethod|QBluetoothDeviceDiscoveryAgent::ClassicMethod)) + map.insert(QStringLiteral("Transport"), QStringLiteral("auto")); + else if (methods & QBluetoothDeviceDiscoveryAgent::LowEnergyMethod) + map.insert(QStringLiteral("Transport"), QStringLiteral("le")); + else + map.insert(QStringLiteral("Transport"), QStringLiteral("bredr")); + + // older BlueZ 5.x versions don't have this function + // filterReply returns UnknownMethod which we ignore + QDBusPendingReply<> filterReply = adapter->SetDiscoveryFilter(map); + filterReply.waitForFinished(); + if (filterReply.isError()) { + if (filterReply.error().type() == QDBusError::Other + && filterReply.error().name() == QStringLiteral("org.bluez.Error.Failed")) { + qCDebug(QT_BT_BLUEZ) << "Discovery method" << methods << "not supported"; + lastError = QBluetoothDeviceDiscoveryAgent::UnsupportedDiscoveryMethod; + errorString = QBluetoothDeviceDiscoveryAgent::tr("One or more device discovery methods " + "are not supported on this platform"); + delete adapter; + adapter = nullptr; + emit q->errorOccurred(lastError); + return; + } else if (filterReply.error().type() != QDBusError::UnknownMethod) { + qCDebug(QT_BT_BLUEZ) << "SetDiscoveryFilter failed:" << filterReply.error(); + } + } + + QtBluezDiscoveryManager::instance()->registerDiscoveryInterest(adapter->path()); + QObject::connect(QtBluezDiscoveryManager::instance(), &QtBluezDiscoveryManager::discoveryInterrupted, + q, [this](const QString &path){ + this->_q_discoveryInterrupted(path); + }); + OrgFreedesktopDBusPropertiesInterface *prop = new OrgFreedesktopDBusPropertiesInterface( + QStringLiteral("org.bluez"), QStringLiteral(""), QDBusConnection::systemBus()); + QObject::connect(prop, &OrgFreedesktopDBusPropertiesInterface::PropertiesChanged, + q, [this](const QString &interface, const QVariantMap &changedProperties, + const QStringList &invalidatedProperties, + const QDBusMessage &signal) { + this->_q_PropertiesChanged(interface, signal.path(), changedProperties, invalidatedProperties); + }); + + // remember what we have to cleanup + propertyMonitors.append(prop); + + // collect initial set of information + QDBusPendingReply reply = manager->GetManagedObjects(); + reply.waitForFinished(); + if (!reply.isError()) { + ManagedObjectList managedObjectList = reply.value(); + for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) { + const QDBusObjectPath &path = it.key(); + const InterfaceList &ifaceList = it.value(); + + for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) { + const QString &iface = jt.key(); + + if (iface == QStringLiteral("org.bluez.Device1")) { + + if (path.path().indexOf(adapter->path()) != 0) + continue; //devices whose path doesn't start with same path we skip + + deviceFound(path.path(), jt.value()); + if (!isActive()) // Can happen if stop() was called from a slot in user code. + return; + } + } + } + } + + // wait interval and sum up what was found + if (!discoveryTimer) { + discoveryTimer = new QTimer(q); + discoveryTimer->setSingleShot(true); + QObject::connect(discoveryTimer, &QTimer::timeout, + q, [this]() { + this->_q_discoveryFinished(); + }); + } + + if (lowEnergySearchTimeout > 0) { // otherwise no timeout and stop() required + discoveryTimer->setInterval(lowEnergySearchTimeout); + discoveryTimer->start(); + } +} + +void QBluetoothDeviceDiscoveryAgentPrivate::stop() +{ + if (!adapter) + return; + + qCDebug(QT_BT_BLUEZ) << Q_FUNC_INFO; + pendingCancel = true; + pendingStart = false; + _q_discoveryFinished(); +} + +// Returns invalid QBluetoothDeviceInfo in case of error +static QBluetoothDeviceInfo createDeviceInfoFromBluez5Device(const QVariantMap& properties) +{ + const QBluetoothAddress btAddress(properties[QStringLiteral("Address")].toString()); + if (btAddress.isNull()) + return QBluetoothDeviceInfo(); + + const QString btName = properties[QStringLiteral("Alias")].toString(); + quint32 btClass = properties[QStringLiteral("Class")].toUInt(); + + QBluetoothDeviceInfo deviceInfo(btAddress, btName, btClass); + deviceInfo.setRssi(qvariant_cast(properties[QStringLiteral("RSSI")])); + + QList uuids; + bool foundLikelyLowEnergyUuid = false; + const QStringList foundUuids = qvariant_cast(properties[QStringLiteral("UUIDs")]); + for (const auto &u: foundUuids) { + const QBluetoothUuid id(u); + if (id.isNull()) + continue; + + if (!foundLikelyLowEnergyUuid) { + //once we found one BTLE service we are done + bool ok = false; + quint16 shortId = id.toUInt16(&ok); + quint16 genericAccessInt = static_cast(QBluetoothUuid::ServiceClassUuid::GenericAccess); + if (ok && ((shortId & genericAccessInt) == genericAccessInt)) + foundLikelyLowEnergyUuid = true; + } + uuids.append(id); + } + deviceInfo.setServiceUuids(uuids); + + if (!btClass) { + deviceInfo.setCoreConfigurations(QBluetoothDeviceInfo::LowEnergyCoreConfiguration); + } else { + deviceInfo.setCoreConfigurations(QBluetoothDeviceInfo::BaseRateCoreConfiguration); + if (foundLikelyLowEnergyUuid) + deviceInfo.setCoreConfigurations(QBluetoothDeviceInfo::BaseRateAndLowEnergyCoreConfiguration); + } + + const ManufacturerDataList deviceManufacturerData = qdbus_cast(properties[QStringLiteral("ManufacturerData")]); + const QList keysManufacturer = deviceManufacturerData.keys(); + for (quint16 key : keysManufacturer) + deviceInfo.setManufacturerData( + key, deviceManufacturerData.value(key).variant().toByteArray()); + + const ServiceDataList deviceServiceData = + qdbus_cast(properties[QStringLiteral("ServiceData")]); + const QList keysService = deviceServiceData.keys(); + for (QString key : keysService) + deviceInfo.setServiceData(QBluetoothUuid(key), + deviceServiceData.value(key).variant().toByteArray()); + + return deviceInfo; +} + +void QBluetoothDeviceDiscoveryAgentPrivate::deviceFound(const QString &devicePath, + const QVariantMap &properties) +{ + Q_Q(QBluetoothDeviceDiscoveryAgent); + + if (!q->isActive()) + return; + + auto deviceAdapter = qvariant_cast(properties[QStringLiteral("Adapter")]); + if (deviceAdapter.path() != adapter->path()) + return; + + // read information + QBluetoothDeviceInfo deviceInfo = createDeviceInfoFromBluez5Device(properties); + if (!deviceInfo.isValid()) // no point reporting an empty address + return; + + qCDebug(QT_BT_BLUEZ) << "Discovered: " << deviceInfo.name() << deviceInfo.address() + << "Num UUIDs" << deviceInfo.serviceUuids().size() + << "total device" << discoveredDevices.size() << "cached" + << "RSSI" << deviceInfo.rssi() + << "Num ManufacturerData" << deviceInfo.manufacturerData().size() + << "Num ServiceData" << deviceInfo.serviceData().size(); + + // Cache the properties so we do not have to access dbus every time to get a value + devicesProperties[devicePath] = properties; + + for (qsizetype i = 0; i < discoveredDevices.size(); ++i) { + if (discoveredDevices[i].address() == deviceInfo.address()) { + if (lowEnergySearchTimeout > 0 && discoveredDevices[i] == deviceInfo) { + qCDebug(QT_BT_BLUEZ) << "Duplicate: " << deviceInfo.address(); + return; + } + discoveredDevices.replace(i, deviceInfo); + + emit q->deviceDiscovered(deviceInfo); + return; // this works if the list doesn't contain duplicates. Don't let it. + } + } + + discoveredDevices.append(deviceInfo); + emit q->deviceDiscovered(deviceInfo); +} + +void QBluetoothDeviceDiscoveryAgentPrivate::_q_InterfacesAdded(const QDBusObjectPath &object_path, + InterfaceList interfaces_and_properties) +{ + Q_Q(QBluetoothDeviceDiscoveryAgent); + + if (!q->isActive()) + return; + + if (interfaces_and_properties.contains(QStringLiteral("org.bluez.Device1"))) { + // device interfaces belonging to different adapter + // will be filtered out by deviceFound(); + deviceFound(object_path.path(), + interfaces_and_properties[QStringLiteral("org.bluez.Device1")]); + } +} + +void QBluetoothDeviceDiscoveryAgentPrivate::_q_discoveryFinished() +{ + Q_Q(QBluetoothDeviceDiscoveryAgent); + + if (discoveryTimer) + discoveryTimer->stop(); + + QtBluezDiscoveryManager::instance()->disconnect(q); + QtBluezDiscoveryManager::instance()->unregisterDiscoveryInterest(adapter->path()); + + qDeleteAll(propertyMonitors); + propertyMonitors.clear(); + + delete adapter; + adapter = nullptr; + + if (pendingCancel && !pendingStart) { + pendingCancel = false; + emit q->canceled(); + } else if (pendingStart) { + pendingStart = false; + pendingCancel = false; + start(QBluetoothDeviceDiscoveryAgent::ClassicMethod + | QBluetoothDeviceDiscoveryAgent::LowEnergyMethod); + } else { + emit q->finished(); + } +} + +void QBluetoothDeviceDiscoveryAgentPrivate::_q_discoveryInterrupted(const QString &path) +{ + Q_Q(QBluetoothDeviceDiscoveryAgent); + + if (!q->isActive()) + return; + + if (path == adapter->path()) { + qCWarning(QT_BT_BLUEZ) << "Device discovery aborted due to unexpected adapter changes from another process."; + + if (discoveryTimer) + discoveryTimer->stop(); + + QtBluezDiscoveryManager::instance()->disconnect(q); + // no need to call unregisterDiscoveryInterest since QtBluezDiscoveryManager + // does this automatically when emitting discoveryInterrupted(QString) signal + + delete adapter; + adapter = nullptr; + + errorString = QBluetoothDeviceDiscoveryAgent::tr("Bluetooth adapter error"); + lastError = QBluetoothDeviceDiscoveryAgent::InputOutputError; + emit q->errorOccurred(lastError); + } +} + +void QBluetoothDeviceDiscoveryAgentPrivate::_q_PropertiesChanged(const QString &interface, + const QString &path, + const QVariantMap &changed_properties, + const QStringList &invalidated_properties) +{ + Q_Q(QBluetoothDeviceDiscoveryAgent); + if (interface != QStringLiteral("org.bluez.Device1")) + return; + + if (!devicesProperties.contains(path)) + return; + + // Update the cached properties before checking changed_properties for RSSI and ManufacturerData + // so the cached properties are always up to date. + QVariantMap & properties = devicesProperties[path]; + for (QVariantMap::const_iterator it = changed_properties.constBegin(); + it != changed_properties.constEnd(); ++it) { + properties[it.key()] = it.value(); + } + + for (const QString & property : invalidated_properties) + properties.remove(property); + + const auto info = createDeviceInfoFromBluez5Device(properties); + if (!info.isValid()) + return; + + if (changed_properties.contains(QStringLiteral("RSSI")) + || changed_properties.contains(QStringLiteral("ManufacturerData"))) { + + for (qsizetype i = 0; i < discoveredDevices.size(); ++i) { + if (discoveredDevices[i].address() == info.address()) { + QBluetoothDeviceInfo::Fields updatedFields = QBluetoothDeviceInfo::Field::None; + if (changed_properties.contains(QStringLiteral("RSSI"))) { + qCDebug(QT_BT_BLUEZ) << "Updating RSSI for" << info.address() + << changed_properties.value(QStringLiteral("RSSI")); + discoveredDevices[i].setRssi( + changed_properties.value(QStringLiteral("RSSI")).toInt()); + updatedFields.setFlag(QBluetoothDeviceInfo::Field::RSSI); + } + if (changed_properties.contains(QStringLiteral("ManufacturerData"))) { + qCDebug(QT_BT_BLUEZ) << "Updating ManufacturerData for" << info.address(); + ManufacturerDataList changedManufacturerData = + qdbus_cast< ManufacturerDataList >(changed_properties.value(QStringLiteral("ManufacturerData"))); + + const QList keys = changedManufacturerData.keys(); + bool wasNewValue = false; + for (quint16 key : keys) { + bool added = discoveredDevices[i].setManufacturerData(key, changedManufacturerData.value(key).variant().toByteArray()); + wasNewValue = (wasNewValue || added); + } + + if (wasNewValue) + updatedFields.setFlag(QBluetoothDeviceInfo::Field::ManufacturerData); + } + + if (lowEnergySearchTimeout > 0) { + if (discoveredDevices[i] != info) { // field other than manufacturer or rssi changed + if (discoveredDevices.at(i).name() == info.name()) { + qCDebug(QT_BT_BLUEZ) << "Almost Duplicate " << info.address() + << info.name() << "- replacing in place"; + discoveredDevices.replace(i, info); + emit q->deviceDiscovered(info); + } + } else { + if (!updatedFields.testFlag(QBluetoothDeviceInfo::Field::None)) + emit q->deviceUpdated(discoveredDevices[i], updatedFields); + } + + return; + } + + discoveredDevices.replace(i, info); + emit q_ptr->deviceDiscovered(discoveredDevices[i]); + + if (!updatedFields.testFlag(QBluetoothDeviceInfo::Field::None)) + emit q->deviceUpdated(discoveredDevices[i], updatedFields); + return; + } + } + } +} +QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_darwin.mm b/src/bluetooth/qbluetoothdevicediscoveryagent_darwin.mm new file mode 100644 index 0000000..0f32898 --- /dev/null +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_darwin.mm @@ -0,0 +1,556 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothdevicediscoveryagent_p.h" +#include "qbluetoothdevicediscoveryagent.h" + +#include "darwin/btledeviceinquiry_p.h" + +#ifdef Q_OS_MACOS +#include "darwin/btdeviceinquiry_p.h" +#include "darwin/btsdpinquiry_p.h" + +#include +#endif // Q_OS_MACOS + +#include "qbluetoothdeviceinfo.h" +#include "darwin/btnotifier_p.h" +#include "darwin/btutility_p.h" +#include "darwin/uistrings_p.h" +#include "qbluetoothhostinfo.h" +#include "darwin/uistrings_p.h" +#include "qbluetoothaddress.h" +#include "darwin/btraii_p.h" +#include "qbluetoothuuid.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +QT_BEGIN_NAMESPACE + +namespace +{ + +void registerQDeviceDiscoveryMetaType() +{ + static bool initDone = false; + if (!initDone) { + qRegisterMetaType(); + qRegisterMetaType(); + initDone = true; + } +} + +} //namespace + +QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate(const QBluetoothAddress &adapter, + QBluetoothDeviceDiscoveryAgent *q) : + adapterAddress(adapter), + agentState(NonActive), + lowEnergySearchTimeout(DarwinBluetooth::defaultLEScanTimeoutMS), +#ifdef Q_OS_MACOS + requestedMethods(QBluetoothDeviceDiscoveryAgent::ClassicMethod | QBluetoothDeviceDiscoveryAgent::LowEnergyMethod), +#else + requestedMethods(QBluetoothDeviceDiscoveryAgent::ClassicMethod), +#endif // Q_OS_MACOS + q_ptr(q) +{ + registerQDeviceDiscoveryMetaType(); + + Q_ASSERT_X(q != nullptr, Q_FUNC_INFO, "invalid q_ptr (null)"); +} + +QBluetoothDeviceDiscoveryAgentPrivate::~QBluetoothDeviceDiscoveryAgentPrivate() +{ + if (inquiryLE && agentState != NonActive) { + // We want the LE scan to stop as soon as possible. + if (dispatch_queue_t leQueue = DarwinBluetooth::qt_LE_queue()) { + // Local variable to be retained ... + DarwinBTLEDeviceInquiry *inq = inquiryLE.getAs(); + dispatch_sync(leQueue, ^{ + [inq stop]; + }); + } + } +} + +bool QBluetoothDeviceDiscoveryAgentPrivate::isActive() const +{ + if (startPending) + return true; + + if (stopPending) + return false; + + return agentState != NonActive; +} + +void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods) +{ + using namespace DarwinBluetooth; + + Q_ASSERT(!isActive()); + Q_ASSERT(methods & (QBluetoothDeviceDiscoveryAgent::ClassicMethod + | QBluetoothDeviceDiscoveryAgent::LowEnergyMethod)); + +#ifdef Q_OS_MACOS + if (!controller) { + IOBluetoothHostController *hostController = [IOBluetoothHostController defaultController]; + if (!hostController) { + qCWarning(QT_BT_DARWIN) << "No default Bluetooth controller found"; + setError(QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError); + emit q_ptr->errorOccurred(lastError); + return; + } else if ([hostController powerState] != kBluetoothHCIPowerStateON) { + qCWarning(QT_BT_DARWIN) << "Default Bluetooth controller is OFF"; + setError(QBluetoothDeviceDiscoveryAgent::PoweredOffError); + emit q_ptr->errorOccurred(lastError); + return; + } else if (!adapterAddress.isNull()) { + // If user has provided the local address, check that it matches with the actual + NSString *const hciAddress = [hostController addressAsString]; + if (adapterAddress != QBluetoothAddress(QString::fromNSString(hciAddress))) { + qCWarning(QT_BT_DARWIN) << "Provided address" << adapterAddress + << "does not match with adapter:" << hciAddress; + setError(QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError); + emit q_ptr->errorOccurred(lastError); + return; + } + } + controller.reset(hostController, DarwinBluetooth::RetainPolicy::doInitialRetain); + } +#endif // Q_OS_MACOS + + // To be able to scan for devices, iOS requires Info.plist containing + // NSBluetoothAlwaysUsageDescription entry with a string, explaining + // the usage of Bluetooth interface. macOS also requires this description, + // starting from Monterey. + + // No Classic on iOS, and Classic does not require a description on macOS: + if (methods.testFlag(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod)) { + const auto permissionStatus = qApp->checkPermission(QBluetoothPermission{}); + if (permissionStatus != Qt::PermissionStatus::Granted) { + qCWarning(QT_BT_DARWIN, + "Use of Bluetooth LE requires explicitly requested permissions."); + setError(QBluetoothDeviceDiscoveryAgent::MissingPermissionsError); + emit q_ptr->errorOccurred(lastError); + // Arguably, Classic scan is still possible, but let's keep the logic + // simple. + return; + } + } + + requestedMethods = methods; + + if (stopPending) { + startPending = true; + return; + } + + // This function (re)starts the scan(s) from the scratch; + // starting from Classic if it's in 'methods' (or LE scan if not). + + agentState = NonActive; + discoveredDevices.clear(); + setError(QBluetoothDeviceDiscoveryAgent::NoError); +#ifdef Q_OS_MACOS + if (requestedMethods & QBluetoothDeviceDiscoveryAgent::ClassicMethod) + return startClassic(); +#endif // Q_OS_MACOS + + startLE(); +} + +#ifdef Q_OS_MACOS + +void QBluetoothDeviceDiscoveryAgentPrivate::startClassic() +{ + Q_ASSERT(!isActive()); + Q_ASSERT(lastError == QBluetoothDeviceDiscoveryAgent::NoError); + Q_ASSERT(requestedMethods & QBluetoothDeviceDiscoveryAgent::ClassicMethod); + Q_ASSERT(agentState == NonActive); + + DarwinBluetooth::qt_test_iobluetooth_runloop(); + + if (!inquiry) { + // The first Classic scan for this DDA. + inquiry.reset([[DarwinBTClassicDeviceInquiry alloc] initWithDelegate:this], + DarwinBluetooth::RetainPolicy::noInitialRetain); + + if (!inquiry) { + qCCritical(QT_BT_DARWIN) << "failed to initialize an Classic device inquiry"; + setError(QBluetoothDeviceDiscoveryAgent::UnknownError, + QCoreApplication::translate(DEV_DISCOVERY, DD_NOT_STARTED)); + emit q_ptr->errorOccurred(lastError); + return; + } + } + + agentState = ClassicScan; + + const IOReturn res = [inquiry.getAs() start]; + if (res != kIOReturnSuccess) { + setError(res, QCoreApplication::translate(DEV_DISCOVERY, DD_NOT_STARTED)); + agentState = NonActive; + emit q_ptr->errorOccurred(lastError); + } +} + +#endif // Q_OS_MACOS + +void QBluetoothDeviceDiscoveryAgentPrivate::startLE() +{ + Q_ASSERT(lastError != QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError); + Q_ASSERT(requestedMethods & QBluetoothDeviceDiscoveryAgent::LowEnergyMethod); + + using namespace DarwinBluetooth; + + std::unique_ptr notifier = std::make_unique(); + // Connections: + using ErrMemFunPtr = void (LECBManagerNotifier::*)(QBluetoothDeviceDiscoveryAgent::Error); + notifier->connect(notifier.get(), ErrMemFunPtr(&LECBManagerNotifier::CBManagerError), + this, &QBluetoothDeviceDiscoveryAgentPrivate::LEinquiryError); + notifier->connect(notifier.get(), &LECBManagerNotifier::LEnotSupported, + this, &QBluetoothDeviceDiscoveryAgentPrivate::LEnotSupported); + notifier->connect(notifier.get(), &LECBManagerNotifier::discoveryFinished, + this, &QBluetoothDeviceDiscoveryAgentPrivate::LEinquiryFinished); + using DeviceMemFunPtr = void (QBluetoothDeviceDiscoveryAgentPrivate::*)(const QBluetoothDeviceInfo &); + notifier->connect(notifier.get(), &LECBManagerNotifier::deviceDiscovered, + this, DeviceMemFunPtr(&QBluetoothDeviceDiscoveryAgentPrivate::deviceFound)); + + // Check queue and create scanner: + inquiryLE.reset([[DarwinBTLEDeviceInquiry alloc] initWithNotifier:notifier.get()], + DarwinBluetooth::RetainPolicy::noInitialRetain); + if (inquiryLE) + notifier.release(); // Whatever happens next, inquiryLE is already the owner ... + + dispatch_queue_t leQueue(qt_LE_queue()); + if (!leQueue || !inquiryLE) { + setError(QBluetoothDeviceDiscoveryAgent::UnknownError, + QCoreApplication::translate(DEV_DISCOVERY, DD_NOT_STARTED_LE)); + agentState = NonActive; + emit q_ptr->errorOccurred(lastError); + return; + } + + // Now start in on LE queue: + agentState = LEScan; + // We need the local variable so that it's retained ... + DarwinBTLEDeviceInquiry *inq = inquiryLE.getAs(); + dispatch_async(leQueue, ^{ + [inq startWithTimeout:lowEnergySearchTimeout]; + }); +} + +void QBluetoothDeviceDiscoveryAgentPrivate::stop() +{ + Q_ASSERT_X(isActive(), Q_FUNC_INFO, "called whithout active inquiry"); + Q_ASSERT_X(lastError != QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError, + Q_FUNC_INFO, "called with invalid bluetooth adapter"); + + using namespace DarwinBluetooth; + + const bool prevStart = startPending; + startPending = false; + stopPending = true; + + setError(QBluetoothDeviceDiscoveryAgent::NoError); + +#ifdef Q_OS_MACOS + if (agentState == ClassicScan) { + const IOReturn res = [inquiry.getAs() stop]; + if (res != kIOReturnSuccess) { + qCWarning(QT_BT_DARWIN) << "failed to stop"; + startPending = prevStart; + stopPending = false; + setError(res, QCoreApplication::translate(DEV_DISCOVERY, DD_NOT_STOPPED)); + emit q_ptr->errorOccurred(lastError); + } + } else { +#else + { + Q_UNUSED(prevStart); +#endif // Q_OS_MACOS + dispatch_queue_t leQueue(qt_LE_queue()); + Q_ASSERT(leQueue); + // We need the local variable so that it's retained ... + DarwinBTLEDeviceInquiry *inq = inquiryLE.getAs(); + dispatch_sync(leQueue, ^{ + [inq stop]; + }); + // We consider LE scan to be stopped immediately and + // do not care about this LEDeviceInquiry object anymore. + LEinquiryFinished(); + } +} + +#ifdef Q_OS_MACOS + +void QBluetoothDeviceDiscoveryAgentPrivate::inquiryFinished() +{ + // The subsequent start(LE) function (if any) + // will (re)set the correct state. + agentState = NonActive; + + if (stopPending && !startPending) { + stopPending = false; + emit q_ptr->canceled(); + } else if (startPending) { + startPending = false; + stopPending = false; + start(requestedMethods); + } else { + // We can be here _only_ if a classic scan + // finished in a normal way (not cancelled) + // and requestedMethods includes LowEnergyMethod. + // startLE() will take care of old devices + // not supporting Bluetooth 4.0. + if (requestedMethods & QBluetoothDeviceDiscoveryAgent::LowEnergyMethod) + startLE(); + else + emit q_ptr->finished(); + } +} + +void QBluetoothDeviceDiscoveryAgentPrivate::error(IOReturn error) +{ + startPending = false; + stopPending = false; + + setError(error); + + emit q_ptr->errorOccurred(lastError); +} + +void QBluetoothDeviceDiscoveryAgentPrivate::classicDeviceFound(void *obj) +{ + auto device = static_cast(obj); + Q_ASSERT_X(device, Q_FUNC_INFO, "invalid IOBluetoothDevice (nil)"); + + Q_ASSERT_X(agentState == ClassicScan, Q_FUNC_INFO, + "invalid agent state (expected classic scan)"); + + QT_BT_MAC_AUTORELEASEPOOL; + + // Let's collect some info about this device: + const QBluetoothAddress deviceAddress(DarwinBluetooth::qt_address([device getAddress])); + if (deviceAddress.isNull()) { + qCWarning(QT_BT_DARWIN) << "invalid Bluetooth address"; + return; + } + + QString deviceName; + if (device.name) + deviceName = QString::fromNSString(device.name); + + const auto classOfDevice = qint32(device.classOfDevice); + + QBluetoothDeviceInfo deviceInfo(deviceAddress, deviceName, classOfDevice); + deviceInfo.setCoreConfigurations(QBluetoothDeviceInfo::BaseRateCoreConfiguration); + deviceInfo.setRssi(device.RSSI); + + const QList uuids(DarwinBluetooth::extract_services_uuids(device)); + deviceInfo.setServiceUuids(uuids); + + deviceFound(deviceInfo); +} + +void QBluetoothDeviceDiscoveryAgentPrivate::setError(IOReturn error, const QString &text) +{ + if (error == kIOReturnSuccess) + setError(QBluetoothDeviceDiscoveryAgent::NoError, text); + else if (error == kIOReturnNoPower) + setError(QBluetoothDeviceDiscoveryAgent::PoweredOffError, text); + else + setError(QBluetoothDeviceDiscoveryAgent::UnknownError, text); +} + +#endif // Q_OS_MACOS + +void QBluetoothDeviceDiscoveryAgentPrivate::setError(QBluetoothDeviceDiscoveryAgent::Error error, const QString &text) +{ + lastError = error; + + if (!text.isEmpty()) { + errorString = text; + } else { + switch (lastError) { + case QBluetoothDeviceDiscoveryAgent::NoError: + errorString = QString(); + break; + case QBluetoothDeviceDiscoveryAgent::PoweredOffError: + errorString = QCoreApplication::translate(DEV_DISCOVERY, DD_POWERED_OFF); + break; + case QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError: + errorString = QCoreApplication::translate(DEV_DISCOVERY, DD_INVALID_ADAPTER); + break; + case QBluetoothDeviceDiscoveryAgent::InputOutputError: + errorString = QCoreApplication::translate(DEV_DISCOVERY, DD_IO); + break; + case QBluetoothDeviceDiscoveryAgent::UnsupportedPlatformError: + errorString = QCoreApplication::translate(DEV_DISCOVERY, DD_NOTSUPPORTED); + break; + case QBluetoothDeviceDiscoveryAgent::MissingPermissionsError: + errorString = QCoreApplication::translate(DEV_DISCOVERY, DD_MISSING_PERMISSION); + break; + case QBluetoothDeviceDiscoveryAgent::UnknownError: + default: + errorString = QCoreApplication::translate(DEV_DISCOVERY, DD_UNKNOWN_ERROR); + } + } +} + +void QBluetoothDeviceDiscoveryAgentPrivate::LEinquiryError(QBluetoothDeviceDiscoveryAgent::Error error) +{ + Q_ASSERT(error == QBluetoothDeviceDiscoveryAgent::PoweredOffError + || error == QBluetoothDeviceDiscoveryAgent::UnsupportedDiscoveryMethod + || error == QBluetoothDeviceDiscoveryAgent::MissingPermissionsError); + + inquiryLE.reset(); + + startPending = false; + stopPending = false; + agentState = NonActive; + setError(error); + emit q_ptr->errorOccurred(lastError); +} + +void QBluetoothDeviceDiscoveryAgentPrivate::LEnotSupported() +{ + qCDebug(QT_BT_DARWIN) << "no Bluetooth LE support"; + +#ifdef Q_OS_MACOS + if (requestedMethods & QBluetoothDeviceDiscoveryAgent::ClassicMethod) { + // Having both Classic | LE means this is not an error. + LEinquiryFinished(); + } else { + // In the past this was never an error, that's why we have + // LEnotSupported as a special method. But now, since + // we can have separate Classic/LE scans, we have to report it + // as UnsupportedDiscoveryMethod. + LEinquiryError(QBluetoothDeviceDiscoveryAgent::UnsupportedDiscoveryMethod); + } +#else + inquiryLE.reset(); + startPending = false; + stopPending = false; + setError(QBluetoothDeviceDiscoveryAgent::UnsupportedPlatformError); + emit q_ptr->errorOccurred(lastError); +#endif +} + +void QBluetoothDeviceDiscoveryAgentPrivate::LEinquiryFinished() +{ + // The same logic as in inquiryFinished, but does not start LE scan. + agentState = NonActive; + inquiryLE.reset(); + + if (stopPending && !startPending) { + stopPending = false; + emit q_ptr->canceled(); + } else if (startPending) { + startPending = false; + stopPending = false; + start(requestedMethods); //Start again. + } else { + emit q_ptr->finished(); + } +} + +void QBluetoothDeviceDiscoveryAgentPrivate::deviceFound(const QBluetoothDeviceInfo &newDeviceInfo) +{ + // Core Bluetooth does not allow us to access addresses, we have to use uuid instead. + // This uuid has nothing to do with uuids in Bluetooth in general (it's generated by + // Apple's framework using some algorithm), but it's a 128-bit uuid after all. + const bool isLE = +#ifdef Q_OS_MACOS + newDeviceInfo.coreConfigurations() == QBluetoothDeviceInfo::LowEnergyCoreConfiguration; +#else + true; +#endif // Q_OS_MACOS + for (qsizetype i = 0, e = discoveredDevices.size(); i < e; ++i) { + if (isLE) { + if (discoveredDevices[i].deviceUuid() == newDeviceInfo.deviceUuid()) { + QBluetoothDeviceInfo::Fields updatedFields = QBluetoothDeviceInfo::Field::None; + if (discoveredDevices[i].rssi() != newDeviceInfo.rssi()) { + qCDebug(QT_BT_DARWIN) << "Updating RSSI for" << newDeviceInfo.address() + << newDeviceInfo.rssi(); + discoveredDevices[i].setRssi(newDeviceInfo.rssi()); + updatedFields.setFlag(QBluetoothDeviceInfo::Field::RSSI); + } + + if (discoveredDevices[i].manufacturerData() != newDeviceInfo.manufacturerData()) { + qCDebug(QT_BT_DARWIN) << "Updating manufacturer data for" << newDeviceInfo.address(); + const QList keys = newDeviceInfo.manufacturerIds(); + for (auto key: keys) + discoveredDevices[i].setManufacturerData(key, newDeviceInfo.manufacturerData(key)); + updatedFields.setFlag(QBluetoothDeviceInfo::Field::ManufacturerData); + } + + if (discoveredDevices[i].serviceData() != newDeviceInfo.serviceData()) { + qCDebug(QT_BT_DARWIN) << "Updating service data for" << newDeviceInfo.address(); + const QList keys = newDeviceInfo.serviceIds(); + for (auto key : keys) + discoveredDevices[i].setServiceData(key, newDeviceInfo.serviceData(key)); + updatedFields.setFlag(QBluetoothDeviceInfo::Field::ServiceData); + } + + if (lowEnergySearchTimeout > 0) { + if (discoveredDevices[i] != newDeviceInfo) { + discoveredDevices.replace(i, newDeviceInfo); + emit q_ptr->deviceDiscovered(newDeviceInfo); + } else { + if (!updatedFields.testFlag(QBluetoothDeviceInfo::Field::None)) + emit q_ptr->deviceUpdated(discoveredDevices[i], updatedFields); + } + + return; + } + + discoveredDevices.replace(i, newDeviceInfo); + emit q_ptr->deviceDiscovered(newDeviceInfo); + + if (!updatedFields.testFlag(QBluetoothDeviceInfo::Field::None)) + emit q_ptr->deviceUpdated(discoveredDevices[i], updatedFields); + + return; + } + } else { +#ifdef Q_OS_MACOS + if (discoveredDevices[i].address() == newDeviceInfo.address()) { + if (discoveredDevices[i] == newDeviceInfo) + return; + + discoveredDevices.replace(i, newDeviceInfo); + emit q_ptr->deviceDiscovered(newDeviceInfo); + return; + } +#else + Q_UNREACHABLE(); +#endif // Q_OS_MACOS + } + } + + discoveredDevices.append(newDeviceInfo); + emit q_ptr->deviceDiscovered(newDeviceInfo); +} + +QBluetoothDeviceDiscoveryAgent::DiscoveryMethods QBluetoothDeviceDiscoveryAgent::supportedDiscoveryMethods() +{ +#ifdef Q_OS_MACOS + return ClassicMethod | LowEnergyMethod; +#else + return LowEnergyMethod; +#endif // Q_OS_MACOS +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_p.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_p.cpp new file mode 100644 index 0000000..ddb9e4c --- /dev/null +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_p.cpp @@ -0,0 +1,56 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothdevicediscoveryagent.h" +#include "qbluetoothdevicediscoveryagent_p.h" +#include "qbluetoothaddress.h" +#include "qbluetoothuuid.h" + +#include "dummy/dummy_helper_p.h" + +#define QT_DEVICEDISCOVERY_DEBUG + +QT_BEGIN_NAMESPACE + +QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate( + const QBluetoothAddress &deviceAdapter, + QBluetoothDeviceDiscoveryAgent *parent) + : lowEnergySearchTimeout(-1), + q_ptr(parent) +{ + Q_UNUSED(deviceAdapter); + printDummyWarning(); +} + +QBluetoothDeviceDiscoveryAgentPrivate::~QBluetoothDeviceDiscoveryAgentPrivate() +{ +} + +bool QBluetoothDeviceDiscoveryAgentPrivate::isActive() const +{ + return false; +} + +QBluetoothDeviceDiscoveryAgent::DiscoveryMethods QBluetoothDeviceDiscoveryAgent::supportedDiscoveryMethods() +{ + return QBluetoothDeviceDiscoveryAgent::NoMethod; +} + +void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods) +{ + Q_Q(QBluetoothDeviceDiscoveryAgent); + lastError = QBluetoothDeviceDiscoveryAgent::UnsupportedPlatformError; + errorString = QBluetoothDeviceDiscoveryAgent::tr("Device discovery not supported on this platform"); + + emit q->errorOccurred(lastError); +} + +void QBluetoothDeviceDiscoveryAgentPrivate::stop() +{ +} + + + +QT_END_NAMESPACE + +#include "moc_qbluetoothdevicediscoveryagent_p.cpp" diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_p.h b/src/bluetooth/qbluetoothdevicediscoveryagent_p.h new file mode 100644 index 0000000..3e5f2a0 --- /dev/null +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_p.h @@ -0,0 +1,212 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2014 Denis Shienkov +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QBLUETOOTHDEVICEDISCOVERYAGENT_P_H +#define QBLUETOOTHDEVICEDISCOVERYAGENT_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 "qbluetoothdevicediscoveryagent.h" +#ifdef QT_ANDROID_BLUETOOTH +#include +#include "android/devicediscoverybroadcastreceiver_p.h" +#include +#endif + +#ifdef Q_OS_DARWIN +#include "darwin/btdelegates_p.h" +#include "darwin/btraii_p.h" +#endif // Q_OS_DARWIN + +#include + +#include +#include + +#if QT_CONFIG(bluez) +#include "bluez/bluez5_helper_p.h" + +class OrgBluezManagerInterface; +class OrgBluezAdapterInterface; +class OrgFreedesktopDBusObjectManagerInterface; +class OrgFreedesktopDBusPropertiesInterface; +class OrgBluezAdapter1Interface; +class OrgBluezDevice1Interface; + +QT_BEGIN_NAMESPACE +class QDBusVariant; +QT_END_NAMESPACE +#endif + +#ifdef QT_WINRT_BLUETOOTH +#include +#include + +using ManufacturerData = QHash; +using ServiceData = QHash; +QT_DECL_METATYPE_EXTERN(ManufacturerData, Q_BLUETOOTH_EXPORT) +QT_DECL_METATYPE_EXTERN(ServiceData, Q_BLUETOOTH_EXPORT) +#endif + +QT_BEGIN_NAMESPACE + +#ifdef QT_WINRT_BLUETOOTH +class QWinRTBluetoothDeviceDiscoveryWorker; +#endif + +class QBluetoothDeviceDiscoveryAgentPrivate +#if defined(QT_ANDROID_BLUETOOTH) || defined(QT_WINRT_BLUETOOTH) \ + || defined(Q_OS_DARWIN) + : public QObject +#if defined(Q_OS_MACOS) + , public DarwinBluetooth::DeviceInquiryDelegate +#endif // Q_OS_MACOS +{ + Q_OBJECT +#else // BlueZ +{ +#endif + Q_DECLARE_PUBLIC(QBluetoothDeviceDiscoveryAgent) +public: + QBluetoothDeviceDiscoveryAgentPrivate( + const QBluetoothAddress &deviceAdapter, + QBluetoothDeviceDiscoveryAgent *parent); + ~QBluetoothDeviceDiscoveryAgentPrivate(); + + void start(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods); + void stop(); + bool isActive() const; + +#if QT_CONFIG(bluez) + void _q_InterfacesAdded(const QDBusObjectPath &object_path, + InterfaceList interfaces_and_properties); + void _q_discoveryFinished(); + void _q_discoveryInterrupted(const QString &path); + void _q_PropertiesChanged(const QString &interface, + const QString &path, + const QVariantMap &changed_properties, + const QStringList &invalidated_properties); +#endif + +private: + QList discoveredDevices; + + QBluetoothDeviceDiscoveryAgent::Error lastError = QBluetoothDeviceDiscoveryAgent::NoError; + QString errorString; + QBluetoothAddress adapterAddress; + +#ifdef QT_ANDROID_BLUETOOTH +private slots: + void processSdpDiscoveryFinished(); + void processDiscoveredDevices(const QBluetoothDeviceInfo &info, bool isLeResult); + friend void QtBluetoothLE_leScanResult(JNIEnv *, jobject, jlong, jobject); + void stopLowEnergyScan(); + +private: + void startLowEnergyScan(); + void classicDiscoveryStartFail(); + bool setErrorIfPowerOff(); + + DeviceDiscoveryBroadcastReceiver *receiver = nullptr; + short m_active; + QJniObject adapter; + QJniObject leScanner; + QTimer *leScanTimeout = nullptr; + QTimer *deviceDiscoveryStartTimeout = nullptr; + short deviceDiscoveryStartAttemptsLeft; + + bool pendingCancel = false; + bool pendingStart = false; +#elif QT_CONFIG(bluez) + bool pendingCancel = false; + bool pendingStart = false; + OrgFreedesktopDBusObjectManagerInterface *manager = nullptr; + OrgBluezAdapter1Interface *adapter = nullptr; + QTimer *discoveryTimer = nullptr; + QList propertyMonitors; + + void deviceFound(const QString &devicePath, const QVariantMap &properties); + + QMap devicesProperties; +#endif + +#ifdef QT_WINRT_BLUETOOTH +private slots: + void registerDevice(const QBluetoothDeviceInfo &info); + void updateDeviceData(const QBluetoothAddress &address, QBluetoothDeviceInfo::Fields fields, + qint16 rssi, ManufacturerData manufacturerData, ServiceData serviceData); + void onErrorOccured(QBluetoothDeviceDiscoveryAgent::Error e); + void onScanFinished(); + +private: + void disconnectAndClearWorker(); + std::shared_ptr worker = nullptr; +#endif + +#ifdef Q_OS_DARWIN + + void startLE(); + +#ifdef Q_OS_MACOS + + void startClassic(); + + // Classic (IOBluetooth) inquiry delegate's methods: + void inquiryFinished() override; + void error(IOReturn error) override; + void classicDeviceFound(void *device) override; + // Classic (IOBluetooth) errors: + void setError(IOReturn error, const QString &text = QString()); + +#endif // Q_OS_MACOS + + // LE scan delegates (CoreBluetooth, all Darwin OSes): + void LEinquiryFinished(); + void LEinquiryError(QBluetoothDeviceDiscoveryAgent::Error error); + void LEnotSupported(); + + // LE errors: + void setError(QBluetoothDeviceDiscoveryAgent::Error, + const QString &text = QString()); + + // Both LE and Classic devices go there: + void deviceFound(const QBluetoothDeviceInfo &newDeviceInfo); + + enum AgentState { + NonActive, + ClassicScan, // macOS (IOBluetooth) only + LEScan + } agentState; + + bool startPending = false; + bool stopPending = false; + +#ifdef Q_OS_MACOS + + DarwinBluetooth::ScopedPointer controller; + DarwinBluetooth::ScopedPointer inquiry; + +#endif // Q_OS_MACOS + + DarwinBluetooth::ScopedPointer inquiryLE; + +#endif // Q_OS_DARWIN + + int lowEnergySearchTimeout = 40000; + QBluetoothDeviceDiscoveryAgent::DiscoveryMethods requestedMethods; + QBluetoothDeviceDiscoveryAgent *q_ptr; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp new file mode 100644 index 0000000..b56ff7e --- /dev/null +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp @@ -0,0 +1,873 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothdevicediscoveryagent.h" +#include "qbluetoothdevicediscoveryagent_p.h" +#include "qbluetoothaddress.h" +#include "qbluetoothuuid.h" + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace winrt::Windows::Devices::Bluetooth; +using namespace winrt::Windows::Devices::Bluetooth::Advertisement; +using namespace winrt::Windows::Devices::Bluetooth::GenericAttributeProfile; +using namespace winrt::Windows::Devices::Bluetooth::Rfcomm; +using namespace winrt::Windows::Devices::Enumeration; +using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::Storage::Streams; + +QT_BEGIN_NAMESPACE + +QT_IMPL_METATYPE_EXTERN(ManufacturerData) +QT_IMPL_METATYPE_EXTERN(ServiceData) + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINDOWS) + +static QByteArray byteArrayFromBuffer(const IBuffer &buffer) +{ + const uint8_t *data = buffer.data(); + return QByteArray(reinterpret_cast(data), + static_cast(buffer.Length())); +} + +static ManufacturerData extractManufacturerData(const BluetoothLEAdvertisement &ad) +{ + ManufacturerData ret; + const auto data = ad.ManufacturerData(); + for (const auto &item : data) { + const uint16_t id = item.CompanyId(); + const QByteArray bufferData = byteArrayFromBuffer(item.Data()); + if (ret.contains(id)) + qCWarning(QT_BT_WINDOWS) << "Company ID already present in manufacturer data."; + ret.insert(id, bufferData); + } + return ret; +} + +static ServiceData extractServiceData(const BluetoothLEAdvertisement &ad) +{ + static constexpr int serviceDataTypes[3] = { 0x16, 0x20, 0x21 }; + + ServiceData ret; + + for (const auto &serviceDataType : serviceDataTypes) { + const auto dataSections = ad.GetSectionsByType(serviceDataType); + for (const auto §ion : dataSections) { + const unsigned char dataType = section.DataType(); + const QByteArray bufferData = byteArrayFromBuffer(section.Data()); + if (dataType == 0x16) { + Q_ASSERT(bufferData.size() >= 2); + ret.insert(QBluetoothUuid(qFromLittleEndian(bufferData.constData())), + bufferData + 2); + } else if (dataType == 0x20) { + Q_ASSERT(bufferData.size() >= 4); + ret.insert(QBluetoothUuid(qFromLittleEndian(bufferData.constData())), + bufferData + 4); + } else if (dataType == 0x21) { + Q_ASSERT(bufferData.size() >= 16); + ret.insert(QBluetoothUuid(qToBigEndian( + qFromLittleEndian(bufferData.constData()))), + bufferData + 16); + } + } + } + + return ret; +} + +// Needed because there is no explicit conversion +static GUID fromWinRtGuid(const winrt::guid &guid) +{ + const GUID uuid { + guid.Data1, + guid.Data2, + guid.Data3, + { guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], + guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7] } + }; + return uuid; +} + +class AdvertisementWatcherWrapper : public QObject, + public std::enable_shared_from_this +{ + Q_OBJECT +public: + AdvertisementWatcherWrapper() {} + ~AdvertisementWatcherWrapper() + { + stop(); + } + void init() + { + m_watcher.AllowExtendedAdvertisements(true); + m_watcher.ScanningMode(BluetoothLEScanningMode::Active); + } + void start() { + subscribeToEvents(); + m_watcher.Start(); + } + void stop() + { + if (canStop()) { + unsubscribeFromEvents(); + m_watcher.Stop(); + } + } + +signals: + // The signal will be emitted from a separate thread, + // so we need to use Qt::QueuedConnection + void advertisementDataReceived(quint64 address, qint16 rssi, + const ManufacturerData &manufacturerData, + const ServiceData &serviceData, + const QList &uuids); +private: + void subscribeToEvents() + { + // The callbacks are triggered from separate threads. So we capture + // thisPtr to make sure that the object is valid. + auto thisPtr = shared_from_this(); + m_receivedToken = m_watcher.Received( + [thisPtr](BluetoothLEAdvertisementWatcher, + BluetoothLEAdvertisementReceivedEventArgs args) { + const uint64_t address = args.BluetoothAddress(); + const short rssi = args.RawSignalStrengthInDBm(); + const BluetoothLEAdvertisement ad = args.Advertisement(); + + const ManufacturerData manufacturerData = extractManufacturerData(ad); + const ServiceData serviceData = extractServiceData(ad); + + QList serviceUuids; + const auto guids = ad.ServiceUuids(); + for (const auto &guid : guids) { + const GUID uuid = fromWinRtGuid(guid); + serviceUuids.append(QBluetoothUuid(uuid)); + } + + emit thisPtr->advertisementDataReceived(address, rssi, manufacturerData, + serviceData, serviceUuids); + }); + } + void unsubscribeFromEvents() + { + m_watcher.Received(m_receivedToken); + } + bool canStop() const + { + const auto status = m_watcher.Status(); + return status == BluetoothLEAdvertisementWatcherStatus::Started + || status == BluetoothLEAdvertisementWatcherStatus::Aborted; + } + + BluetoothLEAdvertisementWatcher m_watcher; + winrt::event_token m_receivedToken; +}; + +// Both constants are taken from Microsoft's docs: +// https://docs.microsoft.com/en-us/windows/uwp/devices-sensors/aep-service-class-ids +// Alternatively we could create separate watchers for paired and unpaired devices. +static const winrt::hstring ClassicDeviceSelector = + L"System.Devices.Aep.ProtocolId:=\"{e0cbf06c-cd8b-4647-bb8a-263b43f0f974}\""; +// Do not use it for now, so comment out. Do not delete in case we want to reuse it. +//static const winrt::hstring LowEnergyDeviceSelector = +// L"System.Devices.Aep.ProtocolId:=\"{bb7bb05e-5972-42b5-94fc-76eaa7084d49}\""; + +class QWinRTBluetoothDeviceDiscoveryWorker : public QObject, + public std::enable_shared_from_this +{ + Q_OBJECT +public: + QWinRTBluetoothDeviceDiscoveryWorker(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods, + int interval); + ~QWinRTBluetoothDeviceDiscoveryWorker(); + void start(); + void stop(); + +private: + void startDeviceDiscovery(QBluetoothDeviceDiscoveryAgent::DiscoveryMethod mode); + + std::shared_ptr createDeviceWatcher(winrt::hstring selector, + int watcherId); + void generateError(QBluetoothDeviceDiscoveryAgent::Error error, const char *msg = nullptr); + void invokeDeviceFoundWithDebug(const QBluetoothDeviceInfo &info); + void finishDiscovery(); + bool isFinished() const; + + // Bluetooth Classic handlers + void getClassicDeviceFromId(const winrt::hstring &id); + void handleClassicDevice(const BluetoothDevice &device); + void handleRfcommServices(const RfcommDeviceServicesResult &servicesResult, + uint64_t address, const QString &name, uint32_t classOfDeviceInt); + + // Bluetooth Low Energy handlers + void getLowEnergyDeviceFromId(const winrt::hstring &id); + void handleLowEnergyDevice(const BluetoothLEDevice &device); + void handleGattServices(const GattDeviceServicesResult &servicesResult, + QBluetoothDeviceInfo &info); + + // Bluetooth Low Energy Advertising handlers + std::shared_ptr createAdvertisementWatcher(); + + // invokable methods for handling finish conditions + Q_INVOKABLE void decrementPendingDevicesCountAndCheckFinished( + std::shared_ptr worker); + +Q_SIGNALS: + void deviceFound(const QBluetoothDeviceInfo &info); + void deviceDataChanged(const QBluetoothAddress &address, QBluetoothDeviceInfo::Fields, + qint16 rssi, ManufacturerData manufacturerData, ServiceData serviceData); + void errorOccured(QBluetoothDeviceDiscoveryAgent::Error error); + void scanFinished(); + +private slots: + void onBluetoothDeviceFound(winrt::hstring deviceId, int watcherId); + void onDeviceEnumerationCompleted(int watcherId); + + void onAdvertisementDataReceived(quint64 address, qint16 rssi, + const ManufacturerData &manufacturerData, + const ServiceData &serviceData, + const QList &uuids); + + void stopAdvertisementWatcher(); + +private: + struct LEAdvertisingInfo { + QList services; + ManufacturerData manufacturerData; + ServiceData serviceData; + qint16 rssi = 0; + }; + + quint8 requestedModes = 0; + QMutex m_leDevicesMutex; + QMap m_foundLEDevicesMap; + int m_pendingDevices = 0; + + static constexpr int ClassicWatcherId = 1; + static constexpr int LowEnergyWatcherId = 2; + + std::shared_ptr m_classicWatcher; + std::shared_ptr m_lowEnergyWatcher; + std::shared_ptr m_advertisementWatcher; + bool m_classicScanStarted = false; + bool m_lowEnergyScanStarted = false; + QTimer *m_leScanTimer = nullptr; +}; + +static void invokeDecrementPendingDevicesCountAndCheckFinished( + std::shared_ptr worker) +{ + QMetaObject::invokeMethod(worker.get(), "decrementPendingDevicesCountAndCheckFinished", + Qt::QueuedConnection, + Q_ARG(std::shared_ptr, + worker)); +} + +QWinRTBluetoothDeviceDiscoveryWorker::QWinRTBluetoothDeviceDiscoveryWorker( + QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods, int interval) + : requestedModes(methods) +{ + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType>(); + + m_classicWatcher = createDeviceWatcher(ClassicDeviceSelector, ClassicWatcherId); + // For LE scan use DeviceWatcher to handle only paired devices. + // Non-paired devices will be found using BluetoothLEAdvertisementWatcher. + const auto leSelector = BluetoothLEDevice::GetDeviceSelectorFromPairingState(true); + m_lowEnergyWatcher = createDeviceWatcher(leSelector, LowEnergyWatcherId); + m_advertisementWatcher = createAdvertisementWatcher(); + + // Docs claim that a negative interval means that the backend handles it on its own + if (interval < 0) + interval = 40000; + + if (interval != 0) { + m_leScanTimer = new QTimer(this); + m_leScanTimer->setSingleShot(true); + m_leScanTimer->setInterval(interval); + connect(m_leScanTimer, &QTimer::timeout, this, + &QWinRTBluetoothDeviceDiscoveryWorker::stopAdvertisementWatcher); + } +} + +QWinRTBluetoothDeviceDiscoveryWorker::~QWinRTBluetoothDeviceDiscoveryWorker() +{ + stop(); +} + +void QWinRTBluetoothDeviceDiscoveryWorker::start() +{ + if (requestedModes & QBluetoothDeviceDiscoveryAgent::ClassicMethod) { + if (m_classicWatcher && m_classicWatcher->init()) { + m_classicWatcher->start(); + m_classicScanStarted = true; + } else { + generateError(QBluetoothDeviceDiscoveryAgent::Error::UnknownError, + "Could not start classic device watcher"); + } + } + if (requestedModes & QBluetoothDeviceDiscoveryAgent::LowEnergyMethod) { + if (m_lowEnergyWatcher && m_lowEnergyWatcher->init()) { + m_lowEnergyWatcher->start(); + m_lowEnergyScanStarted = true; + } else { + generateError(QBluetoothDeviceDiscoveryAgent::Error::UnknownError, + "Could not start low energy device watcher"); + } + if (m_advertisementWatcher) { + m_advertisementWatcher->init(); + m_advertisementWatcher->start(); + if (m_leScanTimer) + m_leScanTimer->start(); + } else { + generateError(QBluetoothDeviceDiscoveryAgent::Error::UnknownError, + "Could not start low energy advertisement watcher"); + } + } + + qCDebug(QT_BT_WINDOWS) << "Worker started"; +} + +void QWinRTBluetoothDeviceDiscoveryWorker::stop() +{ + if (m_leScanTimer && m_leScanTimer->isActive()) + m_leScanTimer->stop(); + m_classicWatcher->stop(); + m_lowEnergyWatcher->stop(); + m_advertisementWatcher->stop(); +} + +void QWinRTBluetoothDeviceDiscoveryWorker::finishDiscovery() +{ + stop(); + emit scanFinished(); +} + +bool QWinRTBluetoothDeviceDiscoveryWorker::isFinished() const +{ + // If the interval is set to 0, we do not start a timer, and that means + // that we need to wait for the user to explicitly call stop() + return (m_pendingDevices == 0) && !m_lowEnergyScanStarted && !m_classicScanStarted + && (m_leScanTimer && !m_leScanTimer->isActive()); +} + +void QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothDeviceFound(winrt::hstring deviceId, int watcherId) +{ + if (watcherId == ClassicWatcherId) + getClassicDeviceFromId(deviceId); + else if (watcherId == LowEnergyWatcherId) + getLowEnergyDeviceFromId(deviceId); +} + +void QWinRTBluetoothDeviceDiscoveryWorker::onDeviceEnumerationCompleted(int watcherId) +{ + qCDebug(QT_BT_WINDOWS) << (watcherId == ClassicWatcherId ? "BT" : "BTLE") + << "enumeration completed"; + if (watcherId == ClassicWatcherId) { + m_classicWatcher->stop(); + m_classicScanStarted = false; + } else if (watcherId == LowEnergyWatcherId) { + m_lowEnergyWatcher->stop(); + m_lowEnergyScanStarted = false; + } + if (isFinished()) + finishDiscovery(); +} + +// this function executes in main worker thread +void QWinRTBluetoothDeviceDiscoveryWorker::onAdvertisementDataReceived( + quint64 address, qint16 rssi, const ManufacturerData &manufacturerData, + const ServiceData &serviceData, const QList &uuids) +{ + // Merge newly found services with list of currently found ones + bool needDiscoverServices = false; + { + QMutexLocker locker(&m_leDevicesMutex); + if (m_foundLEDevicesMap.contains(address)) { + QBluetoothDeviceInfo::Fields changedFields = QBluetoothDeviceInfo::Field::None; + const LEAdvertisingInfo adInfo = m_foundLEDevicesMap.value(address); + QList foundServices = adInfo.services; + if (adInfo.rssi != rssi) { + m_foundLEDevicesMap[address].rssi = rssi; + changedFields.setFlag(QBluetoothDeviceInfo::Field::RSSI); + } + if (adInfo.manufacturerData != manufacturerData) { + m_foundLEDevicesMap[address].manufacturerData.insert(manufacturerData); + if (adInfo.manufacturerData != m_foundLEDevicesMap[address].manufacturerData) + changedFields.setFlag(QBluetoothDeviceInfo::Field::ManufacturerData); + } + if (adInfo.serviceData != serviceData) { + m_foundLEDevicesMap[address].serviceData.insert(serviceData); + if (adInfo.serviceData != m_foundLEDevicesMap[address].serviceData) + changedFields.setFlag((QBluetoothDeviceInfo::Field::ServiceData)); + } + for (const QBluetoothUuid &uuid : std::as_const(uuids)) { + if (!foundServices.contains(uuid)) { + foundServices.append(uuid); + needDiscoverServices = true; + } + } + if (!needDiscoverServices) { + if (!changedFields.testFlag(QBluetoothDeviceInfo::Field::None)) { + QMetaObject::invokeMethod(this, "deviceDataChanged", Qt::AutoConnection, + Q_ARG(QBluetoothAddress, QBluetoothAddress(address)), + Q_ARG(QBluetoothDeviceInfo::Fields, changedFields), + Q_ARG(qint16, rssi), + Q_ARG(ManufacturerData, manufacturerData), + Q_ARG(ServiceData, serviceData)); + } + } + m_foundLEDevicesMap[address].services = foundServices; + } else { + needDiscoverServices = true; + LEAdvertisingInfo info; + info.services = std::move(uuids); + info.manufacturerData = std::move(manufacturerData); + info.serviceData = std::move(serviceData); + info.rssi = rssi; + m_foundLEDevicesMap.insert(address, info); + } + } + if (needDiscoverServices) { + ++m_pendingDevices; // as if we discovered a new LE device + auto thisPtr = shared_from_this(); + auto asyncOp = BluetoothLEDevice::FromBluetoothAddressAsync(address); + asyncOp.Completed([thisPtr, address](auto &&op, AsyncStatus status) { + if (thisPtr) { + if (status == AsyncStatus::Completed) { + BluetoothLEDevice device = op.GetResults(); + if (device) { + thisPtr->handleLowEnergyDevice(device); + return; + } + } + // status != Completed or failed to extract result + qCDebug(QT_BT_WINDOWS) << "Failed to get LE device from address" + << QBluetoothAddress(address); + invokeDecrementPendingDevicesCountAndCheckFinished(thisPtr); + } + }); + } +} + +void QWinRTBluetoothDeviceDiscoveryWorker::stopAdvertisementWatcher() +{ + m_advertisementWatcher->stop(); + if (isFinished()) + finishDiscovery(); +} + +std::shared_ptr +QWinRTBluetoothDeviceDiscoveryWorker::createDeviceWatcher(winrt::hstring selector, int watcherId) +{ + auto watcher = std::make_shared( + watcherId, selector, DeviceInformationKind::AssociationEndpoint); + if (watcher) { + connect(watcher.get(), &QBluetoothDeviceWatcherWinRT::deviceAdded, + this, &QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothDeviceFound, + Qt::QueuedConnection); + connect(watcher.get(), &QBluetoothDeviceWatcherWinRT::enumerationCompleted, + this, &QWinRTBluetoothDeviceDiscoveryWorker::onDeviceEnumerationCompleted, + Qt::QueuedConnection); + } + return watcher; +} + +void QWinRTBluetoothDeviceDiscoveryWorker::generateError( + QBluetoothDeviceDiscoveryAgent::Error error, const char *msg) +{ + emit errorOccured(error); + qCWarning(QT_BT_WINDOWS) << msg; +} + +void QWinRTBluetoothDeviceDiscoveryWorker::invokeDeviceFoundWithDebug(const QBluetoothDeviceInfo &info) +{ + qCDebug(QT_BT_WINDOWS) << "Discovered BTLE device: " << info.address() << info.name() + << "Num UUIDs" << info.serviceUuids().size() << "RSSI:" << info.rssi() + << "Num manufacturer data" << info.manufacturerData().size() + << "Num service data" << info.serviceData().size(); + + QMetaObject::invokeMethod(this, "deviceFound", Qt::AutoConnection, + Q_ARG(QBluetoothDeviceInfo, info)); +} + +// this function executes in main worker thread +void QWinRTBluetoothDeviceDiscoveryWorker::getClassicDeviceFromId(const winrt::hstring &id) +{ + ++m_pendingDevices; + auto thisPtr = shared_from_this(); + auto asyncOp = BluetoothDevice::FromIdAsync(id); + asyncOp.Completed([thisPtr](auto &&op, AsyncStatus status) { + if (thisPtr) { + if (status == AsyncStatus::Completed) { + BluetoothDevice device = op.GetResults(); + if (device) { + thisPtr->handleClassicDevice(device); + return; + } + } + // status != Completed or failed to extract result + qCDebug(QT_BT_WINDOWS) << "Failed to get Classic device from id"; + invokeDecrementPendingDevicesCountAndCheckFinished(thisPtr); + } + }); +} + +// this is a callback - executes in a new thread +void QWinRTBluetoothDeviceDiscoveryWorker::handleClassicDevice(const BluetoothDevice &device) +{ + const uint64_t address = device.BluetoothAddress(); + const std::wstring name { device.Name() }; // via operator std::wstring_view() + const QString btName = QString::fromStdWString(name); + const uint32_t deviceClass = device.ClassOfDevice().RawValue(); + auto thisPtr = shared_from_this(); + auto asyncOp = device.GetRfcommServicesAsync(); + asyncOp.Completed([thisPtr, address, btName, deviceClass](auto &&op, AsyncStatus status) { + if (thisPtr) { + if (status == AsyncStatus::Completed) { + auto servicesResult = op.GetResults(); + if (servicesResult) { + thisPtr->handleRfcommServices(servicesResult, address, btName, deviceClass); + return; + } + } + // Failed to get services + qCDebug(QT_BT_WINDOWS) << "Failed to get RFCOMM services for device" << btName; + invokeDecrementPendingDevicesCountAndCheckFinished(thisPtr); + } + }); +} + +// this is a callback - executes in a new thread +void QWinRTBluetoothDeviceDiscoveryWorker::handleRfcommServices( + const RfcommDeviceServicesResult &servicesResult, uint64_t address, + const QString &name, uint32_t classOfDeviceInt) +{ + // need to perform the check even if some of the operations fails + auto shared = shared_from_this(); + auto guard = qScopeGuard([shared]() { + invokeDecrementPendingDevicesCountAndCheckFinished(shared); + }); + Q_UNUSED(guard); // to suppress warning + + const auto error = servicesResult.Error(); + if (error != BluetoothError::Success) { + qCWarning(QT_BT_WINDOWS) << "Obtain device services completed with BluetoothError" + << static_cast(error); + return; + } + + const auto services = servicesResult.Services(); + QList uuids; + for (const auto &service : services) { + const auto serviceId = service.ServiceId(); + const GUID uuid = fromWinRtGuid(serviceId.Uuid()); + uuids.append(QBluetoothUuid(uuid)); + } + + const QBluetoothAddress btAddress(address); + + qCDebug(QT_BT_WINDOWS) << "Discovered BT device: " << btAddress << name + << "Num UUIDs" << uuids.size(); + + QBluetoothDeviceInfo info(btAddress, name, classOfDeviceInt); + info.setCoreConfigurations(QBluetoothDeviceInfo::BaseRateCoreConfiguration); + info.setServiceUuids(uuids); + info.setCached(true); + + QMetaObject::invokeMethod(this, "deviceFound", Qt::AutoConnection, + Q_ARG(QBluetoothDeviceInfo, info)); +} + +void QWinRTBluetoothDeviceDiscoveryWorker::decrementPendingDevicesCountAndCheckFinished( + std::shared_ptr worker) +{ + --m_pendingDevices; + if (isFinished()) + finishDiscovery(); + // Worker is passed here simply to make sure that the object is still alive + // when we call this method via QObject::invoke(). + Q_UNUSED(worker) +} + +// this function executes in main worker thread +void QWinRTBluetoothDeviceDiscoveryWorker::getLowEnergyDeviceFromId(const winrt::hstring &id) +{ + ++m_pendingDevices; + auto asyncOp = BluetoothLEDevice::FromIdAsync(id); + auto thisPtr = shared_from_this(); + asyncOp.Completed([thisPtr](auto &&op, AsyncStatus status) { + if (thisPtr) { + if (status == AsyncStatus::Completed) { + BluetoothLEDevice device = op.GetResults(); + if (device) { + thisPtr->handleLowEnergyDevice(device); + return; + } + } + // status != Completed or failed to extract result + qCDebug(QT_BT_WINDOWS) << "Failed to get LE device from id"; + invokeDecrementPendingDevicesCountAndCheckFinished(thisPtr); + } + }); +} + +// this is a callback - executes in a new thread +void QWinRTBluetoothDeviceDiscoveryWorker::handleLowEnergyDevice(const BluetoothLEDevice &device) +{ + const uint64_t address = device.BluetoothAddress(); + const std::wstring name { device.Name() }; // via operator std::wstring_view() + const QString btName = QString::fromStdWString(name); + const bool isPaired = device.DeviceInformation().Pairing().IsPaired(); + + m_leDevicesMutex.lock(); + const LEAdvertisingInfo adInfo = m_foundLEDevicesMap.value(address); + m_leDevicesMutex.unlock(); + const ManufacturerData manufacturerData = adInfo.manufacturerData; + const ServiceData serviceData = adInfo.serviceData; + const qint16 rssi = adInfo.rssi; + + QBluetoothDeviceInfo info(QBluetoothAddress(address), btName, 0); + info.setCoreConfigurations(QBluetoothDeviceInfo::LowEnergyCoreConfiguration); + info.setRssi(rssi); + for (quint16 key : manufacturerData.keys()) + info.setManufacturerData(key, manufacturerData.value(key)); + for (QBluetoothUuid key : serviceData.keys()) + info.setServiceData(key, serviceData.value(key)); + info.setCached(true); + + // Use the services obtained from the advertisement data if the device is not paired + if (!isPaired) { + info.setServiceUuids(adInfo.services); + invokeDecrementPendingDevicesCountAndCheckFinished(shared_from_this()); + invokeDeviceFoundWithDebug(info); + } else { + auto asyncOp = device.GetGattServicesAsync(); + auto thisPtr = shared_from_this(); + asyncOp.Completed([thisPtr, info](auto &&op, AsyncStatus status) mutable { + if (status == AsyncStatus::Completed) { + auto servicesResult = op.GetResults(); + if (servicesResult) { + thisPtr->handleGattServices(servicesResult, info); + return; + } + } + // Failed to get services + qCDebug(QT_BT_WINDOWS) << "Failed to get GATT services for device" << info.name(); + invokeDecrementPendingDevicesCountAndCheckFinished(thisPtr); + }); + } +} + +// this is a callback - executes in a new thread +void QWinRTBluetoothDeviceDiscoveryWorker::handleGattServices( + const GattDeviceServicesResult &servicesResult, QBluetoothDeviceInfo &info) +{ + // need to perform the check even if some of the operations fails + auto shared = shared_from_this(); + auto guard = qScopeGuard([shared]() { + invokeDecrementPendingDevicesCountAndCheckFinished(shared); + }); + Q_UNUSED(guard); // to suppress warning + + const auto status = servicesResult.Status(); + if (status == GattCommunicationStatus::Success) { + const auto services = servicesResult.Services(); + QList uuids; + for (const auto &service : services) { + const GUID uuid = fromWinRtGuid(service.Uuid()); + uuids.append(QBluetoothUuid(uuid)); + } + info.setServiceUuids(uuids); + } else { + qCWarning(QT_BT_WINDOWS) << "Obtaining LE services finished with status" + << static_cast(status); + } + invokeDeviceFoundWithDebug(info); +} + +std::shared_ptr +QWinRTBluetoothDeviceDiscoveryWorker::createAdvertisementWatcher() +{ + auto watcher = std::make_shared(); + if (watcher) { + connect(watcher.get(), &AdvertisementWatcherWrapper::advertisementDataReceived, + this, &QWinRTBluetoothDeviceDiscoveryWorker::onAdvertisementDataReceived, + Qt::QueuedConnection); + } + return watcher; +} + +QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate( + const QBluetoothAddress &deviceAdapter, QBluetoothDeviceDiscoveryAgent *parent) + : q_ptr(parent), adapterAddress(deviceAdapter) +{ + mainThreadCoInit(this); +} + +QBluetoothDeviceDiscoveryAgentPrivate::~QBluetoothDeviceDiscoveryAgentPrivate() +{ + disconnectAndClearWorker(); + mainThreadCoUninit(this); +} + +bool QBluetoothDeviceDiscoveryAgentPrivate::isActive() const +{ + return worker != nullptr; +} + +QBluetoothDeviceDiscoveryAgent::DiscoveryMethods QBluetoothDeviceDiscoveryAgent::supportedDiscoveryMethods() +{ + return (ClassicMethod | LowEnergyMethod); +} + +void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods) +{ + QBluetoothLocalDevice adapter(adapterAddress); + if (!adapter.isValid()) { + qCWarning(QT_BT_WINDOWS) << "Cannot find Bluetooth adapter for device search"; + lastError = QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError; + errorString = QBluetoothDeviceDiscoveryAgent::tr("Cannot find valid Bluetooth adapter."); + emit q_ptr->errorOccurred(lastError); + return; + } else if (adapter.hostMode() == QBluetoothLocalDevice::HostPoweredOff) { + qCWarning(QT_BT_WINDOWS) << "Bluetooth adapter powered off"; + lastError = QBluetoothDeviceDiscoveryAgent::PoweredOffError; + errorString = QBluetoothDeviceDiscoveryAgent::tr("Bluetooth adapter powered off."); + emit q_ptr->errorOccurred(lastError); + return; + } + + if (worker) + return; + + worker = std::make_shared(methods, + lowEnergySearchTimeout); + lastError = QBluetoothDeviceDiscoveryAgent::NoError; + errorString.clear(); + discoveredDevices.clear(); + connect(worker.get(), &QWinRTBluetoothDeviceDiscoveryWorker::deviceFound, + this, &QBluetoothDeviceDiscoveryAgentPrivate::registerDevice); + connect(worker.get(), &QWinRTBluetoothDeviceDiscoveryWorker::deviceDataChanged, + this, &QBluetoothDeviceDiscoveryAgentPrivate::updateDeviceData); + connect(worker.get(), &QWinRTBluetoothDeviceDiscoveryWorker::errorOccured, + this, &QBluetoothDeviceDiscoveryAgentPrivate::onErrorOccured); + connect(worker.get(), &QWinRTBluetoothDeviceDiscoveryWorker::scanFinished, + this, &QBluetoothDeviceDiscoveryAgentPrivate::onScanFinished); + worker->start(); +} + +void QBluetoothDeviceDiscoveryAgentPrivate::stop() +{ + Q_Q(QBluetoothDeviceDiscoveryAgent); + if (worker) { + worker->stop(); + disconnectAndClearWorker(); + emit q->canceled(); + } +} + +void QBluetoothDeviceDiscoveryAgentPrivate::registerDevice(const QBluetoothDeviceInfo &info) +{ + Q_Q(QBluetoothDeviceDiscoveryAgent); + + for (QList::iterator iter = discoveredDevices.begin(); + iter != discoveredDevices.end(); ++iter) { + if (iter->address() == info.address()) { + qCDebug(QT_BT_WINDOWS) << "Updating device" << iter->name() << iter->address(); + // merge service uuids + QList uuids = iter->serviceUuids(); + uuids.append(info.serviceUuids()); + const QSet uuidSet(uuids.begin(), uuids.end()); + if (iter->serviceUuids().size() != uuidSet.size()) + iter->setServiceUuids(uuidSet.values().toVector()); + if (iter->coreConfigurations() != info.coreConfigurations()) + iter->setCoreConfigurations(QBluetoothDeviceInfo::BaseRateAndLowEnergyCoreConfiguration); + return; + } + } + + discoveredDevices << info; + emit q->deviceDiscovered(info); +} + +void QBluetoothDeviceDiscoveryAgentPrivate::updateDeviceData(const QBluetoothAddress &address, + QBluetoothDeviceInfo::Fields fields, + qint16 rssi, + ManufacturerData manufacturerData, + ServiceData serviceData) +{ + if (fields.testFlag(QBluetoothDeviceInfo::Field::None)) + return; + + Q_Q(QBluetoothDeviceDiscoveryAgent); + for (QList::iterator iter = discoveredDevices.begin(); + iter != discoveredDevices.end(); ++iter) { + if (iter->address() == address) { + qCDebug(QT_BT_WINDOWS) << "Updating data for device" << iter->name() << iter->address(); + if (fields.testFlag(QBluetoothDeviceInfo::Field::RSSI)) + iter->setRssi(rssi); + if (fields.testFlag(QBluetoothDeviceInfo::Field::ManufacturerData)) + for (quint16 key : manufacturerData.keys()) + iter->setManufacturerData(key, manufacturerData.value(key)); + if (fields.testFlag(QBluetoothDeviceInfo::Field::ServiceData)) + for (QBluetoothUuid key : serviceData.keys()) + iter->setServiceData(key, serviceData.value(key)); + emit q->deviceUpdated(*iter, fields); + return; + } + } +} + +void QBluetoothDeviceDiscoveryAgentPrivate::onErrorOccured(QBluetoothDeviceDiscoveryAgent::Error e) +{ + Q_Q(QBluetoothDeviceDiscoveryAgent); + lastError = e; + emit q->errorOccurred(e); +} + +void QBluetoothDeviceDiscoveryAgentPrivate::onScanFinished() +{ + Q_Q(QBluetoothDeviceDiscoveryAgent); + disconnectAndClearWorker(); + emit q->finished(); +} + +void QBluetoothDeviceDiscoveryAgentPrivate::disconnectAndClearWorker() +{ + if (!worker) + return; + + disconnect(worker.get(), &QWinRTBluetoothDeviceDiscoveryWorker::scanFinished, + this, &QBluetoothDeviceDiscoveryAgentPrivate::onScanFinished); + disconnect(worker.get(), &QWinRTBluetoothDeviceDiscoveryWorker::deviceFound, + this, &QBluetoothDeviceDiscoveryAgentPrivate::registerDevice); + disconnect(worker.get(), &QWinRTBluetoothDeviceDiscoveryWorker::deviceDataChanged, + this, &QBluetoothDeviceDiscoveryAgentPrivate::updateDeviceData); + disconnect(worker.get(), &QWinRTBluetoothDeviceDiscoveryWorker::errorOccured, + this, &QBluetoothDeviceDiscoveryAgentPrivate::onErrorOccured); + + worker = nullptr; +} + +QT_END_NAMESPACE + +#include diff --git a/src/bluetooth/qbluetoothdeviceinfo.cpp b/src/bluetooth/qbluetoothdeviceinfo.cpp new file mode 100644 index 0000000..e85149d --- /dev/null +++ b/src/bluetooth/qbluetoothdeviceinfo.cpp @@ -0,0 +1,764 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothdeviceinfo.h" +#include "qbluetoothdeviceinfo_p.h" + +QT_BEGIN_NAMESPACE + +QT_IMPL_METATYPE_EXTERN(QBluetoothDeviceInfo) +#ifdef QT_WINRT_BLUETOOTH +QT_IMPL_METATYPE_EXTERN_TAGGED(QBluetoothDeviceInfo::Fields, QBluetoothDeviceInfo__Fields) +#endif + +/*! + \class QBluetoothDeviceInfo + \inmodule QtBluetooth + \brief The QBluetoothDeviceInfo class stores information about the Bluetooth + device. + + \since 5.2 + + QBluetoothDeviceInfo provides information about a Bluetooth device's name, address and class of device. +*/ + +/*! + \enum QBluetoothDeviceInfo::MajorDeviceClass + + This enum describes a Bluetooth device's major device class. + + \value MiscellaneousDevice A miscellaneous device. + \value ComputerDevice A computer device or PDA. + \value PhoneDevice A telephone device. + \value NetworkDevice A device that provides access to a local area network (since Qt 5.13). + \value AudioVideoDevice A device capable of playback or capture of audio and/or video. + \value PeripheralDevice A peripheral device such as a keyboard, mouse, and so on. + \value ImagingDevice An imaging device such as a display, printer, scanner or camera. + \value WearableDevice A wearable device such as a watch or pager. + \value ToyDevice A toy. + \value HealthDevice A health reated device such as heart rate or temperature monitor. + \value UncategorizedDevice A device that does not fit into any of the other device classes. +*/ + +/*! + \enum QBluetoothDeviceInfo::Field + + This enum is used in conjuntion with the \l QBluetoothDeviceDiscoveryAgent::deviceUpdated() signal + and indicates the field that changed. + + \value None None of the values changed. + \value RSSI The \l rssi() value of the device changed. + \value ManufacturerData The \l manufacturerData() field changed + \value ServiceData The \l serviceData() field changed + \value All Matches every possible field. + + \since 5.12 +*/ + +/*! + \enum QBluetoothDeviceInfo::MinorMiscellaneousClass + + This enum describes the minor device classes for miscellaneous Bluetooth devices. + + \value UncategorizedMiscellaneous An uncategorized miscellaneous device. +*/ + +/*! + \enum QBluetoothDeviceInfo::MinorComputerClass + + This enum describes the minor device classes for computer devices. + + \value UncategorizedComputer An uncategorized computer device. + \value DesktopComputer A desktop computer. + \value ServerComputer A server computer. + \value LaptopComputer A laptop computer. + \value HandheldClamShellComputer A clamshell handheld computer or PDA. + \value HandheldComputer A handheld computer or PDA. + \value WearableComputer A wearable computer. +*/ + +/*! + \enum QBluetoothDeviceInfo::MinorPhoneClass + + This enum describes the minor device classes for phone devices. + + \value UncategorizedPhone An uncategorized phone device. + \value CellularPhone A cellular phone. + \value CordlessPhone A cordless phone. + \value SmartPhone A smart phone. + \value WiredModemOrVoiceGatewayPhone A wired modem or voice gateway. + \value CommonIsdnAccessPhone A device that provides ISDN access. +*/ + +/*! + \enum QBluetoothDeviceInfo::MinorNetworkClass + + This enum describes the minor device classes for local area network access devices. Local area + network access devices use the minor device class to specify the current network utilization. + + \value NetworkFullService 100% of the total bandwidth is available. + \value NetworkLoadFactorOne 0 - 17% of the total bandwidth is currently being used. + \value NetworkLoadFactorTwo 17 - 33% of the total bandwidth is currently being used. + \value NetworkLoadFactorThree 33 - 50% of the total bandwidth is currently being used. + \value NetworkLoadFactorFour 50 - 67% of the total bandwidth is currently being used. + \value NetworkLoadFactorFive 67 - 83% of the total bandwidth is currently being used. + \value NetworkLoadFactorSix 83 - 99% of the total bandwidth is currently being used. + \value NetworkNoService No network service available. +*/ + +/*! + \enum QBluetoothDeviceInfo::MinorAudioVideoClass + + This enum describes the minor device classes for audio/video devices. + + \value UncategorizedAudioVideoDevice An uncategorized audio/video device. + \value WearableHeadsetDevice A wearable headset device. + \value HandsFreeDevice A handsfree device. + \value Microphone A microphone. + \value Loudspeaker A loudspeaker. + \value Headphones Headphones. + \value PortableAudioDevice A portable audio device. + \value CarAudio A car audio device. + \value SetTopBox A settop box. + \value HiFiAudioDevice A HiFi audio device. + \value Vcr A video cassette recorder. + \value VideoCamera A video camera. + \value Camcorder A video camera. + \value VideoMonitor A video monitor. + \value VideoDisplayAndLoudspeaker A video display with built-in loudspeaker. + \value VideoConferencing A video conferencing device. + \value GamingDevice A gaming device. +*/ + +/*! + \enum QBluetoothDeviceInfo::MinorPeripheralClass + + This enum describes the minor device classes for peripheral devices. + + \value UncategorizedPeripheral An uncategorized peripheral device. + \value KeyboardPeripheral A keyboard. + \value PointingDevicePeripheral A pointing device, for example a mouse. + \value KeyboardWithPointingDevicePeripheral A keyboard with built-in pointing device. + \value JoystickPeripheral A joystick. + \value GamepadPeripheral A game pad. + \value RemoteControlPeripheral A remote control. + \value SensingDevicePeripheral A sensing device. + \value DigitizerTabletPeripheral A digitizer tablet peripheral. + \value CardReaderPeripheral A card reader peripheral. +*/ + +/*! + \enum QBluetoothDeviceInfo::MinorImagingClass + + This enum describes the minor device classes for imaging devices. + + \value UncategorizedImagingDevice An uncategorized imaging device. + \value ImageDisplay A device capable of displaying images. + \value ImageCamera A camera. + \value ImageScanner An image scanner. + \value ImagePrinter A printer. +*/ + +/*! + \enum QBluetoothDeviceInfo::MinorWearableClass + + This enum describes the minor device classes for wearable devices. + + \value UncategorizedWearableDevice An uncategorized wearable device. + \value WearableWristWatch A wristwatch. + \value WearablePager A pager. + \value WearableJacket A jacket. + \value WearableHelmet A helmet. + \value WearableGlasses A pair of glasses. +*/ + +/*! + \enum QBluetoothDeviceInfo::MinorToyClass + + This enum describes the minor device classes for toy devices. + + \value UncategorizedToy An uncategorized toy. + \value ToyRobot A toy robot. + \value ToyVehicle A toy vehicle. + \value ToyDoll A toy doll or action figure. + \value ToyController A controller. + \value ToyGame A game. +*/ + +/*! + \enum QBluetoothDeviceInfo::MinorHealthClass + + This enum describes the minor device classes for health devices. + + \value UncategorizedHealthDevice An uncategorized health device. + \value HealthBloodPressureMonitor A blood pressure monitor. + \value HealthThermometer A Thermometer. + \value HealthWeightScale A scale. + \value HealthGlucoseMeter A glucose meter. + \value HealthPulseOximeter A blood oxygen saturation meter. + \value HealthDataDisplay A data display. + \value HealthStepCounter A pedometer. +*/ + +/*! + \enum QBluetoothDeviceInfo::ServiceClass + + This enum describes the service class of the Bluetooth device. The service class is used as a + rudimentary form of service discovery. It is meant to provide a list of the types + of services that the device might provide. + + \value NoService The device does not provide any services. + \value PositioningService The device provides positioning services. + \value NetworkingService The device provides networking services. + \value RenderingService The device provides rendering services. + \value CapturingService The device provides capturing services. + \value ObjectTransferService The device provides object transfer services. + \value AudioService The device provides audio services. + \value TelephonyService The device provides telephony services. + \value InformationService The device provides information services. + \value AllServices The device provides services of all types. +*/ + +/*! + \enum QBluetoothDeviceInfo::CoreConfiguration + \since 5.4 + + This enum describes the configuration of the device. + + \value UnknownCoreConfiguration The type of the Bluetooth device cannot be determined. + \value BaseRateCoreConfiguration The device is a standard Bluetooth device. + \value BaseRateAndLowEnergyCoreConfiguration The device is a Bluetooth Smart device with support + for standard and Low Energy device. + \value LowEnergyCoreConfiguration The device is a Bluetooth Low Energy device. +*/ +QBluetoothDeviceInfoPrivate::QBluetoothDeviceInfoPrivate() +{ +} + +/*! + Constructs an invalid QBluetoothDeviceInfo object. +*/ +QBluetoothDeviceInfo::QBluetoothDeviceInfo() : + d_ptr(new QBluetoothDeviceInfoPrivate) +{ +} + +/*! + Constructs a QBluetoothDeviceInfo object with Bluetooth address \a address, device name + \a name and the encoded class of device \a classOfDevice. + + The \a classOfDevice parameter is encoded in the following format + + \table + \header \li Bits \li Size \li Description + \row \li 0 - 1 \li 2 \li Unused, set to 0. + \row \li 2 - 7 \li 6 \li Minor device class. + \row \li 8 - 12 \li 5 \li Major device class. + \row \li 13 - 23 \li 11 \li Service class. + \endtable +*/ +QBluetoothDeviceInfo::QBluetoothDeviceInfo(const QBluetoothAddress &address, const QString &name, + quint32 classOfDevice) : + d_ptr(new QBluetoothDeviceInfoPrivate) +{ + Q_D(QBluetoothDeviceInfo); + + d->address = address; + d->name = name; + + d->minorDeviceClass = static_cast((classOfDevice >> 2) & 0x3f); + d->majorDeviceClass = static_cast((classOfDevice >> 8) & 0x1f); + d->serviceClasses = static_cast((classOfDevice >> 13) & 0x7ff); + + d->valid = true; + d->cached = false; + d->rssi = 0; +} + +/*! + Constructs a QBluetoothDeviceInfo object with unique \a uuid, device name + \a name and the encoded class of device \a classOfDevice. + + This constructor is required for Low Energy devices on \macos and iOS. CoreBluetooth + API hides addresses and provides unique UUIDs to identify a device. This UUID is + not the same thing as a service UUID and is required to work later with CoreBluetooth API + and discovered devices. + + \since 5.5 +*/ +QBluetoothDeviceInfo::QBluetoothDeviceInfo(const QBluetoothUuid &uuid, const QString &name, + quint32 classOfDevice) : + d_ptr(new QBluetoothDeviceInfoPrivate) +{ + Q_D(QBluetoothDeviceInfo); + + d->name = name; + d->deviceUuid = uuid; + + d->minorDeviceClass = static_cast((classOfDevice >> 2) & 0x3f); + d->majorDeviceClass = static_cast((classOfDevice >> 8) & 0x1f); + d->serviceClasses = static_cast((classOfDevice >> 13) & 0x7ff); + + d->valid = true; + d->cached = false; + d->rssi = 0; +} + +/*! + Constructs a QBluetoothDeviceInfo that is a copy of \a other. +*/ +QBluetoothDeviceInfo::QBluetoothDeviceInfo(const QBluetoothDeviceInfo &other) : + d_ptr(new QBluetoothDeviceInfoPrivate) +{ + *this = other; +} + +/*! + Destroys the QBluetoothDeviceInfo. +*/ +QBluetoothDeviceInfo::~QBluetoothDeviceInfo() +{ + delete d_ptr; +} + +/*! + Returns true if the QBluetoothDeviceInfo object is valid, otherwise returns false. +*/ +bool QBluetoothDeviceInfo::isValid() const +{ + Q_D(const QBluetoothDeviceInfo); + + return d->valid; +} + +/*! + Returns the signal strength when the device was last scanned + */ +qint16 QBluetoothDeviceInfo::rssi() const +{ + Q_D(const QBluetoothDeviceInfo); + + return d->rssi; +} + +/*! + Set the \a signal strength value, used internally. + */ +void QBluetoothDeviceInfo::setRssi(qint16 signal) +{ + Q_D(QBluetoothDeviceInfo); + d->rssi = signal; +} + +/*! + Makes a copy of the \a other and assigns it to this QBluetoothDeviceInfo object. +*/ +QBluetoothDeviceInfo &QBluetoothDeviceInfo::operator=(const QBluetoothDeviceInfo &other) +{ + Q_D(QBluetoothDeviceInfo); + + d->address = other.d_func()->address; + d->name = other.d_func()->name; + d->minorDeviceClass = other.d_func()->minorDeviceClass; + d->majorDeviceClass = other.d_func()->majorDeviceClass; + d->serviceClasses = other.d_func()->serviceClasses; + d->valid = other.d_func()->valid; + d->cached = other.d_func()->cached; + d->serviceUuids = other.d_func()->serviceUuids; + d->manufacturerData = other.d_func()->manufacturerData; + d->serviceData = other.d_func()->serviceData; + d->rssi = other.d_func()->rssi; + d->deviceCoreConfiguration = other.d_func()->deviceCoreConfiguration; + d->deviceUuid = other.d_func()->deviceUuid; + + return *this; +} + +/*! + \fn bool QBluetoothDeviceInfo::operator==(const QBluetoothDeviceInfo &a, const QBluetoothDeviceInfo &b) + \brief Returns \c true if the two QBluetoothDeviceInfo objects \a a and \a b are equal. +*/ + +/*! + \fn bool QBluetoothDeviceInfo::operator!=(const QBluetoothDeviceInfo &a, + const QBluetoothDeviceInfo &b) + \brief Returns \c true if the two QBluetoothDeviceInfo objects \a a and \a b are not equal. +*/ + +/*! + \brief Returns true if the \a other QBluetoothDeviceInfo object and this are identical. + \internal +*/ + +bool QBluetoothDeviceInfo::equals(const QBluetoothDeviceInfo &a, const QBluetoothDeviceInfo &b) +{ + if (a.d_func()->cached != b.d_func()->cached) + return false; + if (a.d_func()->valid != b.d_func()->valid) + return false; + if (a.d_func()->majorDeviceClass != b.d_func()->majorDeviceClass) + return false; + if (a.d_func()->minorDeviceClass != b.d_func()->minorDeviceClass) + return false; + if (a.d_func()->serviceClasses != b.d_func()->serviceClasses) + return false; + if (a.d_func()->name != b.d_func()->name) + return false; + if (a.d_func()->address != b.d_func()->address) + return false; + if (a.d_func()->serviceUuids.size() != b.d_func()->serviceUuids.size()) + return false; + if (a.d_func()->serviceUuids != b.d_func()->serviceUuids) + return false; + if (a.d_func()->manufacturerData != b.d_func()->manufacturerData) + return false; + if (a.d_func()->serviceData != b.d_func()->serviceData) + return false; + if (a.d_func()->deviceCoreConfiguration != b.d_func()->deviceCoreConfiguration) + return false; + if (a.d_func()->deviceUuid != b.d_func()->deviceUuid) + return false; + + return true; +} + +/*! + Returns the address of the device. + + \note On iOS and \macos this address is invalid. Instead \l deviceUuid() should be used. + Those two platforms do not expose Bluetooth addresses for found Bluetooth devices + and utilize unique device identifiers. + + \sa deviceUuid() +*/ +QBluetoothAddress QBluetoothDeviceInfo::address() const +{ + Q_D(const QBluetoothDeviceInfo); + + return d->address; +} + +/*! + Returns the name assigned to the device. +*/ +QString QBluetoothDeviceInfo::name() const +{ + Q_D(const QBluetoothDeviceInfo); + + return d->name; +} + +/*! + Sets the \a name of the device. + + \since 6.2 + */ +void QBluetoothDeviceInfo::setName(const QString &name) +{ + Q_D(QBluetoothDeviceInfo); + + d->name = name; +} + +/*! + Returns the service class of the device. +*/ +QBluetoothDeviceInfo::ServiceClasses QBluetoothDeviceInfo::serviceClasses() const +{ + Q_D(const QBluetoothDeviceInfo); + + return d->serviceClasses; +} + +/*! + Returns the major device class of the device. +*/ +QBluetoothDeviceInfo::MajorDeviceClass QBluetoothDeviceInfo::majorDeviceClass() const +{ + Q_D(const QBluetoothDeviceInfo); + + return d->majorDeviceClass; +} + +/*! + Returns the minor device class of the device. The actual information + is context dependent on the value of \l majorDeviceClass(). + + \sa MinorAudioVideoClass, MinorComputerClass, MinorHealthClass, MinorImagingClass, + MinorMiscellaneousClass, MinorNetworkClass, MinorPeripheralClass, MinorPhoneClass, + MinorToyClass, MinorWearableClass +*/ +quint8 QBluetoothDeviceInfo::minorDeviceClass() const +{ + Q_D(const QBluetoothDeviceInfo); + + return d->minorDeviceClass; +} + +/*! + Sets the list of service UUIDs to \a uuids. + \since 5.13 + */ +void QBluetoothDeviceInfo::setServiceUuids(const QList &uuids) +{ + Q_D(QBluetoothDeviceInfo); + d->serviceUuids = uuids; +} + +/*! + Returns the list of service UUIDs supported by the device. Most commonly this + list of UUIDs represents custom service UUIDs or a service UUID value specified + by \l QBluetoothUuid::ServiceClassUuid. + + \sa serviceUuids() + \since 6.0 +*/ +QList QBluetoothDeviceInfo::serviceUuids() const +{ + Q_D(const QBluetoothDeviceInfo); + return d->serviceUuids; +} + +/*! + Returns all manufacturer IDs from advertisement packets attached to this device information. + + \sa manufacturerData(), setManufacturerData() + + \since 5.12 + */ +QList QBluetoothDeviceInfo::manufacturerIds() const +{ + Q_D(const QBluetoothDeviceInfo); + return d->manufacturerData.keys().toList(); +} + +/*! + Returns the data associated with the given \a manufacturerId. + + Manufacturer data is defined by + the Supplement to the Bluetooth Core Specification and consists of two segments: + + \list + \li Manufacturer specific identifier code from the + \l {https://www.bluetooth.com/specifications/assigned-numbers} {Assigned Numbers} + Company Identifiers document + \li Sequence of arbitrary data octets + \endlist + + The interpretation of the data octets is defined by the manufacturer + specified by the company identifier. + + \note The remote device may provide multiple data entries per manufacturerId. + This function only returns the first entry. If all entries are needed use + \l manufacturerData() which returns a multi hash. + + \sa manufacturerIds(), setManufacturerData() + \since 5.12 + */ +QByteArray QBluetoothDeviceInfo::manufacturerData(quint16 manufacturerId) const +{ + Q_D(const QBluetoothDeviceInfo); + return d->manufacturerData.value(manufacturerId); +} + +/*! + Sets the advertised manufacturer \a data for the given \a manufacturerId. + Returns \c true if it was inserted, \c false if it was already known. + + Since Qt 5.14, different values for \a data and the same \a manufacturerId no longer + replace each other but are accumulated for the duration of a device scan. + + \sa manufacturerData + \since 5.12 +*/ +bool QBluetoothDeviceInfo::setManufacturerData(quint16 manufacturerId, const QByteArray &data) +{ + Q_D(QBluetoothDeviceInfo); + auto it = d->manufacturerData.constFind(manufacturerId); + while (it != d->manufacturerData.cend() && it.key() == manufacturerId) { + if (*it == data) + return false; + it++; + } + + d->manufacturerData.insert(manufacturerId, data); + return true; +} + +/*! + Returns the complete set of all manufacturer data from advertisement packets. + + Some devices may provide multiple manufacturer data entries per manufacturer ID. + An example might be a Bluetooth Low Energy device that sends a different manufacturer data via + advertisement packets and scan response packets respectively. Therefore the returned hash table + may have multiple entries per manufacturer ID or hash key. + + \sa setManufacturerData + \since 5.12 +*/ +QMultiHash QBluetoothDeviceInfo::manufacturerData() const +{ + Q_D(const QBluetoothDeviceInfo); + return d->manufacturerData; +} + +/*! + Returns all service data IDs from advertisement packets attached to this device information. + + \sa serviceData(), setServiceData() + \since 6.3 + */ +QList QBluetoothDeviceInfo::serviceIds() const +{ + Q_D(const QBluetoothDeviceInfo); + return d->serviceData.keys().toList(); +} + +/*! + Returns the data associated with the given \a serviceId. + + Service data is defined by + the Supplement to the Bluetooth Core Specification and consists of two segments: + + \list + \li Service UUID + \li Sequence of arbitrary data octets + \endlist + + \note The remote device may provide multiple data entries per \a serviceId. + This function only returns the first entry. If all entries are needed use + \l serviceData() which returns a multi hash. + + \sa serviceIds(), setServiceData() + \since 6.3 + */ +QByteArray QBluetoothDeviceInfo::serviceData(const QBluetoothUuid &serviceId) const +{ + Q_D(const QBluetoothDeviceInfo); + return d->serviceData.value(serviceId); +} + +/*! + Sets the advertised service \a data for the given \a serviceId. + Returns \c true if it was inserted, \c false if it was already known. + + \sa serviceData + \since 6.3 +*/ +bool QBluetoothDeviceInfo::setServiceData(const QBluetoothUuid &serviceId, const QByteArray &data) +{ + Q_D(QBluetoothDeviceInfo); + auto it = d->serviceData.constFind(serviceId); + while (it != d->serviceData.cend() && it.key() == serviceId) { + if (*it == data) + return false; + it++; + } + + d->serviceData.insert(serviceId, data); + return true; +} + +/*! + Returns the complete set of all service data from advertisement packets. + + Some devices may provide multiple service data entries per service data ID. + An example might be a Bluetooth Low Energy device that sends a different service data via + advertisement packets and scan response packets respectively. Therefore the returned hash table + may have multiple entries per service data ID or hash key. + + \sa setServiceData + \since 6.3 +*/ +QMultiHash QBluetoothDeviceInfo::serviceData() const +{ + Q_D(const QBluetoothDeviceInfo); + return d->serviceData; +} + +/*! + Sets the CoreConfigurations of the device to \a coreConfigs. This will help to make a difference + between regular and Low Energy devices. + + \sa coreConfigurations() + \since 5.4 +*/ +void QBluetoothDeviceInfo::setCoreConfigurations(QBluetoothDeviceInfo::CoreConfigurations coreConfigs) +{ + Q_D(QBluetoothDeviceInfo); + + d->deviceCoreConfiguration = coreConfigs; +} + +/*! + + Returns the configuration of the device. If device configuration is not set, + basic rate device configuration will be returned. + + \sa setCoreConfigurations() + \since 5.4 +*/ +QBluetoothDeviceInfo::CoreConfigurations QBluetoothDeviceInfo::coreConfigurations() const +{ + Q_D(const QBluetoothDeviceInfo); + + return d->deviceCoreConfiguration; +} + +/*! + Returns true if the QBluetoothDeviceInfo object is created from cached data. +*/ +bool QBluetoothDeviceInfo::isCached() const +{ + Q_D(const QBluetoothDeviceInfo); + + return d->cached; +} + +/*! + Used by the system to set the \a cached flag if the QBluetoothDeviceInfo is created from cached data. Cached + information may not be as accurate as data read from an active device. + */ +void QBluetoothDeviceInfo::setCached(bool cached) +{ + Q_D(QBluetoothDeviceInfo); + + d->cached = cached; +} + +/*! + Sets the unique identifier \a uuid for Bluetooth devices, that do not have addresses. + This happens on \macos and iOS, where the CoreBluetooth API hides addresses, but provides + UUIDs to identify devices/peripherals. + + This uuid is invalid on any other platform. + + \sa deviceUuid() + \since 5.5 + */ +void QBluetoothDeviceInfo::setDeviceUuid(const QBluetoothUuid &uuid) +{ + Q_D(QBluetoothDeviceInfo); + + d->deviceUuid = uuid; +} + +/*! + Returns a unique identifier for a Bluetooth device without an address. + + In general, this uuid is invalid on every platform but \macos and iOS. + It is used as a workaround for those two platforms as they do not + provide Bluetooth addresses for found Bluetooth Low Energy devices. + Every other platform uses \l address() instead. + + \sa setDeviceUuid() + \since 5.5 + */ +QBluetoothUuid QBluetoothDeviceInfo::deviceUuid() const +{ + Q_D(const QBluetoothDeviceInfo); + + return d->deviceUuid; +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothdeviceinfo.h b/src/bluetooth/qbluetoothdeviceinfo.h new file mode 100644 index 0000000..fd8fd50 --- /dev/null +++ b/src/bluetooth/qbluetoothdeviceinfo.h @@ -0,0 +1,248 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QBLUETOOTHDEVICEINFO_H +#define QBLUETOOTHDEVICEINFO_H + +#include +#include + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QBluetoothDeviceInfoPrivate; +class QBluetoothAddress; +class QBluetoothUuid; + +class Q_BLUETOOTH_EXPORT QBluetoothDeviceInfo +{ +public: + enum MajorDeviceClass { + MiscellaneousDevice = 0, + ComputerDevice = 1, + PhoneDevice = 2, + NetworkDevice = 3, + AudioVideoDevice = 4, + PeripheralDevice = 5, + ImagingDevice = 6, + WearableDevice = 7, + ToyDevice = 8, + HealthDevice = 9, + UncategorizedDevice = 31 + }; + + enum MinorMiscellaneousClass { + UncategorizedMiscellaneous = 0 + }; + + enum MinorComputerClass { + UncategorizedComputer = 0, + DesktopComputer = 1, + ServerComputer = 2, + LaptopComputer = 3, + HandheldClamShellComputer = 4, + HandheldComputer = 5, + WearableComputer = 6 + }; + + enum MinorPhoneClass { + UncategorizedPhone = 0, + CellularPhone = 1, + CordlessPhone = 2, + SmartPhone = 3, + WiredModemOrVoiceGatewayPhone = 4, + CommonIsdnAccessPhone = 5 + }; + + enum MinorNetworkClass { + NetworkFullService = 0x00, + NetworkLoadFactorOne = 0x08, + NetworkLoadFactorTwo = 0x10, + NetworkLoadFactorThree = 0x18, + NetworkLoadFactorFour = 0x20, + NetworkLoadFactorFive = 0x28, + NetworkLoadFactorSix = 0x30, + NetworkNoService = 0x38 + }; + + enum MinorAudioVideoClass { + UncategorizedAudioVideoDevice = 0, + WearableHeadsetDevice = 1, + HandsFreeDevice = 2, + // reserved = 3, + Microphone = 4, + Loudspeaker = 5, + Headphones = 6, + PortableAudioDevice = 7, + CarAudio = 8, + SetTopBox = 9, + HiFiAudioDevice = 10, + Vcr = 11, + VideoCamera = 12, + Camcorder = 13, + VideoMonitor = 14, + VideoDisplayAndLoudspeaker = 15, + VideoConferencing = 16, + // reserved = 17, + GamingDevice = 18 + }; + + enum MinorPeripheralClass { + UncategorizedPeripheral = 0, + KeyboardPeripheral = 0x10, + PointingDevicePeripheral = 0x20, + KeyboardWithPointingDevicePeripheral = 0x30, + + JoystickPeripheral = 0x01, + GamepadPeripheral = 0x02, + RemoteControlPeripheral = 0x03, + SensingDevicePeripheral = 0x04, + DigitizerTabletPeripheral = 0x05, + CardReaderPeripheral = 0x06 + }; + + enum MinorImagingClass { + UncategorizedImagingDevice = 0, + ImageDisplay = 0x04, + ImageCamera = 0x08, + ImageScanner = 0x10, + ImagePrinter = 0x20 + }; + + enum MinorWearableClass { + UncategorizedWearableDevice = 0, + WearableWristWatch = 1, + WearablePager = 2, + WearableJacket = 3, + WearableHelmet = 4, + WearableGlasses = 5 + }; + + enum MinorToyClass { + UncategorizedToy = 0, + ToyRobot = 1, + ToyVehicle = 2, + ToyDoll = 3, + ToyController = 4, + ToyGame = 5 + }; + + enum MinorHealthClass { + UncategorizedHealthDevice = 0, + HealthBloodPressureMonitor = 0x1, + HealthThermometer = 0x2, + HealthWeightScale = 0x3, + HealthGlucoseMeter = 0x4, + HealthPulseOximeter = 0x5, + HealthDataDisplay = 0x7, + HealthStepCounter = 0x8 + }; + + enum ServiceClass { + NoService = 0x0000, + PositioningService = 0x0001, + NetworkingService = 0x0002, + RenderingService = 0x0004, + CapturingService = 0x0008, + ObjectTransferService = 0x0010, + AudioService = 0x0020, + TelephonyService = 0x0040, + InformationService = 0x0080, + AllServices = 0x07ff + }; + Q_DECLARE_FLAGS(ServiceClasses, ServiceClass) + + enum class Field { + None = 0x0000, + RSSI = 0x0001, + ManufacturerData = 0x0002, + ServiceData = 0x0004, + All = 0x7fff + }; + Q_DECLARE_FLAGS(Fields, Field) + + enum CoreConfiguration { + UnknownCoreConfiguration = 0x0, + LowEnergyCoreConfiguration = 0x01, + BaseRateCoreConfiguration = 0x02, + BaseRateAndLowEnergyCoreConfiguration = 0x03 + }; + Q_DECLARE_FLAGS(CoreConfigurations, CoreConfiguration) + + QBluetoothDeviceInfo(); + QBluetoothDeviceInfo(const QBluetoothAddress &address, const QString &name, + quint32 classOfDevice); + QBluetoothDeviceInfo(const QBluetoothUuid &uuid, const QString &name, + quint32 classOfDevice); + QBluetoothDeviceInfo(const QBluetoothDeviceInfo &other); + ~QBluetoothDeviceInfo(); + + bool isValid() const; + bool isCached() const; + + void setCached(bool cached); + + QBluetoothDeviceInfo &operator=(const QBluetoothDeviceInfo &other); + friend bool operator==(const QBluetoothDeviceInfo &a, const QBluetoothDeviceInfo &b) + { + return equals(a, b); + } + friend bool operator!=(const QBluetoothDeviceInfo &a, const QBluetoothDeviceInfo &b) + { + return !equals(a, b); + } + + QBluetoothAddress address() const; + QString name() const; + void setName(const QString &name); + + ServiceClasses serviceClasses() const; + MajorDeviceClass majorDeviceClass() const; + quint8 minorDeviceClass() const; + + qint16 rssi() const; + void setRssi(qint16 signal); + + QList serviceUuids() const; + void setServiceUuids(const QList &uuids); + + QList manufacturerIds() const; + QByteArray manufacturerData(quint16 manufacturerId) const; + bool setManufacturerData(quint16 manufacturerId, const QByteArray &data); + QMultiHash manufacturerData() const; + + QList serviceIds() const; + QByteArray serviceData(const QBluetoothUuid &serviceId) const; + bool setServiceData(const QBluetoothUuid &serviceId, const QByteArray &data); + QMultiHash serviceData() const; + + void setCoreConfigurations(QBluetoothDeviceInfo::CoreConfigurations coreConfigs); + QBluetoothDeviceInfo::CoreConfigurations coreConfigurations() const; + + void setDeviceUuid(const QBluetoothUuid &uuid); + QBluetoothUuid deviceUuid() const; + +protected: + QBluetoothDeviceInfoPrivate *d_ptr; + +private: + static bool equals(const QBluetoothDeviceInfo &a, const QBluetoothDeviceInfo &b); + Q_DECLARE_PRIVATE(QBluetoothDeviceInfo) +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QBluetoothDeviceInfo::CoreConfigurations) +Q_DECLARE_OPERATORS_FOR_FLAGS(QBluetoothDeviceInfo::ServiceClasses) + +QT_END_NAMESPACE + +QT_DECL_METATYPE_EXTERN(QBluetoothDeviceInfo, Q_BLUETOOTH_EXPORT) +#ifdef QT_WINRT_BLUETOOTH +QT_DECL_METATYPE_EXTERN_TAGGED(QBluetoothDeviceInfo::Fields, QBluetoothDeviceInfo__Fields, + Q_BLUETOOTH_EXPORT) +#endif + +#endif diff --git a/src/bluetooth/qbluetoothdeviceinfo_p.h b/src/bluetooth/qbluetoothdeviceinfo_p.h new file mode 100644 index 0000000..ba527b2 --- /dev/null +++ b/src/bluetooth/qbluetoothdeviceinfo_p.h @@ -0,0 +1,54 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QBLUETOOTHDEVICEINFO_P_H +#define QBLUETOOTHDEVICEINFO_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 "qbluetoothdeviceinfo.h" +#include "qbluetoothaddress.h" +#include "qbluetoothuuid.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QBluetoothDeviceInfoPrivate +{ +public: + QBluetoothDeviceInfoPrivate(); + + bool valid = false; + bool cached = false; + qint16 rssi = 1; + quint8 minorDeviceClass = 0; + + QBluetoothAddress address; + QString name; + QBluetoothDeviceInfo::MajorDeviceClass majorDeviceClass = QBluetoothDeviceInfo::MiscellaneousDevice; + + QBluetoothDeviceInfo::ServiceClasses serviceClasses = QBluetoothDeviceInfo::NoService; + + QList serviceUuids; + QMultiHash manufacturerData; + QMultiHash serviceData; + QBluetoothDeviceInfo::CoreConfigurations deviceCoreConfiguration = QBluetoothDeviceInfo::UnknownCoreConfiguration; + + QBluetoothUuid deviceUuid; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/bluetooth/qbluetoothdevicewatcher_winrt.cpp b/src/bluetooth/qbluetoothdevicewatcher_winrt.cpp new file mode 100644 index 0000000..fd69ee7 --- /dev/null +++ b/src/bluetooth/qbluetoothdevicewatcher_winrt.cpp @@ -0,0 +1,105 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothdevicewatcher_winrt_p.h" + +#include + +using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::Devices::Enumeration; + +QT_BEGIN_NAMESPACE + +QBluetoothDeviceWatcherWinRT::QBluetoothDeviceWatcherWinRT(int id, winrt::hstring selector) + : m_id(id), + m_watcher(DeviceInformation::CreateWatcher(selector)) +{ + qRegisterMetaType("winrt::hstring"); +} + +QBluetoothDeviceWatcherWinRT::QBluetoothDeviceWatcherWinRT(int id, winrt::hstring selector, + winrt::Windows::Devices::Enumeration::DeviceInformationKind kind) + : m_id(id) +{ + qRegisterMetaType("winrt::hstring"); + const winrt::param::iterable extra {}; + m_watcher = DeviceInformation::CreateWatcher(selector, extra, kind); +} + +QBluetoothDeviceWatcherWinRT::~QBluetoothDeviceWatcherWinRT() +{ + stop(); +} + +bool QBluetoothDeviceWatcherWinRT::init() +{ + if (!m_watcher) { + qWarning("Windows failed to create an instance of DeviceWatcher. " + "Detection of Bluetooth devices might not work correctly."); + return false; + } + return true; +} + +void QBluetoothDeviceWatcherWinRT::start() +{ + if (m_watcher) { + subscribeToEvents(); + m_watcher.Start(); + } +} + +void QBluetoothDeviceWatcherWinRT::stop() +{ + if (m_watcher && canStop()) { + unsubscribeFromEvents(); + m_watcher.Stop(); + } +} + +void QBluetoothDeviceWatcherWinRT::subscribeToEvents() +{ + Q_ASSERT(m_watcher.Status() == DeviceWatcherStatus::Created); + // The callbacks are triggered from separate threads. So we capture + // thisPtr to make sure that the object is valid. + auto thisPtr = shared_from_this(); + m_addedToken = m_watcher.Added([thisPtr](DeviceWatcher, const DeviceInformation &info) { + emit thisPtr->deviceAdded(info.Id(), thisPtr->m_id); + }); + m_removedToken = + m_watcher.Removed([thisPtr](DeviceWatcher, const DeviceInformationUpdate &upd) { + emit thisPtr->deviceRemoved(upd.Id(), thisPtr->m_id); + }); + m_updatedToken = + m_watcher.Updated([thisPtr](DeviceWatcher, const DeviceInformationUpdate &upd) { + emit thisPtr->deviceUpdated(upd.Id(), thisPtr->m_id); + }); + // because of ambiguous declaration + using WinRtInspectable = winrt::Windows::Foundation::IInspectable; + m_enumerationToken = + m_watcher.EnumerationCompleted([thisPtr](DeviceWatcher, const WinRtInspectable &) { + emit thisPtr->enumerationCompleted(thisPtr->m_id); + }); + m_stoppedToken = m_watcher.Stopped([thisPtr](DeviceWatcher, const WinRtInspectable &) { + emit thisPtr->watcherStopped(thisPtr->m_id); + }); +} + +void QBluetoothDeviceWatcherWinRT::unsubscribeFromEvents() +{ + m_watcher.Added(m_addedToken); + m_watcher.Removed(m_removedToken); + m_watcher.Updated(m_updatedToken); + m_watcher.EnumerationCompleted(m_enumerationToken); + m_watcher.Stopped(m_stoppedToken); +} + +bool QBluetoothDeviceWatcherWinRT::canStop() const +{ + const auto status = m_watcher.Status(); + // Also 'Aborted', but calling Stop() there is a no-op + return status == DeviceWatcherStatus::Started + || status == DeviceWatcherStatus::EnumerationCompleted; +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothdevicewatcher_winrt_p.h b/src/bluetooth/qbluetoothdevicewatcher_winrt_p.h new file mode 100644 index 0000000..74f5635 --- /dev/null +++ b/src/bluetooth/qbluetoothdevicewatcher_winrt_p.h @@ -0,0 +1,69 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QBLUETOOTHDEVICEWATCHER_WINRT_P_H +#define QBLUETOOTHDEVICEWATCHER_WINRT_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 + +QT_BEGIN_NAMESPACE + +class QBluetoothDeviceWatcherWinRT : public QObject, + public std::enable_shared_from_this +{ + Q_OBJECT +public: + QBluetoothDeviceWatcherWinRT(int id, winrt::hstring selector); + QBluetoothDeviceWatcherWinRT(int id, winrt::hstring selector, + winrt::Windows::Devices::Enumeration::DeviceInformationKind kind); + ~QBluetoothDeviceWatcherWinRT(); + + bool init(); + void start(); + void stop(); + +signals: + // The signals will be emitted from a separate thread, + // so we need to use Qt::QueuedConnection + void deviceAdded(winrt::hstring deviceId, int id); + void deviceRemoved(winrt::hstring deviceId, int id); + void deviceUpdated(winrt::hstring deviceId, int id); + void enumerationCompleted(int id); + void watcherStopped(int id); + +private: + void subscribeToEvents(); + void unsubscribeFromEvents(); + bool canStop() const; + + const int m_id; // used to uniquely identify the wrapper + winrt::Windows::Devices::Enumeration::DeviceWatcher m_watcher = nullptr; + + winrt::event_token m_addedToken; + winrt::event_token m_removedToken; + winrt::event_token m_updatedToken; + winrt::event_token m_enumerationToken; + winrt::event_token m_stoppedToken; +}; + +QT_END_NAMESPACE + +#endif // QBLUETOOTHDEVICEWATCHER_WINRT_P_H diff --git a/src/bluetooth/qbluetoothhostinfo.cpp b/src/bluetooth/qbluetoothhostinfo.cpp new file mode 100644 index 0000000..a720a0f --- /dev/null +++ b/src/bluetooth/qbluetoothhostinfo.cpp @@ -0,0 +1,123 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothhostinfo.h" +#include "qbluetoothhostinfo_p.h" + +QT_BEGIN_NAMESPACE + +QT_IMPL_METATYPE_EXTERN(QBluetoothHostInfo) + +/*! + \class QBluetoothHostInfo + \inmodule QtBluetooth + \brief The QBluetoothHostInfo class encapsulates the details of a local + QBluetooth device. + + \since 5.2 + + This class holds the name and address of a local Bluetooth device. +*/ + +/*! + Constructs a null QBluetoothHostInfo object. +*/ +QBluetoothHostInfo::QBluetoothHostInfo() : + d_ptr(new QBluetoothHostInfoPrivate) +{ +} + +/*! + Constructs a new QBluetoothHostInfo which is a copy of \a other. +*/ +QBluetoothHostInfo::QBluetoothHostInfo(const QBluetoothHostInfo &other) : + d_ptr(new QBluetoothHostInfoPrivate) +{ + Q_D(QBluetoothHostInfo); + + d->m_address = other.d_func()->m_address; + d->m_name = other.d_func()->m_name; +} + +/*! + Destroys the QBluetoothHostInfo. +*/ +QBluetoothHostInfo::~QBluetoothHostInfo() +{ + delete d_ptr; +} + +/*! + Assigns \a other to this QBluetoothHostInfo instance. +*/ +QBluetoothHostInfo &QBluetoothHostInfo::operator=(const QBluetoothHostInfo &other) +{ + Q_D(QBluetoothHostInfo); + + d->m_address = other.d_func()->m_address; + d->m_name = other.d_func()->m_name; + + return *this; +} + +/*! + \fn bool QBluetoothHostInfo::operator==(const QBluetoothHostInfo &a, + const QBluetoothHostInfo &b) + \brief Returns \c true if \a a and \a b are equal, otherwise \c false. +*/ + +/*! + \fn bool QBluetoothHostInfo::operator!=(const QBluetoothHostInfo &a, + const QBluetoothHostInfo &b) + \brief Returns \c true if \a a and \a b are not equal, otherwise \c false. +*/ + +/*! + \brief Returns \c true if \a a and \a b are equal, otherwise \c false. + \internal +*/ +bool QBluetoothHostInfo::equals(const QBluetoothHostInfo &a, const QBluetoothHostInfo &b) +{ + if (a.d_ptr == b.d_ptr) + return true; + + return a.d_ptr->m_address == b.d_ptr->m_address && a.d_ptr->m_name == b.d_ptr->m_name; +} + +/*! + Returns the Bluetooth address as a QBluetoothAddress. +*/ +QBluetoothAddress QBluetoothHostInfo::address() const +{ + Q_D(const QBluetoothHostInfo); + return d->m_address; +} + +/*! + Sets the Bluetooth \a address for this Bluetooth host info object. +*/ +void QBluetoothHostInfo::setAddress(const QBluetoothAddress &address) +{ + Q_D(QBluetoothHostInfo); + d->m_address = address; +} + +/*! + Returns the user visible name of the host info object. +*/ +QString QBluetoothHostInfo::name() const +{ + Q_D(const QBluetoothHostInfo); + return d->m_name; +} + +/*! + Sets the \a name of the host info object. +*/ +void QBluetoothHostInfo::setName(const QString &name) +{ + Q_D(QBluetoothHostInfo); + d->m_name = name; +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothhostinfo.h b/src/bluetooth/qbluetoothhostinfo.h new file mode 100644 index 0000000..7090ced --- /dev/null +++ b/src/bluetooth/qbluetoothhostinfo.h @@ -0,0 +1,46 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QBLUETOOTHHOSTINFO_H +#define QBLUETOOTHHOSTINFO_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QBluetoothHostInfoPrivate; +class Q_BLUETOOTH_EXPORT QBluetoothHostInfo +{ +public: + QBluetoothHostInfo(); + QBluetoothHostInfo(const QBluetoothHostInfo &other); + ~QBluetoothHostInfo(); + + QBluetoothHostInfo &operator=(const QBluetoothHostInfo &other); + friend bool operator==(const QBluetoothHostInfo &a, const QBluetoothHostInfo &b) + { + return equals(a, b); + } + friend bool operator!=(const QBluetoothHostInfo &a, const QBluetoothHostInfo &b) + { + return !equals(a, b); + } + + QBluetoothAddress address() const; + void setAddress(const QBluetoothAddress &address); + + QString name() const; + void setName(const QString &name); + +private: + static bool equals(const QBluetoothHostInfo &a, const QBluetoothHostInfo &b); + Q_DECLARE_PRIVATE(QBluetoothHostInfo) + QBluetoothHostInfoPrivate *d_ptr; +}; + +QT_END_NAMESPACE + +QT_DECL_METATYPE_EXTERN(QBluetoothHostInfo, Q_BLUETOOTH_EXPORT) + +#endif diff --git a/src/bluetooth/qbluetoothhostinfo_p.h b/src/bluetooth/qbluetoothhostinfo_p.h new file mode 100644 index 0000000..8e95713 --- /dev/null +++ b/src/bluetooth/qbluetoothhostinfo_p.h @@ -0,0 +1,36 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QBLUETOOTHHOSTINFO_P_H +#define QBLUETOOTHHOSTINFO_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 "qbluetoothhostinfo.h" +#include "private/qglobal_p.h" + +QT_BEGIN_NAMESPACE + +class QBluetoothHostInfoPrivate +{ +public: + QBluetoothHostInfoPrivate() + { + } + + QBluetoothAddress m_address; + QString m_name; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/bluetooth/qbluetoothlocaldevice.cpp b/src/bluetooth/qbluetoothlocaldevice.cpp new file mode 100644 index 0000000..a94b80e --- /dev/null +++ b/src/bluetooth/qbluetoothlocaldevice.cpp @@ -0,0 +1,307 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothlocaldevice.h" +#include "qbluetoothlocaldevice_p.h" +#include "qbluetoothaddress.h" + +#include + +QT_BEGIN_NAMESPACE + +QT_IMPL_METATYPE_EXTERN_TAGGED(QBluetoothLocalDevice::Pairing, QBluetoothLocalDevice__Pairing) +QT_IMPL_METATYPE_EXTERN_TAGGED(QBluetoothLocalDevice::HostMode, QBluetoothLocalDevice__HostMode) +QT_IMPL_METATYPE_EXTERN_TAGGED(QBluetoothLocalDevice::Error, QBluetoothLocalDevice__Error) + +/*! + \class QBluetoothLocalDevice + \inmodule QtBluetooth + \brief The QBluetoothLocalDevice class enables access to the local Bluetooth + device. + + \since 5.2 + + QBluetoothLocalDevice provides functions for getting and setting the state of local Bluetooth + devices. + + On iOS, this class cannot be used because the platform does not expose + any data or API which may provide information on the local Bluetooth device. +*/ + +/*! + \enum QBluetoothLocalDevice::Pairing + + This enum describes the pairing state between the two Bluetooth devices. + + \value Unpaired The Bluetooth devices are not paired. + \value Paired The Bluetooth devices are paired. The system will prompt the user for + authorization when the remote device initiates a connection to the + local device. + \value AuthorizedPaired The Bluetooth devices are paired. The system will not prompt the user + for authorization when the remote device initiates a connection to the + local device. +*/ + +/*! + \enum QBluetoothLocalDevice::Error + + This enum describes errors that maybe returned + + \value NoError No known error + \value PairingError Error in pairing + \value [since 6.4] MissingPermissionsError The operating system requests + permissions which were not + granted by the user. + \value UnknownError Unknown error + +*/ + +/*! + \enum QBluetoothLocalDevice::HostMode + + This enum describes the most of the local Bluetooth device. + + \value HostPoweredOff Power off the device + \value HostConnectable Remote Bluetooth devices can connect to the local Bluetooth device + if they have previously been paired with it or otherwise know its address. This powers up the + device if it was powered off. + \value HostDiscoverable Remote Bluetooth devices can discover the presence of the local + Bluetooth device. The device will also be connectable, and powered on. On Android, this mode can only be active + for a maximum of 5 minutes. + \value HostDiscoverableLimitedInquiry Remote Bluetooth devices can discover the presence of the local + Bluetooth device when performing a limited inquiry. This should be used for locating services that are + only made discoverable for a limited period of time. This can speed up discovery between gaming devices, + as service discovery can be skipped on devices not in LimitedInquiry mode. In this mode, the device will + be connectable and powered on, if required. This mode is is not supported on Android. + + \note On \macos, it is not possible to set the \l hostMode() to + HostConnectable or HostPoweredOff. + + \note On Windows, it is not possible to set the \l hostMode() to + HostDiscoverable or HostDiscoverableLimitedInquiry. Using these modes is + equivalent to HostConnectable. + + \note Starting from Android 13 (API level 33) the HostPoweredOff state relies on + non-public Android API as the public one has been deprecated, see + (\l {https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#disable()} + {disable()}). This may change in a future version of Android. + + \note At least on Android 12 the device's Bluetooth visibility setting may dictate the result + of setting either HostDiscoverable or HostConnectable. For example if the visibility is set + \e off, it may not be possible to enter the HostDiscoverable mode, but HostConnectable will be + used instead. This may change in future version of Android. + +*/ + +void registerQBluetoothLocalDeviceMetaType() +{ + static bool initDone = false; + if (!initDone) { + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + initDone = true; + } +} + +#ifndef QT_OSX_BLUETOOTH + +/*! + Destroys the QBluetoothLocalDevice. +*/ +QBluetoothLocalDevice::~QBluetoothLocalDevice() +{ + delete d_ptr; +} + +/*! + Returns \c true if the QBluetoothLocalDevice represents an available local Bluetooth device; + otherwise return false. + + If the local Bluetooth adapter represented by an instance of this class + is removed from the system (e.g. removal of the underlying Bluetooth dongle) + then this instance will become invalid. An already invalid QBluetoothLocalDevice instance + remains invalid even if the same Bluetooth adapter is returned to + the system. + +//! [android-permissions-valid] + \note Starting from Android 12 (API level 31), the construction of this class requires + \l {https://developer.android.com/guide/topics/connectivity/bluetooth/permissions} + {bluetooth runtime permissions} (\e BLUETOOTH_SCAN and \e BLUETOOTH_CONNECT). If the + permissions are not granted, the device will not be valid. +//! [android-permissions-valid] + + \sa allDevices() +*/ +bool QBluetoothLocalDevice::isValid() const +{ + if (d_ptr) + return d_ptr->isValid(); + return false; +} + +#endif + +/*! + \fn void QBluetoothLocalDevice::setHostMode(QBluetoothLocalDevice::HostMode mode) + + Sets the host mode of this local Bluetooth device to \a mode. + + Some transitions such as turning the device on or off may take some time. Therefore + subsequent calls should only be made once the \l hostModeStateChanged() signal + has concluded the previous request. If this is ignored the result of such a series + of calls is not well defined. + + \note Due to varying security policies on the supported platforms, this method may have + differing behaviors on the various platforms. For example the system may ask the user for + confirmation before turning Bluetooth on or off and not all host modes may be supported. + On \macos, it is not possbile to programmatically change the \l hostMode(). + A user can only switch Bluetooth on/off in the System Preferences. + On Windows this method \e must be called from the UI thread because it might + require user confirmation. + Please refer to the platform specific Bluetooth documentation for details. +*/ + +/*! + \fn QBluetoothLocalDevice::HostMode QBluetoothLocalDevice::hostMode() const + + Returns the current host mode of this local Bluetooth device. On \macos, it is either + HostPoweredOff or HostConnectable. +*/ + +/*! + \fn QBluetoothLocalDevice::name() const + + Returns the name assgined by the user to this Bluetooth device. +*/ + +/*! + \fn QBluetoothLocalDevice::address() const + + Returns the MAC address of this Bluetooth device. + + \note On Android, this function always returns the constant + value \c {02:00:00:00:00:00} as local address starting with Android 6.0. + The programmatic access to the device's local MAC address was removed. +*/ + +/*! + \fn QList QBluetoothLocalDevice::allDevices() + + Returns a list of all available local Bluetooth devices. On \macos, there is + only the "default" local device. +*/ + +/*! + \fn QBluetoothLocalDevice::powerOn() + + Powers on the device after returning it to the hostMode() state, if it was powered off. + + \note Due to varying security policies on the supported platforms, this method may have + differing behaviors on the various platforms. For example + the system may ask the user for confirmation before turning Bluetooth on or off. + On \macos it is not possible to power on/off Bluetooth. + Please refer to the platform specific Bluetooth documentation for details. +*/ + +/*! + \fn QBluetoothLocalDevice::QBluetoothLocalDevice(QObject *parent) + Constructs a QBluetoothLocalDevice with \a parent. + + \include qbluetoothlocaldevice.cpp android-permissions-valid + \sa isValid() +*/ + +/*! + \fn QBluetoothLocalDevice::hostModeStateChanged(QBluetoothLocalDevice::HostMode state) + The \a state of the host has transitioned to a different HostMode. +*/ + +/*! + \fn QBluetoothLocalDevice::deviceConnected(const QBluetoothAddress &address) + \since 5.3 + + This signal is emitted when the local device establishes a connection to a remote device + with \a address. + + \sa deviceDisconnected(), connectedDevices() +*/ + +/*! + \fn QBluetoothLocalDevice::deviceDisconnected(const QBluetoothAddress &address) + \since 5.3 + + This signal is emitted when the local device disconnects from a remote Bluetooth device + with \a address. + + \sa deviceConnected(), connectedDevices() +*/ + +/*! + \fn QList QBluetoothLocalDevice::connectedDevices() const + \since 5.3 + + Returns the list of connected devices. This list is different from the list of currently + paired devices. + + On Android and \macos, it is not possible to retrieve a list of connected devices. It is only possible to + listen to (dis)connect changes. For convenience, this class monitors all connect + and disconnect events since its instanciation and returns the current list when calling this function. + Therefore it is possible that this function returns an empty list shortly after creating an + instance. + + \sa deviceConnected(), deviceDisconnected() +*/ + +/*! + \fn QBluetoothLocalDevice::pairingStatus(const QBluetoothAddress &address) const + + Returns the current bluetooth pairing status of \a address, if it's unpaired, paired, or paired and authorized. +*/ + +/*! + \fn QBluetoothLocalDevice::requestPairing(const QBluetoothAddress &address, Pairing pairing) + + Set the \a pairing status with \a address. The results are returned by the signal, pairingFinished(). + + On Android and \macos, AuthorizedPaired is not possible and will have the same behavior as Paired. + On Windows the exact pairing mode decision is up to the operating system. + + On \macos, it is not possible to unpair a device. If Unpaired is requested, \l pairingFinished() + is immediately emitted although the device remains paired. It is possible to request the pairing + for a previously unpaired device. In addition \l AuthorizedPaired has the same behavior as \l Paired. + + Caution: creating a pairing may take minutes, and may require the user to acknowledge. +*/ + +/*! + \fn QBluetoothLocalDevice::pairingFinished(const QBluetoothAddress &address, + QBluetoothLocalDevice::Pairing pairing) + + Pairing or unpairing has completed with \a address. Current pairing status is in \a pairing. + If the pairing request was not successful, this signal will not be emitted. The errorOccurred() + signal is emitted if the pairing request failed. The signal is only ever emitted for pairing + requests which have previously requested by calling \l requestPairing() of the current object + instance. +*/ + +/*! + \fn QBluetoothLocalDevice::errorOccurred(QBluetoothLocalDevice::Error error) + Signal emitted if there's an exceptional \a error while pairing. + + \since 6.2 +*/ + +/*! + \fn QBluetoothLocalDevice::QBluetoothLocalDevice(const QBluetoothAddress &address, QObject *parent = 0) + + Construct new QBluetoothLocalDevice for \a address. If \a address is default constructed + the resulting local device selects the local default device. + + \include qbluetoothlocaldevice.cpp android-permissions-valid + \sa isValid() +*/ + +QT_END_NAMESPACE + +#include "moc_qbluetoothlocaldevice.cpp" diff --git a/src/bluetooth/qbluetoothlocaldevice.h b/src/bluetooth/qbluetoothlocaldevice.h new file mode 100644 index 0000000..298df95 --- /dev/null +++ b/src/bluetooth/qbluetoothlocaldevice.h @@ -0,0 +1,89 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QBLUETOOTHLOCALDEVICE_H +#define QBLUETOOTHLOCALDEVICE_H + +#include + +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +class QBluetoothLocalDevicePrivate; + +class Q_BLUETOOTH_EXPORT QBluetoothLocalDevice : public QObject +{ + Q_OBJECT + +public: + enum Pairing { + Unpaired, + Paired, + AuthorizedPaired + }; + Q_ENUM(Pairing) + + enum HostMode { + HostPoweredOff, + HostConnectable, + HostDiscoverable, + HostDiscoverableLimitedInquiry + }; + Q_ENUM(HostMode) + + enum Error { + NoError, + PairingError, + MissingPermissionsError, + UnknownError = 100 + }; + Q_ENUM(Error) + + explicit QBluetoothLocalDevice(QObject *parent = nullptr); + explicit QBluetoothLocalDevice(const QBluetoothAddress &address, QObject *parent = nullptr); + virtual ~QBluetoothLocalDevice(); + + bool isValid() const; + + void requestPairing(const QBluetoothAddress &address, Pairing pairing); + Pairing pairingStatus(const QBluetoothAddress &address) const; + + void setHostMode(QBluetoothLocalDevice::HostMode mode); + HostMode hostMode() const; + QList connectedDevices() const; + + void powerOn(); + + QString name() const; + QBluetoothAddress address() const; + + static QList allDevices(); + +Q_SIGNALS: + void hostModeStateChanged(QBluetoothLocalDevice::HostMode state); + void deviceConnected(const QBluetoothAddress &address); + void deviceDisconnected(const QBluetoothAddress &address); + void pairingFinished(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing); + + void errorOccurred(QBluetoothLocalDevice::Error error); + +private: + Q_DECLARE_PRIVATE(QBluetoothLocalDevice) + QBluetoothLocalDevicePrivate *d_ptr; +}; + +QT_END_NAMESPACE + +QT_DECL_METATYPE_EXTERN_TAGGED(QBluetoothLocalDevice::Pairing, QBluetoothLocalDevice__Pairing, + Q_BLUETOOTH_EXPORT) +QT_DECL_METATYPE_EXTERN_TAGGED(QBluetoothLocalDevice::HostMode, QBluetoothLocalDevice__HostMode, + Q_BLUETOOTH_EXPORT) +QT_DECL_METATYPE_EXTERN_TAGGED(QBluetoothLocalDevice::Error, QBluetoothLocalDevice__Error, + Q_BLUETOOTH_EXPORT) + +#endif // QBLUETOOTHLOCALDEVICE_H diff --git a/src/bluetooth/qbluetoothlocaldevice_android.cpp b/src/bluetooth/qbluetoothlocaldevice_android.cpp new file mode 100644 index 0000000..9dffeb8 --- /dev/null +++ b/src/bluetooth/qbluetoothlocaldevice_android.cpp @@ -0,0 +1,416 @@ +// Copyright (C) 2016 Lauri Laanmets (Proekspert AS) +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothlocaldevice_p.h" +#include "android/localdevicebroadcastreceiver_p.h" +#include "android/androidutils_p.h" +#include "android/jni_android_p.h" +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID) + +QBluetoothLocalDevicePrivate::QBluetoothLocalDevicePrivate( + QBluetoothLocalDevice *q, const QBluetoothAddress &address) : + q_ptr(q) +{ + registerQBluetoothLocalDeviceMetaType(); + + initialize(address); + + receiver = new LocalDeviceBroadcastReceiver(q_ptr); + connect(receiver, &LocalDeviceBroadcastReceiver::hostModeStateChanged, + this, &QBluetoothLocalDevicePrivate::processHostModeChange); + connect(receiver, &LocalDeviceBroadcastReceiver::pairingStateChanged, + this, &QBluetoothLocalDevicePrivate::processPairingStateChanged); + connect(receiver, &LocalDeviceBroadcastReceiver::connectDeviceChanges, + this, &QBluetoothLocalDevicePrivate::processConnectDeviceChanges); +} + +QBluetoothLocalDevicePrivate::~QBluetoothLocalDevicePrivate() +{ + receiver->unregisterReceiver(); + delete receiver; + delete obj; +} + +QJniObject *QBluetoothLocalDevicePrivate::adapter() +{ + return obj; +} + +void QBluetoothLocalDevicePrivate::initialize(const QBluetoothAddress &address) +{ + QJniObject adapter = getDefaultBluetoothAdapter(); + + if (!adapter.isValid()) { + qCWarning(QT_BT_ANDROID) << "Device does not support Bluetooth"; + return; + } + + if (!ensureAndroidPermission(QBluetoothPermission::Access)) { + qCWarning(QT_BT_ANDROID) << "Local device initialize() failed due to missing permissions"; + return; + } + + obj = new QJniObject(adapter); + if (!address.isNull()) { + const QString localAddress = obj->callMethod("getAddress").toString(); + if (localAddress != address.toString()) { + // passed address not local one -> invalid + delete obj; + obj = nullptr; + } + } +} + +bool QBluetoothLocalDevicePrivate::isValid() const +{ + return obj ? true : false; +} + +void QBluetoothLocalDevicePrivate::processHostModeChange(QBluetoothLocalDevice::HostMode newMode) +{ + qCDebug(QT_BT_ANDROID) << "Processing host mode change:" << newMode + << ", pending transition:" << pendingConnectableHostModeTransition; + if (!pendingConnectableHostModeTransition) { + // If host mode is not in transition -> pass data on + emit q_ptr->hostModeStateChanged(newMode); + return; + } + + // Host mode is in transition: check if the new mode is 'off' in which state + // we can enter the targeted 'Connectable' state + if (isValid() && newMode == QBluetoothLocalDevice::HostPoweredOff) { + const bool success = (bool)QJniObject::callStaticMethod( + QtJniTypes::Traits::className(), + "setEnabled"); + if (!success) { + qCWarning(QT_BT_ANDROID) << "Transitioning Bluetooth from OFF to ON failed"; + emit q_ptr->errorOccurred(QBluetoothLocalDevice::UnknownError); + } + } + pendingConnectableHostModeTransition = false; +} + +// Return -1 if address is not part of a pending pairing request +// Otherwise it returns the index of address in pendingPairings +int QBluetoothLocalDevicePrivate::pendingPairing(const QBluetoothAddress &address) +{ + for (qsizetype i = 0; i < pendingPairings.size(); ++i) { + if (pendingPairings.at(i).first == address) + return i; + } + + return -1; +} + +void QBluetoothLocalDevicePrivate::processPairingStateChanged( + const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing) +{ + int index = pendingPairing(address); + + if (index < 0) + return; // ignore unrelated pairing signals + + QPair entry = pendingPairings.takeAt(index); + if ((entry.second && pairing == QBluetoothLocalDevice::Paired) + || (!entry.second && pairing == QBluetoothLocalDevice::Unpaired)) { + emit q_ptr->pairingFinished(address, pairing); + } else { + emit q_ptr->errorOccurred(QBluetoothLocalDevice::PairingError); + } +} + +void QBluetoothLocalDevicePrivate::processConnectDeviceChanges(const QBluetoothAddress &address, + bool isConnectEvent) +{ + if (isConnectEvent) { // connect event + if (connectedDevices.contains(address)) + return; + connectedDevices.append(address); + emit q_ptr->deviceConnected(address); + } else { // disconnect event + connectedDevices.removeAll(address); + emit q_ptr->deviceDisconnected(address); + } +} + +QBluetoothLocalDevice::QBluetoothLocalDevice(QObject *parent) : + QObject(parent), + d_ptr(new QBluetoothLocalDevicePrivate(this, QBluetoothAddress())) +{ +} + +QBluetoothLocalDevice::QBluetoothLocalDevice(const QBluetoothAddress &address, QObject *parent) : + QObject(parent), + d_ptr(new QBluetoothLocalDevicePrivate(this, address)) +{ +} + +QString QBluetoothLocalDevice::name() const +{ + if (d_ptr->adapter()) + return d_ptr->adapter()->callMethod("getName").toString(); + + return QString(); +} + +QBluetoothAddress QBluetoothLocalDevice::address() const +{ + QString result; + if (d_ptr->adapter()) + result = d_ptr->adapter()->callMethod("getAddress").toString(); + + QBluetoothAddress address(result); + return address; +} + +void QBluetoothLocalDevice::powerOn() +{ + if (hostMode() != HostPoweredOff) + return; + + if (d_ptr->adapter()) { + bool success(false); + if (QNativeInterface::QAndroidApplication::sdkVersion() >= 31) { + success = (bool)QJniObject::callStaticMethod( + QtJniTypes::Traits::className(), + "setEnabled"); + } else { + success = (bool)d_ptr->adapter()->callMethod("enable"); + } + if (!success) { + qCWarning(QT_BT_ANDROID) << "Enabling bluetooth failed"; + emit errorOccurred(QBluetoothLocalDevice::UnknownError); + } + } +} + +void QBluetoothLocalDevice::setHostMode(QBluetoothLocalDevice::HostMode requestedMode) +{ + QBluetoothLocalDevice::HostMode nextMode = requestedMode; + if (requestedMode == HostDiscoverableLimitedInquiry) + nextMode = HostDiscoverable; + + if (nextMode == hostMode()) + return; + + switch (nextMode) { + + case QBluetoothLocalDevice::HostPoweredOff: { + bool success = false; + if (d_ptr->adapter()) { + if (QNativeInterface::QAndroidApplication::sdkVersion() >= 31) { + success = (bool)QJniObject::callStaticMethod( + QtJniTypes::Traits::className(), + "setDisabled"); + } else { + success = (bool)d_ptr->adapter()->callMethod("disable"); + } + } + if (!success) { + qCWarning(QT_BT_ANDROID) << "Unable to power off the adapter"; + emit errorOccurred(QBluetoothLocalDevice::UnknownError); + } + break; + } + + case QBluetoothLocalDevice::HostConnectable: { + if (hostMode() == QBluetoothLocalDevice::HostDiscoverable) { + // On Android 'Discoverable' is actually 'CONNECTABLE_DISCOVERABLE', and + // it seems we cannot go directly from "Discoverable" to "Connectable". Instead + // we need to go to disabled mode first and then to the 'Connectable' mode + setHostMode(QBluetoothLocalDevice::HostPoweredOff); + d_ptr->pendingConnectableHostModeTransition = true; + } else { + const bool success = (bool)QJniObject::callStaticMethod( + QtJniTypes::Traits::className(), + "setEnabled"); + if (!success) { + qCWarning(QT_BT_ANDROID) << "Unable to enable the Bluetooth"; + emit errorOccurred(QBluetoothLocalDevice::UnknownError); + } + } + break; + } + + case QBluetoothLocalDevice::HostDiscoverable: { + if (!ensureAndroidPermission(QBluetoothPermission::Advertise)) { + qCWarning(QT_BT_ANDROID) << "Local device setHostMode() failed due to " + "missing permissions"; + emit errorOccurred(QBluetoothLocalDevice::MissingPermissionsError); + return; + } + const bool success = (bool)QJniObject::callStaticMethod( + QtJniTypes::Traits::className(), + "setDiscoverable"); + if (!success) { + qCWarning(QT_BT_ANDROID) << "Unable to set Bluetooth as discoverable"; + emit errorOccurred(QBluetoothLocalDevice::UnknownError); + } + break; + } + default: + qCWarning(QT_BT_ANDROID) << "setHostMode() unsupported host mode:" << nextMode; + break; + } +} + +QBluetoothLocalDevice::HostMode QBluetoothLocalDevice::hostMode() const +{ + if (d_ptr->adapter()) { + jint scanMode = d_ptr->adapter()->callMethod("getScanMode"); + + switch (scanMode) { + case 20: // BluetoothAdapter.SCAN_MODE_NONE + return HostPoweredOff; + case 21: // BluetoothAdapter.SCAN_MODE_CONNECTABLE + return HostConnectable; + case 23: // BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE + return HostDiscoverable; + default: + break; + } + } + + return HostPoweredOff; +} + +QList QBluetoothLocalDevice::allDevices() +{ + // As a static class function we need to ensure permissions here (in addition to initialize()) + if (!ensureAndroidPermission(QBluetoothPermission::Access)) { + qCWarning(QT_BT_ANDROID) << "Local device allDevices() failed due to " + "missing permissions"; + return {}; + } + // Android only supports max of one device (so far) + QList localDevices; + + QJniObject o = getDefaultBluetoothAdapter(); + if (o.isValid()) { + QBluetoothHostInfo info; + info.setName(o.callMethod("getName").toString()); + info.setAddress(QBluetoothAddress(o.callMethod("getAddress").toString())); + localDevices.append(info); + } + return localDevices; +} + +void QBluetoothLocalDevice::requestPairing(const QBluetoothAddress &address, Pairing pairing) +{ + if (address.isNull()) { + QMetaObject::invokeMethod(this, "errorOccurred", Qt::QueuedConnection, + Q_ARG(QBluetoothLocalDevice::Error, + QBluetoothLocalDevice::PairingError)); + return; + } + + const Pairing previousPairing = pairingStatus(address); + Pairing newPairing = pairing; + if (pairing == AuthorizedPaired) // AuthorizedPaired same as Paired on Android + newPairing = Paired; + + if (previousPairing == newPairing) { + QMetaObject::invokeMethod(this, "pairingFinished", Qt::QueuedConnection, + Q_ARG(QBluetoothAddress, address), + Q_ARG(QBluetoothLocalDevice::Pairing, newPairing)); + return; + } + + if (!d_ptr->adapter()) { + qCWarning(QT_BT_ANDROID) << "Unable to pair, invalid adapter"; + QMetaObject::invokeMethod(this, "errorOccurred", Qt::QueuedConnection, + Q_ARG(QBluetoothLocalDevice::Error, + QBluetoothLocalDevice::PairingError)); + return; + } + + QJniObject inputString = QJniObject::fromString(address.toString()); + jboolean success = QJniObject::callStaticMethod( + QtJniTypes::Traits::className(), + "setPairingMode", + inputString.object(), + jboolean(newPairing == Paired ? JNI_TRUE : JNI_FALSE)); + + if (!success) { + QMetaObject::invokeMethod(this, "errorOccurred", Qt::QueuedConnection, + Q_ARG(QBluetoothLocalDevice::Error, + QBluetoothLocalDevice::PairingError)); + } else { + d_ptr->pendingPairings.append(qMakePair(address, newPairing == Paired ? true : false)); + } +} + +QBluetoothLocalDevice::Pairing QBluetoothLocalDevice::pairingStatus( + const QBluetoothAddress &address) const +{ + if (address.isNull() || !d_ptr->adapter()) + return Unpaired; + + QJniObject inputString = QJniObject::fromString(address.toString()); + QJniObject remoteDevice + = d_ptr->adapter()->callMethod("getRemoteDevice", + inputString.object()); + + if (!remoteDevice.isValid()) + return Unpaired; + + jint bondState = remoteDevice.callMethod("getBondState"); + switch (bondState) { + case 12: // BluetoothDevice.BOND_BONDED + return Paired; + default: + break; + } + + return Unpaired; +} + +QList QBluetoothLocalDevice::connectedDevices() const +{ + /* + * Android does not have an API to list all connected devices. We have to collect + * the information based on a few indicators. + * + * Primarily we detect connected devices by monitoring connect/disconnect signals. + * Unfortunately the list may only be complete after very long monitoring time. + * However there are some Android APIs which provide the list of connected devices + * for specific Bluetooth profiles. QtBluetoothBroadcastReceiver.getConnectedDevices() + * returns a few connections of common profiles. The returned list is not complete either + * but at least it can complement our already detected connections. + */ + QJniObject connectedDevices = QJniObject::callStaticMethod( + QtJniTypes::Traits::className(), "getConnectedDevices"); + + if (!connectedDevices.isValid()) + return d_ptr->connectedDevices; + + jobjectArray connectedDevicesArray = connectedDevices.object(); + if (!connectedDevicesArray) + return d_ptr->connectedDevices; + + QJniEnvironment env; + QList knownAddresses = d_ptr->connectedDevices; + QJniObject p; + + jint size = env->GetArrayLength(connectedDevicesArray); + for (int i = 0; i < size; i++) { + p = env->GetObjectArrayElement(connectedDevicesArray, i); + QBluetoothAddress address(p.toString()); + if (!address.isNull() && !knownAddresses.contains(address)) + knownAddresses.append(address); + } + + return knownAddresses; +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothlocaldevice_bluez.cpp b/src/bluetooth/qbluetoothlocaldevice_bluez.cpp new file mode 100644 index 0000000..7bac1de --- /dev/null +++ b/src/bluetooth/qbluetoothlocaldevice_bluez.cpp @@ -0,0 +1,691 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include +#include +#include + +#include "qbluetoothlocaldevice.h" +#include "qbluetoothaddress.h" +#include "qbluetoothlocaldevice_p.h" + +#include "bluez/bluez5_helper_p.h" +#include "bluez/objectmanager_p.h" +#include "bluez/properties_p.h" +#include "bluez/adapter1_bluez5_p.h" +#include "bluez/device1_bluez5_p.h" + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ) + +QBluetoothLocalDevice::QBluetoothLocalDevice(QObject *parent) : + QObject(parent), + d_ptr(new QBluetoothLocalDevicePrivate(this)) +{ + d_ptr->currentMode = hostMode(); +} + +QBluetoothLocalDevice::QBluetoothLocalDevice(const QBluetoothAddress &address, QObject *parent) : + QObject(parent), + d_ptr(new QBluetoothLocalDevicePrivate(this, address)) +{ + d_ptr->currentMode = hostMode(); +} + +QString QBluetoothLocalDevice::name() const +{ + if (d_ptr->adapter) + return d_ptr->adapter->alias(); + + return QString(); +} + +QBluetoothAddress QBluetoothLocalDevice::address() const +{ + if (d_ptr->adapter) + return QBluetoothAddress(d_ptr->adapter->address()); + + return QBluetoothAddress(); +} + +void QBluetoothLocalDevice::powerOn() +{ + if (d_ptr->adapter) + d_ptr->adapter->setPowered(true); +} + +void QBluetoothLocalDevice::setHostMode(QBluetoothLocalDevice::HostMode mode) +{ + if (!isValid()) + return; + + Q_D(QBluetoothLocalDevice); + + if (d->pendingHostModeChange != -1) { + qCWarning(QT_BT_BLUEZ) << "setHostMode() ignored due to already pending mode change"; + return; + } + + switch (mode) { + case HostDiscoverableLimitedInquiry: + case HostDiscoverable: + if (hostMode() == HostPoweredOff) { + // We first have to wait for BT to be powered on, + // then we can set the host mode correctly + d->pendingHostModeChange = static_cast(HostDiscoverable); + d->adapter->setPowered(true); + } else { + d->adapter->setDiscoverable(true); + } + break; + case HostConnectable: + if (hostMode() == HostPoweredOff) { + d->pendingHostModeChange = static_cast(HostConnectable); + d->adapter->setPowered(true); + } else { + d->adapter->setDiscoverable(false); + } + break; + case HostPoweredOff: + d->adapter->setPowered(false); + break; + } +} + +QBluetoothLocalDevice::HostMode QBluetoothLocalDevice::hostMode() const +{ + if (d_ptr->adapter) { + if (!d_ptr->adapter->powered()) + return HostPoweredOff; + else if (d_ptr->adapter->discoverable()) + return HostDiscoverable; + else if (d_ptr->adapter->powered()) + return HostConnectable; + } + + return HostPoweredOff; +} + +QList QBluetoothLocalDevice::connectedDevices() const +{ + return d_ptr->connectedDevices(); +} + +QList QBluetoothLocalDevice::allDevices() +{ + QList localDevices; + + initializeBluez5(); + OrgFreedesktopDBusObjectManagerInterface manager( + QStringLiteral("org.bluez"), QStringLiteral("/"), QDBusConnection::systemBus()); + QDBusPendingReply reply = manager.GetManagedObjects(); + reply.waitForFinished(); + if (reply.isError()) + return localDevices; + + ManagedObjectList managedObjectList = reply.value(); + for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); + it != managedObjectList.constEnd(); ++it) { + const InterfaceList &ifaceList = it.value(); + + for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); + ++jt) { + const QString &iface = jt.key(); + const QVariantMap &ifaceValues = jt.value(); + + if (iface == QStringLiteral("org.bluez.Adapter1")) { + QBluetoothHostInfo hostInfo; + const QString temp = ifaceValues.value(QStringLiteral("Address")).toString(); + + hostInfo.setAddress(QBluetoothAddress(temp)); + if (hostInfo.address().isNull()) + continue; + hostInfo.setName(ifaceValues.value(QStringLiteral("Name")).toString()); + localDevices.append(hostInfo); + } + } + } + return localDevices; +} + +void QBluetoothLocalDevice::requestPairing(const QBluetoothAddress &address, Pairing pairing) +{ + if (!isValid() || address.isNull()) { + QMetaObject::invokeMethod(this, "errorOccurred", Qt::QueuedConnection, + Q_ARG(QBluetoothLocalDevice::Error, + QBluetoothLocalDevice::PairingError)); + return; + } + + const Pairing current_pairing = pairingStatus(address); + if (current_pairing == pairing) { + if (d_ptr->adapter) { + // A possibly running discovery or pending pairing request should be canceled + if (d_ptr->pairingDiscoveryTimer && d_ptr->pairingDiscoveryTimer->isActive()) { + d_ptr->pairingDiscoveryTimer->stop(); + } + + if (d_ptr->pairingTarget) { + qCDebug(QT_BT_BLUEZ) << "Cancelling pending pairing request to" << d_ptr->pairingTarget->address(); + QDBusPendingReply<> cancelReply = d_ptr->pairingTarget->CancelPairing(); + d_ptr->pairingRequestCanceled = true; + cancelReply.waitForFinished(); + delete d_ptr->pairingTarget; + d_ptr->pairingTarget = nullptr; + } + } + QMetaObject::invokeMethod(this, "pairingFinished", Qt::QueuedConnection, + Q_ARG(QBluetoothAddress, address), + Q_ARG(QBluetoothLocalDevice::Pairing, pairing)); + return; + } + + d_ptr->requestPairing(address, pairing); +} + +void QBluetoothLocalDevicePrivate::requestPairing(const QBluetoothAddress &targetAddress, + QBluetoothLocalDevice::Pairing targetPairing) +{ + if (!isValid()) + return; + + //are we already discovering something? -> abort those attempts + if (pairingDiscoveryTimer && pairingDiscoveryTimer->isActive()) { + pairingDiscoveryTimer->stop(); + QtBluezDiscoveryManager::instance()->unregisterDiscoveryInterest(adapter->path()); + } + + if (pairingTarget) { + delete pairingTarget; + pairingTarget = nullptr; + } + + // pairing implies that the device was found + // if we cannot find it we may have to turn on Discovery mode for a limited amount of time + + // check device doesn't already exist + QDBusPendingReply reply = manager->GetManagedObjects(); + reply.waitForFinished(); + if (reply.isError()) { + emit q_ptr->errorOccurred(QBluetoothLocalDevice::PairingError); + return; + } + + ManagedObjectList managedObjectList = reply.value(); + for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) { + const QDBusObjectPath &path = it.key(); + const InterfaceList &ifaceList = it.value(); + + for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) { + const QString &iface = jt.key(); + + if (iface == QStringLiteral("org.bluez.Device1")) { + + OrgBluezDevice1Interface device(QStringLiteral("org.bluez"), + path.path(), + QDBusConnection::systemBus()); + if (targetAddress == QBluetoothAddress(device.address())) { + qCDebug(QT_BT_BLUEZ) << "Initiating direct pair to" << targetAddress.toString(); + //device exist -> directly work with it + processPairing(path.path(), targetPairing); + return; + } + } + } + } + + //no device matching -> turn on discovery + QtBluezDiscoveryManager::instance()->registerDiscoveryInterest(adapter->path()); + + address = targetAddress; + pairing = targetPairing; + if (!pairingDiscoveryTimer) { + pairingDiscoveryTimer = new QTimer(this); + pairingDiscoveryTimer->setSingleShot(true); + pairingDiscoveryTimer->setInterval(20000); //20s + connect(pairingDiscoveryTimer, &QTimer::timeout, + this, &QBluetoothLocalDevicePrivate::pairingDiscoveryTimedOut); + } + + qCDebug(QT_BT_BLUEZ) << "Initiating discovery for pairing on" << targetAddress.toString(); + pairingDiscoveryTimer->start(); +} + +/*! + * \internal + * + * Found a matching device. Now we must ensure its pairing/trusted state is as desired. + * If it has to be paired then we need another roundtrip through the event loop + * while we wait for the user to accept the pairing dialogs. + */ +void QBluetoothLocalDevicePrivate::processPairing(const QString &objectPath, + QBluetoothLocalDevice::Pairing target) +{ + if (pairingTarget) + delete pairingTarget; + + //stop possibly running discovery + if (pairingDiscoveryTimer && pairingDiscoveryTimer->isActive()) { + pairingDiscoveryTimer->stop(); + + QtBluezDiscoveryManager::instance()->unregisterDiscoveryInterest(adapter->path()); + } + + pairingTarget = new OrgBluezDevice1Interface(QStringLiteral("org.bluez"), objectPath, + QDBusConnection::systemBus(), this); + const QBluetoothAddress targetAddress(pairingTarget->address()); + + Q_Q(QBluetoothLocalDevice); + + switch (target) { + case QBluetoothLocalDevice::Unpaired: { + delete pairingTarget; + pairingTarget = nullptr; + + QDBusPendingReply<> removeReply = adapter->RemoveDevice(QDBusObjectPath(objectPath)); + auto watcher = new QDBusPendingCallWatcher(removeReply, this); + connect(watcher, &QDBusPendingCallWatcher::finished, + this, [q, targetAddress](QDBusPendingCallWatcher* watcher){ + QDBusPendingReply<> reply = *watcher; + if (reply.isError()) + emit q->errorOccurred(QBluetoothLocalDevice::PairingError); + else + emit q->pairingFinished(targetAddress, QBluetoothLocalDevice::Unpaired); + + watcher->deleteLater(); + }); + break; + } + case QBluetoothLocalDevice::Paired: + case QBluetoothLocalDevice::AuthorizedPaired: + pairing = target; + + if (!pairingTarget->paired()) { + qCDebug(QT_BT_BLUEZ) << "Sending pairing request to" << pairingTarget->address(); + //initiate the pairing + QDBusPendingReply<> pairReply = pairingTarget->Pair(); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pairReply, this); + connect(watcher, &QDBusPendingCallWatcher::finished, + this, &QBluetoothLocalDevicePrivate::pairingCompleted); + return; + } + + //already paired but Trust level must be adjusted + if (target == QBluetoothLocalDevice::AuthorizedPaired && !pairingTarget->trusted()) + pairingTarget->setTrusted(true); + else if (target == QBluetoothLocalDevice::Paired && pairingTarget->trusted()) + pairingTarget->setTrusted(false); + + delete pairingTarget; + pairingTarget = nullptr; + + emit q->pairingFinished(targetAddress, target); + + break; + default: + break; + } +} + +void QBluetoothLocalDevicePrivate::pairingDiscoveryTimedOut() +{ + qCWarning(QT_BT_BLUEZ) << "Discovery for pairing purposes failed. Cannot find parable device."; + + QtBluezDiscoveryManager::instance()->unregisterDiscoveryInterest(adapter->path()); + + emit q_ptr->errorOccurred(QBluetoothLocalDevice::PairingError); +} + +QBluetoothLocalDevice::Pairing QBluetoothLocalDevice::pairingStatus( + const QBluetoothAddress &address) const +{ + if (address.isNull()) + return Unpaired; + + if (isValid()) + { + QDBusPendingReply reply = d_ptr->manager->GetManagedObjects(); + reply.waitForFinished(); + if (reply.isError()) + return Unpaired; + + ManagedObjectList managedObjectList = reply.value(); + for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) { + const QDBusObjectPath &path = it.key(); + const InterfaceList &ifaceList = it.value(); + + for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) { + const QString &iface = jt.key(); + + if (iface == QStringLiteral("org.bluez.Device1")) { + + OrgBluezDevice1Interface device(QStringLiteral("org.bluez"), + path.path(), + QDBusConnection::systemBus()); + + if (address == QBluetoothAddress(device.address())) { + if (device.trusted() && device.paired()) + return AuthorizedPaired; + else if (device.paired()) + return Paired; + else + return Unpaired; + } + } + } + } + } + + return Unpaired; +} + +QBluetoothLocalDevicePrivate::QBluetoothLocalDevicePrivate(QBluetoothLocalDevice *q, + QBluetoothAddress address) : + localAddress(address), + pendingHostModeChange(-1), + q_ptr(q) +{ + registerQBluetoothLocalDeviceMetaType(); + initializeBluez5(); + initializeAdapter(); + + connectDeviceChanges(); +} + +bool objectPathIsForThisDevice(const QString &adapterPath, const QString &objectPath) +{ + return (!adapterPath.isEmpty() && objectPath.startsWith(adapterPath)); +} + +void QBluetoothLocalDevicePrivate::connectDeviceChanges() +{ + if (isValid()) { + //setup property change notifications for all existing devices + QDBusPendingReply reply = manager->GetManagedObjects(); + reply.waitForFinished(); + if (reply.isError()) + return; + + OrgFreedesktopDBusPropertiesInterface *monitor = nullptr; + + ManagedObjectList managedObjectList = reply.value(); + for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) { + const QDBusObjectPath &path = it.key(); + const InterfaceList &ifaceList = it.value(); + + // don't track connected devices from other adapters but the current + if (!objectPathIsForThisDevice(deviceAdapterPath, path.path())) + continue; + + for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) { + const QString &iface = jt.key(); + const QVariantMap &ifaceValues = jt.value(); + + if (iface == QStringLiteral("org.bluez.Device1")) { + monitor = new OrgFreedesktopDBusPropertiesInterface(QStringLiteral("org.bluez"), + path.path(), + QDBusConnection::systemBus(), this); + connect(monitor, &OrgFreedesktopDBusPropertiesInterface::PropertiesChanged, + this, &QBluetoothLocalDevicePrivate::PropertiesChanged); + deviceChangeMonitors.insert(path.path(), monitor); + + if (ifaceValues.value(QStringLiteral("Connected"), false).toBool()) { + QBluetoothAddress address(ifaceValues.value(QStringLiteral("Address")).toString()); + connectedDevicesSet.insert(address); + } + } + } + } + } +} + +QBluetoothLocalDevicePrivate::~QBluetoothLocalDevicePrivate() +{ + delete adapter; + delete adapterProperties; + delete manager; + delete pairingTarget; + + qDeleteAll(deviceChangeMonitors); +} + +void QBluetoothLocalDevicePrivate::initializeAdapter() +{ + if (adapter) + return; + + //get all local adapters + if (!manager) + manager = new OrgFreedesktopDBusObjectManagerInterface( + QStringLiteral("org.bluez"), + QStringLiteral("/"), + QDBusConnection::systemBus(), this); + + connect(manager, &OrgFreedesktopDBusObjectManagerInterface::InterfacesAdded, + this, &QBluetoothLocalDevicePrivate::InterfacesAdded); + connect(manager, &OrgFreedesktopDBusObjectManagerInterface::InterfacesRemoved, + this, &QBluetoothLocalDevicePrivate::InterfacesRemoved); + + bool ok = true; + const QString adapterPath = findAdapterForAddress(localAddress, &ok); + if (!ok || adapterPath.isEmpty()) + return; + + deviceAdapterPath = adapterPath; + adapter = new OrgBluezAdapter1Interface(QStringLiteral("org.bluez"), adapterPath, + QDBusConnection::systemBus(), this); + + if (adapter) { + //hook up propertiesChanged for current adapter + adapterProperties = new OrgFreedesktopDBusPropertiesInterface( + QStringLiteral("org.bluez"), adapter->path(), + QDBusConnection::systemBus(), this); + connect(adapterProperties, &OrgFreedesktopDBusPropertiesInterface::PropertiesChanged, + this, &QBluetoothLocalDevicePrivate::PropertiesChanged); + } +} + +void QBluetoothLocalDevicePrivate::PropertiesChanged(const QString &interface, + const QVariantMap &changed_properties, + const QStringList &/*invalidated_properties*/, + const QDBusMessage &) +{ + //qDebug() << "Change" << interface << changed_properties; + if (interface == QStringLiteral("org.bluez.Adapter1")) { + //update host mode + if (changed_properties.contains(QStringLiteral("Discoverable")) + || changed_properties.contains(QStringLiteral("Powered"))) { + + QBluetoothLocalDevice::HostMode mode; + + if (!adapter->powered()) { + mode = QBluetoothLocalDevice::HostPoweredOff; + } else { + if (adapter->discoverable()) + mode = QBluetoothLocalDevice::HostDiscoverable; + else + mode = QBluetoothLocalDevice::HostConnectable; + + if (pendingHostModeChange != -1) { + + if (static_cast(mode) != pendingHostModeChange) { + adapter->setDiscoverable( + pendingHostModeChange + == static_cast(QBluetoothLocalDevice::HostDiscoverable)); + pendingHostModeChange = -1; + return; + } + pendingHostModeChange = -1; + } + } + + if (mode != currentMode) + emit q_ptr->hostModeStateChanged(mode); + + currentMode = mode; + } + } else if (interface == QStringLiteral("org.bluez.Device1") + && changed_properties.contains(QStringLiteral("Connected"))) { + // update list of connected devices + OrgFreedesktopDBusPropertiesInterface *senderIface = + qobject_cast(sender()); + if (!senderIface) + return; + + const QString currentPath = senderIface->path(); + bool isConnected = changed_properties.value(QStringLiteral("Connected"), false).toBool(); + OrgBluezDevice1Interface device(QStringLiteral("org.bluez"), currentPath, + QDBusConnection::systemBus()); + const QBluetoothAddress changedAddress(device.address()); + bool isInSet = connectedDevicesSet.contains(changedAddress); + if (isConnected && !isInSet) { + connectedDevicesSet.insert(changedAddress); + emit q_ptr->deviceConnected(changedAddress); + } else if (!isConnected && isInSet) { + connectedDevicesSet.remove(changedAddress); + emit q_ptr->deviceDisconnected(changedAddress); + } + } +} + +void QBluetoothLocalDevicePrivate::InterfacesAdded(const QDBusObjectPath &object_path, InterfaceList interfaces_and_properties) +{ + if (interfaces_and_properties.contains(QStringLiteral("org.bluez.Device1")) + && !deviceChangeMonitors.contains(object_path.path())) { + // a new device was added which we need to add to list of known devices + + if (objectPathIsForThisDevice(deviceAdapterPath, object_path.path())) { + OrgFreedesktopDBusPropertiesInterface *monitor = new OrgFreedesktopDBusPropertiesInterface( + QStringLiteral("org.bluez"), + object_path.path(), + QDBusConnection::systemBus()); + connect(monitor, &OrgFreedesktopDBusPropertiesInterface::PropertiesChanged, + this, &QBluetoothLocalDevicePrivate::PropertiesChanged); + deviceChangeMonitors.insert(object_path.path(), monitor); + + const QVariantMap ifaceValues = interfaces_and_properties.value(QStringLiteral("org.bluez.Device1")); + if (ifaceValues.value(QStringLiteral("Connected"), false).toBool()) { + QBluetoothAddress address(ifaceValues.value(QStringLiteral("Address")).toString()); + connectedDevicesSet.insert(address); + emit q_ptr->deviceConnected(address); + } + } + } + + if (pairingDiscoveryTimer && pairingDiscoveryTimer->isActive() + && interfaces_and_properties.contains(QStringLiteral("org.bluez.Device1"))) { + //device discovery for pairing found new remote device + OrgBluezDevice1Interface device(QStringLiteral("org.bluez"), + object_path.path(), QDBusConnection::systemBus()); + if (!address.isNull() && address == QBluetoothAddress(device.address())) + processPairing(object_path.path(), pairing); + } +} + +void QBluetoothLocalDevicePrivate::InterfacesRemoved(const QDBusObjectPath &object_path, + const QStringList &interfaces) +{ + if (deviceChangeMonitors.contains(object_path.path()) + && interfaces.contains(QLatin1String("org.bluez.Device1"))) { + + if (objectPathIsForThisDevice(deviceAdapterPath, object_path.path())) { + //a device was removed + delete deviceChangeMonitors.take(object_path.path()); + + //the path contains the address (e.g.: /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX) + //-> use it to update current list of connected devices + QString addressString = object_path.path().right(17); + addressString.replace(QStringLiteral("_"), QStringLiteral(":")); + const QBluetoothAddress address(addressString); + bool found = connectedDevicesSet.remove(address); + if (found) + emit q_ptr->deviceDisconnected(address); + } + } + + if (adapter && object_path.path() == adapter->path() + && interfaces.contains(QLatin1String("org.bluez.Adapter1"))) { + qCDebug(QT_BT_BLUEZ) << "Adapter" << adapter->path() << "was removed"; + // current adapter was removed -> invalidate the instance + delete adapter; + adapter = nullptr; + manager->deleteLater(); + manager = nullptr; + delete adapterProperties; + adapterProperties = nullptr; + + delete pairingTarget; + pairingTarget = nullptr; + + // turn off connectivity monitoring + qDeleteAll(deviceChangeMonitors); + deviceChangeMonitors.clear(); + connectedDevicesSet.clear(); + } +} + +bool QBluetoothLocalDevicePrivate::isValid() const +{ + return adapter && manager; +} + +QList QBluetoothLocalDevicePrivate::connectedDevices() const +{ + return connectedDevicesSet.values(); +} + +void QBluetoothLocalDevicePrivate::pairingCompleted(QDBusPendingCallWatcher *watcher) +{ + Q_Q(QBluetoothLocalDevice); + QDBusPendingReply<> reply = *watcher; + + if (reply.isError()) { + qCWarning(QT_BT_BLUEZ) << "Failed to create pairing" << reply.error().name(); + const bool canceledByUs = + (reply.error().name() == QStringLiteral("org.bluez.Error.AuthenticationCanceled")) + && pairingRequestCanceled; + if (!canceledByUs) + emit q->errorOccurred(QBluetoothLocalDevice::PairingError); + + pairingRequestCanceled = false; + watcher->deleteLater(); + return; + } + + pairingRequestCanceled = false; + + if (adapter) { + if (!pairingTarget) { + qCWarning(QT_BT_BLUEZ) << "Pairing target expected but found null pointer."; + emit q->errorOccurred(QBluetoothLocalDevice::PairingError); + watcher->deleteLater(); + return; + } + + if (!pairingTarget->paired()) { + qCWarning(QT_BT_BLUEZ) << "Device was not paired as requested"; + emit q->errorOccurred(QBluetoothLocalDevice::PairingError); + watcher->deleteLater(); + return; + } + + const QBluetoothAddress targetAddress(pairingTarget->address()); + + if (pairing == QBluetoothLocalDevice::AuthorizedPaired && !pairingTarget->trusted()) + pairingTarget->setTrusted(true); + else if (pairing == QBluetoothLocalDevice::Paired && pairingTarget->trusted()) + pairingTarget->setTrusted(false); + + delete pairingTarget; + pairingTarget = nullptr; + + emit q->pairingFinished(targetAddress, pairing); + } + + watcher->deleteLater(); +} + +QT_END_NAMESPACE + +#include "moc_qbluetoothlocaldevice_p.cpp" diff --git a/src/bluetooth/qbluetoothlocaldevice_macos.mm b/src/bluetooth/qbluetoothlocaldevice_macos.mm new file mode 100644 index 0000000..3d1da5e --- /dev/null +++ b/src/bluetooth/qbluetoothlocaldevice_macos.mm @@ -0,0 +1,457 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "darwin/btconnectionmonitor_p.h" +#include "qbluetoothlocaldevice_p.h" +#include "qbluetoothlocaldevice.h" +#include "darwin/btdevicepair_p.h" +#include "darwin/btdelegates_p.h" +#include "darwin/btutility_p.h" + +#include +#include +#include +#include +#include + + +#include + +#include + +#include + +QT_BEGIN_NAMESPACE + +class QBluetoothLocalDevicePrivate : public DarwinBluetooth::PairingDelegate, + public DarwinBluetooth::ConnectionMonitor +{ + friend class QBluetoothLocalDevice; +public: + typedef QBluetoothLocalDevice::Pairing Pairing; + + QBluetoothLocalDevicePrivate(QBluetoothLocalDevice *, const QBluetoothAddress & = + QBluetoothAddress()); + ~QBluetoothLocalDevicePrivate(); + + bool isValid() const; + void requestPairing(const QBluetoothAddress &address, Pairing pairing); + Pairing pairingStatus(const QBluetoothAddress &address) const; + +private: + + // PairingDelegate: + void connecting(void *pair) override; + void requestPIN(void *pair) override; + void requestUserConfirmation(void *pair, + BluetoothNumericValue) override; + void passkeyNotification(void *pair, + BluetoothPasskey passkey) override; + void error(void *pair, IOReturn errorCode) override; + void pairingFinished(void *pair) override; + + // ConnectionMonitor + void deviceConnected(const QBluetoothAddress &deviceAddress) override; + void deviceDisconnected(const QBluetoothAddress &deviceAddress) override; + + void emitPairingFinished(const QBluetoothAddress &deviceAddress, Pairing pairing, bool queued); + void emitError(QBluetoothLocalDevice::Error error, bool queued); + + void unpair(const QBluetoothAddress &deviceAddress); + + QBluetoothLocalDevice *q_ptr; + + using HostController = DarwinBluetooth::ObjCScopedPointer; + HostController hostController; + + using PairingRequest = DarwinBluetooth::ObjCStrongReference; + using RequestMap = QMap; + + RequestMap pairingRequests; + DarwinBluetooth::ObjCScopedPointer connectionMonitor; + QList discoveredDevices; +}; + +QBluetoothLocalDevicePrivate::QBluetoothLocalDevicePrivate(QBluetoothLocalDevice *q, + const QBluetoothAddress &address) : + q_ptr(q) +{ + registerQBluetoothLocalDeviceMetaType(); + Q_ASSERT_X(q, Q_FUNC_INFO, "invalid q_ptr (null)"); + + QT_BT_MAC_AUTORELEASEPOOL; + + using namespace DarwinBluetooth; + + ObjCScopedPointer defaultController([IOBluetoothHostController defaultController], + RetainPolicy::doInitialRetain); + if (!defaultController) { + qCCritical(QT_BT_DARWIN) << "failed to init a host controller object"; + return; + } + + if (!address.isNull()) { + NSString *const hciAddress = [defaultController addressAsString]; + if (!hciAddress) { + qCCritical(QT_BT_DARWIN) << "failed to obtain an address"; + return; + } + + BluetoothDeviceAddress iobtAddress = {}; + if (IOBluetoothNSStringToDeviceAddress(hciAddress, &iobtAddress) != kIOReturnSuccess) { + qCCritical(QT_BT_DARWIN) << "invalid local device's address"; + return; + } + + if (address != DarwinBluetooth::qt_address(&iobtAddress)) { + qCCritical(QT_BT_DARWIN) << "invalid local device's address"; + return; + } + } + + defaultController.swap(hostController); + // This one is optional, if it fails to initialize, we do not care at all. + connectionMonitor.reset([[DarwinBTConnectionMonitor alloc] initWithMonitor:this], + DarwinBluetooth::RetainPolicy::noInitialRetain); +} + +QBluetoothLocalDevicePrivate::~QBluetoothLocalDevicePrivate() +{ + + [connectionMonitor stopMonitoring]; +} + +bool QBluetoothLocalDevicePrivate::isValid() const +{ + return hostController; +} + +void QBluetoothLocalDevicePrivate::requestPairing(const QBluetoothAddress &address, Pairing pairing) +{ + Q_ASSERT_X(isValid(), Q_FUNC_INFO, "invalid local device"); + Q_ASSERT_X(!address.isNull(), Q_FUNC_INFO, "invalid device address"); + + using DarwinBluetooth::device_with_address; + using DarwinBluetooth::ObjCStrongReference; + using DarwinBluetooth::RetainPolicy; + + // That's a really special case on OS X. + if (pairing == QBluetoothLocalDevice::Unpaired) + return unpair(address); + + QT_BT_MAC_AUTORELEASEPOOL; + + if (pairing == QBluetoothLocalDevice::AuthorizedPaired) + pairing = QBluetoothLocalDevice::Paired; + + RequestMap::iterator pos = pairingRequests.find(address); + if (pos != pairingRequests.end()) { + if ([pos.value() isActive]) // Still trying to pair, continue. + return; + + // 'device' is autoreleased: + IOBluetoothDevice *const device = [pos.value() targetDevice]; + if ([device isPaired]) { + emitPairingFinished(address, pairing, true); + } else if ([pos.value() start] != kIOReturnSuccess) { + qCCritical(QT_BT_DARWIN) << "failed to start a new pairing request"; + emitError(QBluetoothLocalDevice::PairingError, true); + } + return; + } + + // That's a totally new request ('Paired', since we are here). + // Even if this device is paired (not by our local device), I still create a pairing request, + // it'll just finish with success (skipping any intermediate steps). + PairingRequest newRequest([[DarwinBTClassicPairing alloc] initWithTarget:address delegate:this], + RetainPolicy::noInitialRetain); + if (!newRequest) { + qCCritical(QT_BT_DARWIN) << "failed to allocate a new pairing request"; + emitError(QBluetoothLocalDevice::PairingError, true); + return; + } + + pos = pairingRequests.insert(address, newRequest); + const IOReturn result = [newRequest start]; + if (result != kIOReturnSuccess) { + pairingRequests.erase(pos); + qCCritical(QT_BT_DARWIN) << "failed to start a new pairing request"; + emitError(QBluetoothLocalDevice::PairingError, true); + } +} + +QBluetoothLocalDevice::Pairing QBluetoothLocalDevicePrivate::pairingStatus(const QBluetoothAddress &address)const +{ + Q_ASSERT_X(isValid(), Q_FUNC_INFO, "invalid local device"); + Q_ASSERT_X(!address.isNull(), Q_FUNC_INFO, "invalid address"); + + using DarwinBluetooth::device_with_address; + using DarwinBluetooth::ObjCStrongReference; + + QT_BT_MAC_AUTORELEASEPOOL; + + RequestMap::const_iterator it = pairingRequests.find(address); + if (it != pairingRequests.end()) { + // All Obj-C objects are autoreleased. + IOBluetoothDevice *const device = [it.value() targetDevice]; + if (device && [device isPaired]) + return QBluetoothLocalDevice::Paired; + } else { + // Try even if device was not paired by this local device ... + const ObjCStrongReference device(device_with_address(address)); + if (device && [device isPaired]) + return QBluetoothLocalDevice::Paired; + } + + return QBluetoothLocalDevice::Unpaired; +} + +void QBluetoothLocalDevicePrivate::connecting(void *pair) +{ + // TODO: why unused and if cannot be used - remove? + Q_UNUSED(pair); +} + +void QBluetoothLocalDevicePrivate::requestPIN(void *pair) +{ + // TODO: why unused and if cannot be used - remove? + Q_UNUSED(pair); +} + +void QBluetoothLocalDevicePrivate::requestUserConfirmation(void *pair, BluetoothNumericValue intPin) +{ + // TODO: why unused and if cannot be used - remove? + Q_UNUSED(pair); + Q_UNUSED(intPin); +} + +void QBluetoothLocalDevicePrivate::passkeyNotification(void *pair, BluetoothPasskey passkey) +{ + // TODO: why unused and if cannot be used - remove? + Q_UNUSED(pair); + Q_UNUSED(passkey); +} + +void QBluetoothLocalDevicePrivate::error(void *pair, IOReturn errorCode) +{ + Q_UNUSED(pair); + Q_UNUSED(errorCode); + + emitError(QBluetoothLocalDevice::PairingError, false); +} + +void QBluetoothLocalDevicePrivate::pairingFinished(void *generic) +{ + auto pair = static_cast(generic); + Q_ASSERT_X(pair, Q_FUNC_INFO, "invalid pairing request (nil)"); + + const QBluetoothAddress &deviceAddress = [pair targetAddress]; + Q_ASSERT_X(!deviceAddress.isNull(), Q_FUNC_INFO, + "invalid target address"); + + emitPairingFinished(deviceAddress, QBluetoothLocalDevice::Paired, false); +} + +void QBluetoothLocalDevicePrivate::deviceConnected(const QBluetoothAddress &deviceAddress) +{ + if (!discoveredDevices.contains(deviceAddress)) + discoveredDevices.append(deviceAddress); + + QMetaObject::invokeMethod(q_ptr, "deviceConnected", Qt::QueuedConnection, + Q_ARG(QBluetoothAddress, deviceAddress)); +} + +void QBluetoothLocalDevicePrivate::deviceDisconnected(const QBluetoothAddress &deviceAddress) +{ + QList::iterator devicePos =std::find(discoveredDevices.begin(), + discoveredDevices.end(), + deviceAddress); + + if (devicePos != discoveredDevices.end()) + discoveredDevices.erase(devicePos); + + QMetaObject::invokeMethod(q_ptr, "deviceDisconnected", Qt::QueuedConnection, + Q_ARG(QBluetoothAddress, deviceAddress)); +} + +void QBluetoothLocalDevicePrivate::emitError(QBluetoothLocalDevice::Error error, bool queued) +{ + if (queued) { + QMetaObject::invokeMethod(q_ptr, "errorOccurred", Qt::QueuedConnection, + Q_ARG(QBluetoothLocalDevice::Error, error)); + } else { + emit q_ptr->errorOccurred(QBluetoothLocalDevice::PairingError); + } +} + +void QBluetoothLocalDevicePrivate::emitPairingFinished(const QBluetoothAddress &deviceAddress, + Pairing pairing, bool queued) +{ + Q_ASSERT_X(!deviceAddress.isNull(), Q_FUNC_INFO, "invalid target device address"); + Q_ASSERT_X(q_ptr, Q_FUNC_INFO, "invalid q_ptr (null)"); + + if (queued) { + QMetaObject::invokeMethod(q_ptr, "pairingFinished", Qt::QueuedConnection, + Q_ARG(QBluetoothAddress, deviceAddress), + Q_ARG(QBluetoothLocalDevice::Pairing, pairing)); + } else { + emit q_ptr->pairingFinished(deviceAddress, pairing); + } +} + +void QBluetoothLocalDevicePrivate::unpair(const QBluetoothAddress &deviceAddress) +{ + Q_ASSERT_X(!deviceAddress.isNull(), Q_FUNC_INFO, + "invalid target address"); + + emitPairingFinished(deviceAddress, QBluetoothLocalDevice::Unpaired, true); +} + +QBluetoothLocalDevice::QBluetoothLocalDevice(QObject *parent) : + QObject(parent), + d_ptr(new QBluetoothLocalDevicePrivate(this)) +{ +} + +QBluetoothLocalDevice::QBluetoothLocalDevice(const QBluetoothAddress &address, QObject *parent) : + QObject(parent), + d_ptr(new QBluetoothLocalDevicePrivate(this, address)) +{ +} + +QBluetoothLocalDevice::~QBluetoothLocalDevice() +{ + delete d_ptr; +} + +bool QBluetoothLocalDevice::isValid() const +{ + return d_ptr->isValid(); +} + + +QString QBluetoothLocalDevice::name() const +{ + QT_BT_MAC_AUTORELEASEPOOL; + + if (isValid()) { + if (NSString *const nsn = [d_ptr->hostController nameAsString]) + return QString::fromNSString(nsn); + qCCritical(QT_BT_DARWIN) << Q_FUNC_INFO << "failed to obtain a name"; + } + + return QString(); +} + +QBluetoothAddress QBluetoothLocalDevice::address() const +{ + QT_BT_MAC_AUTORELEASEPOOL; + + if (isValid()) { + if (NSString *const nsa = [d_ptr->hostController addressAsString]) + return QBluetoothAddress(DarwinBluetooth::qt_address(nsa)); + + qCCritical(QT_BT_DARWIN) << Q_FUNC_INFO << "failed to obtain an address"; + } else { + qCWarning(QT_BT_DARWIN) << Q_FUNC_INFO << "invalid local device"; + } + + return QBluetoothAddress(); +} + +void QBluetoothLocalDevice::powerOn() +{ + if (!isValid()) + qCWarning(QT_BT_DARWIN) << Q_FUNC_INFO << "invalid local device"; +} + +void QBluetoothLocalDevice::setHostMode(QBluetoothLocalDevice::HostMode mode) +{ + Q_UNUSED(mode); + + if (!isValid()) + qCWarning(QT_BT_DARWIN) << Q_FUNC_INFO << "invalid local device"; +} + +QBluetoothLocalDevice::HostMode QBluetoothLocalDevice::hostMode() const +{ + if (!isValid() || ![d_ptr->hostController powerState]) + return HostPoweredOff; + + return HostConnectable; +} + +QList QBluetoothLocalDevice::connectedDevices() const +{ + QT_BT_MAC_AUTORELEASEPOOL; + + QList connectedDevices; + + // Take the devices known to IOBluetooth to be paired and connected first: + NSArray *const pairedDevices = [IOBluetoothDevice pairedDevices]; + for (IOBluetoothDevice *device in pairedDevices) { + if ([device isConnected]) { + const QBluetoothAddress address(DarwinBluetooth::qt_address([device getAddress])); + if (!address.isNull()) + connectedDevices.append(address); + } + } + + // Add devices, discovered by the connection monitor: + connectedDevices += d_ptr->discoveredDevices; + // Find something more elegant? :) + // But after all, addresses are integers. + std::sort(connectedDevices.begin(), connectedDevices.end()); + connectedDevices.erase(std::unique(connectedDevices.begin(), + connectedDevices.end()), + connectedDevices.end()); + + return connectedDevices; +} + +QList QBluetoothLocalDevice::allDevices() +{ + QList localDevices; + + QBluetoothLocalDevice defaultAdapter; + if (!defaultAdapter.isValid() || defaultAdapter.address().isNull()) { + qCWarning(QT_BT_DARWIN) << Q_FUNC_INFO <<"no valid device found"; + return localDevices; + } + + QBluetoothHostInfo deviceInfo; + deviceInfo.setName(defaultAdapter.name()); + deviceInfo.setAddress(defaultAdapter.address()); + + localDevices.append(deviceInfo); + + return localDevices; +} + +void QBluetoothLocalDevice::requestPairing(const QBluetoothAddress &address, Pairing pairing) +{ + if (!isValid()) + qCWarning(QT_BT_DARWIN) << Q_FUNC_INFO << "invalid local device"; + + if (!isValid() || address.isNull()) { + d_ptr->emitError(PairingError, true); + return; + } + + DarwinBluetooth::qt_test_iobluetooth_runloop(); + + return d_ptr->requestPairing(address, pairing); +} + +QBluetoothLocalDevice::Pairing QBluetoothLocalDevice::pairingStatus(const QBluetoothAddress &address) const +{ + if (!isValid()) + qCWarning(QT_BT_DARWIN) << Q_FUNC_INFO << "invalid local device"; + + if (!isValid() || address.isNull()) + return Unpaired; + + return d_ptr->pairingStatus(address); +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothlocaldevice_p.cpp b/src/bluetooth/qbluetoothlocaldevice_p.cpp new file mode 100644 index 0000000..189da70 --- /dev/null +++ b/src/bluetooth/qbluetoothlocaldevice_p.cpp @@ -0,0 +1,82 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothlocaldevice.h" +#include "qbluetoothaddress.h" + +#include "qbluetoothlocaldevice_p.h" +#ifndef QT_IOS_BLUETOOTH +#include "dummy/dummy_helper_p.h" +#endif + +QT_BEGIN_NAMESPACE + +QBluetoothLocalDevice::QBluetoothLocalDevice(QObject *parent) : + QObject(parent), + d_ptr(new QBluetoothLocalDevicePrivate(this, QBluetoothAddress())) +{ +#if !defined(QT_IOS_BLUETOOTH) + printDummyWarning(); +#endif + registerQBluetoothLocalDeviceMetaType(); +} + +QBluetoothLocalDevice::QBluetoothLocalDevice(const QBluetoothAddress &address, QObject *parent) : + QObject(parent), + d_ptr(new QBluetoothLocalDevicePrivate(this, address)) +{ + registerQBluetoothLocalDeviceMetaType(); +} + +QString QBluetoothLocalDevice::name() const +{ + return QString(); +} + +QBluetoothAddress QBluetoothLocalDevice::address() const +{ + return QBluetoothAddress(); +} + +void QBluetoothLocalDevice::powerOn() +{ +} + +void QBluetoothLocalDevice::setHostMode(QBluetoothLocalDevice::HostMode mode) +{ + Q_UNUSED(mode); +} + +QBluetoothLocalDevice::HostMode QBluetoothLocalDevice::hostMode() const +{ + return HostPoweredOff; +} + +QList QBluetoothLocalDevice::connectedDevices() const +{ + return QList(); +} + +QList QBluetoothLocalDevice::allDevices() +{ + QList localDevices; + return localDevices; +} + +void QBluetoothLocalDevice::requestPairing(const QBluetoothAddress &address, Pairing pairing) +{ + Q_UNUSED(address); + Q_UNUSED(pairing); + QMetaObject::invokeMethod(this, "errorOccurred", Qt::QueuedConnection, + Q_ARG(QBluetoothLocalDevice::Error, + QBluetoothLocalDevice::PairingError)); +} + +QBluetoothLocalDevice::Pairing QBluetoothLocalDevice::pairingStatus( + const QBluetoothAddress &address) const +{ + Q_UNUSED(address); + return Unpaired; +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothlocaldevice_p.h b/src/bluetooth/qbluetoothlocaldevice_p.h new file mode 100644 index 0000000..d0dad8d --- /dev/null +++ b/src/bluetooth/qbluetoothlocaldevice_p.h @@ -0,0 +1,203 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2014 Denis Shienkov +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QBLUETOOTHLOCALDEVICE_P_H +#define QBLUETOOTHLOCALDEVICE_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 "qbluetoothlocaldevice.h" + +#if QT_CONFIG(bluez) +#include +#include +#include +#include +#include "bluez/bluez5_helper_p.h" + +class OrgBluezAdapter1Interface; +class OrgFreedesktopDBusPropertiesInterface; +class OrgFreedesktopDBusObjectManagerInterface; +class OrgBluezDevice1Interface; + +QT_BEGIN_NAMESPACE +class QDBusPendingCallWatcher; +QT_END_NAMESPACE +#endif + +#ifdef QT_WINRT_BLUETOOTH +#include "qbluetoothutils_winrt_p.h" +#include +QT_BEGIN_NAMESPACE +struct PairingWorker; +QT_END_NAMESPACE +#endif + +#ifdef QT_ANDROID_BLUETOOTH +#include +#include +#include +#include +#endif + +QT_BEGIN_NAMESPACE + +extern void registerQBluetoothLocalDeviceMetaType(); + +class QBluetoothAddress; + +#ifdef QT_ANDROID_BLUETOOTH +class LocalDeviceBroadcastReceiver; +class QBluetoothLocalDevicePrivate : public QObject +{ + Q_OBJECT +public: + QBluetoothLocalDevicePrivate( + QBluetoothLocalDevice *q, const QBluetoothAddress &address = QBluetoothAddress()); + ~QBluetoothLocalDevicePrivate(); + + QJniObject *adapter(); + void initialize(const QBluetoothAddress &address); + static bool startDiscovery(); + static bool cancelDiscovery(); + static bool isDiscovering(); + bool isValid() const; + +private slots: + void processHostModeChange(QBluetoothLocalDevice::HostMode newMode); + void processPairingStateChanged(const QBluetoothAddress &address, + QBluetoothLocalDevice::Pairing pairing); + void processConnectDeviceChanges(const QBluetoothAddress &address, bool isConnectEvent); + +private: + QBluetoothLocalDevice *q_ptr; + QJniObject *obj = nullptr; + + int pendingPairing(const QBluetoothAddress &address); + +public: + LocalDeviceBroadcastReceiver *receiver; + bool pendingConnectableHostModeTransition = false; + QList > pendingPairings; + + QList connectedDevices; +}; + +#elif QT_CONFIG(bluez) +class QBluetoothLocalDevicePrivate : public QObject +{ + Q_OBJECT + Q_DECLARE_PUBLIC(QBluetoothLocalDevice) +public: + QBluetoothLocalDevicePrivate(QBluetoothLocalDevice *q, + QBluetoothAddress localAddress = QBluetoothAddress()); + ~QBluetoothLocalDevicePrivate(); + + QSet connectedDevicesSet; + OrgBluezAdapter1Interface *adapter = nullptr; + OrgFreedesktopDBusPropertiesInterface *adapterProperties = nullptr; + OrgFreedesktopDBusObjectManagerInterface *manager = nullptr; + QMap deviceChangeMonitors; + + QList connectedDevices() const; + + QBluetoothAddress localAddress; + QBluetoothAddress address; + QBluetoothLocalDevice::Pairing pairing; + OrgBluezDevice1Interface *pairingTarget = nullptr; + QTimer *pairingDiscoveryTimer = nullptr; + QBluetoothLocalDevice::HostMode currentMode; + int pendingHostModeChange; + bool pairingRequestCanceled = false; + +public slots: + void pairingCompleted(QDBusPendingCallWatcher *); + + bool isValid() const; + + void requestPairing(const QBluetoothAddress &address, + QBluetoothLocalDevice::Pairing targetPairing); + +private Q_SLOTS: + void PropertiesChanged(const QString &interface, + const QVariantMap &changed_properties, + const QStringList &invalidated_properties, + const QDBusMessage &signal); + void InterfacesAdded(const QDBusObjectPath &object_path, + InterfaceList interfaces_and_properties); + void InterfacesRemoved(const QDBusObjectPath &object_path, + const QStringList &interfaces); + void processPairing(const QString &objectPath, QBluetoothLocalDevice::Pairing target); + void pairingDiscoveryTimedOut(); + +private: + void connectDeviceChanges(); + + QString deviceAdapterPath; + + QBluetoothLocalDevice *q_ptr; + + void initializeAdapter(); +}; + +#elif defined(QT_WINRT_BLUETOOTH) +class QBluetoothLocalDevicePrivate : public QObject +{ + Q_OBJECT + Q_DECLARE_PUBLIC(QBluetoothLocalDevice) +public: + QBluetoothLocalDevicePrivate(QBluetoothLocalDevice *q, + QBluetoothAddress = QBluetoothAddress()); + ~QBluetoothLocalDevicePrivate(); + + bool isValid() const; + + void updateAdapterState(QBluetoothLocalDevice::HostMode mode); + Q_SLOT void onAdapterRemoved(winrt::hstring id); + Q_SLOT void onAdapterAdded(winrt::hstring id); + Q_SLOT void radioModeChanged(winrt::hstring id, QBluetoothLocalDevice::HostMode mode); + Q_SLOT void onDeviceAdded(const QBluetoothAddress &address); + Q_SLOT void onDeviceRemoved(const QBluetoothAddress &address); + + QBluetoothLocalDevice *q_ptr; + winrt::com_ptr mPairingWorker; + winrt::Windows::Devices::Bluetooth::BluetoothAdapter mAdapter; + winrt::hstring mDeviceId; + QString mAdapterName; + QBluetoothLocalDevice::HostMode mMode; + winrt::event_token mModeChangeToken; + +signals: + void updateMode(winrt::hstring id, QBluetoothLocalDevice::HostMode mode); +}; +#elif !defined(QT_OSX_BLUETOOTH) // dummy backend +class QBluetoothLocalDevicePrivate : public QObject +{ +public: + QBluetoothLocalDevicePrivate(QBluetoothLocalDevice * = nullptr, + QBluetoothAddress = QBluetoothAddress()) + { + } + + bool isValid() const + { + return false; + } +}; +#endif + +QT_END_NAMESPACE + +#endif // QBLUETOOTHLOCALDEVICE_P_H diff --git a/src/bluetooth/qbluetoothlocaldevice_winrt.cpp b/src/bluetooth/qbluetoothlocaldevice_winrt.cpp new file mode 100644 index 0000000..ec0787d --- /dev/null +++ b/src/bluetooth/qbluetoothlocaldevice_winrt.cpp @@ -0,0 +1,798 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include + +#include "qbluetoothlocaldevice.h" +#include "qbluetoothaddress.h" + +#include "qbluetoothdevicewatcher_winrt_p.h" +#include "qbluetoothlocaldevice_p.h" +#include "qbluetoothutils_winrt_p.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::Foundation::Collections; +using namespace winrt::Windows::Devices::Enumeration; +using namespace winrt::Windows::Devices::Bluetooth; +using namespace winrt::Windows::Devices::Radios; + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINDOWS) + +template +static bool await(IAsyncOperation &&asyncInfo, T &result, uint timeout = 0) +{ + using WinRtAsyncStatus = winrt::Windows::Foundation::AsyncStatus; + WinRtAsyncStatus status; + QElapsedTimer timer; + if (timeout) + timer.start(); + do { + QCoreApplication::processEvents(); + status = asyncInfo.Status(); + } while (status == WinRtAsyncStatus::Started && (!timeout || !timer.hasExpired(timeout))); + if (status == WinRtAsyncStatus::Completed) { + result = asyncInfo.GetResults(); + return true; + } else { + return false; + } +} + +static QBluetoothLocalDevice::HostMode adjustHostMode(QBluetoothLocalDevice::HostMode mode) +{ + // Windows APIs do not seem to support HostDiscoverable and + // HostDiscoverableLimitedInquiry, so we just treat them as HostConnectable + return (mode == QBluetoothLocalDevice::HostPoweredOff) + ? mode : QBluetoothLocalDevice::HostConnectable; +} + +static QBluetoothLocalDevice::HostMode modeFromWindowsBluetoothState(RadioState state) +{ + return (state == RadioState::On) ? QBluetoothLocalDevice::HostConnectable + : QBluetoothLocalDevice::HostPoweredOff; +} + +static RadioState windowsStateFromMode(QBluetoothLocalDevice::HostMode mode) +{ + return (mode == QBluetoothLocalDevice::HostPoweredOff) ? RadioState::Off : RadioState::On; +} + +class AdapterManager; + +class WatcherWrapper +{ +public: + // we do not really care about unique ids here + WatcherWrapper(winrt::hstring selector) : + mWatcher(std::make_shared(0, selector)) + { + } + + template + void init(AdapterManager *manager, AddedSlot onAdded, RemovedSlot onRemoved) + { + if (!mWatcher) { + qWarning("QBluetoothLocalDevice: failed to create device watcher!"); + return; + } + + QObject::connect(mWatcher.get(), &QBluetoothDeviceWatcherWinRT::deviceAdded, + manager, onAdded, Qt::QueuedConnection); + QObject::connect(mWatcher.get(), &QBluetoothDeviceWatcherWinRT::deviceRemoved, + manager, onRemoved, Qt::QueuedConnection); + + // This will also print a warning on failure. + if (mWatcher->init()) + mWatcher->start(); + } + +private: + std::shared_ptr mWatcher = nullptr; +}; + +/* + This class is supposed to manage winrt::Windows::Devices::Radios::Radio + instances. It looks like Windows behaves incorrectly when there are multiple + instances representing the same physical device. So this class will be a + single point for keeping track of all used Radios. + At the same time this class takes care of monitoring adapter connections + and disconnections. + Note that access to internal structs should be protected, because all + Windows callbacks come in separate threads. We also can't use + Qt::QueuedConnection to "forward" the execution to the right thread, because + Windows' IUnknown-based classes have a deleted operator new(), and so can't + be used in QMetaType. + However, we will still mostly use signals/slots to communicate with actual + QBluetoothLocalDevice instances, so we do not need any protection on that + side. +*/ +class AdapterManager : public QObject +{ + Q_OBJECT +public: + AdapterManager(); + ~AdapterManager(); + + QList connectedDevices(); + +public slots: + QBluetoothLocalDevice::HostMode addClient(QBluetoothLocalDevicePrivate *client); + void removeClient(winrt::hstring adapterId); + void updateMode(winrt::hstring adapterId, QBluetoothLocalDevice::HostMode mode); + +signals: + void adapterAdded(winrt::hstring id); + void adapterRemoved(winrt::hstring id); + void modeChanged(winrt::hstring id, QBluetoothLocalDevice::HostMode mode); + void deviceAdded(const QBluetoothAddress &address); + void deviceRemoved(const QBluetoothAddress &address); + +private: + struct RadioInfo { + Radio radio = nullptr; + winrt::event_token stateToken; + int numClients = 0; + RadioState currentState = RadioState::Unknown; + }; + + Radio getRadioFromAdapterId(winrt::hstring id); + Q_SLOT void onAdapterAdded(winrt::hstring id); + Q_SLOT void onAdapterRemoved(winrt::hstring id); + void subscribeToStateChanges(RadioInfo &info); + void unsubscribeFromStateChanges(RadioInfo &info); + void onStateChange(Radio radio); + Q_SLOT void tryResubscribeToStateChanges(winrt::hstring id, int numAttempts); + + Q_SLOT void onDeviceAdded(winrt::hstring id); + Q_SLOT void onDeviceRemoved(winrt::hstring id); + + std::unique_ptr mAdapterWatcher = nullptr; + std::unique_ptr mLeDevicesWatcher = nullptr; + std::unique_ptr mClassicDevicesWatcher = nullptr; + QMutex mMutex; + // Key for this map is BluetoothAdapter Id, *not* Radio Id. + QMap mRadios; + QList mConnectedDevices; +}; + +AdapterManager::AdapterManager() : QObject() +{ + const auto adapterSelector = BluetoothAdapter::GetDeviceSelector(); + mAdapterWatcher = std::make_unique(adapterSelector); + mAdapterWatcher->init(this, &AdapterManager::onAdapterAdded, &AdapterManager::onAdapterRemoved); + + // Once created, device watchers will also populate the initial list of + // connected devices. + + const auto leSelector = BluetoothLEDevice::GetDeviceSelectorFromConnectionStatus( + BluetoothConnectionStatus::Connected); + mLeDevicesWatcher = std::make_unique(leSelector); + mLeDevicesWatcher->init(this, &AdapterManager::onDeviceAdded, &AdapterManager::onDeviceRemoved); + + const auto classicSelector = BluetoothDevice::GetDeviceSelectorFromConnectionStatus( + BluetoothConnectionStatus::Connected); + mClassicDevicesWatcher = std::make_unique(classicSelector); + mClassicDevicesWatcher->init(this, &AdapterManager::onDeviceAdded, + &AdapterManager::onDeviceRemoved); +} + +AdapterManager::~AdapterManager() +{ +} + +QList AdapterManager::connectedDevices() +{ + QMutexLocker locker(&mMutex); + return mConnectedDevices; +} + +QBluetoothLocalDevice::HostMode AdapterManager::addClient(QBluetoothLocalDevicePrivate *client) +{ + connect(this, &AdapterManager::modeChanged, client, + &QBluetoothLocalDevicePrivate::radioModeChanged, Qt::QueuedConnection); + connect(client, &QBluetoothLocalDevicePrivate::updateMode, this, &AdapterManager::updateMode, + Qt::QueuedConnection); + connect(this, &AdapterManager::adapterAdded, client, + &QBluetoothLocalDevicePrivate::onAdapterAdded, Qt::QueuedConnection); + connect(this, &AdapterManager::adapterRemoved, client, + &QBluetoothLocalDevicePrivate::onAdapterRemoved, Qt::QueuedConnection); + connect(this, &AdapterManager::deviceAdded, client, + &QBluetoothLocalDevicePrivate::onDeviceAdded, Qt::QueuedConnection); + connect(this, &AdapterManager::deviceRemoved, client, + &QBluetoothLocalDevicePrivate::onDeviceRemoved, Qt::QueuedConnection); + + QMutexLocker locker(&mMutex); + const auto adapterId = client->mDeviceId; + if (mRadios.contains(adapterId)) { + auto &radioInfo = mRadios[adapterId]; + radioInfo.numClients++; + return modeFromWindowsBluetoothState(radioInfo.radio.State()); + } else { + // Note that when we use await(), we need to unlock the mutex, because + // it calls processEvents(), so other methods that demand the mutex can + // be invoked. + locker.unlock(); + Radio r = getRadioFromAdapterId(adapterId); + if (r) { + locker.relock(); + RadioInfo info; + info.radio = r; + info.numClients = 1; + info.currentState = r.State(); + subscribeToStateChanges(info); + mRadios.insert(adapterId, info); + return modeFromWindowsBluetoothState(info.currentState); + } + } + qCWarning(QT_BT_WINDOWS, "Failed to subscribe to adapter state changes"); + return QBluetoothLocalDevice::HostPoweredOff; +} + +void AdapterManager::removeClient(winrt::hstring adapterId) +{ + QMutexLocker locker(&mMutex); + if (mRadios.contains(adapterId)) { + auto &radioInfo = mRadios[adapterId]; + if (--radioInfo.numClients == 0) { + unsubscribeFromStateChanges(radioInfo); + mRadios.remove(adapterId); + } + } else { + qCWarning(QT_BT_WINDOWS) << "Removing client for an unknown adapter id" + << QString::fromStdString(winrt::to_string(adapterId)); + } +} + +void AdapterManager::updateMode(winrt::hstring adapterId, QBluetoothLocalDevice::HostMode mode) +{ + QMutexLocker locker(&mMutex); + if (mRadios.contains(adapterId)) { + RadioAccessStatus status = RadioAccessStatus::Unspecified; + auto radio = mRadios[adapterId].radio; // can be nullptr + locker.unlock(); + if (radio) { + const bool res = await(radio.SetStateAsync(windowsStateFromMode(mode)), status); + // If operation succeeds, we will update the state in the event handler. + if (!res || status != RadioAccessStatus::Allowed) { + qCWarning(QT_BT_WINDOWS, "Failed to update adapter state: SetStateAsync() failed!"); + if (status == RadioAccessStatus::DeniedBySystem) { + qCWarning(QT_BT_WINDOWS) << "Check that the user has permissions to manipulate" + " the selected Bluetooth device"; + } + } + } + } +} + +Radio AdapterManager::getRadioFromAdapterId(winrt::hstring id) +{ + BluetoothAdapter a(nullptr); + bool res = await(BluetoothAdapter::FromIdAsync(id), a); + if (res && a) { + Radio r(nullptr); + res = await(a.GetRadioAsync(), r); + if (res && r) + return r; + } + return nullptr; +} + +void AdapterManager::onStateChange(Radio radio) +{ + QMutexLocker locker(&mMutex); + for (const auto &key : mRadios.keys()) { + auto &info = mRadios[key]; + if (info.radio == radio) { + if (info.currentState != radio.State()) { + info.currentState = radio.State(); + emit modeChanged(key, modeFromWindowsBluetoothState(info.currentState)); + } + break; + } + } +} + +static const int kMaximumAttempts = 5; + +// In practice when the adapter is reconnected, the Radio object can't be +// retrieved immediately. I'm not sure if such behavior is normal, or specific +// to my machine only. I also do not know what is the proper time to wait before +// the Radio instance can be retrieved. So we introduce a helper method, which +// tries to resubscribe several times with a 100ms interval between retries. +void AdapterManager::tryResubscribeToStateChanges(winrt::hstring id, int numAttempts) +{ + QMutexLocker locker(&mMutex); + if (mRadios.contains(id)) { + // The Added event can come when we first create and use adapter. Such + // event should not be handled. + if (mRadios[id].radio != nullptr) + return; + locker.unlock(); + Radio r = getRadioFromAdapterId(id); + if (r) { + locker.relock(); + // We have to check once again because the record could be deleted + // while we were await'ing in getRadioFromAdapterId(). + if (mRadios.contains(id)) { + auto &info = mRadios[id]; + info.radio = r; + info.currentState = r.State(); + subscribeToStateChanges(info); + emit modeChanged(id, modeFromWindowsBluetoothState(info.currentState)); + } + } else { + if (++numAttempts < kMaximumAttempts) { + qCDebug(QT_BT_WINDOWS, "Trying to resubscribe for the state changes"); + QPointer thisPtr(this); + QTimer::singleShot(100, [thisPtr, id, numAttempts]() { + if (thisPtr) + thisPtr->tryResubscribeToStateChanges(id, numAttempts); + }); + } else { + qCWarning(QT_BT_WINDOWS, + "Failed to resubscribe to the state changes after %d attempts!", + numAttempts); + } + } + } +} + +struct BluetoothInfo +{ + QBluetoothAddress address; + bool isConnected; +}; + +static BluetoothInfo getBluetoothInfo(winrt::hstring id) +{ + // We do not know if it's a BT classic or BTLE device, so we try both. + BluetoothDevice device(nullptr); + bool res = await(BluetoothDevice::FromIdAsync(id), device, 5000); + if (res && device) { + return { QBluetoothAddress(device.BluetoothAddress()), + device.ConnectionStatus() == BluetoothConnectionStatus::Connected }; + } + + BluetoothLEDevice leDevice(nullptr); + res = await(BluetoothLEDevice::FromIdAsync(id), leDevice, 5000); + if (res && leDevice) { + return { QBluetoothAddress(leDevice.BluetoothAddress()), + leDevice.ConnectionStatus() == BluetoothConnectionStatus::Connected }; + } + + return {}; +} + +void AdapterManager::onDeviceAdded(winrt::hstring id) +{ + const BluetoothInfo &info = getBluetoothInfo(id); + // In practice this callback might come even for disconnected device. + // So check status explicitly. + if (!info.address.isNull() && info.isConnected) { + bool found = false; + { + // A scope is needed, because we need to emit a signal when mutex is already unlocked + QMutexLocker locker(&mMutex); + found = mConnectedDevices.contains(info.address); + if (!found) { + mConnectedDevices.push_back(info.address); + } + } + if (!found) + emit deviceAdded(info.address); + } +} + +void AdapterManager::onDeviceRemoved(winrt::hstring id) +{ + const BluetoothInfo &info = getBluetoothInfo(id); + if (!info.address.isNull() && !info.isConnected) { + bool found = false; + { + QMutexLocker locker(&mMutex); + found = mConnectedDevices.removeOne(info.address); + } + if (found) + emit deviceRemoved(info.address); + } +} + +void AdapterManager::onAdapterAdded(winrt::hstring id) +{ + emit adapterAdded(id); + // We need to invoke the method from a Qt thread, so that we could start a + // timer there. + QMetaObject::invokeMethod(this, "tryResubscribeToStateChanges", Qt::QueuedConnection, + Q_ARG(winrt::hstring, id), Q_ARG(int, 0)); +} + +void AdapterManager::onAdapterRemoved(winrt::hstring id) +{ + emit adapterRemoved(id); + QMutexLocker locker(&mMutex); + if (mRadios.contains(id)) { + // here we can't simply remove the record from the map, because the + // same adapter can later be reconnected, and we need to keep track of + // the created clients. + mRadios[id].radio = nullptr; + } +} + +void AdapterManager::subscribeToStateChanges(AdapterManager::RadioInfo &info) +{ + QPointer thisPtr(this); + info.stateToken = info.radio.StateChanged([thisPtr](Radio r, const auto &) { + // This callback fires twice. Looks like an MS bug. + // This callback comes in a separate thread + if (thisPtr) { + thisPtr->onStateChange(r); + } + }); +} + +void AdapterManager::unsubscribeFromStateChanges(AdapterManager::RadioInfo &info) +{ + // This method can be called after the radio is disconnected + if (info.radio) + info.radio.StateChanged(info.stateToken); +} + +Q_GLOBAL_STATIC(AdapterManager, adapterManager) + +static DeviceInformationCollection getAvailableAdapters() +{ + const auto btSelector = BluetoothAdapter::GetDeviceSelector(); + DeviceInformationCollection deviceInfoCollection(nullptr); + await(DeviceInformation::FindAllAsync(btSelector), deviceInfoCollection); + return deviceInfoCollection; +} + +DeviceInformationPairing pairingInfoFromAddress(const QBluetoothAddress &address) +{ + const quint64 addr64 = address.toUInt64(); + BluetoothLEDevice leDevice(nullptr); + bool res = await(BluetoothLEDevice::FromBluetoothAddressAsync(addr64), leDevice, 5000); + if (res && leDevice) + return leDevice.DeviceInformation().Pairing(); + + BluetoothDevice device(nullptr); + res = await(BluetoothDevice::FromBluetoothAddressAsync(addr64), device, 5000); + if (res && device) + return device.DeviceInformation().Pairing(); + + return nullptr; +} + +struct PairingWorker + : public winrt::implements +{ + PairingWorker(QBluetoothLocalDevice *device): q(device) {} + ~PairingWorker() = default; + + void pairAsync(const QBluetoothAddress &addr, QBluetoothLocalDevice::Pairing pairing); + +private: + QPointer q; + void onPairingRequested(DeviceInformationCustomPairing const&, + DevicePairingRequestedEventArgs args); +}; + +void PairingWorker::pairAsync(const QBluetoothAddress &addr, QBluetoothLocalDevice::Pairing pairing) +{ + // Note: some of the functions called here use await() in their implementation. + // Hence we need to verify that the 'q' is still valid after such calls, as + // it may have been destroyed. In that scenario the ComPtr pointing to this + // object is destroyed, but to protect this function's possible execution at that time, + // the get_strong() call below will ensure we can execute until the end. + auto ref = get_strong(); + DeviceInformationPairing pairingInfo = pairingInfoFromAddress(addr); + switch (pairing) { + case QBluetoothLocalDevice::Paired: + case QBluetoothLocalDevice::AuthorizedPaired: + { + DeviceInformationCustomPairing customPairing = pairingInfo.Custom(); + auto token = customPairing.PairingRequested( + { get_weak(), &PairingWorker::onPairingRequested }); + DevicePairingResult result{nullptr}; + bool res = await(customPairing.PairAsync(DevicePairingKinds::ConfirmOnly), result, 30000); + customPairing.PairingRequested(token); + if (!res || result.Status() != DevicePairingResultStatus::Paired) { + if (q) + emit q->errorOccurred(QBluetoothLocalDevice::PairingError); + return; + } + + // Check the actual protection level used and signal the success + if (q) { + const auto resultingPairingStatus = q->pairingStatus(addr); + // pairingStatus() uses await/spins eventloop => check 'q' validity again + if (q) + emit q->pairingFinished(addr, resultingPairingStatus); + } + return; + } + case QBluetoothLocalDevice::Unpaired: + DeviceUnpairingResult unpairingResult{nullptr}; + bool res = await(pairingInfo.UnpairAsync(), unpairingResult, 10000); + if (!res || unpairingResult.Status() != DeviceUnpairingResultStatus::Unpaired) { + if (q) + emit q->errorOccurred(QBluetoothLocalDevice::PairingError); + return; + } + if (q) + emit q->pairingFinished(addr, QBluetoothLocalDevice::Unpaired); + return; + } +} + +void PairingWorker::onPairingRequested(const DeviceInformationCustomPairing &, + DevicePairingRequestedEventArgs args) +{ + if (args.PairingKind() != DevicePairingKinds::ConfirmOnly) { + Q_ASSERT(false); + return; + } + + args.Accept(); +} + +QBluetoothLocalDevice::QBluetoothLocalDevice(QObject *parent) : + QObject(parent), + d_ptr(new QBluetoothLocalDevicePrivate(this, QBluetoothAddress())) +{ + registerQBluetoothLocalDeviceMetaType(); +} + +QBluetoothLocalDevice::QBluetoothLocalDevice(const QBluetoothAddress &address, QObject *parent) : + QObject(parent), + d_ptr(new QBluetoothLocalDevicePrivate(this, address)) +{ + registerQBluetoothLocalDeviceMetaType(); +} + +QBluetoothLocalDevicePrivate::QBluetoothLocalDevicePrivate(QBluetoothLocalDevice *q, + QBluetoothAddress address) + : q_ptr(q), + mAdapter(nullptr), + mMode(QBluetoothLocalDevice::HostPoweredOff) +{ + mPairingWorker = winrt::make_self(q); + if (address.isNull()) { + // use default adapter + bool res = await(BluetoothAdapter::GetDefaultAsync(), mAdapter); + if (res && mAdapter) { + // get adapter name + mDeviceId = mAdapter.DeviceId(); + DeviceInformation devInfo(nullptr); + res = await(DeviceInformation::CreateFromIdAsync(mDeviceId), devInfo); + if (res && devInfo) + mAdapterName = QString::fromStdString(winrt::to_string(devInfo.Name())); + } + } else { + // try to select a proper device + const auto deviceInfoCollection = getAvailableAdapters(); + for (const auto &devInfo : deviceInfoCollection) { + BluetoothAdapter adapter(nullptr); + const bool res = await(BluetoothAdapter::FromIdAsync(devInfo.Id()), adapter); + if (res && adapter) { + QBluetoothAddress adapterAddress(adapter.BluetoothAddress()); + if (adapterAddress == address) { + mAdapter = adapter; + mDeviceId = adapter.DeviceId(); + mAdapterName = QString::fromStdString(winrt::to_string(devInfo.Name())); + break; + } + } + } + } + if (mAdapter) { + mMode = adapterManager->addClient(this); + } else { + if (address.isNull()) { + qCWarning(QT_BT_WINDOWS, "Failed to create QBluetoothLocalDevice - no adapter found"); + } else { + qCWarning(QT_BT_WINDOWS) << "Failed to create QBluetoothLocalDevice for address" + << address; + } + } +} + +QBluetoothLocalDevicePrivate::~QBluetoothLocalDevicePrivate() +{ + adapterManager->removeClient(mDeviceId); + mAdapter = nullptr; +} + +bool QBluetoothLocalDevicePrivate::isValid() const +{ + return mAdapter != nullptr; +} + +void QBluetoothLocalDevicePrivate::updateAdapterState(QBluetoothLocalDevice::HostMode mode) +{ + if (!mAdapter) { + qCWarning(QT_BT_WINDOWS, "Trying to update state for an uninitialized adapter"); + return; + } + const auto desiredMode = adjustHostMode(mode); + if (desiredMode != mMode) { + // From the MS docs: Note that your code should call RequestAccessAsync + // at least once, from the UI thread, before trying to call + // SetStateAsync. This is because in some regions, with some user + // settings choices, attempting to change radio state requires user + // permission. + RadioAccessStatus status = RadioAccessStatus::Unspecified; + bool res = await(Radio::RequestAccessAsync(), status); + if (res && status == RadioAccessStatus::Allowed) { + // Now send a signal to the AdapterWatcher. That class will manage + // the actual state change. + emit updateMode(mDeviceId, desiredMode); + } else { + qCWarning(QT_BT_WINDOWS, "Failed to update adapter state: operation denied!"); + } + } +} + +void QBluetoothLocalDevicePrivate::onAdapterRemoved(winrt::hstring id) +{ + if (id == mDeviceId) { + qCDebug(QT_BT_WINDOWS, "Current adapter is removed"); + mAdapter = nullptr; + if (mMode != QBluetoothLocalDevice::HostPoweredOff) { + mMode = QBluetoothLocalDevice::HostPoweredOff; + emit q_ptr->hostModeStateChanged(mMode); + } + } +} + +void QBluetoothLocalDevicePrivate::onAdapterAdded(winrt::hstring id) +{ + if (id == mDeviceId && !mAdapter) { + // adapter was reconnected - try to recreate the internals + qCDebug(QT_BT_WINDOWS, "Adapter reconnected - trying to restore QBluetoothLocalDevice"); + const bool res = await(BluetoothAdapter::FromIdAsync(mDeviceId), mAdapter); + if (!res || !mAdapter) + qCWarning(QT_BT_WINDOWS, "Failed to restore adapter"); + } +} + +void QBluetoothLocalDevicePrivate::radioModeChanged(winrt::hstring id, QBluetoothLocalDevice::HostMode mode) +{ + if (id == mDeviceId && mAdapter) { + if (mode != mMode) { + mMode = mode; + emit q_ptr->hostModeStateChanged(mMode); + } + } +} + +void QBluetoothLocalDevicePrivate::onDeviceAdded(const QBluetoothAddress &address) +{ + if (isValid()) + emit q_ptr->deviceConnected(address); +} + +void QBluetoothLocalDevicePrivate::onDeviceRemoved(const QBluetoothAddress &address) +{ + if (isValid()) + emit q_ptr->deviceDisconnected(address); +} + +void QBluetoothLocalDevice::requestPairing(const QBluetoothAddress &address, Pairing pairing) +{ + Q_D(QBluetoothLocalDevice); + if (!isValid() || address.isNull()) { + QMetaObject::invokeMethod(this, "errorOccurred", Qt::QueuedConnection, + Q_ARG(QBluetoothLocalDevice::Error, + QBluetoothLocalDevice::PairingError)); + return; + } + + // Check current pairing status and determine if there is a need to do anything + const Pairing currentPairingStatus = pairingStatus(address); + if ((currentPairingStatus == Unpaired && pairing == Unpaired) + || (currentPairingStatus != Unpaired && pairing != Unpaired)) { + qCDebug(QT_BT_WINDOWS) << "requestPairing() no change needed to pairing" << address; + QMetaObject::invokeMethod(this, "pairingFinished", Qt::QueuedConnection, + Q_ARG(QBluetoothAddress, address), + Q_ARG(QBluetoothLocalDevice::Pairing, + currentPairingStatus)); + return; + } + + qCDebug(QT_BT_WINDOWS) << "requestPairing() initiating (un)pairing" << address << pairing; + d->mPairingWorker->pairAsync(address, pairing); +} + +QBluetoothLocalDevice::Pairing QBluetoothLocalDevice::pairingStatus( + const QBluetoothAddress &address) const +{ + if (!isValid() || address.isNull()) + return Unpaired; + + const DeviceInformationPairing pairingInfo = pairingInfoFromAddress(address); + if (!pairingInfo || !pairingInfo.IsPaired()) + return Unpaired; + + const DevicePairingProtectionLevel protection = pairingInfo.ProtectionLevel(); + if (protection == DevicePairingProtectionLevel::Encryption + || protection == DevicePairingProtectionLevel::EncryptionAndAuthentication) + return AuthorizedPaired; + return Paired; +} + +void QBluetoothLocalDevice::setHostMode(QBluetoothLocalDevice::HostMode mode) +{ + Q_D(QBluetoothLocalDevice); + d->updateAdapterState(mode); +} + +QBluetoothLocalDevice::HostMode QBluetoothLocalDevice::hostMode() const +{ + Q_D(const QBluetoothLocalDevice); + return d->mMode; +} + +QList QBluetoothLocalDevice::connectedDevices() const +{ + // On windows we have only one Bluetooth adapter, but generally can create multiple + // QBluetoothLocalDevice instances (both valid and invalid). Invalid instances shouldn't return + // any connected devices, while all valid instances can use information from a global static. + Q_D(const QBluetoothLocalDevice); + return d->isValid() ? adapterManager->connectedDevices() : QList(); +} + +void QBluetoothLocalDevice::powerOn() +{ + setHostMode(HostConnectable); +} + +QString QBluetoothLocalDevice::name() const +{ + Q_D(const QBluetoothLocalDevice); + return d->mAdapterName; +} + +QBluetoothAddress QBluetoothLocalDevice::address() const +{ + Q_D(const QBluetoothLocalDevice); + return d->mAdapter ? QBluetoothAddress(d->mAdapter.BluetoothAddress()) : QBluetoothAddress(); +} + +QList QBluetoothLocalDevice::allDevices() +{ + QList devices; + const auto deviceInfoCollection = getAvailableAdapters(); + if (deviceInfoCollection) { + for (const auto &devInfo : deviceInfoCollection) { + BluetoothAdapter adapter(nullptr); + const bool res = await(BluetoothAdapter::FromIdAsync(devInfo.Id()), adapter); + if (res && adapter) { + QBluetoothHostInfo info; + info.setName(QString::fromStdString(winrt::to_string(devInfo.Name()))); + info.setAddress(QBluetoothAddress(adapter.BluetoothAddress())); + devices.push_back(std::move(info)); + } + } + } + return devices; +} + +QT_END_NAMESPACE + +#include "qbluetoothlocaldevice_winrt.moc" diff --git a/src/bluetooth/qbluetoothserver.cpp b/src/bluetooth/qbluetoothserver.cpp new file mode 100644 index 0000000..d61c67a --- /dev/null +++ b/src/bluetooth/qbluetoothserver.cpp @@ -0,0 +1,296 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2016 BlackBerry Limited. All rights reserved. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothserver.h" +#include "qbluetoothserver_p.h" +#include "qbluetoothsocket.h" +#include "qbluetoothserviceinfo.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QBluetoothServer + \inmodule QtBluetooth + \brief The QBluetoothServer class uses the RFCOMM or L2cap protocol to communicate with + a Bluetooth device. + + \since 5.2 + + QBluetoothServer is used to implement Bluetooth services over RFCOMM or L2cap. + + Start listening for incoming connections with listen(). Wait till the newConnection() signal + is emitted when a new connection is established, and call nextPendingConnection() to get a QBluetoothSocket + for the new connection. + + To enable other devices to find your service, create a QBluetoothServiceInfo with the + applicable attributes for your service and register it using QBluetoothServiceInfo::registerService(). + Call serverPort() to get the channel number that is being used. + + If the \l QBluetoothServiceInfo::Protocol is not supported by a platform, \l listen() will return \c false. + Android and WinRT only support RFCOMM for example. + + On iOS, this class cannot be used because the platform does not expose + an API which may permit access to QBluetoothServer related features. + + \sa QBluetoothServiceInfo, QBluetoothSocket +*/ + +/*! + \fn void QBluetoothServer::newConnection() + + This signal is emitted when a new connection is available. + + The connected slot should call nextPendingConnection() to get a QBluetoothSocket object to + send and receive data over the connection. + + \sa nextPendingConnection(), hasPendingConnections() +*/ + +/*! + \fn void QBluetoothServer::errorOccurred(QBluetoothServer::Error error) + + This signal is emitted when an \a error occurs. + + \sa error(), QBluetoothServer::Error + \since 6.2 +*/ + +/*! + \fn void QBluetoothServer::close() + + Closes and resets the listening socket. Any already established \l QBluetoothSocket + continues to operate and must be separately \l {QBluetoothSocket::close()}{closed}. +*/ + +/*! + \enum QBluetoothServer::Error + + This enum describes Bluetooth server error types. + + \value NoError No error. + \value UnknownError An unknown error occurred. + \value PoweredOffError The Bluetooth adapter is powered off. + \value InputOutputError An input output error occurred. + \value ServiceAlreadyRegisteredError The service or port was already registered + \value UnsupportedProtocolError The \l {QBluetoothServiceInfo::Protocol}{Protocol} is not + supported on this platform. + \value [since 6.4] MissingPermissionsError The operating system requests + permissions which were not + granted by the user. +*/ + +/*! + \fn bool QBluetoothServer::listen(const QBluetoothAddress &address, quint16 port) + + Start listening for incoming connections to \a address on \a port. \a address + must be a local Bluetooth adapter address and \a port must be larger than zero + and not be taken already by another Bluetooth server object. It is recommended + to avoid setting a port number to enable the system to automatically choose + a port. + + Returns \c true if the operation succeeded and the server is listening for + incoming connections, otherwise returns \c false. + + If the server object is already listening for incoming connections this function + always returns \c false. \l close() should be called before calling this function. + + \sa isListening(), newConnection() +*/ + +/*! + \fn void QBluetoothServer::setMaxPendingConnections(int numConnections) + + Sets the maximum number of pending connections to \a numConnections. If + the number of pending sockets exceeds this limit new sockets will be rejected. + + \sa maxPendingConnections() +*/ + +/*! + \fn bool QBluetoothServer::hasPendingConnections() const + Returns true if a connection is pending, otherwise false. +*/ + +/*! + \fn QBluetoothSocket *QBluetoothServer::nextPendingConnection() + + Returns a pointer to the QBluetoothSocket for the next pending connection. It is the callers + responsibility to delete the pointer. +*/ + +/*! + \fn QBluetoothAddress QBluetoothServer::serverAddress() const + + Returns the server address. +*/ + +/*! + \fn quint16 QBluetoothServer::serverPort() const + + Returns the server port number. +*/ + +/*! + Constructs a bluetooth server with \a parent and \a serverType. +*/ +QBluetoothServer::QBluetoothServer(QBluetoothServiceInfo::Protocol serverType, QObject *parent) + : QObject(parent), d_ptr(new QBluetoothServerPrivate(serverType, this)) +{ +} + +/*! + Destroys the bluetooth server. +*/ +QBluetoothServer::~QBluetoothServer() +{ + delete d_ptr; +} + +/*! + \fn QBluetoothServiceInfo QBluetoothServer::listen(const QBluetoothUuid &uuid, const QString &serviceName) + + Convenience function for registering an SPP service with \a uuid and \a serviceName. + Because this function already registers the service, the QBluetoothServiceInfo object + which is returned can not be changed any more. To shutdown the server later on it is + required to call \l QBluetoothServiceInfo::unregisterService() and \l close() on this + server object. + + Returns a registered QBluetoothServiceInfo instance if successful otherwise an + invalid QBluetoothServiceInfo. This function always assumes that the default Bluetooth adapter + should be used. + + If the server object is already listening for incoming connections this function + returns an invalid \l QBluetoothServiceInfo. + + For an RFCOMM server this function is equivalent to following code snippet. + + \snippet qbluetoothserver.cpp listen + \snippet qbluetoothserver.cpp listen2 + \snippet qbluetoothserver.cpp listen3 + + \sa isListening(), newConnection(), listen() +*/ +QBluetoothServiceInfo QBluetoothServer::listen(const QBluetoothUuid &uuid, const QString &serviceName) +{ + Q_D(const QBluetoothServer); + if (!listen()) + return QBluetoothServiceInfo(); +//! [listen] + QBluetoothServiceInfo serviceInfo; + serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceName, serviceName); + QBluetoothServiceInfo::Sequence browseSequence; + browseSequence << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ServiceClassUuid::PublicBrowseGroup)); + serviceInfo.setAttribute(QBluetoothServiceInfo::BrowseGroupList, + browseSequence); + + QBluetoothServiceInfo::Sequence profileSequence; + QBluetoothServiceInfo::Sequence classId; + classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ServiceClassUuid::SerialPort)); + classId << QVariant::fromValue(quint16(0x100)); + profileSequence.append(QVariant::fromValue(classId)); + serviceInfo.setAttribute(QBluetoothServiceInfo::BluetoothProfileDescriptorList, + profileSequence); + + classId.clear(); + //Android requires custom uuid to be set as service class + classId << QVariant::fromValue(uuid); + classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ServiceClassUuid::SerialPort)); + serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classId); + serviceInfo.setServiceUuid(uuid); + + QBluetoothServiceInfo::Sequence protocolDescriptorList; + QBluetoothServiceInfo::Sequence protocol; + protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ProtocolUuid::L2cap)); + if (d->serverType == QBluetoothServiceInfo::L2capProtocol) + protocol << QVariant::fromValue(serverPort()); + protocolDescriptorList.append(QVariant::fromValue(protocol)); + protocol.clear(); +//! [listen] + if (d->serverType == QBluetoothServiceInfo::RfcommProtocol) { +//! [listen2] + protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ProtocolUuid::Rfcomm)) + << QVariant::fromValue(quint8(serverPort())); + protocolDescriptorList.append(QVariant::fromValue(protocol)); +//! [listen2] + } +//! [listen3] + serviceInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, + protocolDescriptorList); + bool result = serviceInfo.registerService(); +//! [listen3] + if (!result) { + close(); //close the still listening socket + return QBluetoothServiceInfo(); + } + return serviceInfo; +} + +/*! + Returns true if the server is listening for incoming connections, otherwise false. +*/ +bool QBluetoothServer::isListening() const +{ + Q_D(const QBluetoothServer); + +#if defined(QT_ANDROID_BLUETOOTH) || defined(QT_WINRT_BLUETOOTH) || defined(QT_OSX_BLUETOOTH) + return d->isListening(); +#endif + + return d->socket->state() == QBluetoothSocket::SocketState::ListeningState; +} + +/*! + Returns the maximum number of pending connections. + + \sa setMaxPendingConnections() +*/ +int QBluetoothServer::maxPendingConnections() const +{ + Q_D(const QBluetoothServer); + + return d->maxPendingConnections; +} + +/*! + \fn QBluetoothServer::setSecurityFlags(QBluetooth::SecurityFlags security) + Sets the Bluetooth security flags to \a security. This function must be called + before calling listen(). The Bluetooth link will always be encrypted when using + Bluetooth 2.1 devices as encryption is mandatory. + + Android only supports two levels of security (secure and non-secure). If this flag + is set to \l QBluetooth::Security::NoSecurity the server object will not employ + any authentication or encryption. Any other security flag combination will + trigger a secure Bluetooth connection. + + On \macos, security flags are not supported and will be ignored. +*/ + +/*! + \fn QBluetooth::SecurityFlags QBluetoothServer::securityFlags() const + Returns the Bluetooth security flags. +*/ + +/*! + \fn QBluetoothSocket::ServerType QBluetoothServer::serverType() const + Returns the type of the QBluetoothServer. +*/ +QBluetoothServiceInfo::Protocol QBluetoothServer::serverType() const +{ + Q_D(const QBluetoothServer); + return d->serverType; +} + +/*! + \fn QBluetoothServer::Error QBluetoothServer::error() const + Returns the last error of the QBluetoothServer. +*/ +QBluetoothServer::Error QBluetoothServer::error() const +{ + Q_D(const QBluetoothServer); + return d->m_lastError; +} + +QT_END_NAMESPACE + +#include "moc_qbluetoothserver.cpp" diff --git a/src/bluetooth/qbluetoothserver.h b/src/bluetooth/qbluetoothserver.h new file mode 100644 index 0000000..ac11c30 --- /dev/null +++ b/src/bluetooth/qbluetoothserver.h @@ -0,0 +1,77 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2016 BlackBerry Limited. All rights reserved. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QBLUETOOTHSERVER_H +#define QBLUETOOTHSERVER_H + +#include + +#include + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QBluetoothServerPrivate; +class QBluetoothSocket; + +class Q_BLUETOOTH_EXPORT QBluetoothServer : public QObject +{ + Q_OBJECT + +public: + enum Error { + NoError, + UnknownError, + PoweredOffError, + InputOutputError, + ServiceAlreadyRegisteredError, + UnsupportedProtocolError, + MissingPermissionsError + }; + Q_ENUM(Error) + + explicit QBluetoothServer(QBluetoothServiceInfo::Protocol serverType, QObject *parent = nullptr); + ~QBluetoothServer(); + + void close(); + + bool listen(const QBluetoothAddress &address = QBluetoothAddress(), quint16 port = 0); + [[nodiscard]] QBluetoothServiceInfo listen(const QBluetoothUuid &uuid, + const QString &serviceName = QString()); + bool isListening() const; + + void setMaxPendingConnections(int numConnections); + int maxPendingConnections() const; + + bool hasPendingConnections() const; + QBluetoothSocket *nextPendingConnection(); + + QBluetoothAddress serverAddress() const; + quint16 serverPort() const; + + void setSecurityFlags(QBluetooth::SecurityFlags security); + QBluetooth::SecurityFlags securityFlags() const; + + QBluetoothServiceInfo::Protocol serverType() const; + + Error error() const; + +Q_SIGNALS: + void newConnection(); + void errorOccurred(QBluetoothServer::Error error); + +protected: + QBluetoothServerPrivate *d_ptr; + +private: + Q_DECLARE_PRIVATE(QBluetoothServer) +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/bluetooth/qbluetoothserver_android.cpp b/src/bluetooth/qbluetoothserver_android.cpp new file mode 100644 index 0000000..df26dae --- /dev/null +++ b/src/bluetooth/qbluetoothserver_android.cpp @@ -0,0 +1,247 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "android/serveracceptancethread_p.h" +#include "android/androidutils_p.h" +#include "android/jni_android_p.h" +#include "qbluetoothserver.h" +#include "qbluetoothserver_p.h" +#include "qbluetoothsocket.h" +#include "qbluetoothsocket_android_p.h" +#include "qbluetoothlocaldevice.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID) + +QHash __fakeServerPorts; + +QBluetoothServerPrivate::QBluetoothServerPrivate(QBluetoothServiceInfo::Protocol sType, + QBluetoothServer *parent) + : serverType(sType), q_ptr(parent) +{ + thread = new ServerAcceptanceThread(); + thread->setMaxPendingConnections(maxPendingConnections); +} + +QBluetoothServerPrivate::~QBluetoothServerPrivate() +{ + Q_Q(QBluetoothServer); + if (isListening()) + q->close(); + + __fakeServerPorts.remove(this); + + thread->deleteLater(); + thread = nullptr; +} + +bool QBluetoothServerPrivate::initiateActiveListening( + const QBluetoothUuid& uuid, const QString &serviceName) +{ + qCDebug(QT_BT_ANDROID) << "Initiate active listening" << uuid.toString() << serviceName; + + if (uuid.isNull() || serviceName.isEmpty()) + return false; + + //no change of SP profile details -> do nothing + if (uuid == m_uuid && serviceName == m_serviceName && thread->isRunning()) + return true; + + m_uuid = uuid; + m_serviceName = serviceName; + thread->setServiceDetails(m_uuid, m_serviceName, securityFlags); + + thread->run(); + if (!thread->isRunning()) + return false; + + return true; +} + +bool QBluetoothServerPrivate::deactivateActiveListening() +{ + if (isListening()) { + //suppress last error signal due to intended closure + thread->disconnect(); + thread->stop(); + } + return true; +} + +bool QBluetoothServerPrivate::isListening() const +{ + return __fakeServerPorts.contains(const_cast(this)); +} + +void QBluetoothServer::close() +{ + Q_D(QBluetoothServer); + + __fakeServerPorts.remove(d); + if (d->thread->isRunning()) { + //suppress last error signal due to intended closure + d->thread->disconnect(); + d->thread->stop(); + } +} + +bool QBluetoothServer::listen(const QBluetoothAddress &localAdapter, quint16 port) +{ + Q_D(QBluetoothServer); + if (serverType() != QBluetoothServiceInfo::RfcommProtocol) { + d->m_lastError = UnsupportedProtocolError; + emit errorOccurred(d->m_lastError); + return false; + } + + if (!ensureAndroidPermission(QBluetoothPermission::Access)) { + qCWarning(QT_BT_ANDROID) << "Bluetooth server listen() failed due to missing permissions"; + d->m_lastError = QBluetoothServer::MissingPermissionsError; + emit errorOccurred(d->m_lastError); + return false; + } + + const QList localDevices = QBluetoothLocalDevice::allDevices(); + if (localDevices.isEmpty()) { + qCWarning(QT_BT_ANDROID) << "Device does not support Bluetooth"; + d->m_lastError = QBluetoothServer::UnknownError; + emit errorOccurred(d->m_lastError); + return false; //no Bluetooth device + } + + if (!localAdapter.isNull()) { + bool found = false; + for (const QBluetoothHostInfo &hostInfo : localDevices) { + if (hostInfo.address() == localAdapter) { + found = true; + break; + } + } + + if (!found) { + qCWarning(QT_BT_ANDROID) << localAdapter.toString() << "is not a valid local Bt adapter"; + return false; + } + } + + if (d->isListening()) + return false; + + //check Bluetooth is available and online + QJniObject btAdapter = getDefaultBluetoothAdapter(); + + if (!btAdapter.isValid()) { + qCWarning(QT_BT_ANDROID) << "Device does not support Bluetooth"; + d->m_lastError = QBluetoothServer::UnknownError; + emit errorOccurred(d->m_lastError); + return false; + } + + const int state = btAdapter.callMethod("getState"); + if (state != 12 ) { //BluetoothAdapter.STATE_ON + d->m_lastError = QBluetoothServer::PoweredOffError; + emit errorOccurred(d->m_lastError); + qCWarning(QT_BT_ANDROID) << "Bluetooth device is powered off"; + return false; + } + + //We can not register an actual Rfcomm port, because the platform does not allow it + //but we need a way to associate a server with a service + if (port == 0) { //Try to assign a non taken port id + for (int i=1; ; i++){ + if (__fakeServerPorts.key(i) == 0) { + port = i; + break; + } + } + } + + if (__fakeServerPorts.key(port) == 0) { + __fakeServerPorts[d] = port; + + qCDebug(QT_BT_ANDROID) << "Port" << port << "registered"; + } else { + qCWarning(QT_BT_ANDROID) << "server with port" << port << "already registered or port invalid"; + d->m_lastError = ServiceAlreadyRegisteredError; + emit errorOccurred(d->m_lastError); + return false; + } + + connect(d->thread, SIGNAL(newConnection()), + this, SIGNAL(newConnection())); + connect(d->thread, SIGNAL(errorOccurred(QBluetoothServer::Error)), this, + SIGNAL(errorOccurred(QBluetoothServer::Error)), Qt::QueuedConnection); + + return true; +} + +void QBluetoothServer::setMaxPendingConnections(int numConnections) +{ + Q_D(QBluetoothServer); + d->maxPendingConnections = numConnections; + d->thread->setMaxPendingConnections(numConnections); +} + +QBluetoothAddress QBluetoothServer::serverAddress() const +{ + //Android only supports one local adapter + QList hosts = QBluetoothLocalDevice::allDevices(); + Q_ASSERT(hosts.size() <= 1); + + if (hosts.isEmpty()) + return QBluetoothAddress(); + else + return hosts.at(0).address(); +} + +quint16 QBluetoothServer::serverPort() const +{ + //We return the fake port + Q_D(const QBluetoothServer); + return __fakeServerPorts.value((QBluetoothServerPrivate*)d, 0); +} + +bool QBluetoothServer::hasPendingConnections() const +{ + Q_D(const QBluetoothServer); + + return d->thread->hasPendingConnections(); +} + +QBluetoothSocket *QBluetoothServer::nextPendingConnection() +{ + Q_D(const QBluetoothServer); + + QJniObject socket = d->thread->nextPendingConnection(); + if (!socket.isValid()) + return 0; + + + QBluetoothSocket *newSocket = new QBluetoothSocket(); + bool success = newSocket->d_ptr->setSocketDescriptor(socket, d->serverType); + if (!success) { + delete newSocket; + newSocket = nullptr; + } + + return newSocket; +} + +void QBluetoothServer::setSecurityFlags(QBluetooth::SecurityFlags security) +{ + Q_D(QBluetoothServer); + d->securityFlags = security; +} + +QBluetooth::SecurityFlags QBluetoothServer::securityFlags() const +{ + Q_D(const QBluetoothServer); + return d->securityFlags; +} + +QT_END_NAMESPACE + diff --git a/src/bluetooth/qbluetoothserver_bluez.cpp b/src/bluetooth/qbluetoothserver_bluez.cpp new file mode 100644 index 0000000..3181611 --- /dev/null +++ b/src/bluetooth/qbluetoothserver_bluez.cpp @@ -0,0 +1,331 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothserver.h" +#include "qbluetoothserver_p.h" +#include "qbluetoothsocket.h" +#include "qbluetoothsocket_bluez_p.h" +#include "qbluetoothlocaldevice.h" +#include "bluez/bluez_data_p.h" + +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ) + +QBluetoothSocket *QBluetoothServerPrivate::createSocketForServer( + QBluetoothServiceInfo::Protocol socketType) +{ + // QBluetoothServer does not work with the BluetoothSocket implementation for DBus. + // Fall back to the raw socket implementation. + // Usually the private implementation is picked based on detected BlueZ version. + + // ownership of these objects is taken care of inside QBluetoothSocket and QBluetoothServer + QBluetoothSocketPrivateBluez *rawSocketPrivate = new QBluetoothSocketPrivateBluez(); + QBluetoothSocket *socket = new QBluetoothSocket(rawSocketPrivate, socketType); + return socket; +} + +QBluetoothServerPrivate::QBluetoothServerPrivate(QBluetoothServiceInfo::Protocol sType, + QBluetoothServer *parent) + : securityFlags(QBluetooth::Security::Authorization), + serverType(sType), + q_ptr(parent) +{ + if (sType == QBluetoothServiceInfo::RfcommProtocol) + socket = createSocketForServer(QBluetoothServiceInfo::RfcommProtocol); + else + socket = createSocketForServer(QBluetoothServiceInfo::L2capProtocol); +} + +QBluetoothServerPrivate::~QBluetoothServerPrivate() +{ + delete socketNotifier; + + delete socket; +} + +void QBluetoothServerPrivate::_q_newConnection() +{ + // disable socket notifier until application calls nextPendingConnection(). + socketNotifier->setEnabled(false); + + emit q_ptr->newConnection(); +} + +void QBluetoothServerPrivate::setSocketSecurityLevel( + QBluetooth::SecurityFlags requestedSecLevel, int *errnoCode) +{ + if (requestedSecLevel == QBluetooth::SecurityFlags(QBluetooth::Security::NoSecurity)) { + qCWarning(QT_BT_BLUEZ) << "Cannot set NoSecurity on server socket"; + return; + } + + struct bt_security security; + memset(&security, 0, sizeof(security)); + + // ignore QBluetooth::Security::Authentication -> not used anymore + if (requestedSecLevel & QBluetooth::Security::Authorization) + security.level = BT_SECURITY_LOW; + if (requestedSecLevel & QBluetooth::Security::Encryption) + security.level = BT_SECURITY_MEDIUM; + if (requestedSecLevel & QBluetooth::Security::Secure) + security.level = BT_SECURITY_HIGH; + + if (setsockopt(socket->socketDescriptor(), SOL_BLUETOOTH, BT_SECURITY, + &security, sizeof(security)) != 0) { + if (errnoCode) + *errnoCode = errno; + } +} + +QBluetooth::SecurityFlags QBluetoothServerPrivate::socketSecurityLevel() const +{ + struct bt_security security; + memset(&security, 0, sizeof(security)); + socklen_t length = sizeof(security); + + if (getsockopt(socket->socketDescriptor(), SOL_BLUETOOTH, BT_SECURITY, + &security, &length) != 0) { + qCWarning(QT_BT_BLUEZ) << "Failed to get security flags" << qt_error_string(errno); + return QBluetooth::Security::NoSecurity; + } + + switch (security.level) { + case BT_SECURITY_LOW: + return QBluetooth::Security::Authorization; + case BT_SECURITY_MEDIUM: + return QBluetooth::Security::Encryption; + case BT_SECURITY_HIGH: + return QBluetooth::Security::Secure; + default: + qCWarning(QT_BT_BLUEZ) << "Unknown server socket security level" << security.level; + return QBluetooth::Security::NoSecurity; + } +} + +void QBluetoothServer::close() +{ + Q_D(QBluetoothServer); + + delete d->socketNotifier; + d->socketNotifier = nullptr; + + d->socket->close(); +} + +bool QBluetoothServer::listen(const QBluetoothAddress &address, quint16 port) +{ + Q_D(QBluetoothServer); + + if (d->socket->state() == QBluetoothSocket::SocketState::ListeningState) { + qCWarning(QT_BT_BLUEZ) << "Socket already in listen mode, close server first"; + return false; //already listening, nothing to do + } + + QBluetoothLocalDevice device(address); + if (!device.isValid()) { + qCWarning(QT_BT_BLUEZ) << "Device does not support Bluetooth or" + << address.toString() << "is not a valid local adapter"; + d->m_lastError = QBluetoothServer::UnknownError; + emit errorOccurred(d->m_lastError); + return false; + } + + QBluetoothLocalDevice::HostMode hostMode = device.hostMode(); + if (hostMode == QBluetoothLocalDevice::HostPoweredOff) { + d->m_lastError = QBluetoothServer::PoweredOffError; + emit errorOccurred(d->m_lastError); + qCWarning(QT_BT_BLUEZ) << "Bluetooth device is powered off"; + return false; + } + + int sock = d->socket->socketDescriptor(); + if (sock < 0) { + /* Negative socket descriptor is not always an error case + * Another cause could be a call to close()/abort() + * Check whether we can recover by re-creating the socket + * we should really call Bluez::QBluetoothSocketPrivateDarwin::ensureNativeSocket + * but a re-creation of the socket will do as well. + */ + + delete d->socket; + if (serverType() == QBluetoothServiceInfo::RfcommProtocol) + d->socket = QBluetoothServerPrivate::createSocketForServer(QBluetoothServiceInfo::RfcommProtocol); + else + d->socket = QBluetoothServerPrivate::createSocketForServer(QBluetoothServiceInfo::L2capProtocol); + + sock = d->socket->socketDescriptor(); + if (sock < 0) { + d->m_lastError = InputOutputError; + emit errorOccurred(d->m_lastError); + return false; + } + } + + if (d->serverType == QBluetoothServiceInfo::RfcommProtocol) { + sockaddr_rc addr; + + addr.rc_family = AF_BLUETOOTH; + addr.rc_channel = port; + + if (!address.isNull()) + convertAddress(address.toUInt64(), addr.rc_bdaddr.b); + else + convertAddress(device.address().toUInt64(), addr.rc_bdaddr.b); + + if (::bind(sock, reinterpret_cast(&addr), sizeof(sockaddr_rc)) < 0) { + if (errno == EADDRINUSE) + d->m_lastError = ServiceAlreadyRegisteredError; + else + d->m_lastError = InputOutputError; + emit errorOccurred(d->m_lastError); + return false; + } + } else { + sockaddr_l2 addr; + + memset(&addr, 0, sizeof(sockaddr_l2)); + addr.l2_family = AF_BLUETOOTH; + addr.l2_psm = port; + + if (!address.isNull()) + convertAddress(address.toUInt64(), addr.l2_bdaddr.b); + else + convertAddress(Q_UINT64_C(0), addr.l2_bdaddr.b); + + if (::bind(sock, reinterpret_cast(&addr), sizeof(sockaddr_l2)) < 0) { + d->m_lastError = InputOutputError; + emit errorOccurred(d->m_lastError); + return false; + } + } + + d->setSocketSecurityLevel(d->securityFlags, nullptr); + + if (::listen(sock, d->maxPendingConnections) < 0) { + d->m_lastError = InputOutputError; + emit errorOccurred(d->m_lastError); + return false; + } + + d->socket->setSocketState(QBluetoothSocket::SocketState::ListeningState); + + if (!d->socketNotifier) { + d->socketNotifier = new QSocketNotifier(d->socket->socketDescriptor(), + QSocketNotifier::Read); + connect(d->socketNotifier, &QSocketNotifier::activated, + this, [d](){ + d->_q_newConnection(); + }); + } + + return true; +} + +void QBluetoothServer::setMaxPendingConnections(int numConnections) +{ + Q_D(QBluetoothServer); + + if (d->socket->state() == QBluetoothSocket::SocketState::UnconnectedState) + d->maxPendingConnections = numConnections; +} + +bool QBluetoothServer::hasPendingConnections() const +{ + Q_D(const QBluetoothServer); + + if (!d || !d->socketNotifier) + return false; + + // if the socket notifier is disabled there is a pending connection waiting for us to accept. + return !d->socketNotifier->isEnabled(); +} + +QBluetoothSocket *QBluetoothServer::nextPendingConnection() +{ + Q_D(QBluetoothServer); + + if (!hasPendingConnections()) + return nullptr; + + int pending; + if (d->serverType == QBluetoothServiceInfo::RfcommProtocol) { + sockaddr_rc addr; + socklen_t length = sizeof(sockaddr_rc); + pending = ::accept(d->socket->socketDescriptor(), + reinterpret_cast(&addr), &length); + } else { + sockaddr_l2 addr; + socklen_t length = sizeof(sockaddr_l2); + pending = ::accept(d->socket->socketDescriptor(), + reinterpret_cast(&addr), &length); + } + + if (pending >= 0) { + QBluetoothSocket *newSocket = QBluetoothServerPrivate::createSocketForServer(); + if (d->serverType == QBluetoothServiceInfo::RfcommProtocol) + newSocket->setSocketDescriptor(pending, QBluetoothServiceInfo::RfcommProtocol); + else + newSocket->setSocketDescriptor(pending, QBluetoothServiceInfo::L2capProtocol); + + d->socketNotifier->setEnabled(true); + + return newSocket; + } else { + d->socketNotifier->setEnabled(true); + } + + return nullptr; +} + +QBluetoothAddress QBluetoothServer::serverAddress() const +{ + Q_D(const QBluetoothServer); + + return d->socket->localAddress(); +} + +quint16 QBluetoothServer::serverPort() const +{ + Q_D(const QBluetoothServer); + + return d->socket->localPort(); +} + +void QBluetoothServer::setSecurityFlags(QBluetooth::SecurityFlags security) +{ + Q_D(QBluetoothServer); + + if (d->socket->state() == QBluetoothSocket::SocketState::UnconnectedState) { + // nothing to set beyond the fact to remember the sec level for the next listen() + d->securityFlags = security; + return; + } + + int errorCode = 0; + d->setSocketSecurityLevel(security, &errorCode); + if (errorCode) { + qCWarning(QT_BT_BLUEZ) << "Failed to set socket option, closing socket for safety" << errorCode; + qCWarning(QT_BT_BLUEZ) << "Error: " << qt_error_string(errorCode); + d->m_lastError = InputOutputError; + emit errorOccurred(d->m_lastError); + d->socket->close(); + } +} + +QBluetooth::SecurityFlags QBluetoothServer::securityFlags() const +{ + Q_D(const QBluetoothServer); + + if (d->socket->state() == QBluetoothSocket::SocketState::UnconnectedState) + return d->securityFlags; + + return d->socketSecurityLevel(); +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothserver_macos.mm b/src/bluetooth/qbluetoothserver_macos.mm new file mode 100644 index 0000000..079a9c6 --- /dev/null +++ b/src/bluetooth/qbluetoothserver_macos.mm @@ -0,0 +1,383 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "darwin/btsocketlistener_p.h" +#include "qbluetoothserver_p.h" + +// The order is important: a workround for +// a private header included by private header +// (incorrectly handled dependencies). +#include "qbluetoothsocketbase_p.h" +#include "qbluetoothsocket_macos_p.h" + +#include "qbluetoothlocaldevice.h" +#include "darwin/btutility_p.h" +#include "qbluetoothserver.h" +#include "qbluetoothsocket.h" + +#include +#include +#include +#include + +#include + +#include + +#include + +QT_BEGIN_NAMESPACE + +namespace { + +using DarwinBluetooth::RetainPolicy; +using ServiceInfo = QBluetoothServiceInfo; + +QMap &busyPSMs() +{ + static QMap psms; + return psms; +} + +QMap &busyChannels() +{ + static QMap channels; + return channels; +} + +typedef QMap::iterator ServerMapIterator; + +} // unnamed namespace + +QBluetoothServerPrivate::QBluetoothServerPrivate(ServiceInfo::Protocol type, + QBluetoothServer *parent) + : serverType(type), + q_ptr(parent), + port(0) +{ + if (serverType == ServiceInfo::UnknownProtocol) + qCWarning(QT_BT_DARWIN) << "unknown protocol"; +} + +QBluetoothServerPrivate::~QBluetoothServerPrivate() +{ + const QMutexLocker lock(&channelMapMutex()); + unregisterServer(this); +} + +bool QBluetoothServerPrivate::startListener(quint16 realPort) +{ + Q_ASSERT_X(realPort, Q_FUNC_INFO, "invalid port"); + + if (serverType == ServiceInfo::UnknownProtocol) { + qCWarning(QT_BT_DARWIN) << "invalid protocol"; + return false; + } + + if (!listener) { + listener.reset([[DarwinBTSocketListener alloc] initWithListener:this], + RetainPolicy::noInitialRetain); + } + + bool result = false; + if (serverType == ServiceInfo::RfcommProtocol) + result = [listener.getAs() listenRFCOMMConnectionsWithChannelID:realPort]; + else + result = [listener.getAs() listenL2CAPConnectionsWithPSM:realPort]; + + if (!result) + listener.reset(); + + return result; +} + +bool QBluetoothServerPrivate::isListening() const +{ + if (serverType == ServiceInfo::UnknownProtocol) + return false; + + const QMutexLocker lock(&QBluetoothServerPrivate::channelMapMutex()); + return QBluetoothServerPrivate::registeredServer(q_ptr->serverPort(), serverType); +} + +void QBluetoothServerPrivate::stopListener() +{ + listener.reset(); +} + +void QBluetoothServerPrivate::openNotifyRFCOMM(void *generic) +{ + auto channel = static_cast(generic); + + Q_ASSERT_X(listener, Q_FUNC_INFO, "invalid listener (nil)"); + Q_ASSERT_X(channel, Q_FUNC_INFO, "invalid channel (nil)"); + Q_ASSERT_X(q_ptr, Q_FUNC_INFO, "invalid q_ptr (null)"); + + PendingConnection newConnection(channel, RetainPolicy::doInitialRetain); + pendingConnections.append(newConnection); + + emit q_ptr->newConnection(); +} + +void QBluetoothServerPrivate::openNotifyL2CAP(void *generic) +{ + auto channel = static_cast(generic); + + Q_ASSERT_X(listener, Q_FUNC_INFO, "invalid listener (nil)"); + Q_ASSERT_X(channel, Q_FUNC_INFO, "invalid channel (nil)"); + Q_ASSERT_X(q_ptr, Q_FUNC_INFO, "invalid q_ptr (null)"); + + PendingConnection newConnection(channel, RetainPolicy::doInitialRetain); + pendingConnections.append(newConnection); + + emit q_ptr->newConnection(); +} + +QMutex &QBluetoothServerPrivate::channelMapMutex() +{ + static QMutex mutex; + return mutex; +} + +bool QBluetoothServerPrivate::channelIsBusy(quint16 channelID) +{ + // External lock is required. + return busyChannels().contains(channelID); +} + +quint16 QBluetoothServerPrivate::findFreeChannel() +{ + // External lock is required. + for (quint16 i = 1; i <= 30; ++i) { + if (!busyChannels().contains(i)) + return i; + } + + return 0; //Invalid port. +} + +bool QBluetoothServerPrivate::psmIsBusy(quint16 psm) +{ + // External lock is required. + return busyPSMs().contains(psm); +} + +quint16 QBluetoothServerPrivate::findFreePSM() +{ + // External lock is required. + for (quint16 i = 1, e = std::numeric_limits::max(); i < e; i += 2) { + if (!psmIsBusy(i)) + return i; + } + + return 0; // Invalid PSM. +} + +void QBluetoothServerPrivate::registerServer(QBluetoothServerPrivate *server, quint16 port) +{ + // External lock is required + port must be free. + Q_ASSERT_X(server, Q_FUNC_INFO, "invalid server (null)"); + + const ServiceInfo::Protocol type = server->serverType; + if (type == ServiceInfo::RfcommProtocol) { + Q_ASSERT_X(!channelIsBusy(port), Q_FUNC_INFO, "port is busy"); + busyChannels()[port] = server; + } else if (type == ServiceInfo::L2capProtocol) { + Q_ASSERT_X(!psmIsBusy(port), Q_FUNC_INFO, "port is busy"); + busyPSMs()[port] = server; + } else { + qCWarning(QT_BT_DARWIN) << "can not register a server " + "with unknown protocol type"; + } +} + +QBluetoothServerPrivate *QBluetoothServerPrivate::registeredServer(quint16 port, QBluetoothServiceInfo::Protocol protocol) +{ + // Eternal lock is required. + if (protocol == ServiceInfo::RfcommProtocol) { + ServerMapIterator it = busyChannels().find(port); + if (it != busyChannels().end()) + return it.value(); + } else if (protocol == ServiceInfo::L2capProtocol) { + ServerMapIterator it = busyPSMs().find(port); + if (it != busyPSMs().end()) + return it.value(); + } else { + qCWarning(QT_BT_DARWIN) << "invalid protocol"; + } + + return nullptr; +} + +void QBluetoothServerPrivate::unregisterServer(QBluetoothServerPrivate *server) +{ + // External lock is required. + const ServiceInfo::Protocol type = server->serverType; + const quint16 port = server->port; + + if (type == ServiceInfo::RfcommProtocol) { + ServerMapIterator it = busyChannels().find(port); + if (it != busyChannels().end()) { + busyChannels().erase(it); + } else { + qCWarning(QT_BT_DARWIN) << "server is not registered"; + } + } else if (type == ServiceInfo::L2capProtocol) { + ServerMapIterator it = busyPSMs().find(port); + if (it != busyPSMs().end()) { + busyPSMs().erase(it); + } else { + qCWarning(QT_BT_DARWIN) << "server is not registered"; + } + } else { + qCWarning(QT_BT_DARWIN) << "invalid protocol"; + } +} + +void QBluetoothServer::close() +{ + d_ptr->listener.reset(); + + // Needs a lock :( + const QMutexLocker lock(&d_ptr->channelMapMutex()); + d_ptr->unregisterServer(d_ptr); + d_ptr->port = 0; +} + +bool QBluetoothServer::listen(const QBluetoothAddress &address, quint16 port) +{ + DarwinBluetooth::qt_test_iobluetooth_runloop(); + + if (d_ptr->listener) { + qCWarning(QT_BT_DARWIN) << "already in listen mode, close server first"; + return false; + } + + const QBluetoothLocalDevice device(address); + if (!device.isValid()) { + qCWarning(QT_BT_DARWIN) << "device does not support Bluetooth or" + << address.toString() + << "is not a valid local adapter"; + d_ptr->m_lastError = UnknownError; + emit errorOccurred(UnknownError); + return false; + } + + const QBluetoothLocalDevice::HostMode hostMode = device.hostMode(); + if (hostMode == QBluetoothLocalDevice::HostPoweredOff) { + qCWarning(QT_BT_DARWIN) << "Bluetooth device is powered off"; + d_ptr->m_lastError = PoweredOffError; + emit errorOccurred(PoweredOffError); + return false; + } + + const ServiceInfo::Protocol type = d_ptr->serverType; + + if (type == ServiceInfo::UnknownProtocol) { + qCWarning(QT_BT_DARWIN) << "invalid protocol"; + d_ptr->m_lastError = UnsupportedProtocolError; + emit errorOccurred(d_ptr->m_lastError); + return false; + } + + d_ptr->m_lastError = QBluetoothServer::NoError; + + // Now we have to register a (fake) port, doing a proper (?) lock. + const QMutexLocker lock(&d_ptr->channelMapMutex()); + + if (port) { + if (type == ServiceInfo::RfcommProtocol) { + if (d_ptr->channelIsBusy(port)) { + qCWarning(QT_BT_DARWIN) << "server port:" << port + << "already registered"; + d_ptr->m_lastError = ServiceAlreadyRegisteredError; + } + } else { + if (d_ptr->psmIsBusy(port)) { + qCWarning(QT_BT_DARWIN) << "server port:" << port + << "already registered"; + d_ptr->m_lastError = ServiceAlreadyRegisteredError; + } + } + } else { + type == ServiceInfo::RfcommProtocol ? port = d_ptr->findFreeChannel() + : port = d_ptr->findFreePSM(); + } + + if (d_ptr->m_lastError != QBluetoothServer::NoError) { + emit errorOccurred(d_ptr->m_lastError); + return false; + } + + if (!port) { + qCWarning(QT_BT_DARWIN) << "all ports are busy"; + d_ptr->m_lastError = ServiceAlreadyRegisteredError; + emit errorOccurred(d_ptr->m_lastError); + return false; + } + + // It's a fake port, the real one will be different + // (provided after a service was registered). + d_ptr->port = port; + d_ptr->registerServer(d_ptr, port); + d_ptr->listener.reset([[DarwinBTSocketListener alloc] initWithListener:d_ptr], + RetainPolicy::noInitialRetain); + + return true; +} + +void QBluetoothServer::setMaxPendingConnections(int numConnections) +{ + d_ptr->maxPendingConnections = numConnections; +} + +bool QBluetoothServer::hasPendingConnections() const +{ + return d_ptr->pendingConnections.size(); +} + +QBluetoothSocket *QBluetoothServer::nextPendingConnection() +{ + if (!d_ptr->pendingConnections.size()) + return nullptr; + + std::unique_ptr newSocket = std::make_unique(); + QBluetoothServerPrivate::PendingConnection channel(d_ptr->pendingConnections.front()); + + // Remove it even if we have some errors below. + d_ptr->pendingConnections.pop_front(); + + if (d_ptr->serverType == ServiceInfo::RfcommProtocol) { + if (!static_cast(newSocket->d_ptr)->setRFCOMChannel(channel.getAs())) + return nullptr; + } else { + if (!static_cast(newSocket->d_ptr)->setL2CAPChannel(channel.getAs())) + return nullptr; + } + + return newSocket.release(); +} + +QBluetoothAddress QBluetoothServer::serverAddress() const +{ + return QBluetoothLocalDevice().address(); +} + +quint16 QBluetoothServer::serverPort() const +{ + return d_ptr->port; +} + +void QBluetoothServer::setSecurityFlags(QBluetooth::SecurityFlags security) +{ + Q_UNUSED(security); + Q_UNIMPLEMENTED(); +} + +QBluetooth::SecurityFlags QBluetoothServer::securityFlags() const +{ + Q_UNIMPLEMENTED(); + return QBluetooth::Security::NoSecurity; +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothserver_p.cpp b/src/bluetooth/qbluetoothserver_p.cpp new file mode 100644 index 0000000..8183a2b --- /dev/null +++ b/src/bluetooth/qbluetoothserver_p.cpp @@ -0,0 +1,81 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothserver.h" +#include "qbluetoothserver_p.h" +#include "qbluetoothsocket.h" +#ifndef QT_IOS_BLUETOOTH +#include "dummy/dummy_helper_p.h" +#endif + +QT_BEGIN_NAMESPACE + +QBluetoothServerPrivate::QBluetoothServerPrivate(QBluetoothServiceInfo::Protocol sType, + QBluetoothServer *parent) + : serverType(sType), + q_ptr(parent) +{ +#ifndef QT_IOS_BLUETOOTH + printDummyWarning(); +#endif + if (sType == QBluetoothServiceInfo::RfcommProtocol) + socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol); + else + socket = new QBluetoothSocket(QBluetoothServiceInfo::L2capProtocol); +} + +QBluetoothServerPrivate::~QBluetoothServerPrivate() +{ + delete socket; +} + +void QBluetoothServer::close() +{ +} + +bool QBluetoothServer::listen(const QBluetoothAddress &address, quint16 port) +{ + Q_UNUSED(address); + Q_UNUSED(port); + Q_D(QBluetoothServer); + d->m_lastError = UnsupportedProtocolError; + emit errorOccurred(d->m_lastError); + return false; +} + +void QBluetoothServer::setMaxPendingConnections(int numConnections) +{ + Q_UNUSED(numConnections); +} + +bool QBluetoothServer::hasPendingConnections() const +{ + return false; +} + +QBluetoothSocket *QBluetoothServer::nextPendingConnection() +{ + return nullptr; +} + +QBluetoothAddress QBluetoothServer::serverAddress() const +{ + return QBluetoothAddress(); +} + +quint16 QBluetoothServer::serverPort() const +{ + return 0; +} + +void QBluetoothServer::setSecurityFlags(QBluetooth::SecurityFlags security) +{ + Q_UNUSED(security); +} + +QBluetooth::SecurityFlags QBluetoothServer::securityFlags() const +{ + return QBluetooth::Security::NoSecurity; +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothserver_p.h b/src/bluetooth/qbluetoothserver_p.h new file mode 100644 index 0000000..09c4335 --- /dev/null +++ b/src/bluetooth/qbluetoothserver_p.h @@ -0,0 +1,167 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QBLUETOOTHSERVER_P_H +#define QBLUETOOTHSERVER_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 "qbluetoothserver.h" +#include "qbluetooth.h" + +#if QT_CONFIG(bluez) +QT_FORWARD_DECLARE_CLASS(QSocketNotifier) +#endif + +#ifdef QT_ANDROID_BLUETOOTH +#include +#include +#include + +class ServerAcceptanceThread; +#endif + +#ifdef QT_WINRT_BLUETOOTH +#include + +#include +// No forward declares because QBluetoothServerPrivate::listener does not work with them +#include +#endif + +#ifdef QT_OSX_BLUETOOTH + +#include "darwin/btdelegates_p.h" +#include "darwin/btraii_p.h" + +#include + +#endif // QT_OSX_BLUETOOTH + +QT_BEGIN_NAMESPACE + +class QBluetoothAddress; +class QBluetoothSocket; +class QBluetoothServer; + +class QBluetoothServerPrivate +#ifdef QT_OSX_BLUETOOTH + : public DarwinBluetooth::SocketListener +#endif +{ + Q_DECLARE_PUBLIC(QBluetoothServer) + +public: + QBluetoothServerPrivate(QBluetoothServiceInfo::Protocol serverType, QBluetoothServer *parent); + ~QBluetoothServerPrivate(); + +#if QT_CONFIG(bluez) + void _q_newConnection(); + void setSocketSecurityLevel(QBluetooth::SecurityFlags requestedSecLevel, int *errnoCode); + QBluetooth::SecurityFlags socketSecurityLevel() const; + static QBluetoothSocket *createSocketForServer( + QBluetoothServiceInfo::Protocol socketType = QBluetoothServiceInfo::RfcommProtocol); +#endif + +public: + QBluetoothSocket *socket = nullptr; + + int maxPendingConnections = 1; + QBluetooth::SecurityFlags securityFlags = QBluetooth::Security::NoSecurity; + QBluetoothServiceInfo::Protocol serverType; + +protected: + QBluetoothServer *q_ptr; + +private: + QBluetoothServer::Error m_lastError = QBluetoothServer::NoError; +#if QT_CONFIG(bluez) + QSocketNotifier *socketNotifier = nullptr; +#elif defined(QT_ANDROID_BLUETOOTH) + ServerAcceptanceThread *thread; + QString m_serviceName; + QBluetoothUuid m_uuid; +public: + bool isListening() const; + bool initiateActiveListening(const QBluetoothUuid& uuid, const QString &serviceName); + bool deactivateActiveListening(); +#elif defined(QT_WINRT_BLUETOOTH) + EventRegistrationToken connectionToken {-1}; + + mutable QMutex pendingConnectionsMutex; + QList> + pendingConnections; + + Microsoft::WRL::ComPtr socketListener; + HRESULT handleClientConnection(ABI::Windows::Networking::Sockets::IStreamSocketListener *listener, + ABI::Windows::Networking::Sockets::IStreamSocketListenerConnectionReceivedEventArgs *args); + +public: + bool isListening() const; + Microsoft::WRL::ComPtr listener() { return socketListener; } + bool initiateActiveListening(const QString &serviceName); + bool deactivateActiveListening(); +#endif + +#ifdef QT_OSX_BLUETOOTH + +public: + + friend class QBluetoothServer; + friend class QBluetoothServiceInfoPrivate; + +private: + bool startListener(quint16 realPort); + void stopListener(); + bool isListening() const; + + // SocketListener (delegate): + void openNotifyRFCOMM(void *channel) override; + void openNotifyL2CAP(void *channel) override; + + // Either a "temporary" channelID/PSM assigned by QBluetoothServer::listen, + // or a real channelID/PSM returned by IOBluetooth after we've registered + // a service. + quint16 port; + + DarwinBluetooth::StrongReference listener; + + // These static functions below + // deal with differences between bluetooth sockets + // (bluez and QtBluetooth's API) and IOBluetooth, where it's not possible + // to have a real PSM/channelID _before_ a service is registered, + // the solution - "fake" ports. + // These functions require external locking - using channelMapMutex. + static QMutex &channelMapMutex(); + + static bool channelIsBusy(quint16 channelID); + static quint16 findFreeChannel(); + + static bool psmIsBusy(quint16 psm); + static quint16 findFreePSM(); + + static void registerServer(QBluetoothServerPrivate *server, quint16 port); + static QBluetoothServerPrivate *registeredServer(quint16 port, QBluetoothServiceInfo::Protocol protocol); + static void unregisterServer(QBluetoothServerPrivate *server); + + using PendingConnection = DarwinBluetooth::StrongReference; + QList pendingConnections; + +#endif // QT_OSX_BLUETOOTH +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/bluetooth/qbluetoothserver_winrt.cpp b/src/bluetooth/qbluetoothserver_winrt.cpp new file mode 100644 index 0000000..c7961f8 --- /dev/null +++ b/src/bluetooth/qbluetoothserver_winrt.cpp @@ -0,0 +1,225 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothserver.h" +#include "qbluetoothserver_p.h" +#include "qbluetoothsocket.h" +#include "qbluetoothlocaldevice.h" +#include "qbluetoothsocket_winrt_p.h" +#include "qbluetoothutils_winrt_p.h" + +#include +#include + +#include +#include +#include + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Devices; +using namespace ABI::Windows::Devices::Enumeration; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Networking; +using namespace ABI::Windows::Networking::Sockets; +using namespace ABI::Windows::Networking::Connectivity; + +typedef ITypedEventHandler ClientConnectedHandler; + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINDOWS) + +QHash __fakeServerPorts; + +QBluetoothServerPrivate::QBluetoothServerPrivate(QBluetoothServiceInfo::Protocol sType, + QBluetoothServer *parent) + : serverType(sType), q_ptr(parent) +{ + mainThreadCoInit(this); +} + +QBluetoothServerPrivate::~QBluetoothServerPrivate() +{ + deactivateActiveListening(); + __fakeServerPorts.remove(this); + // If we do not reset that pointer, socketListener will go out of scope after CoUninitialize was + // called, which will lead to a crash. + socketListener = nullptr; + mainThreadCoUninit(this); +} + +bool QBluetoothServerPrivate::isListening() const +{ + return __fakeServerPorts.contains(const_cast(this)); +} + +bool QBluetoothServerPrivate::initiateActiveListening(const QString &serviceName) +{ + HStringReference serviceNameRef(reinterpret_cast(serviceName.utf16())); + + ComPtr bindAction; + HRESULT hr = socketListener->BindServiceNameAsync(serviceNameRef.Get(), &bindAction); + Q_ASSERT_SUCCEEDED(hr); + hr = QWinRTFunctions::await(bindAction); + Q_ASSERT_SUCCEEDED(hr); + return true; +} + +bool QBluetoothServerPrivate::deactivateActiveListening() +{ + if (!isListening()) + return true; + + HRESULT hr; + hr = socketListener->remove_ConnectionReceived(connectionToken); + Q_ASSERT_SUCCEEDED(hr); + return true; +} + +HRESULT QBluetoothServerPrivate::handleClientConnection(IStreamSocketListener *listener, + IStreamSocketListenerConnectionReceivedEventArgs *args) +{ + Q_Q(QBluetoothServer); + if (!socketListener || socketListener.Get() != listener) { + qCDebug(QT_BT_WINDOWS) << "Accepting connection from wrong listener. We should not be here."; + Q_UNREACHABLE(); + return S_OK; + } + + HRESULT hr; + ComPtr socket; + hr = args->get_Socket(&socket); + Q_ASSERT_SUCCEEDED(hr); + QMutexLocker locker(&pendingConnectionsMutex); + if (pendingConnections.size() < maxPendingConnections) { + qCDebug(QT_BT_WINDOWS) << "Accepting connection"; + pendingConnections.append(socket); + locker.unlock(); + q->newConnection(); + } else { + qCDebug(QT_BT_WINDOWS) << "Refusing connection"; + } + + return S_OK; +} + +void QBluetoothServer::close() +{ + Q_D(QBluetoothServer); + + d->deactivateActiveListening(); + __fakeServerPorts.remove(d); +} + +bool QBluetoothServer::listen(const QBluetoothAddress &address, quint16 port) +{ + Q_UNUSED(address); + Q_D(QBluetoothServer); + if (serverType() != QBluetoothServiceInfo::RfcommProtocol) { + d->m_lastError = UnsupportedProtocolError; + emit errorOccurred(d->m_lastError); + return false; + } + + if (isListening()) + return false; + + HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_StreamSocketListener).Get(), + &d->socketListener); + Q_ASSERT_SUCCEEDED(hr); + hr = d->socketListener->add_ConnectionReceived(Callback(d, &QBluetoothServerPrivate::handleClientConnection).Get(), + &d->connectionToken); + Q_ASSERT_SUCCEEDED(hr); + + //We can not register an actual Rfcomm port, because the platform does not allow it + //but we need a way to associate a server with a service + if (port == 0) { //Try to assign a non taken port id + for (int i = 1; ; i++){ + if (__fakeServerPorts.key(i) == 0) { + port = i; + break; + } + } + } + + if (__fakeServerPorts.key(port) == 0) { + __fakeServerPorts[d] = port; + + qCDebug(QT_BT_WINDOWS) << "Port" << port << "registered"; + } else { + qCWarning(QT_BT_WINDOWS) << "server with port" << port << "already registered or port invalid"; + d->m_lastError = ServiceAlreadyRegisteredError; + emit errorOccurred(d->m_lastError); + return false; + } + + return true; +} + +void QBluetoothServer::setMaxPendingConnections(int numConnections) +{ + Q_D(QBluetoothServer); + QMutexLocker locker(&d->pendingConnectionsMutex); + if (d->pendingConnections.size() > numConnections) { + qCWarning(QT_BT_WINDOWS) << "There are currently more than" << numConnections << "connections" + << "pending. Number of maximum pending connections was not changed."; + return; + } + + d->maxPendingConnections = numConnections; +} + +bool QBluetoothServer::hasPendingConnections() const +{ + Q_D(const QBluetoothServer); + QMutexLocker locker(&d->pendingConnectionsMutex); + return !d->pendingConnections.isEmpty(); +} + +QBluetoothSocket *QBluetoothServer::nextPendingConnection() +{ + Q_D(QBluetoothServer); + if (d->pendingConnections.isEmpty()) + return nullptr; + + ComPtr socket = d->pendingConnections.takeFirst(); + + QBluetoothSocket *newSocket = new QBluetoothSocket(); + bool success = newSocket->d_ptr->setSocketDescriptor(socket, d->serverType); + if (!success) { + delete newSocket; + newSocket = nullptr; + } + + return newSocket; +} + +QBluetoothAddress QBluetoothServer::serverAddress() const +{ + QList hosts = QBluetoothLocalDevice::allDevices(); + + if (hosts.isEmpty()) + return QBluetoothAddress(); + else + return hosts.at(0).address(); +} + +quint16 QBluetoothServer::serverPort() const +{ + //We return the fake port + Q_D(const QBluetoothServer); + return __fakeServerPorts.value((QBluetoothServerPrivate*)d, 0); +} + +void QBluetoothServer::setSecurityFlags(QBluetooth::SecurityFlags security) +{ + Q_UNUSED(security); +} + +QBluetooth::SecurityFlags QBluetoothServer::securityFlags() const +{ + return QBluetooth::Security::NoSecurity; +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothservicediscoveryagent.cpp b/src/bluetooth/qbluetoothservicediscoveryagent.cpp new file mode 100644 index 0000000..2f5d9dd --- /dev/null +++ b/src/bluetooth/qbluetoothservicediscoveryagent.cpp @@ -0,0 +1,571 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothhostinfo.h" +#include "qbluetoothlocaldevice.h" +#include "qbluetoothservicediscoveryagent.h" +#include "qbluetoothservicediscoveryagent_p.h" + +#include "qbluetoothdevicediscoveryagent.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QBluetoothServiceDiscoveryAgent + \inmodule QtBluetooth + \brief The QBluetoothServiceDiscoveryAgent class enables you to query for + Bluetooth services. + + \since 5.2 + + The discovery process relies on the Bluetooth Service Discovery Process (SDP). + The following steps are required to query the services provided by all contactable + Bluetooth devices: + + \list + \li create an instance of QBluetoothServiceDiscoveryAgent, + \li connect to either the serviceDiscovered() or finished() signals, + \li and call start(). + \endlist + + \snippet doc_src_qtbluetooth.cpp service_discovery + + By default a minimal service discovery is performed. In this mode, the returned \l QBluetoothServiceInfo + objects are guaranteed to contain only device and service UUID information. Depending + on platform and device capabilities, other service information may also be available. + The minimal service discovery mode relies on cached SDP data of the platform. Therefore it + is possible that this discovery does not find a device although it is physically available. + In such cases a full discovery must be performed to force an update of the platform cache. + However for most use cases a minimal discovery is adequate as it is much quicker and other + classes which require up-to-date information such as QBluetoothSocket::connectToService() + will perform additional discovery if required. If the full service information is required, + pass \l FullDiscovery as the discoveryMode parameter to start(). + + This class may internally utilize \l QBluetoothDeviceDiscoveryAgent to find unknown devices. + + The service discovery may find Bluetooth Low Energy services too if the target device + is a combination of a classic and Low Energy device. Those devices are required to advertise + their Low Energy services via SDP. If the target device only supports Bluetooth Low + Energy services, it is likely to not advertise them via SDP. The \l QLowEnergyController class + should be utilized to perform the service discovery on Low Energy devices. + + On iOS, this class cannot be used because the platform does not expose + an API which may permit access to QBluetoothServiceDiscoveryAgent related features. + + \sa QBluetoothDeviceDiscoveryAgent, QLowEnergyController +*/ + +/*! + \enum QBluetoothServiceDiscoveryAgent::Error + + This enum describes errors that can occur during service discovery. + + \value NoError No error has occurred. + \value PoweredOffError The Bluetooth adaptor is powered off, power it on before doing discovery. + \value InputOutputError Writing or reading from the device resulted in an error. + \value [since 5.3] InvalidBluetoothAdapterError The passed local adapter address does not + match the physical adapter address of any + local Bluetooth device. + \value [since 6.4] MissingPermissionsError The operating system requests + permissions which were not + granted by the user. + \value UnknownError An unknown error has occurred. +*/ + +/*! + \enum QBluetoothServiceDiscoveryAgent::DiscoveryMode + + This enum describes the service discovery mode. + + \value MinimalDiscovery Performs a minimal service discovery. The QBluetoothServiceInfo + objects returned may be incomplete and are only guaranteed to contain device and service UUID information. + Since a minimal discovery relies on cached SDP data it may not find a physically existing + device until a \c FullDiscovery is performed. + \value FullDiscovery Performs a full service discovery. +*/ + +/*! + \fn QBluetoothServiceDiscoveryAgent::serviceDiscovered(const QBluetoothServiceInfo &info) + + This signal is emitted when the Bluetooth service described by \a info is discovered. + + \note The passed \l QBluetoothServiceInfo parameter may contain a Bluetooth Low Energy + service if the target device advertises the service via SDP. This is required from device + which support both, classic Bluetooth (BaseRate) and Low Energy services. + + \sa QBluetoothDeviceInfo::coreConfigurations() +*/ + +/*! + \fn QBluetoothServiceDiscoveryAgent::finished() + + This signal is emitted when the Bluetooth service discovery completes. + + Unlike the \l QBluetoothDeviceDiscoveryAgent::finished() signal this + signal will even be emitted when an error occurred during the service discovery. Therefore + it is recommended to check the \l errorOccurred() signal to evaluate the success of the + service discovery discovery. +*/ + +/*! + \fn void QBluetoothServiceDiscoveryAgent::errorOccurred(QBluetoothServiceDiscoveryAgent::Error + error) + + This signal is emitted when an \a error occurs. The \a error parameter describes the error that + occurred. + + \since 6.2 +*/ + +/*! + Constructs a new QBluetoothServiceDiscoveryAgent with \a parent. The search is performed via the + local default Bluetooth adapter. +*/ +QBluetoothServiceDiscoveryAgent::QBluetoothServiceDiscoveryAgent(QObject *parent) + : QObject(parent), + d_ptr(new QBluetoothServiceDiscoveryAgentPrivate(this, QBluetoothAddress())) +{ +} + +/*! + Constructs a new QBluetoothServiceDiscoveryAgent for \a deviceAdapter and with \a parent. + + It uses \a deviceAdapter for the service search. If \a deviceAdapter is default constructed + the resulting QBluetoothServiceDiscoveryAgent object will use the local default Bluetooth adapter. + + If a \a deviceAdapter is specified that is not a local adapter \l error() will be set to + \l InvalidBluetoothAdapterError. Therefore it is recommended to test the error flag immediately after + using this constructor. + + \note On WinRT the passed adapter address will be ignored. + + \note On Android passing any \a deviceAdapter address is meaningless as Android 6.0 or later does not publish + the local Bluetooth address anymore. Subsequently, the passed adapter address can never be matched + against the local adapter address. Therefore the subsequent call to \l start() will always trigger + \l InvalidBluetoothAdapterError. + + \sa error() +*/ +QBluetoothServiceDiscoveryAgent::QBluetoothServiceDiscoveryAgent(const QBluetoothAddress &deviceAdapter, QObject *parent) + : QObject(parent), + d_ptr(new QBluetoothServiceDiscoveryAgentPrivate(this, deviceAdapter)) +{ + if (!deviceAdapter.isNull()) { + const QList localDevices = QBluetoothLocalDevice::allDevices(); + for (const QBluetoothHostInfo &hostInfo : localDevices) { + if (hostInfo.address() == deviceAdapter) + return; + } + d_ptr->error = InvalidBluetoothAdapterError; + d_ptr->errorString = tr("Invalid Bluetooth adapter address"); + } +} + +/*! + + Destructor for QBluetoothServiceDiscoveryAgent + +*/ + +QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent() +{ + if (isActive()) { + disconnect(); //don't emit any signals due to stop() + stop(); + } + + delete d_ptr; +} + +/*! + Returns the list of all discovered services. + + This list of services accumulates newly discovered services from multiple calls + to \l start(). Unless \l clear() is called the list cannot decrease in size. This implies + that if a remote Bluetooth device moves out of range in between two subsequent calls + to \l start() the list may contain stale entries. + + \note The list of services should always be cleared before the discovery mode is changed. + + \sa clear() +*/ +QList QBluetoothServiceDiscoveryAgent::discoveredServices() const +{ + Q_D(const QBluetoothServiceDiscoveryAgent); + + return d->discoveredServices; +} +/*! + Sets the UUID filter to \a uuids. Only services matching the UUIDs in \a uuids will be + returned. The matching applies to the service's + \l {QBluetoothServiceInfo::ServiceId}{ServiceId} and \l {QBluetoothServiceInfo::ServiceClassIds} {ServiceClassIds} + attributes. + + An empty UUID list is equivalent to a list containing only QBluetoothUuid::ServiceClassUuid::PublicBrowseGroup. + + \sa uuidFilter() +*/ +void QBluetoothServiceDiscoveryAgent::setUuidFilter(const QList &uuids) +{ + Q_D(QBluetoothServiceDiscoveryAgent); + + d->uuidFilter = uuids; +} + +/*! + This is an overloaded member function, provided for convenience. + + Sets the UUID filter to a list containing the single element \a uuid. + The matching applies to the service's \l {QBluetoothServiceInfo::ServiceId}{ServiceId} + and \l {QBluetoothServiceInfo::ServiceClassIds} {ServiceClassIds} + attributes. + + \sa uuidFilter() +*/ +void QBluetoothServiceDiscoveryAgent::setUuidFilter(const QBluetoothUuid &uuid) +{ + Q_D(QBluetoothServiceDiscoveryAgent); + + d->uuidFilter.clear(); + d->uuidFilter.append(uuid); +} + +/*! + Returns the UUID filter. + + \sa setUuidFilter() +*/ +QList QBluetoothServiceDiscoveryAgent::uuidFilter() const +{ + Q_D(const QBluetoothServiceDiscoveryAgent); + + return d->uuidFilter; +} + +/*! + Sets the remote device address to \a address. If \a address is default constructed, + services will be discovered on all contactable Bluetooth devices. A new remote + address can only be set while there is no service discovery in progress; otherwise + this function returns false. + + On some platforms the service discovery might lead to pairing requests. + Therefore it is not recommended to do service discoveries on all devices. + This function can be used to restrict the service discovery to a particular device. + + \sa remoteAddress() +*/ +bool QBluetoothServiceDiscoveryAgent::setRemoteAddress(const QBluetoothAddress &address) +{ + if (isActive()) + return false; + if (!address.isNull()) + d_ptr->singleDevice = true; + d_ptr->deviceAddress = address; + return true; +} + +/*! + Returns the remote device address. If \l setRemoteAddress() is not called, the function + will return a default constructed \l QBluetoothAddress. + + \sa setRemoteAddress() +*/ +QBluetoothAddress QBluetoothServiceDiscoveryAgent::remoteAddress() const +{ + if (d_ptr->singleDevice == true) + return d_ptr->deviceAddress; + else + return QBluetoothAddress(); +} + +namespace DarwinBluetooth { + +void qt_test_iobluetooth_runloop(); + +} + + +/*! + Starts service discovery. \a mode specifies the type of service discovery to perform. + + On some platforms, device discovery may lead to pairing requests. + + \sa DiscoveryMode +*/ +void QBluetoothServiceDiscoveryAgent::start(DiscoveryMode mode) +{ + Q_D(QBluetoothServiceDiscoveryAgent); +#ifdef QT_OSX_BLUETOOTH + // Make sure we are on the right thread/have a run loop: + DarwinBluetooth::qt_test_iobluetooth_runloop(); +#endif + + if (d->discoveryState() == QBluetoothServiceDiscoveryAgentPrivate::Inactive + && d->error != InvalidBluetoothAdapterError) { +#if QT_CONFIG(bluez) + // done to avoid repeated parsing for adapter address + // on Bluez5 + d->foundHostAdapterPath.clear(); +#endif + d->setDiscoveryMode(mode); + // Clear any possible previous errors + d->error = QBluetoothServiceDiscoveryAgent::NoError; + d->errorString.clear(); + if (d->deviceAddress.isNull()) { + d->startDeviceDiscovery(); + } else { + d->discoveredDevices << QBluetoothDeviceInfo(d->deviceAddress, QString(), 0); + d->startServiceDiscovery(); + } + } +} + +/*! + Stops the service discovery process. The \l canceled() signal will be emitted once + the search has stopped. +*/ +void QBluetoothServiceDiscoveryAgent::stop() +{ + Q_D(QBluetoothServiceDiscoveryAgent); + + if (d->error == InvalidBluetoothAdapterError || !isActive()) + return; + + switch (d->discoveryState()) { + case QBluetoothServiceDiscoveryAgentPrivate::DeviceDiscovery: + d->stopDeviceDiscovery(); + break; + case QBluetoothServiceDiscoveryAgentPrivate::ServiceDiscovery: + d->stopServiceDiscovery(); + default: + ; + } + + d->discoveredDevices.clear(); +} + +/*! + Clears the results of previous service discoveries and resets \l uuidFilter(). + This function does nothing during an ongoing service discovery (see \l isActive()). + + \sa discoveredServices() +*/ +void QBluetoothServiceDiscoveryAgent::clear() +{ + Q_D(QBluetoothServiceDiscoveryAgent); + + //don't clear the list while the search is ongoing + if (isActive()) + return; + + d->discoveredDevices.clear(); + d->discoveredServices.clear(); + d->uuidFilter.clear(); +} + +/*! + Returns \c true if the service discovery is currently active; otherwise returns \c false. + An active discovery can be stopped by calling \l stop(). +*/ +bool QBluetoothServiceDiscoveryAgent::isActive() const +{ + Q_D(const QBluetoothServiceDiscoveryAgent); + + return d->state != QBluetoothServiceDiscoveryAgentPrivate::Inactive; +} + +/*! + Returns the type of error that last occurred. If the service discovery is done + for a single \l remoteAddress() it will return errors that occurred while trying to discover + services on that device. If the \l remoteAddress() is not set and devices are + discovered by a scan, errors during service discovery on individual + devices are not saved and no signals are emitted. In this case, errors are + fairly normal as some devices may not respond to discovery or + may no longer be in range. Such errors are suppressed. If no services + are returned, it can be assumed no services could be discovered. + + Any possible previous errors are cleared upon restarting the discovery. +*/ +QBluetoothServiceDiscoveryAgent::Error QBluetoothServiceDiscoveryAgent::error() const +{ + Q_D(const QBluetoothServiceDiscoveryAgent); + + return d->error; +} + +/*! + Returns a human-readable description of the last error that occurred during the + service discovery. + + \sa error(), errorOccurred() +*/ +QString QBluetoothServiceDiscoveryAgent::errorString() const +{ + Q_D(const QBluetoothServiceDiscoveryAgent); + return d->errorString; +} + + +/*! + \fn QBluetoothServiceDiscoveryAgent::canceled() + + This signal is triggered when the service discovery was canceled via a call to \l stop(). + */ + + +/*! + Starts device discovery. +*/ +void QBluetoothServiceDiscoveryAgentPrivate::startDeviceDiscovery() +{ + Q_Q(QBluetoothServiceDiscoveryAgent); + + if (!deviceDiscoveryAgent) { +#if QT_CONFIG(bluez) + deviceDiscoveryAgent = new QBluetoothDeviceDiscoveryAgent(m_deviceAdapterAddress, q); +#else + deviceDiscoveryAgent = new QBluetoothDeviceDiscoveryAgent(q); +#endif + QObject::connect(deviceDiscoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, + q, [this](){ + this->_q_deviceDiscoveryFinished(); + }); + QObject::connect(deviceDiscoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, + q, [this](const QBluetoothDeviceInfo &info){ + this->_q_deviceDiscovered(info); + }); + QObject::connect(deviceDiscoveryAgent, &QBluetoothDeviceDiscoveryAgent::errorOccurred, q, + [this](QBluetoothDeviceDiscoveryAgent::Error newError) { + this->_q_deviceDiscoveryError(newError); + }); + } + + setDiscoveryState(DeviceDiscovery); + + deviceDiscoveryAgent->start(QBluetoothDeviceDiscoveryAgent::ClassicMethod); +} + +/*! + Stops device discovery. +*/ +void QBluetoothServiceDiscoveryAgentPrivate::stopDeviceDiscovery() +{ + // disconnect to avoid recursion during stop() - QTBUG-60131 + // we don't care about a potential signals from device discovery agent anymore + deviceDiscoveryAgent->disconnect(); + + deviceDiscoveryAgent->stop(); + delete deviceDiscoveryAgent; + deviceDiscoveryAgent = nullptr; + + setDiscoveryState(Inactive); + + Q_Q(QBluetoothServiceDiscoveryAgent); + emit q->canceled(); +} + +/*! + Called when device discovery finishes. +*/ +void QBluetoothServiceDiscoveryAgentPrivate::_q_deviceDiscoveryFinished() +{ + if (deviceDiscoveryAgent->error() != QBluetoothDeviceDiscoveryAgent::NoError) { + //Forward the device discovery error + error = static_cast(deviceDiscoveryAgent->error()); + errorString = deviceDiscoveryAgent->errorString(); + setDiscoveryState(Inactive); + Q_Q(QBluetoothServiceDiscoveryAgent); + emit q->errorOccurred(error); + emit q->finished(); + return; + } + + delete deviceDiscoveryAgent; + deviceDiscoveryAgent = nullptr; + + startServiceDiscovery(); +} + +void QBluetoothServiceDiscoveryAgentPrivate::_q_deviceDiscovered(const QBluetoothDeviceInfo &info) +{ + // look for duplicates, and cached entries + const auto addressEquals = [](const auto &a) { + return [a](const auto &info) { return info.address() == a; }; + }; + erase_if(discoveredDevices, addressEquals(info.address())); + discoveredDevices.prepend(info); +} + +void QBluetoothServiceDiscoveryAgentPrivate::_q_deviceDiscoveryError(QBluetoothDeviceDiscoveryAgent::Error newError) +{ + error = static_cast(newError); + errorString = deviceDiscoveryAgent->errorString(); + + // disconnect to avoid recursion during stop() - QTBUG-60131 + // we don't care about a potential signals from device discovery agent anymore + deviceDiscoveryAgent->disconnect(); + + deviceDiscoveryAgent->stop(); + delete deviceDiscoveryAgent; + deviceDiscoveryAgent = nullptr; + + setDiscoveryState(Inactive); + Q_Q(QBluetoothServiceDiscoveryAgent); + emit q->errorOccurred(error); + emit q->finished(); +} + +/*! + Starts service discovery for the next device. +*/ +void QBluetoothServiceDiscoveryAgentPrivate::startServiceDiscovery() +{ + Q_Q(QBluetoothServiceDiscoveryAgent); + + if (discoveredDevices.isEmpty()) { + setDiscoveryState(Inactive); + emit q->finished(); + return; + } + + setDiscoveryState(ServiceDiscovery); + start(discoveredDevices.at(0).address()); +} + +/*! + Stops service discovery. +*/ +void QBluetoothServiceDiscoveryAgentPrivate::stopServiceDiscovery() +{ + stop(); + + setDiscoveryState(Inactive); +} + +void QBluetoothServiceDiscoveryAgentPrivate::_q_serviceDiscoveryFinished() +{ + if(!discoveredDevices.isEmpty()) { + discoveredDevices.removeFirst(); + } + + startServiceDiscovery(); +} + +bool QBluetoothServiceDiscoveryAgentPrivate::isDuplicatedService( + const QBluetoothServiceInfo &serviceInfo) const +{ + //check the service is not already part of our known list + for (const QBluetoothServiceInfo &info : discoveredServices) { + if (info.device() == serviceInfo.device() + && info.serviceClassUuids() == serviceInfo.serviceClassUuids() + && info.serviceUuid() == serviceInfo.serviceUuid() + && info.serverChannel() == serviceInfo.serverChannel()) { + return true; + } + } + return false; +} + +QT_END_NAMESPACE + +#include "moc_qbluetoothservicediscoveryagent.cpp" diff --git a/src/bluetooth/qbluetoothservicediscoveryagent.h b/src/bluetooth/qbluetoothservicediscoveryagent.h new file mode 100644 index 0000000..9c34b43 --- /dev/null +++ b/src/bluetooth/qbluetoothservicediscoveryagent.h @@ -0,0 +1,83 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QBLUETOOTHSERVICEDISCOVERYAGENT_H +#define QBLUETOOTHSERVICEDISCOVERYAGENT_H + +#include + +#include +#include + +#include +#include +#include + +#if QT_CONFIG(bluez) +#include +#endif + +QT_BEGIN_NAMESPACE + +class QBluetoothAddress; +class QBluetoothServiceDiscoveryAgentPrivate; + +class Q_BLUETOOTH_EXPORT QBluetoothServiceDiscoveryAgent : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QBluetoothServiceDiscoveryAgent) + +public: + enum Error { + NoError = QBluetoothDeviceDiscoveryAgent::NoError, + InputOutputError = QBluetoothDeviceDiscoveryAgent::InputOutputError, + PoweredOffError = QBluetoothDeviceDiscoveryAgent::PoweredOffError, + InvalidBluetoothAdapterError = QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError, + MissingPermissionsError = QBluetoothDeviceDiscoveryAgent::MissingPermissionsError, + UnknownError = QBluetoothDeviceDiscoveryAgent::UnknownError //=100 + //New Errors must be added after Unknown Error the space before UnknownError is reserved + //for future device discovery errors + }; + Q_ENUM(Error) + + enum DiscoveryMode { + MinimalDiscovery, + FullDiscovery + }; + Q_ENUM(DiscoveryMode) + + explicit QBluetoothServiceDiscoveryAgent(QObject *parent = nullptr); + explicit QBluetoothServiceDiscoveryAgent(const QBluetoothAddress &deviceAdapter, QObject *parent = nullptr); + ~QBluetoothServiceDiscoveryAgent(); + + bool isActive() const; + + Error error() const; + QString errorString() const; + + QList discoveredServices() const; + + void setUuidFilter(const QList &uuids); + void setUuidFilter(const QBluetoothUuid &uuid); + QList uuidFilter() const; + bool setRemoteAddress(const QBluetoothAddress &address); + QBluetoothAddress remoteAddress() const; + +public Q_SLOTS: + void start(DiscoveryMode mode = MinimalDiscovery); + void stop(); + void clear(); + +Q_SIGNALS: + void serviceDiscovered(const QBluetoothServiceInfo &info); + void finished(); + void canceled(); + void errorOccurred(QBluetoothServiceDiscoveryAgent::Error error); + +private: + QBluetoothServiceDiscoveryAgentPrivate *d_ptr; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp new file mode 100644 index 0000000..952ba3d --- /dev/null +++ b/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp @@ -0,0 +1,474 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothservicediscoveryagent_p.h" +#include "qbluetoothsocket_android_p.h" +#include "android/servicediscoverybroadcastreceiver_p.h" +#include "android/localdevicebroadcastreceiver_p.h" +#include "android/androidutils_p.h" +#include "android/jni_android_p.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID) + +static constexpr auto uuidFetchTimeLimit = std::chrono::seconds{4}; + +QBluetoothServiceDiscoveryAgentPrivate::QBluetoothServiceDiscoveryAgentPrivate( + QBluetoothServiceDiscoveryAgent *qp, const QBluetoothAddress &deviceAdapter) + : error(QBluetoothServiceDiscoveryAgent::NoError), + m_deviceAdapterAddress(deviceAdapter), + state(Inactive), + mode(QBluetoothServiceDiscoveryAgent::MinimalDiscovery), + singleDevice(false), + q_ptr(qp) + +{ + // If a specific adapter address is requested we need to check it matches + // the current local adapter. If it does not match we emit + // InvalidBluetoothAdapterError when calling start() + + bool createAdapter = true; + if (!deviceAdapter.isNull()) { + const QList devices = QBluetoothLocalDevice::allDevices(); + if (devices.isEmpty()) { + createAdapter = false; + } else { + auto match = [deviceAdapter](const QBluetoothHostInfo& info) { + return info.address() == deviceAdapter; + }; + + auto result = std::find_if(devices.begin(), devices.end(), match); + if (result == devices.end()) + createAdapter = false; + } + } + + /* + We assume that the current local adapter has been passed. + The logic below must change once there is more than one adapter. + */ + + if (createAdapter) + btAdapter = getDefaultBluetoothAdapter(); + + if (!btAdapter.isValid()) + qCWarning(QT_BT_ANDROID) << "Platform does not support Bluetooth"; + + qRegisterMetaType >(); +} + +QBluetoothServiceDiscoveryAgentPrivate::~QBluetoothServiceDiscoveryAgentPrivate() +{ + if (receiver) { + receiver->unregisterReceiver(); + delete receiver; + } + if (localDeviceReceiver) { + localDeviceReceiver->unregisterReceiver(); + delete localDeviceReceiver; + } +} + +void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &address) +{ + Q_Q(QBluetoothServiceDiscoveryAgent); + + if (!ensureAndroidPermission(QBluetoothPermission::Access)) { + qCWarning(QT_BT_ANDROID) << "Service discovery start() failed due to missing permissions"; + error = QBluetoothServiceDiscoveryAgent::MissingPermissionsError; + errorString = QBluetoothServiceDiscoveryAgent::tr( + "Failed to start service discovery due to missing permissions."); + emit q->errorOccurred(error); + _q_serviceDiscoveryFinished(); + return; + } + + if (!btAdapter.isValid()) { + if (m_deviceAdapterAddress.isNull()) { + error = QBluetoothServiceDiscoveryAgent::UnknownError; + errorString = QBluetoothServiceDiscoveryAgent::tr("Platform does not support Bluetooth"); + } else { + // specific adapter was requested which does not match the locally + // existing adapter + error = QBluetoothServiceDiscoveryAgent::InvalidBluetoothAdapterError; + errorString = QBluetoothServiceDiscoveryAgent::tr("Invalid Bluetooth adapter address"); + } + + //abort any outstanding discoveries + discoveredDevices.clear(); + emit q->errorOccurred(error); + _q_serviceDiscoveryFinished(); + + return; + } + + QJniObject inputString = QJniObject::fromString(address.toString()); + QJniObject remoteDevice = + btAdapter.callMethod("getRemoteDevice", + inputString.object()); + if (!remoteDevice.isValid()) { + + //if it was only device then its error -> otherwise go to next device + if (singleDevice) { + error = QBluetoothServiceDiscoveryAgent::InputOutputError; + errorString = QBluetoothServiceDiscoveryAgent::tr("Cannot create Android BluetoothDevice"); + + qCWarning(QT_BT_ANDROID) << "Cannot start SDP for" << discoveredDevices.at(0).name() + << "(" << address.toString() << ")"; + emit q->errorOccurred(error); + } + _q_serviceDiscoveryFinished(); + return; + } + + + if (mode == QBluetoothServiceDiscoveryAgent::MinimalDiscovery) { + qCDebug(QT_BT_ANDROID) << "Minimal discovery on (" << discoveredDevices.at(0).name() + << ")" << address.toString() ; + + //Minimal discovery uses BluetoothDevice.getUuids() + QJniObject parcelUuidArray = + remoteDevice.callMethod("getUuids"); + + if (!parcelUuidArray.isValid()) { + if (singleDevice) { + error = QBluetoothServiceDiscoveryAgent::InputOutputError; + errorString = QBluetoothServiceDiscoveryAgent::tr("Cannot obtain service uuids"); + emit q->errorOccurred(error); + } + qCWarning(QT_BT_ANDROID) << "Cannot retrieve SDP UUIDs for" << discoveredDevices.at(0).name() + << "(" << address.toString() << ")"; + _q_serviceDiscoveryFinished(); + return; + } + + const QList results = ServiceDiscoveryBroadcastReceiver::convertParcelableArray(parcelUuidArray); + populateDiscoveredServices(discoveredDevices.at(0), results); + + _q_serviceDiscoveryFinished(); + } else { + qCDebug(QT_BT_ANDROID) << "Full discovery on (" << discoveredDevices.at(0).name() + << ")" << address.toString(); + + //Full discovery uses BluetoothDevice.fetchUuidsWithSdp() + if (!receiver) { + receiver = new ServiceDiscoveryBroadcastReceiver(); + QObject::connect(receiver, &ServiceDiscoveryBroadcastReceiver::uuidFetchFinished, + q, [this](const QBluetoothAddress &address, const QList& uuids) { + this->_q_processFetchedUuids(address, uuids); + }); + } + + if (!localDeviceReceiver) { + localDeviceReceiver = new LocalDeviceBroadcastReceiver(); + QObject::connect(localDeviceReceiver, &LocalDeviceBroadcastReceiver::hostModeStateChanged, + q, [this](QBluetoothLocalDevice::HostMode state){ + this->_q_hostModeStateChanged(state); + }); + } + + jboolean result = remoteDevice.callMethod("fetchUuidsWithSdp"); + if (!result) { + //kill receiver to limit load of signals + receiver->unregisterReceiver(); + receiver->deleteLater(); + receiver = nullptr; + qCWarning(QT_BT_ANDROID) << "Cannot start dynamic fetch."; + _q_serviceDiscoveryFinished(); + } + } +} + +void QBluetoothServiceDiscoveryAgentPrivate::stop() +{ + sdpCache.clear(); + discoveredDevices.clear(); + + //kill receiver to limit load of signals + if (receiver) { + receiver->unregisterReceiver(); + receiver->deleteLater(); + receiver = nullptr; + } + + Q_Q(QBluetoothServiceDiscoveryAgent); + emit q->canceled(); + +} + +void QBluetoothServiceDiscoveryAgentPrivate::_q_processFetchedUuids( + const QBluetoothAddress &address, const QList &uuids) +{ + //don't leave more data through if we are not interested anymore + if (discoveredDevices.isEmpty()) + return; + + //could not find any service for the current address/device -> go to next one + if (address.isNull() || uuids.isEmpty()) { + if (discoveredDevices.size() == 1) { + Q_Q(QBluetoothServiceDiscoveryAgent); + QTimer::singleShot(uuidFetchTimeLimit, q, [this]() { + this->_q_fetchUuidsTimeout(); + }); // will also call _q_serviceDiscoveryFinished() + } else { + _q_serviceDiscoveryFinished(); + } + return; + } + + if (QT_BT_ANDROID().isDebugEnabled()) { + qCDebug(QT_BT_ANDROID) << "Found UUID for" << address.toString() + << "\ncount: " << uuids.size(); + + QString result; + for (const QBluetoothUuid &uuid : uuids) + result += uuid.toString() + QLatin1String("**"); + qCDebug(QT_BT_ANDROID) << result; + } + + /* In general there may be up-to two uuid events per device. + * We'll wait for the second event to arrive before we process the UUIDs. + * We utilize a timeout to catch cases when the second + * event doesn't arrive at all. + * Generally we assume that the second uuid event carries the most up-to-date + * set of uuids and discard the first events results. + */ + + if (sdpCache.contains(address)) { + //second event + QPair > pair = sdpCache.take(address); + + //prefer second uuid set over first + populateDiscoveredServices(pair.first, uuids); + + if (discoveredDevices.size() == 1 && sdpCache.isEmpty()) { + //last regular uuid data set from OS -> we finish here + _q_serviceDiscoveryFinished(); + } + } else { + //first event + QPair > pair; + pair.first = discoveredDevices.at(0); + pair.second = uuids; + + if (pair.first.address() != address) + return; + + sdpCache.insert(address, pair); + + //the discovery on the last device cannot immediately finish + //we have to grant the timeout delay to allow potential second event to arrive + if (discoveredDevices.size() == 1) { + Q_Q(QBluetoothServiceDiscoveryAgent); + QTimer::singleShot(uuidFetchTimeLimit, q, [this]() { + this->_q_fetchUuidsTimeout(); + }); + return; + } + + _q_serviceDiscoveryFinished(); + } +} + +void QBluetoothServiceDiscoveryAgentPrivate::populateDiscoveredServices(const QBluetoothDeviceInfo &remoteDevice, const QList &uuids) +{ + /* Android doesn't provide decent SDP data. A flat list of uuids is all we get. + * + * The following approach is chosen: + * - If we see an SPP service class and we see + * one or more custom uuids we match them up. Such services will always + * be SPP services. There is the chance that a custom uuid is eronously + * mapped as being an SPP service. In addition, the SPP uuid will be mapped as + * standalone SPP service. + * - If we see a custom uuid but no SPP uuid then we return + * BluetoothServiceInfo instance with just a serviceUuid (no service class set) + * - If we don't find any custom uuid but the SPP uuid, we return a + * BluetoothServiceInfo instance where classId and serviceUuid() are set to SPP. + * - Any other service uuid will stand on its own. + * */ + + Q_Q(QBluetoothServiceDiscoveryAgent); + + //find SPP and custom uuid + bool haveSppClass = false; + QVarLengthArray customUuids; + + for (qsizetype i = 0; i < uuids.size(); ++i) { + const QBluetoothUuid uuid = uuids.at(i); + + if (uuid.isNull()) + continue; + + //check for SPP protocol + haveSppClass |= uuid == QBluetoothUuid::ServiceClassUuid::SerialPort; + + //check for custom uuid + if (uuid.minimumSize() == 16) + customUuids.append(i); + } + + auto rfcommProtocolDescriptorList = []() -> QBluetoothServiceInfo::Sequence { + QBluetoothServiceInfo::Sequence protocol; + protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ProtocolUuid::Rfcomm)) + << QVariant::fromValue(0); + return protocol; + }; + + auto sppProfileDescriptorList = []() -> QBluetoothServiceInfo::Sequence { + QBluetoothServiceInfo::Sequence profileSequence; + QBluetoothServiceInfo::Sequence classId; + classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ServiceClassUuid::SerialPort)); + classId << QVariant::fromValue(quint16(0x100)); + profileSequence.append(QVariant::fromValue(classId)); + return profileSequence; + }; + + for (qsizetype i = 0; i < uuids.size(); ++i) { + const QBluetoothUuid &uuid = uuids.at(i); + if (uuid.isNull()) + continue; + + QBluetoothServiceInfo serviceInfo; + serviceInfo.setDevice(remoteDevice); + + QBluetoothServiceInfo::Sequence protocolDescriptorList; + { + QBluetoothServiceInfo::Sequence protocol; + protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ProtocolUuid::L2cap)); + protocolDescriptorList.append(QVariant::fromValue(protocol)); + } + + if (customUuids.contains(i) && haveSppClass) { + //we have a custom uuid of service class type SPP + + //set rfcomm protocol + protocolDescriptorList.append(QVariant::fromValue(rfcommProtocolDescriptorList())); + + //set SPP profile descriptor list + serviceInfo.setAttribute(QBluetoothServiceInfo::BluetoothProfileDescriptorList, + sppProfileDescriptorList()); + + QBluetoothServiceInfo::Sequence classId; + //set SPP service class uuid + classId << QVariant::fromValue(uuid); + classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ServiceClassUuid::SerialPort)); + serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classId); + + serviceInfo.setServiceName(QBluetoothServiceDiscoveryAgent::tr("Serial Port Profile")); + serviceInfo.setServiceUuid(uuid); + } else if (uuid == QBluetoothUuid{QBluetoothUuid::ServiceClassUuid::SerialPort}) { + //set rfcomm protocol + protocolDescriptorList.append(QVariant::fromValue(rfcommProtocolDescriptorList())); + + //set SPP profile descriptor list + serviceInfo.setAttribute(QBluetoothServiceInfo::BluetoothProfileDescriptorList, + sppProfileDescriptorList()); + + //also we need to set the custom uuid to the SPP uuid + //otherwise QBluetoothSocket::connectToService() would fail due to a missing service uuid + serviceInfo.setServiceUuid(uuid); + } else if (customUuids.contains(i)) { + //custom uuid but no serial port + serviceInfo.setServiceUuid(uuid); + } + + serviceInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, protocolDescriptorList); + QBluetoothServiceInfo::Sequence publicBrowse; + publicBrowse << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ServiceClassUuid::PublicBrowseGroup)); + serviceInfo.setAttribute(QBluetoothServiceInfo::BrowseGroupList, publicBrowse); + + if (!customUuids.contains(i)) { + //if we don't have custom uuid use it as class id as well + QBluetoothServiceInfo::Sequence classId; + classId << QVariant::fromValue(uuid); + serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classId); + auto clsId = QBluetoothUuid::ServiceClassUuid(uuid.toUInt16()); + serviceInfo.setServiceName(QBluetoothUuid::serviceClassToString(clsId)); + } + + //Check if the service is in the uuidFilter + if (!uuidFilter.isEmpty()) { + bool match = uuidFilter.contains(serviceInfo.serviceUuid()); + match |= uuidFilter.contains(QBluetoothSocketPrivateAndroid::reverseUuid(serviceInfo.serviceUuid())); + for (const auto &uuid : std::as_const(uuidFilter)) { + match |= serviceInfo.serviceClassUuids().contains(uuid); + match |= serviceInfo.serviceClassUuids().contains(QBluetoothSocketPrivateAndroid::reverseUuid(uuid)); + } + + if (!match) + continue; + } + + //don't include the service if we already discovered it before + if (!isDuplicatedService(serviceInfo)) { + discoveredServices << serviceInfo; + // Use queued connection to allow us finish the service discovery reporting; + // the application might call stop() when it has detected the service-of-interest, + // which in turn can cause the use of already released resources + QMetaObject::invokeMethod(q, "serviceDiscovered", Qt::QueuedConnection, + Q_ARG(QBluetoothServiceInfo, serviceInfo)); + } + } +} + +void QBluetoothServiceDiscoveryAgentPrivate::_q_fetchUuidsTimeout() +{ + // In practice if device list is empty, discovery has been stopped or bluetooth is offline + if (discoveredDevices.isEmpty()) + return; + + // Process remaining services in the cache (these didn't get a second UUID event) + if (!sdpCache.isEmpty()) { + QPair > pair; + const QList keys = sdpCache.keys(); + for (const QBluetoothAddress &key : keys) { + pair = sdpCache.take(key); + populateDiscoveredServices(pair.first, pair.second); + } + } + + Q_ASSERT(sdpCache.isEmpty()); + + //kill receiver to limit load of signals + if (receiver) { + receiver->unregisterReceiver(); + receiver->deleteLater(); + receiver = nullptr; + } + _q_serviceDiscoveryFinished(); +} + +void QBluetoothServiceDiscoveryAgentPrivate::_q_hostModeStateChanged(QBluetoothLocalDevice::HostMode state) +{ + if (discoveryState() == QBluetoothServiceDiscoveryAgentPrivate::ServiceDiscovery && + state == QBluetoothLocalDevice::HostPoweredOff ) { + + discoveredDevices.clear(); + sdpCache.clear(); + error = QBluetoothServiceDiscoveryAgent::PoweredOffError; + errorString = QBluetoothServiceDiscoveryAgent::tr("Device is powered off"); + + //kill receiver to limit load of signals + if (receiver) { + receiver->unregisterReceiver(); + receiver->deleteLater(); + receiver = nullptr; + } + + Q_Q(QBluetoothServiceDiscoveryAgent); + emit q->errorOccurred(error); + _q_serviceDiscoveryFinished(); + } +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp new file mode 100644 index 0000000..844c79b --- /dev/null +++ b/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp @@ -0,0 +1,460 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothservicediscoveryagent.h" +#include "qbluetoothservicediscoveryagent_p.h" + +#include "bluez/bluez5_helper_p.h" +#include "bluez/objectmanager_p.h" +#include "bluez/adapter1_bluez5_p.h" + +#include +#include +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ) + +QBluetoothServiceDiscoveryAgentPrivate::QBluetoothServiceDiscoveryAgentPrivate( + QBluetoothServiceDiscoveryAgent *qp, const QBluetoothAddress &deviceAdapter) +: error(QBluetoothServiceDiscoveryAgent::NoError), m_deviceAdapterAddress(deviceAdapter), state(Inactive), + mode(QBluetoothServiceDiscoveryAgent::MinimalDiscovery), singleDevice(false), + q_ptr(qp) +{ + initializeBluez5(); + manager = new OrgFreedesktopDBusObjectManagerInterface( + QStringLiteral("org.bluez"), QStringLiteral("/"), QDBusConnection::systemBus()); + qRegisterMetaType(); +} + +QBluetoothServiceDiscoveryAgentPrivate::~QBluetoothServiceDiscoveryAgentPrivate() +{ + delete manager; +} + +void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &address) +{ + Q_Q(QBluetoothServiceDiscoveryAgent); + + qCDebug(QT_BT_BLUEZ) << "Discovery on: " << address.toString() << "Mode:" << DiscoveryMode(); + + if (foundHostAdapterPath.isEmpty()) { + // check that we match adapter addresses or use first if it wasn't specified + + bool ok = false; + foundHostAdapterPath = findAdapterForAddress(m_deviceAdapterAddress, &ok); + if (!ok) { + discoveredDevices.clear(); + error = QBluetoothServiceDiscoveryAgent::InputOutputError; + errorString = QBluetoothDeviceDiscoveryAgent::tr("Cannot access adapter during service discovery"); + emit q->errorOccurred(error); + _q_serviceDiscoveryFinished(); + return; + } + + if (foundHostAdapterPath.isEmpty()) { + // Cannot find a local adapter + // Abort any outstanding discoveries + discoveredDevices.clear(); + + error = QBluetoothServiceDiscoveryAgent::InvalidBluetoothAdapterError; + errorString = QBluetoothServiceDiscoveryAgent::tr("Cannot find local Bluetooth adapter"); + emit q->errorOccurred(error); + _q_serviceDiscoveryFinished(); + + return; + } + } + + // ensure we didn't go offline yet + OrgBluezAdapter1Interface adapter(QStringLiteral("org.bluez"), + foundHostAdapterPath, QDBusConnection::systemBus()); + if (!adapter.powered()) { + discoveredDevices.clear(); + + error = QBluetoothServiceDiscoveryAgent::PoweredOffError; + errorString = QBluetoothServiceDiscoveryAgent::tr("Local device is powered off"); + emit q->errorOccurred(error); + + _q_serviceDiscoveryFinished(); + return; + } + + if (DiscoveryMode() == QBluetoothServiceDiscoveryAgent::MinimalDiscovery) { + performMinimalServiceDiscovery(address); + } else { + runExternalSdpScan(address, QBluetoothAddress(adapter.address())); + } +} + +/* Bluez 5 + * src/tools/sdpscanner performs an SDP scan. This is + * done out-of-process to avoid license issues. At this stage Bluez uses GPLv2. + */ +void QBluetoothServiceDiscoveryAgentPrivate::runExternalSdpScan( + const QBluetoothAddress &remoteAddress, const QBluetoothAddress &localAddress) +{ + Q_Q(QBluetoothServiceDiscoveryAgent); + + if (!sdpScannerProcess) { + const QString binPath = QLibraryInfo::path(QLibraryInfo::LibraryExecutablesPath); + QFileInfo fileInfo(binPath, QStringLiteral("sdpscanner")); + if (!fileInfo.exists() || !fileInfo.isExecutable()) { + _q_finishSdpScan(QBluetoothServiceDiscoveryAgent::InputOutputError, + QBluetoothServiceDiscoveryAgent::tr("Unable to find sdpscanner"), + QStringList()); + qCWarning(QT_BT_BLUEZ) << "Cannot find sdpscanner:" + << fileInfo.canonicalFilePath(); + return; + } + + sdpScannerProcess = new QProcess(q); + sdpScannerProcess->setReadChannel(QProcess::StandardOutput); + if (QT_BT_BLUEZ().isDebugEnabled()) + sdpScannerProcess->setProcessChannelMode(QProcess::ForwardedErrorChannel); + sdpScannerProcess->setProgram(fileInfo.canonicalFilePath()); + q->connect(sdpScannerProcess, + QOverload::of(&QProcess::finished), + q, [this](int exitCode, QProcess::ExitStatus status){ + this->_q_sdpScannerDone(exitCode, status); + }); + } + + QStringList arguments; + arguments << remoteAddress.toString() << localAddress.toString(); + + // No filter implies PUBLIC_BROWSE_GROUP based SDP scan + if (!uuidFilter.isEmpty()) { + arguments << QLatin1String("-u"); // cmd line option for list of uuids + for (const QBluetoothUuid& uuid : std::as_const(uuidFilter)) + arguments << uuid.toString(); + } + + sdpScannerProcess->setArguments(arguments); + sdpScannerProcess->start(); +} + +void QBluetoothServiceDiscoveryAgentPrivate::_q_sdpScannerDone(int exitCode, QProcess::ExitStatus status) +{ + if (status != QProcess::NormalExit || exitCode != 0) { + qCWarning(QT_BT_BLUEZ) << "SDP scan failure" << status << exitCode; + if (singleDevice) { + _q_finishSdpScan(QBluetoothServiceDiscoveryAgent::InputOutputError, + QBluetoothServiceDiscoveryAgent::tr("Unable to perform SDP scan"), + QStringList()); + } else { + // go to next device + _q_finishSdpScan(QBluetoothServiceDiscoveryAgent::NoError, QString(), QStringList()); + } + return; + } + + QStringList xmlRecords; + const QByteArray utf8Data = QByteArray::fromBase64(sdpScannerProcess->readAllStandardOutput()); + const QByteArrayView utf8View = utf8Data; + + // split the various xml docs up + constexpr auto matcher = qMakeStaticByteArrayMatcher("")); + // We have an error which we need to indicate and stop further processing + discoveredDevices.clear(); + error = errorCode; + errorString = errorDescription; + emit q->errorOccurred(error); + } else if (!xmlRecords.isEmpty() && discoveryState() != Inactive) { + for (const QString &record : xmlRecords) { + QBluetoothServiceInfo serviceInfo = parseServiceXml(record); + + //apply uuidFilter + if (!uuidFilter.isEmpty()) { + bool serviceNameMatched = uuidFilter.contains(serviceInfo.serviceUuid()); + bool serviceClassMatched = false; + const QList serviceClassUuids + = serviceInfo.serviceClassUuids(); + for (const QBluetoothUuid &id : serviceClassUuids) { + if (uuidFilter.contains(id)) { + serviceClassMatched = true; + break; + } + } + + if (!serviceNameMatched && !serviceClassMatched) + continue; + } + + if (!serviceInfo.isValid()) + continue; + + // Bluez sdpscanner declares custom uuids into the service class uuid list. + // Let's move a potential custom uuid from QBluetoothServiceInfo::serviceClassUuids() + // to QBluetoothServiceInfo::serviceUuid(). If there is more than one, just move the first uuid + const QList serviceClassUuids = serviceInfo.serviceClassUuids(); + for (const QBluetoothUuid &id : serviceClassUuids) { + if (id.minimumSize() == 16) { + serviceInfo.setServiceUuid(id); + if (serviceInfo.serviceName().isEmpty()) { + serviceInfo.setServiceName( + QBluetoothServiceDiscoveryAgent::tr("Custom Service")); + } + QBluetoothServiceInfo::Sequence modSeq = + serviceInfo.attribute(QBluetoothServiceInfo::ServiceClassIds).value(); + modSeq.removeOne(QVariant::fromValue(id)); + serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, modSeq); + break; + } + } + + if (!isDuplicatedService(serviceInfo)) { + discoveredServices.append(serviceInfo); + qCDebug(QT_BT_BLUEZ) << "Discovered services" << discoveredDevices.at(0).address().toString() + << serviceInfo.serviceName() << serviceInfo.serviceUuid() + << ">>>" << serviceInfo.serviceClassUuids(); + // Use queued connection to allow us finish the service looping; the application + // might call stop() when it has detected the service-of-interest. + QMetaObject::invokeMethod(q, "serviceDiscovered", Qt::QueuedConnection, + Q_ARG(QBluetoothServiceInfo, serviceInfo)); + } + } + } + + _q_serviceDiscoveryFinished(); +} + +void QBluetoothServiceDiscoveryAgentPrivate::stop() +{ + qCDebug(QT_BT_BLUEZ) << Q_FUNC_INFO << "Stop called"; + + discoveredDevices.clear(); + setDiscoveryState(Inactive); + + // must happen after discoveredDevices.clear() above to avoid retrigger of next scan + // while waitForFinished() is waiting + if (sdpScannerProcess) { // Bluez 5 + if (sdpScannerProcess->state() != QProcess::NotRunning) { + sdpScannerProcess->kill(); + sdpScannerProcess->waitForFinished(); + } + } + + Q_Q(QBluetoothServiceDiscoveryAgent); + emit q->canceled(); +} + +QBluetoothServiceInfo QBluetoothServiceDiscoveryAgentPrivate::parseServiceXml( + const QString& xmlRecord) +{ + QXmlStreamReader xml(xmlRecord); + + QBluetoothServiceInfo serviceInfo; + serviceInfo.setDevice(discoveredDevices.at(0)); + + while (!xml.atEnd()) { + xml.readNext(); + + if (xml.tokenType() == QXmlStreamReader::StartElement && + xml.name() == QLatin1String("attribute")) { + quint16 attributeId = + xml.attributes().value(QLatin1String("id")).toUShort(nullptr, 0); + + if (xml.readNextStartElement()) { + const QVariant value = readAttributeValue(xml); + serviceInfo.setAttribute(attributeId, value); + } + } + } + + return serviceInfo; +} + +// Bluez 5 +void QBluetoothServiceDiscoveryAgentPrivate::performMinimalServiceDiscovery(const QBluetoothAddress &deviceAddress) +{ + if (foundHostAdapterPath.isEmpty()) { + _q_serviceDiscoveryFinished(); + return; + } + + Q_Q(QBluetoothServiceDiscoveryAgent); + + QDBusPendingReply reply = manager->GetManagedObjects(); + reply.waitForFinished(); + if (reply.isError()) { + if (singleDevice) { + error = QBluetoothServiceDiscoveryAgent::InputOutputError; + errorString = reply.error().message(); + emit q->errorOccurred(error); + } + _q_serviceDiscoveryFinished(); + return; + } + + QStringList uuidStrings; + + ManagedObjectList managedObjectList = reply.value(); + for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) { + const InterfaceList &ifaceList = it.value(); + + for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) { + const QString &iface = jt.key(); + const QVariantMap &ifaceValues = jt.value(); + + if (iface == QStringLiteral("org.bluez.Device1")) { + if (deviceAddress.toString() == ifaceValues.value(QStringLiteral("Address")).toString()) { + uuidStrings = ifaceValues.value(QStringLiteral("UUIDs")).toStringList(); + break; + } + } + } + if (!uuidStrings.isEmpty()) + break; + } + + if (uuidStrings.isEmpty() || discoveredDevices.isEmpty()) { + qCWarning(QT_BT_BLUEZ) << "No uuids found for" << deviceAddress.toString(); + // nothing found -> go to next uuid + _q_serviceDiscoveryFinished(); + return; + } + + qCDebug(QT_BT_BLUEZ) << "Minimal uuid list for" << deviceAddress.toString() << uuidStrings; + + QBluetoothUuid uuid; + for (qsizetype i = 0; i < uuidStrings.size(); ++i) { + uuid = QBluetoothUuid(uuidStrings.at(i)); + if (uuid.isNull()) + continue; + + //apply uuidFilter + if (!uuidFilter.isEmpty() && !uuidFilter.contains(uuid)) + continue; + + QBluetoothServiceInfo serviceInfo; + serviceInfo.setDevice(discoveredDevices.at(0)); + + if (uuid.minimumSize() == 16) { // not derived from Bluetooth Base UUID + serviceInfo.setServiceUuid(uuid); + serviceInfo.setServiceName(QBluetoothServiceDiscoveryAgent::tr("Custom Service")); + } else { + // set uuid as service class id + QBluetoothServiceInfo::Sequence classId; + classId << QVariant::fromValue(uuid); + serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classId); + QBluetoothUuid::ServiceClassUuid clsId + = static_cast(uuid.data1 & 0xffff); + serviceInfo.setServiceName(QBluetoothUuid::serviceClassToString(clsId)); + } + + QBluetoothServiceInfo::Sequence protocolDescriptorList; + { + QBluetoothServiceInfo::Sequence protocol; + protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ProtocolUuid::L2cap)); + protocolDescriptorList.append(QVariant::fromValue(protocol)); + } + { + QBluetoothServiceInfo::Sequence protocol; + protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ProtocolUuid::Att)); + protocolDescriptorList.append(QVariant::fromValue(protocol)); + } + serviceInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, protocolDescriptorList); + + //don't include the service if we already discovered it before + if (!isDuplicatedService(serviceInfo)) { + discoveredServices << serviceInfo; + qCDebug(QT_BT_BLUEZ) << "Discovered services" << discoveredDevices.at(0).address().toString() + << serviceInfo.serviceName(); + emit q->serviceDiscovered(serviceInfo); + } + } + + _q_serviceDiscoveryFinished(); +} + +QVariant QBluetoothServiceDiscoveryAgentPrivate::readAttributeValue(QXmlStreamReader &xml) +{ + auto skippingCurrentElementByDefault = qScopeGuard([&] { xml.skipCurrentElement(); }); + + if (xml.name() == QLatin1String("boolean")) { + return xml.attributes().value(QLatin1String("value")) == QLatin1String("true"); + } else if (xml.name() == QLatin1String("uint8")) { + quint8 value = xml.attributes().value(QLatin1String("value")).toUShort(nullptr, 0); + return value; + } else if (xml.name() == QLatin1String("uint16")) { + quint16 value = xml.attributes().value(QLatin1String("value")).toUShort(nullptr, 0); + return value; + } else if (xml.name() == QLatin1String("uint32")) { + quint32 value = xml.attributes().value(QLatin1String("value")).toUInt(nullptr, 0); + return value; + } else if (xml.name() == QLatin1String("uint64")) { + quint64 value = xml.attributes().value(QLatin1String("value")).toULongLong(nullptr, 0); + return value; + } else if (xml.name() == QLatin1String("uuid")) { + QBluetoothUuid uuid; + const QStringView value = xml.attributes().value(QLatin1String("value")); + if (value.startsWith(QLatin1String("0x"))) { + if (value.size() == 6) { + quint16 v = value.toUShort(nullptr, 0); + uuid = QBluetoothUuid(v); + } else if (value.size() == 10) { + quint32 v = value.toUInt(nullptr, 0); + uuid = QBluetoothUuid(v); + } + } else { + uuid = QBluetoothUuid(value.toString()); + } + return QVariant::fromValue(uuid); + } else if (xml.name() == QLatin1String("text") || xml.name() == QLatin1String("url")) { + const QStringView value = xml.attributes().value(QLatin1String("value")); + if (xml.attributes().value(QLatin1String("encoding")) == QLatin1String("hex")) + return QString::fromUtf8(QByteArray::fromHex(value.toLatin1())); + return value.toString(); + } else if (xml.name() == QLatin1String("sequence")) { + QBluetoothServiceInfo::Sequence sequence; + + skippingCurrentElementByDefault.dismiss(); // we skip several elements here + + while (xml.readNextStartElement()) { + QVariant value = readAttributeValue(xml); + sequence.append(value); + } + + return QVariant::fromValue(sequence); + } else { + qCWarning(QT_BT_BLUEZ) << "unknown attribute type" + << xml.name() + << xml.attributes().value(QLatin1String("value")); + return QVariant(); + } +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_macos.mm b/src/bluetooth/qbluetoothservicediscoveryagent_macos.mm new file mode 100644 index 0000000..10d36e9 --- /dev/null +++ b/src/bluetooth/qbluetoothservicediscoveryagent_macos.mm @@ -0,0 +1,231 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothservicediscoveryagent_p.h" +#include "qbluetoothservicediscoveryagent.h" +#include "qbluetoothdevicediscoveryagent.h" +#include "qbluetoothlocaldevice.h" +#include "darwin/btsdpinquiry_p.h" +#include "qbluetoothhostinfo.h" +#include "darwin/btutility_p.h" +#include "darwin/uistrings_p.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +QT_BEGIN_NAMESPACE + +namespace { + +using DarwinBluetooth::RetainPolicy; + +} + +QBluetoothServiceDiscoveryAgentPrivate::QBluetoothServiceDiscoveryAgentPrivate( + QBluetoothServiceDiscoveryAgent *qp, const QBluetoothAddress &localAddress) : + + error(QBluetoothServiceDiscoveryAgent::NoError), + m_deviceAdapterAddress(localAddress), + state(Inactive), + mode(QBluetoothServiceDiscoveryAgent::MinimalDiscovery), + singleDevice(false), + q_ptr(qp) + +{ + Q_ASSERT(q_ptr); + serviceInquiry.reset([[DarwinBTSDPInquiry alloc] initWithDelegate:this], RetainPolicy::noInitialRetain); +} + +QBluetoothServiceDiscoveryAgentPrivate::~QBluetoothServiceDiscoveryAgentPrivate() +{ +} + +void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &deviceAddress) +{ + QT_BT_MAC_AUTORELEASEPOOL; + + if (deviceAddress.isNull()) { + // This can happen: LE scan works with CoreBluetooth, but CBPeripherals + // do not expose hardware addresses. + // Pop the current QBluetoothDeviceInfo and decide what to do next. + return _q_serviceDiscoveryFinished(); + } + + // Autoreleased object. + IOBluetoothHostController *const hc = [IOBluetoothHostController defaultController]; + if (![hc powerState]) { + discoveredDevices.clear(); + if (singleDevice) { + error = QBluetoothServiceDiscoveryAgent::PoweredOffError; + errorString = QCoreApplication::translate(SERVICE_DISCOVERY, SD_LOCAL_DEV_OFF); + emit q_ptr->errorOccurred(error); + } + + return _q_serviceDiscoveryFinished(); + } + + if (DiscoveryMode() == QBluetoothServiceDiscoveryAgent::MinimalDiscovery) { + performMinimalServiceDiscovery(deviceAddress); + } else { + IOReturn result = kIOReturnSuccess; + auto nativeInquiry = serviceInquiry.getAs(); + if (uuidFilter.size()) + result = [nativeInquiry performSDPQueryWithDevice:deviceAddress filters:uuidFilter]; + else + result = [nativeInquiry performSDPQueryWithDevice:deviceAddress]; + + if (result != kIOReturnSuccess) { + // Failed immediately to perform an SDP inquiry on IOBluetoothDevice: + SDPInquiryError(nil, result); + } + } +} + +void QBluetoothServiceDiscoveryAgentPrivate::stop() +{ + Q_ASSERT_X(q_ptr, Q_FUNC_INFO, "invalid q_ptr (null)"); + + discoveredDevices.clear(); + + // "Stops" immediately. + [serviceInquiry.getAs() stopSDPQuery]; + + emit q_ptr->canceled(); +} + +void QBluetoothServiceDiscoveryAgentPrivate::SDPInquiryFinished(void *generic) +{ + auto device = static_cast(generic); + Q_ASSERT_X(device, Q_FUNC_INFO, "invalid IOBluetoothDevice (nil)"); + + if (state == Inactive) + return; + + QT_BT_MAC_AUTORELEASEPOOL; + + NSArray *const records = device.services; + qCDebug(QT_BT_DARWIN) << "SDP finished for device" << [device nameOrAddress] + << ", services found:" << [records count]; + for (IOBluetoothSDPServiceRecord *record in records) { + QBluetoothServiceInfo serviceInfo; + Q_ASSERT_X(discoveredDevices.size() >= 1, Q_FUNC_INFO, "invalid number of devices"); + + qCDebug(QT_BT_DARWIN) << "Processing service" << [record getServiceName]; + serviceInfo.setDevice(discoveredDevices.at(0)); + DarwinBluetooth::extract_service_record(record, serviceInfo); + + if (!serviceInfo.isValid()) { + qCDebug(QT_BT_DARWIN) << "Discarding invalid service"; + continue; + } + + if (QOperatingSystemVersion::current() > QOperatingSystemVersion::MacOSBigSur + && uuidFilter.size()) { + const auto &serviceId = serviceInfo.serviceUuid(); + bool match = !serviceId.isNull() && uuidFilter.contains(serviceId); + if (!match) { + const auto &classUuids = serviceInfo.serviceClassUuids(); + for (const auto &uuid : classUuids) { + if (uuidFilter.contains(uuid)) { + match = true; + break; + } + } + if (!match) + continue; + } + } + + + if (!isDuplicatedService(serviceInfo)) { + discoveredServices.append(serviceInfo); + emit q_ptr->serviceDiscovered(serviceInfo); + // Here a user code can ... interrupt us by calling + // stop. Check this. + if (state == Inactive) + break; + } + } + + _q_serviceDiscoveryFinished(); +} + +void QBluetoothServiceDiscoveryAgentPrivate::SDPInquiryError(void *device, IOReturn errorCode) +{ + Q_UNUSED(device); + + qCWarning(QT_BT_DARWIN) << "inquiry failed with IOKit code:" << int(errorCode); + + discoveredDevices.clear(); + // TODO: find a better mapping from IOReturn to QBluetoothServiceDiscoveryAgent::Error. + if (singleDevice) { + error = QBluetoothServiceDiscoveryAgent::UnknownError; + errorString = QCoreApplication::translate(DEV_DISCOVERY, DD_UNKNOWN_ERROR); + emit q_ptr->errorOccurred(error); + } + + _q_serviceDiscoveryFinished(); +} + +void QBluetoothServiceDiscoveryAgentPrivate::performMinimalServiceDiscovery(const QBluetoothAddress &deviceAddress) +{ + Q_ASSERT_X(!deviceAddress.isNull(), Q_FUNC_INFO, "invalid device address"); + + QT_BT_MAC_AUTORELEASEPOOL; + + const BluetoothDeviceAddress iobtAddress = DarwinBluetooth::iobluetooth_address(deviceAddress); + IOBluetoothDevice *const device = [IOBluetoothDevice deviceWithAddress:&iobtAddress]; + if (!device || !device.services) { + if (singleDevice) { + error = QBluetoothServiceDiscoveryAgent::UnknownError; + errorString = QCoreApplication::translate(SERVICE_DISCOVERY, SD_MINIMAL_FAILED); + emit q_ptr->errorOccurred(error); + } + } else { + + NSArray *const records = device.services; + for (IOBluetoothSDPServiceRecord *record in records) { + QBluetoothServiceInfo serviceInfo; + Q_ASSERT_X(discoveredDevices.size() >= 1, Q_FUNC_INFO, + "invalid number of devices"); + + serviceInfo.setDevice(discoveredDevices.at(0)); + DarwinBluetooth::extract_service_record(record, serviceInfo); + + if (!serviceInfo.isValid()) + continue; + + if (!uuidFilter.isEmpty() && !serviceHasMatchingUuid(serviceInfo)) + continue; + + if (!isDuplicatedService(serviceInfo)) { + discoveredServices.append(serviceInfo); + emit q_ptr->serviceDiscovered(serviceInfo); + } + } + } + + _q_serviceDiscoveryFinished(); +} + +bool QBluetoothServiceDiscoveryAgentPrivate::serviceHasMatchingUuid(const QBluetoothServiceInfo &serviceInfo) const +{ + for (const auto &requestedUuid : uuidFilter) { + if (serviceInfo.serviceUuid() == requestedUuid) + return true; + if (serviceInfo.serviceClassUuids().contains(requestedUuid)) + return true; + } + return false; +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_p.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_p.cpp new file mode 100644 index 0000000..aaaf3dd --- /dev/null +++ b/src/bluetooth/qbluetoothservicediscoveryagent_p.cpp @@ -0,0 +1,41 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothservicediscoveryagent.h" +#include "qbluetoothservicediscoveryagent_p.h" +#ifndef QT_IOS_BLUETOOTH +#include "dummy/dummy_helper_p.h" +#endif + +QT_BEGIN_NAMESPACE + +QBluetoothServiceDiscoveryAgentPrivate::QBluetoothServiceDiscoveryAgentPrivate( + QBluetoothServiceDiscoveryAgent *qp, const QBluetoothAddress &deviceAdapter) + : error(QBluetoothServiceDiscoveryAgent::NoError), + state(Inactive), + mode(QBluetoothServiceDiscoveryAgent::MinimalDiscovery), + singleDevice(false), + q_ptr(qp) +{ +#ifndef QT_IOS_BLUETOOTH + printDummyWarning(); +#endif + Q_UNUSED(deviceAdapter); +} + +QBluetoothServiceDiscoveryAgentPrivate::~QBluetoothServiceDiscoveryAgentPrivate() +{ +} + +void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &address) +{ + Q_UNUSED(address); +} + +void QBluetoothServiceDiscoveryAgentPrivate::stop() +{ +} + +QT_END_NAMESPACE + +#include "moc_qbluetoothservicediscoveryagent_p.cpp" diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_p.h b/src/bluetooth/qbluetoothservicediscoveryagent_p.h new file mode 100644 index 0000000..2bdfd40 --- /dev/null +++ b/src/bluetooth/qbluetoothservicediscoveryagent_p.h @@ -0,0 +1,201 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QBLUETOOTHSERVICEDISCOVERYAGENT_P_H +#define QBLUETOOTHSERVICEDISCOVERYAGENT_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 "qbluetoothaddress.h" +#include "qbluetoothdeviceinfo.h" +#include "qbluetoothserviceinfo.h" +#include "qbluetoothservicediscoveryagent.h" + +#include +#include + +#if QT_CONFIG(bluez) +class OrgBluezManagerInterface; +class OrgBluezAdapterInterface; +class OrgBluezDeviceInterface; +class OrgFreedesktopDBusObjectManagerInterface; +#include + +QT_BEGIN_NAMESPACE +class QDBusPendingCallWatcher; +class QXmlStreamReader; +QT_END_NAMESPACE +#endif + +#ifdef QT_WINRT_BLUETOOTH +#include +#endif + +#ifdef QT_OSX_BLUETOOTH +#include "darwin/btdelegates_p.h" +#include "darwin/btraii_p.h" +#endif + +#ifdef QT_ANDROID_BLUETOOTH +#include +#include +#endif + +QT_BEGIN_NAMESPACE + +class QBluetoothDeviceDiscoveryAgent; +#ifdef QT_ANDROID_BLUETOOTH +class ServiceDiscoveryBroadcastReceiver; +class LocalDeviceBroadcastReceiver; +#endif + +#ifdef QT_WINRT_BLUETOOTH +class QWinRTBluetoothServiceDiscoveryWorker; +#endif + +class QBluetoothServiceDiscoveryAgentPrivate +#if defined(QT_WINRT_BLUETOOTH) + : public QObject +{ + Q_OBJECT +#elif defined(QT_OSX_BLUETOOTH) + : public QObject, public DarwinBluetooth::SDPInquiryDelegate +{ +#else +{ +#endif + Q_DECLARE_PUBLIC(QBluetoothServiceDiscoveryAgent) + +public: + enum DiscoveryState { + Inactive, + DeviceDiscovery, + ServiceDiscovery, + }; + + QBluetoothServiceDiscoveryAgentPrivate(QBluetoothServiceDiscoveryAgent *qp, + const QBluetoothAddress &deviceAdapter); + ~QBluetoothServiceDiscoveryAgentPrivate(); + + void startDeviceDiscovery(); + void stopDeviceDiscovery(); + void startServiceDiscovery(); + void stopServiceDiscovery(); + + void setDiscoveryState(DiscoveryState s) { state = s; } + inline DiscoveryState discoveryState() { return state; } + + void setDiscoveryMode(QBluetoothServiceDiscoveryAgent::DiscoveryMode m) { mode = m; } + QBluetoothServiceDiscoveryAgent::DiscoveryMode DiscoveryMode() { return mode; } + + void _q_deviceDiscoveryFinished(); + void _q_deviceDiscovered(const QBluetoothDeviceInfo &info); + void _q_serviceDiscoveryFinished(); + void _q_deviceDiscoveryError(QBluetoothDeviceDiscoveryAgent::Error); +#if QT_CONFIG(bluez) + void _q_sdpScannerDone(int exitCode, QProcess::ExitStatus status); + void _q_finishSdpScan(QBluetoothServiceDiscoveryAgent::Error errorCode, + const QString &errorDescription, + const QStringList &xmlRecords); +#endif +#ifdef QT_ANDROID_BLUETOOTH + void _q_processFetchedUuids(const QBluetoothAddress &address, const QList &uuids); + + void populateDiscoveredServices(const QBluetoothDeviceInfo &remoteDevice, + const QList &uuids); + void _q_fetchUuidsTimeout(); + void _q_hostModeStateChanged(QBluetoothLocalDevice::HostMode state); +#endif + +private: + void start(const QBluetoothAddress &address); + void stop(); + bool isDuplicatedService(const QBluetoothServiceInfo &serviceInfo) const; + +#if QT_CONFIG(bluez) + void startBluez5(const QBluetoothAddress &address); + void runExternalSdpScan(const QBluetoothAddress &remoteAddress, + const QBluetoothAddress &localAddress); + void sdpScannerDone(int exitCode, QProcess::ExitStatus exitStatus); + QVariant readAttributeValue(QXmlStreamReader &xml); + QBluetoothServiceInfo parseServiceXml(const QString& xml); + void performMinimalServiceDiscovery(const QBluetoothAddress &deviceAddress); +#endif + +public: + QBluetoothServiceDiscoveryAgent::Error error; + QString errorString; + QBluetoothAddress deviceAddress; + QList discoveredServices; + QList discoveredDevices; + QBluetoothAddress m_deviceAdapterAddress; + +private: + DiscoveryState state; + QList uuidFilter; + + QBluetoothDeviceDiscoveryAgent *deviceDiscoveryAgent = nullptr; + + QBluetoothServiceDiscoveryAgent::DiscoveryMode mode; + + bool singleDevice; +#if QT_CONFIG(bluez) + QString foundHostAdapterPath; + OrgFreedesktopDBusObjectManagerInterface *manager = nullptr; + QProcess *sdpScannerProcess = nullptr; +#endif + +#ifdef QT_ANDROID_BLUETOOTH + ServiceDiscoveryBroadcastReceiver *receiver = nullptr; + LocalDeviceBroadcastReceiver *localDeviceReceiver = nullptr; + + QJniObject btAdapter; + // The sdpCache caches service discovery results while it is running, and is + // cleared once finished. The cache is used as we may (or may not) get more accurate + // results after the first result. This temporary caching allows to send the + // serviceDiscovered() signal once per service and with the most accurate information. + // Partial cache clearing may occur already during the scan if the second (more accurate) + // scan result is received. + QMap > > sdpCache; +#endif + +#ifdef QT_WINRT_BLUETOOTH +private slots: + void processFoundService(quint64 deviceAddress, const QBluetoothServiceInfo &info); + void onScanFinished(quint64 deviceAddress); + void onError(); + +private: + void releaseWorker(); + QPointer worker; +#endif + +#ifdef QT_OSX_BLUETOOTH + // SDPInquiryDelegate: + void SDPInquiryFinished(void *device) override; + void SDPInquiryError(void *device, IOReturn errorCode) override; + + void performMinimalServiceDiscovery(const QBluetoothAddress &deviceAddress); + //void serviceDiscoveryFinished(); + + bool serviceHasMatchingUuid(const QBluetoothServiceInfo &serviceInfo) const; + + DarwinBluetooth::ScopedPointer serviceInquiry; +#endif // QT_OSX_BLUETOOTH + +protected: + QBluetoothServiceDiscoveryAgent *q_ptr; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_winrt.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_winrt.cpp new file mode 100644 index 0000000..928dc4b --- /dev/null +++ b/src/bluetooth/qbluetoothservicediscoveryagent_winrt.cpp @@ -0,0 +1,558 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothservicediscoveryagent.h" +#include "qbluetoothservicediscoveryagent_p.h" +#include "qbluetoothutils_winrt_p.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::Devices; +using namespace ABI::Windows::Devices::Bluetooth; +using namespace ABI::Windows::Devices::Bluetooth::Rfcomm; +using namespace ABI::Windows::Devices::Enumeration; +using namespace ABI::Windows::Storage::Streams; + +typedef Collections::IKeyValuePair ValueItem; +typedef Collections::IIterable ValueIterable; +typedef Collections::IIterator ValueIterator; + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINDOWS) + +#define TYPE_UINT8 8 +#define TYPE_UINT16 9 +#define TYPE_UINT32 10 +#define TYPE_SHORT_UUID 25 +#define TYPE_LONG_UUID 28 +#define TYPE_STRING 37 +#define TYPE_SEQUENCE 53 + +// Helper to reverse given uchar array +static void reverseArray(uchar data[], size_t length) +{ + for (size_t i = length; i > length/2; i--) + std::swap(data[length - i], data[i - 1]); +} + +class QWinRTBluetoothServiceDiscoveryWorker : public QObject +{ + Q_OBJECT +public: + explicit QWinRTBluetoothServiceDiscoveryWorker(quint64 targetAddress, + QBluetoothServiceDiscoveryAgent::DiscoveryMode mode); + ~QWinRTBluetoothServiceDiscoveryWorker(); + void start(); + +Q_SIGNALS: + void serviceFound(quint64 deviceAddress, const QBluetoothServiceInfo &info); + void scanFinished(quint64 deviceAddress); + void errorOccured(); + +private: + HRESULT onBluetoothDeviceFoundAsync(IAsyncOperation *op, AsyncStatus status); + + void processServiceSearchResult(quint64 address, ComPtr> services); + QBluetoothServiceInfo::Sequence readSequence(ComPtr dataReader, bool *ok, quint8 *bytesRead); + +private: + quint64 m_targetAddress; + QBluetoothServiceDiscoveryAgent::DiscoveryMode m_mode; +}; + +QWinRTBluetoothServiceDiscoveryWorker::QWinRTBluetoothServiceDiscoveryWorker(quint64 targetAddress, + QBluetoothServiceDiscoveryAgent::DiscoveryMode mode) + : m_targetAddress(targetAddress) + , m_mode(mode) +{ +} + +QWinRTBluetoothServiceDiscoveryWorker::~QWinRTBluetoothServiceDiscoveryWorker() +{ +} + +void QWinRTBluetoothServiceDiscoveryWorker::start() +{ + ComPtr deviceStatics; + HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Devices_Bluetooth_BluetoothDevice).Get(), &deviceStatics); + Q_ASSERT_SUCCEEDED(hr); + ComPtr> deviceFromAddressOperation; + hr = deviceStatics->FromBluetoothAddressAsync(m_targetAddress, &deviceFromAddressOperation); + Q_ASSERT_SUCCEEDED(hr); + hr = deviceFromAddressOperation->put_Completed(Callback> + (this, &QWinRTBluetoothServiceDiscoveryWorker::onBluetoothDeviceFoundAsync).Get()); + Q_ASSERT_SUCCEEDED(hr); +} + +HRESULT QWinRTBluetoothServiceDiscoveryWorker::onBluetoothDeviceFoundAsync(IAsyncOperation *op, AsyncStatus status) +{ + if (status != Completed) { + qCDebug(QT_BT_WINDOWS) << "Could not find device"; + emit errorOccured(); + return S_OK; + } + + ComPtr device; + HRESULT hr; + hr = op->GetResults(&device); + Q_ASSERT_SUCCEEDED(hr); + quint64 address; + device->get_BluetoothAddress(&address); + + ComPtr device3; + hr = device.As(&device3); + Q_ASSERT_SUCCEEDED(hr); + ComPtr> serviceOp; + const BluetoothCacheMode cacheMode = m_mode == QBluetoothServiceDiscoveryAgent::MinimalDiscovery + ? BluetoothCacheMode_Cached : BluetoothCacheMode_Uncached; + hr = device3->GetRfcommServicesWithCacheModeAsync(cacheMode, &serviceOp); + Q_ASSERT_SUCCEEDED(hr); + hr = serviceOp->put_Completed(Callback> + ([address, this](IAsyncOperation *op, AsyncStatus status) + { + if (status != Completed) { + qCDebug(QT_BT_WINDOWS) << "Could not obtain service list"; + emit errorOccured(); + return S_OK; + } + + ComPtr result; + HRESULT hr = op->GetResults(&result); + Q_ASSERT_SUCCEEDED(hr); + ComPtr> commServices; + hr = result->get_Services(&commServices); + Q_ASSERT_SUCCEEDED(hr); + processServiceSearchResult(address, commServices); + return S_OK; + }).Get()); + Q_ASSERT_SUCCEEDED(hr); + + return S_OK; +} + +void QWinRTBluetoothServiceDiscoveryWorker::processServiceSearchResult(quint64 address, ComPtr> services) +{ + quint32 size; + HRESULT hr; + hr = services->get_Size(&size); + Q_ASSERT_SUCCEEDED(hr); + for (quint32 i = 0; i < size; ++i) { + ComPtr service; + hr = services->GetAt(i, &service); + Q_ASSERT_SUCCEEDED(hr); + HString name; + hr = service->get_ConnectionServiceName(name.GetAddressOf()); + Q_ASSERT_SUCCEEDED(hr); + const QString serviceName = QString::fromWCharArray(WindowsGetStringRawBuffer(name.Get(), nullptr)); + ComPtr host; + hr = service->get_ConnectionHostName(host.GetAddressOf()); + Q_ASSERT_SUCCEEDED(hr); + HString hostName; + hr = host->get_RawName(hostName.GetAddressOf()); + Q_ASSERT_SUCCEEDED(hr); + const QString qHostName = QString::fromWCharArray(WindowsGetStringRawBuffer(hostName.Get(), + nullptr)); + ComPtr id; + hr = service->get_ServiceId(&id); + Q_ASSERT_SUCCEEDED(hr); + GUID guid; + hr = id->get_Uuid(&guid); + const QBluetoothUuid uuid(guid); + Q_ASSERT_SUCCEEDED(hr); + + QBluetoothServiceInfo info; + info.setAttribute(0xBEEF, QVariant(qHostName)); + info.setAttribute(0xBEF0, QVariant(serviceName)); + info.setServiceName(serviceName); + info.setServiceUuid(uuid); + ComPtr *>> op; + hr = service->GetSdpRawAttributesAsync(op.GetAddressOf()); + if (FAILED(hr)) { + emit errorOccured(); + qCDebug(QT_BT_WINDOWS) << "Check manifest capabilities"; + continue; + } + ComPtr> mapView; + hr = QWinRTFunctions::await(op, mapView.GetAddressOf()); + Q_ASSERT_SUCCEEDED(hr); + // TODO timeout + ComPtr iterable; + ComPtr iterator; + + hr = mapView.As(&iterable); + if (FAILED(hr)) + continue; + + boolean current = false; + hr = iterable->First(&iterator); + if (FAILED(hr)) + continue; + hr = iterator->get_HasCurrent(¤t); + if (FAILED(hr)) + continue; + + while (SUCCEEDED(hr) && current) { + ComPtr item; + hr = iterator->get_Current(&item); + if (FAILED(hr)) + continue; + + UINT32 key; + hr = item->get_Key(&key); + if (FAILED(hr)) + continue; + + ComPtr buffer; + hr = item->get_Value(&buffer); + Q_ASSERT_SUCCEEDED(hr); + + ComPtr dataReader; + ComPtr dataReaderStatics; + hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_DataReader).Get(), &dataReaderStatics); + Q_ASSERT_SUCCEEDED(hr); + hr = dataReaderStatics->FromBuffer(buffer.Get(), dataReader.GetAddressOf()); + Q_ASSERT_SUCCEEDED(hr); + BYTE type; + hr = dataReader->ReadByte(&type); + Q_ASSERT_SUCCEEDED(hr); + if (type == TYPE_UINT8) { + quint8 value; + hr = dataReader->ReadByte(&value); + Q_ASSERT_SUCCEEDED(hr); + info.setAttribute(key, value); + qCDebug(QT_BT_WINDOWS) << "UUID" << uuid << "KEY" << Qt::hex << key << "TYPE" << Qt::dec << type << "UINT8" << Qt::hex << value; + } else if (type == TYPE_UINT16) { + quint16 value; + hr = dataReader->ReadUInt16(&value); + Q_ASSERT_SUCCEEDED(hr); + info.setAttribute(key, value); + qCDebug(QT_BT_WINDOWS) << "UUID" << uuid << "KEY" << Qt::hex << key << "TYPE" << Qt::dec << type << "UINT16" << Qt::hex << value; + } else if (type == TYPE_UINT32) { + quint32 value; + hr = dataReader->ReadUInt32(&value); + Q_ASSERT_SUCCEEDED(hr); + info.setAttribute(key, value); + qCDebug(QT_BT_WINDOWS) << "UUID" << uuid << "KEY" << Qt::hex << key << "TYPE" << Qt::dec << type << "UINT32" << Qt::hex << value; + } else if (type == TYPE_SHORT_UUID) { + quint16 value; + hr = dataReader->ReadUInt16(&value); + Q_ASSERT_SUCCEEDED(hr); + const QBluetoothUuid uuid(value); + info.setAttribute(key, uuid); + qCDebug(QT_BT_WINDOWS) << "UUID" << uuid << "KEY" << Qt::hex << key << "TYPE" << Qt::dec << type << "UUID" << Qt::hex << uuid; + } else if (type == TYPE_LONG_UUID) { + GUID value; + hr = dataReader->ReadGuid(&value); + Q_ASSERT_SUCCEEDED(hr); + // The latter 8 bytes are in reverse order + reverseArray(value.Data4, sizeof(value.Data4)/sizeof(value.Data4[0])); + const QBluetoothUuid uuid(value); + info.setAttribute(key, uuid); + qCDebug(QT_BT_WINDOWS) << "UUID" << uuid << "KEY" << Qt::hex << key << "TYPE" << Qt::dec << type << "UUID" << Qt::hex << uuid; + } else if (type == TYPE_STRING) { + BYTE length; + hr = dataReader->ReadByte(&length); + Q_ASSERT_SUCCEEDED(hr); + HString value; + hr = dataReader->ReadString(length, value.GetAddressOf()); + Q_ASSERT_SUCCEEDED(hr); + const QString str = QString::fromWCharArray(WindowsGetStringRawBuffer(value.Get(), nullptr)); + info.setAttribute(key, str); + qCDebug(QT_BT_WINDOWS) << "UUID" << uuid << "KEY" << Qt::hex << key << "TYPE" << Qt::dec << type << "STRING" << str; + } else if (type == TYPE_SEQUENCE) { + bool ok; + QBluetoothServiceInfo::Sequence sequence = readSequence(dataReader, &ok, nullptr); + if (ok) { + info.setAttribute(key, sequence); + qCDebug(QT_BT_WINDOWS) << "UUID" << uuid << "KEY" << Qt::hex << key << "TYPE" << Qt::dec << type << "SEQUENCE" << sequence; + } else { + qCDebug(QT_BT_WINDOWS) << "UUID" << uuid << "KEY" << Qt::hex << key << "TYPE" << Qt::dec << type << "SEQUENCE ERROR"; + } + } else { + qCDebug(QT_BT_WINDOWS) << "UUID" << uuid << "KEY" << Qt::hex << key << "TYPE" << Qt::dec << type; + } + hr = iterator->MoveNext(¤t); + } + // Windows is only able to discover Rfcomm services but the according protocolDescriptor is + // not always set in the raw attribute map. If we encounter a service like that we should + // fill the protocol descriptor ourselves. + if (info.protocolDescriptor(QBluetoothUuid::ProtocolUuid::Rfcomm).isEmpty()) { + QBluetoothServiceInfo::Sequence protocolDescriptorList; + QBluetoothServiceInfo::Sequence protocol; + protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ProtocolUuid::Rfcomm)) + << QVariant::fromValue(0); + protocolDescriptorList.append(QVariant::fromValue(protocol)); + info.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, protocolDescriptorList); + } + emit serviceFound(address, info); + } + emit scanFinished(address); + deleteLater(); +} + +QBluetoothServiceInfo::Sequence QWinRTBluetoothServiceDiscoveryWorker::readSequence(ComPtr dataReader, bool *ok, quint8 *bytesRead) +{ + if (ok) + *ok = false; + if (bytesRead) + *bytesRead = 0; + QBluetoothServiceInfo::Sequence result; + if (!dataReader) + return result; + + quint8 remainingLength; + HRESULT hr = dataReader->ReadByte(&remainingLength); + Q_ASSERT_SUCCEEDED(hr); + if (bytesRead) + *bytesRead += 1; + BYTE type; + hr = dataReader->ReadByte(&type); + remainingLength -= 1; + if (bytesRead) + *bytesRead += 1; + Q_ASSERT_SUCCEEDED(hr); + while (true) { + switch (type) { + case TYPE_UINT8: { + quint8 value; + hr = dataReader->ReadByte(&value); + Q_ASSERT_SUCCEEDED(hr); + result.append(QVariant::fromValue(value)); + remainingLength -= 1; + if (bytesRead) + *bytesRead += 1; + break; + } + case TYPE_UINT16: { + quint16 value; + hr = dataReader->ReadUInt16(&value); + Q_ASSERT_SUCCEEDED(hr); + result.append(QVariant::fromValue(value)); + remainingLength -= 2; + if (bytesRead) + *bytesRead += 2; + break; + } + case TYPE_UINT32: { + quint32 value; + hr = dataReader->ReadUInt32(&value); + Q_ASSERT_SUCCEEDED(hr); + result.append(QVariant::fromValue(value)); + remainingLength -= 4; + if (bytesRead) + *bytesRead += 4; + break; + } + case TYPE_SHORT_UUID: { + quint16 b; + hr = dataReader->ReadUInt16(&b); + Q_ASSERT_SUCCEEDED(hr); + + const QBluetoothUuid uuid(b); + result.append(QVariant::fromValue(uuid)); + remainingLength -= 2; + if (bytesRead) + *bytesRead += 2; + break; + } + case TYPE_LONG_UUID: { + GUID b; + hr = dataReader->ReadGuid(&b); + Q_ASSERT_SUCCEEDED(hr); + // The latter 8 bytes are in reverse order + reverseArray(b.Data4, sizeof(b.Data4)/sizeof(b.Data4[0])); + const QBluetoothUuid uuid(b); + result.append(QVariant::fromValue(uuid)); + remainingLength -= sizeof(GUID); + if (bytesRead) + *bytesRead += sizeof(GUID); + break; + } + case TYPE_STRING: { + BYTE length; + hr = dataReader->ReadByte(&length); + Q_ASSERT_SUCCEEDED(hr); + remainingLength -= 1; + if (bytesRead) + *bytesRead += 1; + HString value; + hr = dataReader->ReadString(length, value.GetAddressOf()); + Q_ASSERT_SUCCEEDED(hr); + + const QString str = QString::fromWCharArray(WindowsGetStringRawBuffer(value.Get(), nullptr)); + result.append(QVariant::fromValue(str)); + remainingLength -= length; + if (bytesRead) + *bytesRead += length; + break; + } + case TYPE_SEQUENCE: { + quint8 bytesR; + const QBluetoothServiceInfo::Sequence sequence = readSequence(dataReader, ok, &bytesR); + if (*ok) + result.append(QVariant::fromValue(sequence)); + else + return result; + remainingLength -= bytesR; + if (bytesRead) + *bytesRead += bytesR; + break; + } + default: + qCDebug(QT_BT_WINDOWS) << "SEQUENCE ERROR" << type; + result.clear(); + return result; + } + if (remainingLength == 0) + break; + + hr = dataReader->ReadByte(&type); + Q_ASSERT_SUCCEEDED(hr); + remainingLength -= 1; + if (bytesRead) + *bytesRead += 1; + } + + if (ok) + *ok = true; + return result; +} + +QBluetoothServiceDiscoveryAgentPrivate::QBluetoothServiceDiscoveryAgentPrivate( + QBluetoothServiceDiscoveryAgent *qp, const QBluetoothAddress &deviceAdapter) + : error(QBluetoothServiceDiscoveryAgent::NoError), + state(Inactive), + mode(QBluetoothServiceDiscoveryAgent::MinimalDiscovery), + singleDevice(false), + q_ptr(qp) +{ + mainThreadCoInit(this); + // TODO: use local adapter for discovery. Possible? + Q_UNUSED(deviceAdapter); +} + +QBluetoothServiceDiscoveryAgentPrivate::~QBluetoothServiceDiscoveryAgentPrivate() +{ + releaseWorker(); + mainThreadCoUninit(this); +} + +void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &address) +{ + if (worker) + return; + + worker = new QWinRTBluetoothServiceDiscoveryWorker(address.toUInt64(), mode); + + connect(worker, &QWinRTBluetoothServiceDiscoveryWorker::serviceFound, + this, &QBluetoothServiceDiscoveryAgentPrivate::processFoundService, Qt::QueuedConnection); + connect(worker, &QWinRTBluetoothServiceDiscoveryWorker::scanFinished, + this, &QBluetoothServiceDiscoveryAgentPrivate::onScanFinished, Qt::QueuedConnection); + connect(worker, &QWinRTBluetoothServiceDiscoveryWorker::errorOccured, + this, &QBluetoothServiceDiscoveryAgentPrivate::onError, Qt::QueuedConnection); + worker->start(); +} + +void QBluetoothServiceDiscoveryAgentPrivate::stop() +{ + releaseWorker(); + Q_Q(QBluetoothServiceDiscoveryAgent); + emit q->canceled(); +} + +void QBluetoothServiceDiscoveryAgentPrivate::processFoundService(quint64 deviceAddress, const QBluetoothServiceInfo &info) +{ + Q_Q(QBluetoothServiceDiscoveryAgent); + //apply uuidFilter + if (!uuidFilter.isEmpty()) { + bool serviceNameMatched = uuidFilter.contains(info.serviceUuid()); + bool serviceClassMatched = false; + const QList serviceClassUuids + = info.serviceClassUuids(); + for (const QBluetoothUuid &id : serviceClassUuids) { + if (uuidFilter.contains(id)) { + serviceClassMatched = true; + break; + } + } + + if (!serviceNameMatched && !serviceClassMatched) + return; + } + + if (!info.isValid()) + return; + + QBluetoothServiceInfo returnInfo(info); + bool deviceFound; + for (const QBluetoothDeviceInfo &deviceInfo : std::as_const(discoveredDevices)) { + if (deviceInfo.address().toUInt64() == deviceAddress) { + deviceFound = true; + returnInfo.setDevice(deviceInfo); + break; + } + } + Q_ASSERT(deviceFound); + + if (!isDuplicatedService(returnInfo)) { + discoveredServices.append(returnInfo); + qCDebug(QT_BT_WINDOWS) << "Discovered services" << discoveredDevices.at(0).address().toString() + << returnInfo.serviceName() << returnInfo.serviceUuid() + << ">>>" << returnInfo.serviceClassUuids(); + + emit q->serviceDiscovered(returnInfo); + } +} + +void QBluetoothServiceDiscoveryAgentPrivate::onScanFinished(quint64 deviceAddress) +{ + // The scan for a device's services has finished. Disconnect the + // worker and call the baseclass function which starts the scan for + // the next device if there are any unscanned devices left (or finishes + // the scan if none left) + releaseWorker(); + _q_serviceDiscoveryFinished(); +} + +void QBluetoothServiceDiscoveryAgentPrivate::onError() +{ + Q_Q(QBluetoothServiceDiscoveryAgent); + discoveredDevices.clear(); + error = QBluetoothServiceDiscoveryAgent::InputOutputError; + errorString = QStringLiteral("errorDescription"); + emit q->errorOccurred(error); +} + +void QBluetoothServiceDiscoveryAgentPrivate::releaseWorker() +{ + if (!worker) + return; + + disconnect(worker, &QWinRTBluetoothServiceDiscoveryWorker::serviceFound, + this, &QBluetoothServiceDiscoveryAgentPrivate::processFoundService); + disconnect(worker, &QWinRTBluetoothServiceDiscoveryWorker::scanFinished, + this, &QBluetoothServiceDiscoveryAgentPrivate::onScanFinished); + disconnect(worker, &QWinRTBluetoothServiceDiscoveryWorker::errorOccured, + this, &QBluetoothServiceDiscoveryAgentPrivate::onError); + // mWorker will delete itself as soon as it is done with its discovery + worker = nullptr; +} + +QT_END_NAMESPACE + +#include diff --git a/src/bluetooth/qbluetoothserviceinfo.cpp b/src/bluetooth/qbluetoothserviceinfo.cpp new file mode 100644 index 0000000..927b9ed --- /dev/null +++ b/src/bluetooth/qbluetoothserviceinfo.cpp @@ -0,0 +1,653 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothserviceinfo.h" +#include "qbluetoothserviceinfo_p.h" + +#include + +QT_BEGIN_NAMESPACE + +QT_IMPL_METATYPE_EXTERN(QBluetoothServiceInfo) +QT_IMPL_METATYPE_EXTERN_TAGGED(QBluetoothServiceInfo::Sequence, QBluetoothServiceInfo__Sequence) +QT_IMPL_METATYPE_EXTERN_TAGGED(QBluetoothServiceInfo::Alternative, + QBluetoothServiceInfo__Alternative) + +/*! + \class QBluetoothServiceInfo::Sequence + \inmodule QtBluetooth + \brief The Sequence class stores attributes of a Bluetooth Data Element + Sequence. + + \since 5.2 + +*/ + +/*! + \fn QBluetoothServiceInfo::Sequence::Sequence() + + Constructs a new empty sequence. +*/ + +/*! + \fn QBluetoothServiceInfo::Sequence::Sequence(const QList &list) + + Constructs a new sequence that is a copy of \a list. +*/ + +/*! + \class QBluetoothServiceInfo::Alternative + \inmodule QtBluetooth + \brief The Alternative class stores attributes of a Bluetooth Data Element + Alternative. + + \since 5.2 +*/ + +/*! + \fn QBluetoothServiceInfo::Alternative::Alternative() + + Constructs a new empty alternative. +*/ + +/*! + \fn QBluetoothServiceInfo::Alternative::Alternative(const QList &list) + + Constructs a new alternative that is a copy of \a list. +*/ + +/*! + \class QBluetoothServiceInfo + \inmodule QtBluetooth + \brief The QBluetoothServiceInfo class enables access to the attributes of a + Bluetooth service. + + \since 5.2 + + QBluetoothServiceInfo provides information about a service offered by a Bluetooth device. + In addition it can be used to register new services on the local device. Note that such + a registration only affects the Bluetooth SDP entries. Any server listening + for incoming connections (e.g an RFCOMM server) must be started before registerService() + is called. Deregistration must happen in the reverse order. + + QBluetoothServiceInfo is not a value type in the traditional sense. All copies of the same + service info object share the same data as they do not detach upon changing them. This + ensures that two copies can (de)register the same Bluetooth service. + + On iOS, this class cannot be used because the platform does not expose + an API which may permit access to QBluetoothServiceInfo related features. +*/ + +/*! + \enum QBluetoothServiceInfo::AttributeId + + Bluetooth service attributes. Please check the Bluetooth Core Specification for a more detailed description of these attributes. + + \value ServiceRecordHandle Specifies a service record from which attributes can be retrieved. + \value ServiceClassIds UUIDs of service classes that the service conforms to. The + most common service classes are defined in (\l QBluetoothUuid::ServiceClassUuid) + \value ServiceRecordState Attibute changes when any other service attribute is added, deleted or modified. + \value ServiceId UUID that uniquely identifies the service. + \value ProtocolDescriptorList List of protocols used by the service. The most common protocol Uuids are defined + in \l QBluetoothUuid::ProtocolUuid + \value BrowseGroupList List of browse groups the service is in. + \value LanguageBaseAttributeIdList List of language base attribute IDs to support human-readable attributes. + \value ServiceInfoTimeToLive Number of seconds for which the service record is expected to remain valid and unchanged. + \value ServiceAvailability Value indicating the availability of the service. + \value BluetoothProfileDescriptorList List of profiles to which the service conforms. + \value DocumentationUrl URL that points to the documentation on the service.. + \value ClientExecutableUrl URL that refers to the location of an application that can be used to utilize the service. + \value IconUrl URL to the location of the icon representing the service. + \value AdditionalProtocolDescriptorList Additional protocols used by the service. This attribute extends \c ProtocolDescriptorList. + \value PrimaryLanguageBase Base index for primary language text descriptors. + \value ServiceName Name of the Bluetooth service in the primary language. + \value ServiceDescription Description of the Bluetooth service in the primary language. + \value ServiceProvider Name of the company / entity that provides the Bluetooth service primary language. + + \note On Windows ServiceClassIds and ProtocolDescriptorList are automatically set to default + values when a service is created. Manually setting values for these attributes will not work and + might lead to unexpected results on this platform. +*/ + +/*! + \enum QBluetoothServiceInfo::Protocol + + This enum describes the socket protocol used by the service. + + \value UnknownProtocol The service uses an unknown socket protocol. + \value L2capProtocol The service uses the L2CAP socket protocol. This protocol is not supported + for direct socket connections on Android. + \value RfcommProtocol The service uses the RFCOMM socket protocol. +*/ + +/*! + \fn bool QBluetoothServiceInfo::isRegistered() const + + Returns true if the service information is registered with the platform's Service Discovery Protocol + (SDP) implementation, otherwise returns false. +*/ + +bool QBluetoothServiceInfo::isRegistered() const +{ + return d_ptr->isRegistered(); +} + +/*! + \fn bool QBluetoothServiceInfo::registerService(const QBluetoothAddress &localAdapter) + + Registers this service with the platform's Service Discovery Protocol (SDP) implementation, + making it findable by other devices when they perform service discovery. Returns true if the + service is successfully registered, otherwise returns false. Once registered changes to the record + cannot be made. The service must be unregistered and registered again with the changes. + + The \a localAdapter parameter determines the local Bluetooth adapter under which + the service should be registered. If \a localAdapter is \c null the default Bluetooth adapter + will be used. If this service info object is already registered via a local adapter + and this is function is called using a different local adapter, the previous registration + is removed and the service reregistered using the new adapter. +*/ + +bool QBluetoothServiceInfo::registerService(const QBluetoothAddress &localAdapter) +{ +#ifdef QT_OSX_BLUETOOTH + Q_UNUSED(localAdapter); + return d_ptr->registerService(*this); +#else + return d_ptr->registerService(localAdapter); +#endif +} + +/*! + \fn bool QBluetoothServiceInfo::unregisterService() + + Unregisters this service with the platform's Service Discovery Protocol (SDP) implementation. + After this, the service will no longer be findable by other devices through service discovery. + + Returns true if the service is successfully unregistered, otherwise returns false. +*/ + +bool QBluetoothServiceInfo::unregisterService() +{ + return d_ptr->unregisterService(); +} + + +/*! + \fn void QBluetoothServiceInfo::setAttribute(quint16 attributeId, const QBluetoothUuid &value) + + This is a convenience function. + + Sets the attribute identified by \a attributeId to \a value. + + If the service information is already registered with the platform's SDP database, + the database entry will not be updated until \l registerService() was called again. +*/ + +/*! + \fn void QBluetoothServiceInfo::setAttribute(quint16 attributeId, const QBluetoothServiceInfo::Sequence &value) + + This is a convenience function. + + Sets the attribute identified by \a attributeId to \a value. + + If the service information is already registered with the platform's SDP database, + the database entry will not be updated until \l registerService() was called again. +*/ + +/*! + \fn void QBluetoothServiceInfo::setAttribute(quint16 attributeId, const QBluetoothServiceInfo::Alternative &value) + + This is a convenience function. + + Sets the attribute identified by \a attributeId to \a value. + + If the service information is already registered with the platform's SDP database, + the database entry will not be updated until \l registerService() was called again. +*/ + +/*! + \fn void QBluetoothServiceInfo::setServiceName(const QString &name) + + This is a convenience function. It is equivalent to calling + setAttribute(QBluetoothServiceInfo::ServiceName, name). + + Sets the service name in the primary language to \a name. + + \sa serviceName(), setAttribute() +*/ + +/*! + \fn QString QBluetoothServiceInfo::serviceName() const + + This is a convenience function. It is equivalent to calling + attribute(QBluetoothServiceInfo::ServiceName).toString(). + + Returns the service name in the primary language. + + \sa setServiceName(), attribute() +*/ + +/*! + \fn void QBluetoothServiceInfo::setServiceDescription(const QString &description) + + This is a convenience function. It is equivalent to calling + setAttribute(QBluetoothServiceInfo::ServiceDescription, description). + + Sets the service description in the primary language to \a description. + + \sa serviceDescription(), setAttribute() +*/ + +/*! + \fn QString QBluetoothServiceInfo::serviceDescription() const + + This is a convenience function. It is equivalent to calling + attribute(QBluetoothServiceInfo::ServiceDescription).toString(). + + Returns the service description in the primary language. + + \sa setServiceDescription(), attribute() +*/ + +/*! + \fn void QBluetoothServiceInfo::setServiceProvider(const QString &provider) + + This is a convenience function. It is equivalent to calling + setAttribute(QBluetoothServiceInfo::ServiceProvider, provider). + + Sets the service provider in the primary language to \a provider. + + \sa serviceProvider(), setAttribute() +*/ + +/*! + \fn QString QBluetoothServiceInfo::serviceProvider() const + + This is a convenience function. It is equivalent to calling + attribute(QBluetoothServiceInfo::ServiceProvider).toString(). + + Returns the service provider in the primary language. + + \sa setServiceProvider(), attribute() +*/ + +/*! + \fn void QBluetoothServiceInfo::setServiceAvailability(quint8 availability) + + This is a convenience function. It is equivalent to calling + setAttribute(QBluetoothServiceInfo::ServiceAvailability, availability). + + Sets the availabiltiy of the service to \a availability. + + \sa serviceAvailability(), setAttribute() +*/ + +/*! + \fn quint8 QBluetoothServiceInfo::serviceAvailability() const + + This is a convenience function. It is equivalent to calling + attribute(QBluetoothServiceInfo::ServiceAvailability).toUInt(). + + Returns the availability of the service. + + \sa setServiceAvailability(), attribute() +*/ + +/*! + \fn void QBluetoothServiceInfo::setServiceUuid(const QBluetoothUuid &uuid) + + This is a convenience function. It is equivalent to calling + setAttribute(QBluetoothServiceInfo::ServiceId, uuid). + + Sets the custom service UUID to \a uuid. This function should not be used + to set a standardized service UUID. + + \sa serviceUuid(), setAttribute() +*/ + +/*! + \fn QBluetoothUuid QBluetoothServiceInfo::serviceUuid() const + + This is a convenience function. It is equivalent to calling + attribute(QBluetoothServiceInfo::ServiceId).value(). + + Returns the custom UUID of the service. This UUID may be null. + UUIDs based on \l{https://bluetooth.org}{Bluetooth SIG standards} + should be retrieved via \l serviceClassUuids(). + + \sa setServiceUuid(), attribute() +*/ + +/*! + Construct a new invalid QBluetoothServiceInfo; +*/ +QBluetoothServiceInfo::QBluetoothServiceInfo() + : d_ptr(QSharedPointer::create()) +{ + qRegisterMetaType(); +} + +/*! + Construct a new QBluetoothServiceInfo that is a copy of \a other. + + The two copies continue to share the same underlying data which does not detach + upon write. +*/ +QBluetoothServiceInfo::QBluetoothServiceInfo(const QBluetoothServiceInfo &other) + : d_ptr(other.d_ptr) +{ +} + +/*! + Destroys the QBluetoothServiceInfo object. +*/ +QBluetoothServiceInfo::~QBluetoothServiceInfo() +{ +} + +/*! + Returns true if the QBluetoothServiceInfo object is valid, otherwise returns false. + + An invalid QBluetoothServiceInfo object will have no attributes. +*/ +bool QBluetoothServiceInfo::isValid() const +{ + return !d_ptr->attributes.isEmpty(); +} + +/*! + Returns true if the QBluetoothServiceInfo object is considered complete, otherwise returns false. + + A complete QBluetoothServiceInfo object contains a ProtocolDescriptorList attribute. +*/ +bool QBluetoothServiceInfo::isComplete() const +{ + return d_ptr->attributes.contains(ProtocolDescriptorList); +} + +/*! + Returns the address of the Bluetooth device that provides this service. +*/ +QBluetoothDeviceInfo QBluetoothServiceInfo::device() const +{ + return d_ptr->deviceInfo; +} + +/*! + Sets the Bluetooth device that provides this service to \a device. +*/ +void QBluetoothServiceInfo::setDevice(const QBluetoothDeviceInfo &device) +{ + d_ptr->deviceInfo = device; +} + +/*! + Sets the attribute identified by \a attributeId to \a value. + + If the service information is already registered with the platform's SDP database, + the database entry will not be updated until \l registerService() was called again. + + \note If an attribute expectes a byte-encoded value (e.g. Bluetooth HID services), + it should be set as QByteArray. + + \sa isRegistered(), registerService() +*/ +void QBluetoothServiceInfo::setAttribute(quint16 attributeId, const QVariant &value) +{ + d_ptr->attributes[attributeId] = value; +} + +/*! + Returns the value of the attribute \a attributeId. +*/ +QVariant QBluetoothServiceInfo::attribute(quint16 attributeId) const +{ + return d_ptr->attributes.value(attributeId); +} + +/*! + Returns a list of all attribute ids that the QBluetoothServiceInfo object has. +*/ +QList QBluetoothServiceInfo::attributes() const +{ + return d_ptr->attributes.keys(); +} + +/*! + Returns true if the QBluetoothServiceInfo object contains the attribute \a attributeId, otherwise returns + false. +*/ +bool QBluetoothServiceInfo::contains(quint16 attributeId) const +{ + return d_ptr->attributes.contains(attributeId); +} + +/*! + Removes the attribute \a attributeId from the QBluetoothServiceInfo object. + + If the service information is already registered with the platforms SDP database, + the database entry will not be updated until \l registerService() was called again. +*/ +void QBluetoothServiceInfo::removeAttribute(quint16 attributeId) +{ + d_ptr->attributes.remove(attributeId); +} + +/*! + Returns the protocol that the QBluetoothServiceInfo object uses. +*/ +QBluetoothServiceInfo::Protocol QBluetoothServiceInfo::socketProtocol() const +{ + QBluetoothServiceInfo::Sequence parameters = protocolDescriptor(QBluetoothUuid::ProtocolUuid::Rfcomm); + if (!parameters.isEmpty()) + return RfcommProtocol; + + parameters = protocolDescriptor(QBluetoothUuid::ProtocolUuid::L2cap); + if (!parameters.isEmpty()) + return L2capProtocol; + + return UnknownProtocol; +} + +/*! + This is a convenience function. Returns the protocol/service multiplexer for services which + support the L2CAP protocol, otherwise returns -1. + + This function is equivalent to extracting the information from + QBluetoothServiceInfo::Sequence returned by + QBluetoothServiceInfo::attribute(QBluetoothServiceInfo::ProtocolDescriptorList). +*/ +int QBluetoothServiceInfo::protocolServiceMultiplexer() const +{ + QBluetoothServiceInfo::Sequence parameters = protocolDescriptor(QBluetoothUuid::ProtocolUuid::L2cap); + + if (parameters.isEmpty()) + return -1; + else if (parameters.size() == 1) + return 0; + else + return parameters.at(1).toUInt(); +} + +/*! + This is a convenience function. Returns the server channel for services which support the + RFCOMM protocol, otherwise returns -1. + + This function is equivalent to extracting the information from + QBluetoothServiceInfo::Sequence returned by + QBluetoothServiceInfo::attribute(QBluetootherServiceInfo::ProtocolDescriptorList). +*/ +int QBluetoothServiceInfo::serverChannel() const +{ + return d_ptr->serverChannel(); +} + +/*! + Returns the protocol parameters as a QBluetoothServiceInfo::Sequence for protocol \a protocol. + + An empty QBluetoothServiceInfo::Sequence is returned if \a protocol is not supported. +*/ +QBluetoothServiceInfo::Sequence QBluetoothServiceInfo::protocolDescriptor(QBluetoothUuid::ProtocolUuid protocol) const +{ + return d_ptr->protocolDescriptor(protocol); +} + +/*! + Returns a list of UUIDs describing the service classes that this service conforms to. + + This is a convenience function. It is equivalent to calling + attribute(QBluetoothServiceInfo::ServiceClassIds).value() + and subsequently iterating over its QBluetoothUuid entries. + + \sa attribute() +*/ +QList QBluetoothServiceInfo::serviceClassUuids() const +{ + QList results; + + const QVariant var = attribute(QBluetoothServiceInfo::ServiceClassIds); + if (!var.isValid()) + return results; + + const QBluetoothServiceInfo::Sequence seq = var.value(); + for (qsizetype i = 0; i < seq.size(); ++i) + results.append(seq.at(i).value()); + + return results; +} + +/*! + Makes a copy of the \a other and assigns it to this QBluetoothServiceInfo object. + The two copies continue to share the same service and registration details. +*/ +QBluetoothServiceInfo &QBluetoothServiceInfo::operator=(const QBluetoothServiceInfo &other) +{ + d_ptr = other.d_ptr; + + return *this; +} + +static void dumpAttributeVariant(QDebug dbg, const QVariant &var, const QString& indent) +{ + switch (var.typeId()) { + case QMetaType::Void: + dbg << QString::asprintf("%sEmpty\n", indent.toUtf8().constData()); + break; + case QMetaType::UChar: + dbg << QString::asprintf("%suchar %u\n", indent.toUtf8().constData(), var.toUInt()); + break; + case QMetaType::UShort: + dbg << QString::asprintf("%sushort %u\n", indent.toUtf8().constData(), var.toUInt()); + break; + case QMetaType::UInt: + dbg << QString::asprintf("%suint %u\n", indent.toUtf8().constData(), var.toUInt()); + break; + case QMetaType::Char: + dbg << QString::asprintf("%schar %d\n", indent.toUtf8().constData(), var.toInt()); + break; + case QMetaType::Short: + dbg << QString::asprintf("%sshort %d\n", indent.toUtf8().constData(), var.toInt()); + break; + case QMetaType::Int: + dbg << QString::asprintf("%sint %d\n", indent.toUtf8().constData(), var.toInt()); + break; + case QMetaType::QString: + dbg << QString::asprintf("%sstring %s\n", indent.toUtf8().constData(), + var.toString().toUtf8().constData()); + break; + case QMetaType::QByteArray: + dbg << QString::asprintf("%sbytearray %s\n", indent.toUtf8().constData(), + var.toByteArray().toHex().constData()); + break; + case QMetaType::Bool: + dbg << QString::asprintf("%sbool %d\n", indent.toUtf8().constData(), var.toBool()); + break; + case QMetaType::QUrl: + dbg << QString::asprintf("%surl %s\n", indent.toUtf8().constData(), + var.toUrl().toString().toUtf8().constData()); + break; + default: + if (var.typeId() == qMetaTypeId()) { + QBluetoothUuid uuid = var.value(); + switch (uuid.minimumSize()) { + case 0: + dbg << QString::asprintf("%suuid NULL\n", indent.toUtf8().constData()); + break; + case 2: + dbg << QString::asprintf("%suuid2 %04x\n", indent.toUtf8().constData(), + uuid.toUInt16()); + break; + case 4: + dbg << QString::asprintf("%suuid %08x\n", indent.toUtf8().constData(), + uuid.toUInt32()); + break; + case 16: + dbg << QString::asprintf("%suuid %s\n", + indent.toUtf8().constData(), + uuid.toByteArray(QUuid::Id128).constData()); + break; + default: + dbg << QString::asprintf("%suuid ???\n", indent.toUtf8().constData()); + } + } else if (var.typeId() == qMetaTypeId()) { + dbg << QString::asprintf("%sSequence\n", indent.toUtf8().constData()); + const QBluetoothServiceInfo::Sequence *sequence = static_cast(var.data()); + for (const QVariant &v : *sequence) + dumpAttributeVariant(dbg, v, indent + QLatin1Char('\t')); + } else if (var.typeId() == qMetaTypeId()) { + dbg << QString::asprintf("%sAlternative\n", indent.toUtf8().constData()); + const QBluetoothServiceInfo::Alternative *alternative = static_cast(var.data()); + for (const QVariant &v : *alternative) + dumpAttributeVariant(dbg, v, indent + QLatin1Char('\t')); + } else { + dbg << QString::asprintf("%sunknown variant type %d\n", indent.toUtf8().constData(), var.typeId()); + } + } +} + +#ifndef QT_NO_DEBUG_STREAM +QDebug QBluetoothServiceInfo::streamingOperator(QDebug dbg, const QBluetoothServiceInfo &info) +{ + QDebugStateSaver saver(dbg); + dbg.noquote() << "\n"; + const QList attributes = info.attributes(); + for (quint16 id : attributes) { + dumpAttributeVariant(dbg, info.attribute(id), QStringLiteral("(%1)\t").arg(id)); + } + return dbg; +} +#endif + +QBluetoothServiceInfo::Sequence QBluetoothServiceInfoPrivate::protocolDescriptor(QBluetoothUuid::ProtocolUuid protocol) const +{ + if (!attributes.contains(QBluetoothServiceInfo::ProtocolDescriptorList)) + return QBluetoothServiceInfo::Sequence(); + + const QBluetoothServiceInfo::Sequence sequence + = attributes.value(QBluetoothServiceInfo::ProtocolDescriptorList).value(); + for (const QVariant &v : sequence) { + QBluetoothServiceInfo::Sequence parameters = v.value(); + if (parameters.empty()) + continue; + if (parameters.at(0).userType() == qMetaTypeId()) { + if (parameters.at(0).value() == protocol) + return parameters; + } + } + + return QBluetoothServiceInfo::Sequence(); +} + +int QBluetoothServiceInfoPrivate::serverChannel() const +{ + QBluetoothServiceInfo::Sequence parameters = protocolDescriptor(QBluetoothUuid::ProtocolUuid::Rfcomm); + + if (parameters.isEmpty()) + return -1; + else if (parameters.size() == 1) + return 0; + else + return parameters.at(1).toUInt(); +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothserviceinfo.h b/src/bluetooth/qbluetoothserviceinfo.h new file mode 100644 index 0000000..8ab2086 --- /dev/null +++ b/src/bluetooth/qbluetoothserviceinfo.h @@ -0,0 +1,203 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QBLUETOOTHSERVICEINFO_H +#define QBLUETOOTHSERVICEINFO_H + +#include + +#include +#include + +#include +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +class QBluetoothServiceInfoPrivate; +class QBluetoothDeviceInfo; + +class Q_BLUETOOTH_EXPORT QBluetoothServiceInfo +{ +public: + enum AttributeId { + ServiceRecordHandle = 0x0000, + ServiceClassIds = 0x0001, + ServiceRecordState = 0x0002, + ServiceId = 0x0003, + ProtocolDescriptorList = 0x0004, + BrowseGroupList = 0x0005, + LanguageBaseAttributeIdList = 0x0006, + ServiceInfoTimeToLive = 0x0007, + ServiceAvailability = 0x0008, + BluetoothProfileDescriptorList = 0x0009, + DocumentationUrl = 0x000A, + ClientExecutableUrl = 0x000B, + IconUrl = 0x000C, + AdditionalProtocolDescriptorList = 0x000D, + PrimaryLanguageBase = 0x0100, + ServiceName = PrimaryLanguageBase + 0x0000, + ServiceDescription = PrimaryLanguageBase + 0x0001, + ServiceProvider = PrimaryLanguageBase + 0x0002 + }; + + enum Protocol { + UnknownProtocol, + L2capProtocol, + RfcommProtocol + }; + + class Sequence : public QList + { + public: + Sequence() { } + Sequence(const QList &list) : QList(list) { } + }; + + class Alternative : public QList + { + public: + Alternative() { } + Alternative(const QList &list) : QList(list) { } + }; + + QBluetoothServiceInfo(); + QBluetoothServiceInfo(const QBluetoothServiceInfo &other); + ~QBluetoothServiceInfo(); + + bool isValid() const; + bool isComplete() const; + + void setDevice(const QBluetoothDeviceInfo &info); + QBluetoothDeviceInfo device() const; + + void setAttribute(quint16 attributeId, const QVariant &value); + void setAttribute(quint16 attributeId, const QBluetoothUuid &value); + void setAttribute(quint16 attributeId, const QBluetoothServiceInfo::Sequence &value); + void setAttribute(quint16 attributeId, const QBluetoothServiceInfo::Alternative &value); + QVariant attribute(quint16 attributeId) const; + QList attributes() const; + bool contains(quint16 attributeId) const; + void removeAttribute(quint16 attributeId); + + inline void setServiceName(const QString &name); + inline QString serviceName() const; + inline void setServiceDescription(const QString &description); + inline QString serviceDescription() const; + inline void setServiceProvider(const QString &provider); + inline QString serviceProvider() const; + + QBluetoothServiceInfo::Protocol socketProtocol() const; + int protocolServiceMultiplexer() const; + int serverChannel() const; + + QBluetoothServiceInfo::Sequence protocolDescriptor(QBluetoothUuid::ProtocolUuid protocol) const; + + inline void setServiceAvailability(quint8 availability); + inline quint8 serviceAvailability() const; + + inline void setServiceUuid(const QBluetoothUuid &uuid); + inline QBluetoothUuid serviceUuid() const; + + QList serviceClassUuids() const; + + QBluetoothServiceInfo &operator=(const QBluetoothServiceInfo &other); + + bool isRegistered() const; + bool registerService(const QBluetoothAddress &localAdapter = QBluetoothAddress()); + bool unregisterService(); + +private: +#ifndef QT_NO_DEBUG_STREAM + friend QDebug operator<<(QDebug d, const QBluetoothServiceInfo &i) + { + return streamingOperator(d, i); + } + static QDebug streamingOperator(QDebug, const QBluetoothServiceInfo &); +#endif +protected: + QSharedPointer d_ptr; +}; + +QT_END_NAMESPACE + +QT_DECL_METATYPE_EXTERN(QBluetoothServiceInfo, Q_BLUETOOTH_EXPORT) +QT_DECL_METATYPE_EXTERN_TAGGED(QBluetoothServiceInfo::Sequence, QBluetoothServiceInfo__Sequence, + Q_BLUETOOTH_EXPORT) +QT_DECL_METATYPE_EXTERN_TAGGED(QBluetoothServiceInfo::Alternative, + QBluetoothServiceInfo__Alternative, + Q_BLUETOOTH_EXPORT) + +QT_BEGIN_NAMESPACE + +inline void QBluetoothServiceInfo::setAttribute(quint16 attributeId, const QBluetoothUuid &value) +{ + setAttribute(attributeId, QVariant::fromValue(value)); +} + +inline void QBluetoothServiceInfo::setAttribute(quint16 attributeId, const QBluetoothServiceInfo::Sequence &value) +{ + setAttribute(attributeId, QVariant::fromValue(value)); +} + +inline void QBluetoothServiceInfo::setAttribute(quint16 attributeId, const QBluetoothServiceInfo::Alternative &value) +{ + setAttribute(attributeId, QVariant::fromValue(value)); +} + +inline void QBluetoothServiceInfo::setServiceName(const QString &name) +{ + setAttribute(ServiceName, QVariant::fromValue(name)); +} + +inline QString QBluetoothServiceInfo::serviceName() const +{ + return attribute(ServiceName).toString(); +} + +inline void QBluetoothServiceInfo::setServiceDescription(const QString &description) +{ + setAttribute(ServiceDescription, QVariant::fromValue(description)); +} + +inline QString QBluetoothServiceInfo::serviceDescription() const +{ + return attribute(ServiceDescription).toString(); +} + +inline void QBluetoothServiceInfo::setServiceProvider(const QString &provider) +{ + setAttribute(ServiceProvider, QVariant::fromValue(provider)); +} + +inline QString QBluetoothServiceInfo::serviceProvider() const +{ + return attribute(ServiceProvider).toString(); +} + +inline void QBluetoothServiceInfo::setServiceAvailability(quint8 availability) +{ + setAttribute(ServiceAvailability, QVariant::fromValue(availability)); +} + +inline quint8 QBluetoothServiceInfo::serviceAvailability() const +{ + return attribute(ServiceAvailability).toUInt(); +} + +inline void QBluetoothServiceInfo::setServiceUuid(const QBluetoothUuid &uuid) +{ + setAttribute(ServiceId, uuid); +} + +inline QBluetoothUuid QBluetoothServiceInfo::serviceUuid() const +{ + return attribute(ServiceId).value(); +} +QT_END_NAMESPACE + +#endif diff --git a/src/bluetooth/qbluetoothserviceinfo_android.cpp b/src/bluetooth/qbluetoothserviceinfo_android.cpp new file mode 100644 index 0000000..33ca7d5 --- /dev/null +++ b/src/bluetooth/qbluetoothserviceinfo_android.cpp @@ -0,0 +1,110 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + + +#include "android/androidutils_p.h" +#include "qbluetoothhostinfo.h" +#include "qbluetoothlocaldevice.h" +#include "qbluetoothserviceinfo.h" +#include "qbluetoothserviceinfo_p.h" +#include "qbluetoothserver_p.h" +#include "qbluetoothserver.h" + +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID) + +extern QHash __fakeServerPorts; + +QBluetoothServiceInfoPrivate::QBluetoothServiceInfoPrivate() +: registered(false) +{ +} + +QBluetoothServiceInfoPrivate::~QBluetoothServiceInfoPrivate() +{ +} + +bool QBluetoothServiceInfoPrivate::isRegistered() const +{ + return registered; +} + +bool QBluetoothServiceInfoPrivate::unregisterService() +{ + if (!registered) + return false; + + QBluetoothServerPrivate *sPriv = __fakeServerPorts.key(serverChannel()); + if (!sPriv) { + //QBluetoothServer::close() was called without prior call to unregisterService(). + //Now it is unregistered anyway. + registered = false; + return true; + } + + bool result = sPriv->deactivateActiveListening(); + if (!result) + return false; + + registered = false; + return true; +} + +bool QBluetoothServiceInfoPrivate::registerService(const QBluetoothAddress& localAdapter) +{ + if (!ensureAndroidPermission(QBluetoothPermission::Access)) { + qCWarning(QT_BT_ANDROID) << "Serviceinfo registerService() failed due to" + "missing permissions"; + return false; + } + + const QList localDevices = QBluetoothLocalDevice::allDevices(); + if (localDevices.isEmpty()) + return false; //no Bluetooth device + + if (!localAdapter.isNull()) { + bool found = false; + for (const QBluetoothHostInfo &hostInfo : localDevices) { + if (hostInfo.address() == localAdapter) { + found = true; + break; + } + } + + if (!found) { + qCWarning(QT_BT_ANDROID) << localAdapter.toString() << "is not a valid local Bt adapter"; + return false; + } + } + + //already registered on local adapter => nothing to do + if (registered) + return false; + + if (protocolDescriptor(QBluetoothUuid::ProtocolUuid::Rfcomm).isEmpty()) { + qCWarning(QT_BT_ANDROID) << Q_FUNC_INFO << "Only RFCOMM services can be registered on Android"; + return false; + } + + QBluetoothServerPrivate *sPriv = __fakeServerPorts.key(serverChannel()); + if (!sPriv) + return false; + + //tell the server what service name and uuid our listener should have + //and start the real listener + bool result = sPriv->initiateActiveListening( + attributes.value(QBluetoothServiceInfo::ServiceId).value(), + attributes.value(QBluetoothServiceInfo::ServiceName).toString()); + if (!result) { + return false; + } + + + registered = true; + return true; +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothserviceinfo_bluez.cpp b/src/bluetooth/qbluetoothserviceinfo_bluez.cpp new file mode 100644 index 0000000..14c3e45 --- /dev/null +++ b/src/bluetooth/qbluetoothserviceinfo_bluez.cpp @@ -0,0 +1,258 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothserviceinfo.h" +#include "qbluetoothserviceinfo_p.h" + +#include "bluez/bluez5_helper_p.h" +#include "bluez/profilemanager1_p.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace Qt::StringLiterals; + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ) + +static QAtomicInt pathCounter; + +static void writeAttribute(QXmlStreamWriter *stream, const QVariant &attribute) +{ + const QString unsignedFormat(QStringLiteral("0x%1")); + + switch (attribute.typeId()) { + case QMetaType::Void: + stream->writeEmptyElement(QStringLiteral("nil")); + break; + case QMetaType::UChar: + stream->writeEmptyElement(QStringLiteral("uint8")); + stream->writeAttribute(QStringLiteral("value"), + unsignedFormat.arg(attribute.value(), 2, 16, + QLatin1Char('0'))); + break; + case QMetaType::UShort: + stream->writeEmptyElement(QStringLiteral("uint16")); + stream->writeAttribute(QStringLiteral("value"), + unsignedFormat.arg(attribute.value(), 4, 16, + QLatin1Char('0'))); + break; + case QMetaType::UInt: + stream->writeEmptyElement(QStringLiteral("uint32")); + stream->writeAttribute(QStringLiteral("value"), + unsignedFormat.arg(attribute.value(), 8, 16, + QLatin1Char('0'))); + break; + case QMetaType::Char: + stream->writeEmptyElement(QStringLiteral("int8")); + stream->writeAttribute(QStringLiteral("value"), + QString::number(attribute.value())); + break; + case QMetaType::Short: + stream->writeEmptyElement(QStringLiteral("int16")); + stream->writeAttribute(QStringLiteral("value"), + QString::number(attribute.value())); + break; + case QMetaType::Int: + stream->writeEmptyElement(QStringLiteral("int32")); + stream->writeAttribute(QStringLiteral("value"), + QString::number(attribute.value())); + break; + case QMetaType::QByteArray: + stream->writeEmptyElement(QStringLiteral("text")); + stream->writeAttribute(QStringLiteral("value"), + QString::fromLatin1(attribute.value().toHex().constData())); + stream->writeAttribute(QStringLiteral("encoding"), QStringLiteral("hex")); + break; + case QMetaType::QString: + stream->writeEmptyElement(QStringLiteral("text")); + stream->writeAttribute(QStringLiteral("value"), attribute.value()); + stream->writeAttribute(QStringLiteral("encoding"), QStringLiteral("normal")); + break; + case QMetaType::Bool: + stream->writeEmptyElement(QStringLiteral("boolean")); + if (attribute.value()) + stream->writeAttribute(QStringLiteral("value"), QStringLiteral("true")); + else + stream->writeAttribute(QStringLiteral("value"), QStringLiteral("false")); + break; + case QMetaType::QUrl: + stream->writeEmptyElement(QStringLiteral("url")); + stream->writeAttribute(QStringLiteral("value"), attribute.value().toString()); + break; + default: + if (attribute.userType() == qMetaTypeId()) { + stream->writeEmptyElement(QStringLiteral("uuid")); + + QBluetoothUuid uuid = attribute.value(); + switch (uuid.minimumSize()) { + case 0: + stream->writeAttribute(QStringLiteral("value"), + unsignedFormat.arg(quint16(0), 4, 16, QLatin1Char('0'))); + break; + case 2: + stream->writeAttribute(QStringLiteral("value"), + unsignedFormat.arg(uuid.toUInt16(), 4, 16, + QLatin1Char('0'))); + break; + case 4: + stream->writeAttribute(QStringLiteral("value"), + unsignedFormat.arg(uuid.toUInt32(), 8, 16, + QLatin1Char('0'))); + break; + case 16: + stream->writeAttribute(QStringLiteral("value"), uuid.toString().mid(1, 36)); + break; + default: + stream->writeAttribute(QStringLiteral("value"), uuid.toString().mid(1, 36)); + } + } else if (attribute.userType() == qMetaTypeId()) { + stream->writeStartElement(QStringLiteral("sequence")); + const QBluetoothServiceInfo::Sequence *sequence = + static_cast(attribute.data()); + for (const QVariant &v : *sequence) + writeAttribute(stream, v); + stream->writeEndElement(); + } else if (attribute.userType() == qMetaTypeId()) { + const QBluetoothServiceInfo::Alternative *alternative = + static_cast(attribute.data()); + for (const QVariant &v : *alternative) + writeAttribute(stream, v); + stream->writeEndElement(); + } else { + qCWarning(QT_BT_BLUEZ) << "Unknown variant type" << attribute.userType(); + } + } +} + +QBluetoothServiceInfoPrivate::QBluetoothServiceInfoPrivate() +: serviceRecord(0), registered(false) +{ + initializeBluez5(); + service = new OrgBluezProfileManager1Interface(QStringLiteral("org.bluez"), + QStringLiteral("/org/bluez"), + QDBusConnection::systemBus(), this); +} + +QBluetoothServiceInfoPrivate::~QBluetoothServiceInfoPrivate() +{ +} + +bool QBluetoothServiceInfoPrivate::isRegistered() const +{ + return registered; +} + +bool QBluetoothServiceInfoPrivate::unregisterService() +{ + if (!registered) + return false; + + if (profilePath.isEmpty()) + return false; + + QDBusPendingReply<> reply = service->UnregisterProfile(QDBusObjectPath(profilePath)); + reply.waitForFinished(); + if (reply.isError()) { + qCWarning(QT_BT_BLUEZ) << "Cannot unregister profile:" << profilePath + << reply.error().message(); + return false; + } + profilePath.clear(); + + registered = false; + return true; +} + +// TODO Implement local adapter behavior +bool QBluetoothServiceInfoPrivate::registerService(const QBluetoothAddress & /*localAdapter*/) +{ + if (registered) + return false; + + QString xmlServiceRecord; + + QXmlStreamWriter stream(&xmlServiceRecord); + stream.setAutoFormatting(true); + + stream.writeStartDocument(QStringLiteral("1.0")); + + stream.writeStartElement(QStringLiteral("record")); + + const QString unsignedFormat(QStringLiteral("0x%1")); + + QMap::ConstIterator i = attributes.constBegin(); + while (i != attributes.constEnd()) { + stream.writeStartElement(QStringLiteral("attribute")); + stream.writeAttribute(QStringLiteral("id"), unsignedFormat.arg(i.key(), 4, 16, QLatin1Char('0'))); + writeAttribute(&stream, i.value()); + stream.writeEndElement(); + + ++i; + } + + stream.writeEndElement(); + + stream.writeEndDocument(); + + // create path + profilePath = u"/qt/profile"_s; + profilePath.append(QString::fromLatin1("/%1%2/%3") + .arg(sanitizeNameForDBus(QCoreApplication::applicationName())) + .arg(QCoreApplication::applicationPid()) + .arg(pathCounter.fetchAndAddOrdered(1))); + + QVariantMap mapping; + mapping.insert(QStringLiteral("ServiceRecord"), xmlServiceRecord); + mapping.insert(QStringLiteral("Role"), QStringLiteral("server")); + + // Strategy to pick service uuid + // 1.) use serviceUuid() + // 2.) use first custom uuid if available + // 3.) use first service class uuid + QBluetoothUuid profileUuid = + attributes.value(QBluetoothServiceInfo::ServiceId).value(); + QBluetoothUuid firstCustomUuid; + if (profileUuid.isNull()) { + const QVariant var = attributes.value(QBluetoothServiceInfo::ServiceClassIds); + if (var.isValid()) { + const QBluetoothServiceInfo::Sequence seq = + var.value(); + for (const auto &e : seq) { + auto tempUuid = e.value(); + if (tempUuid.isNull()) + continue; + + int size = tempUuid.minimumSize(); + if (size == 2 || size == 4) { // Base UUID derived + if (profileUuid.isNull()) + profileUuid = tempUuid; + } else if (firstCustomUuid.isNull()) { + firstCustomUuid = tempUuid; + } + } + } + } + + if (!firstCustomUuid.isNull()) + profileUuid = firstCustomUuid; + + QString uuidString = profileUuid.toString(QUuid::WithoutBraces); + + qCDebug(QT_BT_BLUEZ) << "Registering profile under" << profilePath << uuidString; + + QDBusPendingReply<> reply = + service->RegisterProfile(QDBusObjectPath(profilePath), uuidString, mapping); + reply.waitForFinished(); + if (reply.isError()) { + qCWarning(QT_BT_BLUEZ) << "Cannot register profile" << reply.error().message(); + return false; + } + + registered = true; + return true; +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothserviceinfo_macos.mm b/src/bluetooth/qbluetoothserviceinfo_macos.mm new file mode 100644 index 0000000..e038a72 --- /dev/null +++ b/src/bluetooth/qbluetoothserviceinfo_macos.mm @@ -0,0 +1,176 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothserviceinfo_p.h" +#include "darwin/btservicerecord_p.h" +#include "qbluetoothserviceinfo.h" +#include "qbluetoothdeviceinfo.h" +#include "qbluetoothserver_p.h" +#include "darwin/btutility_p.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include + +QT_BEGIN_NAMESPACE + +namespace { + +using DarwinBluetooth::RetainPolicy; +using ServiceInfo = QBluetoothServiceInfo; + +// Alas, since there is no d_ptr<->q_ptr link (which is not that bad in itself), +// I need these getters duplicated here: +ServiceInfo::Protocol socket_protocol(const QBluetoothServiceInfoPrivate &privateInfo) +{ + ServiceInfo::Sequence parameters = privateInfo.protocolDescriptor(QBluetoothUuid::ProtocolUuid::Rfcomm); + if (!parameters.isEmpty()) + return ServiceInfo::RfcommProtocol; + + parameters = privateInfo.protocolDescriptor(QBluetoothUuid::ProtocolUuid::L2cap); + if (!parameters.isEmpty()) + return ServiceInfo::L2capProtocol; + + return ServiceInfo::UnknownProtocol; +} + +int channel_or_psm(const QBluetoothServiceInfoPrivate &privateInfo, QBluetoothUuid::ProtocolUuid uuid) +{ + const auto parameters = privateInfo.protocolDescriptor(uuid); + if (parameters.isEmpty()) + return -1; + else if (parameters.size() == 1) + return 0; + + return parameters.at(1).toInt(); +} + +} // unnamed namespace + +QBluetoothServiceInfoPrivate::QBluetoothServiceInfoPrivate() +{ +} + +QBluetoothServiceInfoPrivate::~QBluetoothServiceInfoPrivate() +{ +} + +bool QBluetoothServiceInfoPrivate::registerService(const QBluetoothAddress &localAddress) +{ + Q_UNUSED(localAddress); + return false; +} + +bool QBluetoothServiceInfoPrivate::registerService(const QBluetoothServiceInfo &info) +{ + using namespace DarwinBluetooth; + + if (isRegistered()) + return false; + + using namespace DarwinBluetooth; + + ObjCStrongReference serviceDict(iobluetooth_service_dictionary(info)); + if (!serviceDict) { + qCWarning(QT_BT_DARWIN) << "failed to create a service dictionary"; + return false; + } + + Q_ASSERT(!registered); + Q_ASSERT_X(!serviceRecord, Q_FUNC_INFO, "not registered, but serviceRecord is not nil"); + + SDPRecord newRecord; + newRecord.reset([IOBluetoothSDPServiceRecord + publishedServiceRecordWithDictionary:serviceDict], RetainPolicy::doInitialRetain); + if (!newRecord) { + qCWarning(QT_BT_DARWIN) << "failed to register a service record"; + return false; + } + + BluetoothSDPServiceRecordHandle newRecordHandle = 0; + auto *ioSDPRecord = newRecord.getAs(); + if ([ioSDPRecord getServiceRecordHandle:&newRecordHandle] != kIOReturnSuccess) { + qCWarning(QT_BT_DARWIN) << "failed to register a service record"; + [ioSDPRecord removeServiceRecord]; + return false; + } + + const ServiceInfo::Protocol type = info.socketProtocol(); + quint16 realPort = 0; + QBluetoothServerPrivate *server = nullptr; + bool configured = false; + + if (type == QBluetoothServiceInfo::L2capProtocol) { + BluetoothL2CAPPSM psm = 0; + server = QBluetoothServerPrivate::registeredServer(info.protocolServiceMultiplexer(), type); + if ([ioSDPRecord getL2CAPPSM:&psm] == kIOReturnSuccess) { + configured = true; + realPort = psm; + } + } else if (type == QBluetoothServiceInfo::RfcommProtocol) { + BluetoothRFCOMMChannelID channelID = 0; + server = QBluetoothServerPrivate::registeredServer(info.serverChannel(), type); + if ([ioSDPRecord getRFCOMMChannelID:&channelID] == kIOReturnSuccess) { + configured = true; + realPort = channelID; + } + } + + if (!configured) { + [ioSDPRecord removeServiceRecord]; + qCWarning(QT_BT_DARWIN) << "failed to register a service record"; + return false; + } + + registered = true; + serviceRecord.swap(newRecord); + serviceRecordHandle = newRecordHandle; + + if (server) + server->startListener(realPort); + + return true; +} + +bool QBluetoothServiceInfoPrivate::isRegistered() const +{ + return registered; +} + +bool QBluetoothServiceInfoPrivate::unregisterService() +{ + if (!registered) + return false; + + Q_ASSERT_X(serviceRecord, Q_FUNC_INFO, "service registered, but serviceRecord is nil"); + + auto *nativeRecord = serviceRecord.getAs(); + [nativeRecord removeServiceRecord]; + serviceRecord.reset(); + + const ServiceInfo::Protocol type = socket_protocol(*this); + QBluetoothServerPrivate *server = nullptr; + + const QMutexLocker lock(&QBluetoothServerPrivate::channelMapMutex()); + if (type == ServiceInfo::RfcommProtocol) + server = QBluetoothServerPrivate::registeredServer(channel_or_psm(*this, QBluetoothUuid::ProtocolUuid::Rfcomm), type); + else if (type == ServiceInfo::L2capProtocol) + server = QBluetoothServerPrivate::registeredServer(channel_or_psm(*this, QBluetoothUuid::ProtocolUuid::L2cap), type); + + if (server) + server->stopListener(); + + registered = false; + serviceRecordHandle = 0; + + return true; +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothserviceinfo_p.cpp b/src/bluetooth/qbluetoothserviceinfo_p.cpp new file mode 100644 index 0000000..cefdcb9 --- /dev/null +++ b/src/bluetooth/qbluetoothserviceinfo_p.cpp @@ -0,0 +1,41 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothserviceinfo.h" +#include "qbluetoothserviceinfo_p.h" +#ifndef QT_IOS_BLUETOOTH +#include "dummy/dummy_helper_p.h" +#endif + +QT_BEGIN_NAMESPACE + +QBluetoothServiceInfoPrivate::QBluetoothServiceInfoPrivate() +{ +#ifndef QT_IOS_BLUETOOTH + printDummyWarning(); +#endif +} + +QBluetoothServiceInfoPrivate::~QBluetoothServiceInfoPrivate() +{ +} + +bool QBluetoothServiceInfoPrivate::isRegistered() const +{ + return false; +} + +bool QBluetoothServiceInfoPrivate::registerService(const QBluetoothAddress &localAdapter) +{ + Q_UNUSED(localAdapter); + return false; +} + +bool QBluetoothServiceInfoPrivate::unregisterService() +{ + return false; +} + +QT_END_NAMESPACE + +#include "moc_qbluetoothserviceinfo_p.cpp" diff --git a/src/bluetooth/qbluetoothserviceinfo_p.h b/src/bluetooth/qbluetoothserviceinfo_p.h new file mode 100644 index 0000000..8f4a029 --- /dev/null +++ b/src/bluetooth/qbluetoothserviceinfo_p.h @@ -0,0 +1,103 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QBLUETOOTHSERVICEINFO_P_H +#define QBLUETOOTHSERVICEINFO_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 "qbluetoothuuid.h" +#include "qbluetoothaddress.h" +#include "qbluetoothdeviceinfo.h" +#include "qbluetoothserviceinfo.h" + +#include +#include + +#ifdef Q_OS_MACOS +#include "darwin/btraii_p.h" +#endif + +class OrgBluezServiceInterface; +class OrgBluezProfileManager1Interface; + +#ifdef QT_WINRT_BLUETOOTH +#include + +namespace ABI { + namespace Windows { + namespace Devices { + namespace Bluetooth { + namespace Rfcomm { + struct IRfcommServiceProvider; + } + } + } + } +} +#endif + +QT_BEGIN_NAMESPACE + +class QBluetoothServiceInfo; + + +class QBluetoothServiceInfoPrivate + : public QObject +{ + Q_OBJECT +public: + QBluetoothServiceInfoPrivate(); + ~QBluetoothServiceInfoPrivate(); + + bool registerService(const QBluetoothAddress &localAdapter = QBluetoothAddress()); + + bool isRegistered() const; + + bool unregisterService(); + + QBluetoothDeviceInfo deviceInfo; + QMap attributes; + + QBluetoothServiceInfo::Sequence protocolDescriptor(QBluetoothUuid::ProtocolUuid protocol) const; + int serverChannel() const; +private: +#if QT_CONFIG(bluez) + OrgBluezProfileManager1Interface *service = nullptr; + quint32 serviceRecord; + QBluetoothAddress currentLocalAdapter; + QString profilePath; +#endif + +#ifdef QT_WINRT_BLUETOOTH + Microsoft::WRL::ComPtr serviceProvider; + + bool writeSdpAttributes(); +#endif + +#if QT_OSX_BLUETOOTH +public: + bool registerService(const QBluetoothServiceInfo &info); + +private: + + using SDPRecord = DarwinBluetooth::ScopedPointer; + SDPRecord serviceRecord; + quint32 serviceRecordHandle = 0; +#endif // QT_OSX_BLUETOOTH + + mutable bool registered = false; +}; + +QT_END_NAMESPACE + +#endif // QBLUETOOTHSERVICEINFO_P_H diff --git a/src/bluetooth/qbluetoothserviceinfo_winrt.cpp b/src/bluetooth/qbluetoothserviceinfo_winrt.cpp new file mode 100644 index 0000000..8f6f111 --- /dev/null +++ b/src/bluetooth/qbluetoothserviceinfo_winrt.cpp @@ -0,0 +1,554 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothserviceinfo.h" +#include "qbluetoothserviceinfo_p.h" +#include "qbluetoothserver_p.h" +#include "qbluetoothutils_winrt_p.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Devices::Bluetooth; +using namespace ABI::Windows::Devices::Bluetooth::Rfcomm; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::Networking::Sockets; +using namespace ABI::Windows::Storage::Streams; + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINDOWS) + +#define TYPE_VOID 0 +#define TYPE_UINT8 8 +#define TYPE_UINT16 9 +#define TYPE_UINT32 10 +#define TYPE_UINT64 11 +//#define TYPE_UINT128 12 +#define TYPE_INT8 16 +#define TYPE_INT16 17 +#define TYPE_INT32 18 +#define TYPE_INT64 19 +//#define TYPE_INT128 20 +#define TYPE_UUID16 25 +#define TYPE_UUID32 26 +#define TYPE_UUID128 28 +#define TYPE_STRING_BASE 32 +#define TYPE_BOOLEAN 40 +#define TYPE_SEQUENCE_BASE 48 +#define TYPE_ALTERNATIVE_BASE 56 +#define TYPE_URL_BASE 64 + +extern QHash __fakeServerPorts; + +inline bool typeIsOfBase(unsigned char type, unsigned char baseType) +{ + return ((type & baseType) == baseType); +} + +qint64 getLengthForBaseType(unsigned char type, ComPtr &reader) +{ + const bool isOfBase = (typeIsOfBase(type, TYPE_STRING_BASE) + || typeIsOfBase(type, TYPE_SEQUENCE_BASE) + || typeIsOfBase(type, TYPE_ALTERNATIVE_BASE) + || typeIsOfBase(type, TYPE_URL_BASE)); + if (!isOfBase) + return -1; + + HRESULT hr; + // For these types, the first 5 bits are the base type followed by 3 bits + // describing the size index. This index decides how many additional bits + // have to be read to get the type's length. + const unsigned char sizeIndex = (type & 0x7); + switch (sizeIndex) { + case 5: { + quint8 length; + hr = reader->ReadByte(&length); + RETURN_IF_FAILED("Could not read length from buffer", return -1); + return length; + } case 6: { + quint16 length; + hr = reader->ReadUInt16(&length); + RETURN_IF_FAILED("Could not read length from buffer", return -1); + return length; + } case 7: { + quint32 length; + hr = reader->ReadUInt32(&length); + RETURN_IF_FAILED("Could not read length from buffer", return -1); + return length; + } + } + return -1; +} + +bool writeStringHelper(const QString &string, ComPtr writer) +{ + HRESULT hr; + const qsizetype stringLength = string.size(); + unsigned char type = TYPE_STRING_BASE; + if (stringLength < 0) { + qCWarning(QT_BT_WINDOWS) << "Can not write invalid string value to buffer"; + return false; + } if (stringLength <= 0xff) { + type += 5; + hr = writer->WriteByte(type); + RETURN_FALSE_IF_FAILED("Could not write string type data."); + hr = writer->WriteByte(stringLength); + RETURN_FALSE_IF_FAILED("Could not write string length."); + } else if (stringLength <= 0xffff) { + type += 6; + hr = writer->WriteByte(type); + RETURN_FALSE_IF_FAILED("Could not write string type data."); + hr = writer->WriteUInt16(stringLength); + RETURN_FALSE_IF_FAILED("Could not write string length."); + } else { + type += 7; + hr = writer->WriteByte(type); + RETURN_FALSE_IF_FAILED("Could not write string type data."); + hr = writer->WriteUInt32(stringLength); + RETURN_FALSE_IF_FAILED("Could not write string length."); + } + HStringReference stringRef(reinterpret_cast(string.utf16())); + quint32 bytesWritten; + hr = writer->WriteString(stringRef.Get(), &bytesWritten); + RETURN_FALSE_IF_FAILED("Could not write string to buffer."); + if (bytesWritten != size_t(string.size())) { + qCWarning(QT_BT_WINDOWS) << "Did not write full value to buffer"; + return false; + } + return true; +} + +bool repairProfileDescriptorListIfNeeded(ComPtr &buffer) +{ + ComPtr dataReaderStatics; + HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_DataReader).Get(), + &dataReaderStatics); + Q_ASSERT_SUCCEEDED(hr); + + ComPtr reader; + hr = dataReaderStatics->FromBuffer(buffer.Get(), reader.GetAddressOf()); + Q_ASSERT_SUCCEEDED(hr); + + BYTE type; + hr = reader->ReadByte(&type); + Q_ASSERT_SUCCEEDED(hr); + if (!typeIsOfBase(type, TYPE_SEQUENCE_BASE)) { + qCWarning(QT_BT_WINDOWS) << Q_FUNC_INFO << "Malformed profile descriptor list read"; + return false; + } + + qint64 length = getLengthForBaseType(type, reader); + hr = reader->ReadByte(&type); + Q_ASSERT_SUCCEEDED(hr); + // We have to "repair" the structure if the outer sequence contains a uuid directly + if (type == TYPE_UUID16 && length == 4) { + qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Repairing profile descriptor list"; + quint16 uuid; + hr = reader->ReadUInt16(&uuid); + Q_ASSERT_SUCCEEDED(hr); + + ComPtr writer; + hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_DataWriter).Get(), + &writer); + Q_ASSERT_SUCCEEDED(hr); + + hr = writer->WriteByte(TYPE_SEQUENCE_BASE + 5); + Q_ASSERT_SUCCEEDED(hr); + // 8 == length of nested sequence (outer sequence -> inner sequence -> uuid and version) + hr = writer->WriteByte(8); + Q_ASSERT_SUCCEEDED(hr); + hr = writer->WriteByte(TYPE_SEQUENCE_BASE + 5); + Q_ASSERT_SUCCEEDED(hr); + hr = writer->WriteByte(7); + Q_ASSERT_SUCCEEDED(hr); + hr = writer->WriteByte(TYPE_UUID16); + Q_ASSERT_SUCCEEDED(hr); + hr = writer->WriteUInt16(uuid); + Q_ASSERT_SUCCEEDED(hr); + // Write default version to make WinRT happy + hr = writer->WriteByte(TYPE_UINT16); + Q_ASSERT_SUCCEEDED(hr); + hr = writer->WriteUInt16(0x100); + Q_ASSERT_SUCCEEDED(hr); + + hr = writer->DetachBuffer(&buffer); + Q_ASSERT_SUCCEEDED(hr); + } + + return true; +} + +static ComPtr bufferFromAttribute(const QVariant &attribute) +{ + ComPtr writer; + HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_DataWriter).Get(), + &writer); + Q_ASSERT_SUCCEEDED(hr); + + switch (attribute.typeId()) { + case QMetaType::Void: + qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registering attribute of type QMetaType::Void:"; + hr = writer->WriteByte(TYPE_VOID); + Q_ASSERT_SUCCEEDED(hr); + break; + case QMetaType::UChar: + qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registering attribute of type QMetaType::UChar:" << attribute.value(); + hr = writer->WriteByte(TYPE_UINT8); + Q_ASSERT_SUCCEEDED(hr); + hr = writer->WriteByte(attribute.value()); + Q_ASSERT_SUCCEEDED(hr); + break; + case QMetaType::UShort: + qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registering attribute of type QMetaType::UShort:" << attribute.value(); + hr = writer->WriteByte(TYPE_UINT16); + Q_ASSERT_SUCCEEDED(hr); + hr = writer->WriteUInt16(attribute.value()); + Q_ASSERT_SUCCEEDED(hr); + break; + case QMetaType::UInt: + qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registering attribute of type QMetaType::UInt:" << attribute.value(); + hr = writer->WriteByte(TYPE_UINT32); + Q_ASSERT_SUCCEEDED(hr); + hr = writer->WriteUInt32(attribute.value()); + Q_ASSERT_SUCCEEDED(hr); + break; + case QMetaType::ULongLong: + qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registering attribute of type QMetaType::ULongLong:" << attribute.value(); + hr = writer->WriteByte(TYPE_UINT64); + Q_ASSERT_SUCCEEDED(hr); + hr = writer->WriteUInt64(attribute.value()); + Q_ASSERT_SUCCEEDED(hr); + break; + case QMetaType::Char: + qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registering attribute of type QMetaType::Char:" << attribute.value(); + hr = writer->WriteByte(TYPE_INT8); + Q_ASSERT_SUCCEEDED(hr); + hr = writer->WriteByte(attribute.value()); + Q_ASSERT_SUCCEEDED(hr); + break; + case QMetaType::Short: + qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registering attribute of type QMetaType::Short:" << attribute.value(); + hr = writer->WriteByte(TYPE_INT16); + Q_ASSERT_SUCCEEDED(hr); + hr = writer->WriteInt16(attribute.value()); + Q_ASSERT_SUCCEEDED(hr); + break; + case QMetaType::Int: + qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registering attribute of type QMetaType::Int:" << attribute.value(); + hr = writer->WriteByte(TYPE_INT32); + Q_ASSERT_SUCCEEDED(hr); + hr = writer->WriteInt32(attribute.value()); + Q_ASSERT_SUCCEEDED(hr); + break; + case QMetaType::LongLong: + qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registering attribute of type QMetaType::LongLong:" << attribute.value(); + hr = writer->WriteByte(TYPE_INT64); + Q_ASSERT_SUCCEEDED(hr); + hr = writer->WriteInt64(attribute.value()); + Q_ASSERT_SUCCEEDED(hr); + break; + case QMetaType::QByteArray: { + qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registering attribute of type QMetaType::QByteArray:" << attribute.value(); + const QString stringValue = QString::fromLatin1(attribute.value().toHex()); + const bool writeSuccess = writeStringHelper(stringValue, writer); + if (!writeSuccess) + return nullptr; + break; + } + case QMetaType::QString: { + qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registering attribute of type QMetaType::QString:" << attribute.value(); + const QString stringValue = attribute.value(); + const bool writeSucces = writeStringHelper(stringValue, writer); + if (!writeSucces) + return nullptr; + break; + } + case QMetaType::Bool: + qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registering attribute of type QMetaType::Bool:" << attribute.value(); + hr = writer->WriteByte(TYPE_BOOLEAN); + Q_ASSERT_SUCCEEDED(hr); + hr = writer->WriteByte(attribute.value()); + Q_ASSERT_SUCCEEDED(hr); + break; + case QMetaType::QUrl: + qCWarning(QT_BT_WINDOWS) << "Don't know how to register QMetaType::QUrl"; + return nullptr; + break; + default: + if (attribute.userType() == qMetaTypeId()) { + QBluetoothUuid uuid = attribute.value(); + switch (uuid.minimumSize()) { + case 0: + qCWarning(QT_BT_WINDOWS) << "Don't know how to register Uuid of length 0"; + return nullptr; + case 2: + qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registering Uuid attribute with length 2:" << uuid; + hr = writer->WriteByte(TYPE_UUID16); + Q_ASSERT_SUCCEEDED(hr); + hr = writer->WriteUInt16(uuid.toUInt16()); + Q_ASSERT_SUCCEEDED(hr); + break; + case 4: + qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registering Uuid attribute with length 4:" << uuid; + hr = writer->WriteByte(TYPE_UUID32); + Q_ASSERT_SUCCEEDED(hr); + hr = writer->WriteUInt32(uuid.toUInt32()); + Q_ASSERT_SUCCEEDED(hr); + break; + case 16: + default: + qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registering Uuid attribute:" << uuid; + hr = writer->WriteByte(TYPE_UUID128); + Q_ASSERT_SUCCEEDED(hr); + hr = writer->WriteGuid(uuid); + Q_ASSERT_SUCCEEDED(hr); + break; + } + } else if (attribute.userType() == qMetaTypeId()) { + qCDebug(QT_BT_WINDOWS) << "Registering sequence attribute"; + const QBluetoothServiceInfo::Sequence *sequence = + static_cast(attribute.data()); + ComPtr tmpWriter; + HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_DataWriter).Get(), + &tmpWriter); + Q_ASSERT_SUCCEEDED(hr); + for (const QVariant &v : *sequence) { + ComPtr tmpBuffer = bufferFromAttribute(v); + if (!tmpBuffer) { + qCWarning(QT_BT_WINDOWS) << "Could not create buffer from attribute in sequence"; + return nullptr; + } + quint32 l; + hr = tmpBuffer->get_Length(&l); + Q_ASSERT_SUCCEEDED(hr); + hr = tmpWriter->WriteBuffer(tmpBuffer.Get()); + Q_ASSERT_SUCCEEDED(hr); + } + ComPtr tmpBuffer; + hr = tmpWriter->DetachBuffer(&tmpBuffer); + Q_ASSERT_SUCCEEDED(hr); + // write sequence length + quint32 length; + tmpBuffer->get_Length(&length); + Q_ASSERT_SUCCEEDED(hr); + unsigned char type = TYPE_SEQUENCE_BASE; + length += 1; + if (length <= 0xff) { + type += 5; + hr = writer->WriteByte(type); + Q_ASSERT_SUCCEEDED(hr); + hr = writer->WriteByte(length); + Q_ASSERT_SUCCEEDED(hr); + } else if (length <= 0xffff) { + type += 6; + hr = writer->WriteByte(type); + Q_ASSERT_SUCCEEDED(hr); + hr = writer->WriteUInt16(length); + Q_ASSERT_SUCCEEDED(hr); + } else { + type += 7; + hr = writer->WriteByte(type); + Q_ASSERT_SUCCEEDED(hr); + hr = writer->WriteUInt32(length); + Q_ASSERT_SUCCEEDED(hr); + } + // write sequence data + hr = writer->WriteBuffer(tmpBuffer.Get()); + Q_ASSERT_SUCCEEDED(hr); + qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registered sequence attribute with length" << length; + } else if (attribute.userType() == qMetaTypeId()) { + qCWarning(QT_BT_WINDOWS) << "Don't know how to register user type Alternative"; + return nullptr; + } else { + qCWarning(QT_BT_WINDOWS) << "Unknown variant type" << attribute.userType(); + return nullptr; + } + } + ComPtr buffer; + hr = writer->DetachBuffer(&buffer); + Q_ASSERT_SUCCEEDED(hr); + return buffer; +} + +QBluetoothServiceInfoPrivate::QBluetoothServiceInfoPrivate() + : registered(false) +{ + mainThreadCoInit(this); +} + +QBluetoothServiceInfoPrivate::~QBluetoothServiceInfoPrivate() +{ + mainThreadCoUninit(this); +} + +bool QBluetoothServiceInfoPrivate::isRegistered() const +{ + return registered; +} + +bool QBluetoothServiceInfoPrivate::registerService(const QBluetoothAddress &localAdapter) +{ + Q_UNUSED(localAdapter); + if (registered) + return false; + + if (protocolDescriptor(QBluetoothUuid::ProtocolUuid::Rfcomm).isEmpty()) { + qCWarning(QT_BT_WINDOWS) << Q_FUNC_INFO << "Only RFCOMM services can be registered on WinRT"; + return false; + } + + QBluetoothServerPrivate *sPriv = __fakeServerPorts.key(serverChannel()); + if (!sPriv) + return false; + + HRESULT hr; + QBluetoothUuid uuid = attributes.value(QBluetoothServiceInfo::ServiceId).value(); + ComPtr serviceIdStatics; + hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Devices_Bluetooth_Rfcomm_RfcommServiceId).Get(), + IID_PPV_ARGS(&serviceIdStatics)); + Q_ASSERT_SUCCEEDED(hr); + ComPtr serviceId; + hr = serviceIdStatics->FromUuid(uuid, &serviceId); + Q_ASSERT_SUCCEEDED(hr); + ComPtr providerStatics; + hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Devices_Bluetooth_Rfcomm_RfcommServiceProvider).Get(), + IID_PPV_ARGS(&providerStatics)); + Q_ASSERT_SUCCEEDED(hr); + ComPtr> op; + hr = providerStatics->CreateAsync(serviceId.Get(), &op); + Q_ASSERT_SUCCEEDED(hr); + hr = QWinRTFunctions::await(op, serviceProvider.GetAddressOf()); + if (hr == HRESULT_FROM_WIN32(ERROR_DEVICE_NOT_AVAILABLE)) { + qCWarning(QT_BT_WINDOWS) << Q_FUNC_INFO << "No bluetooth adapter available."; + return false; + } else { + Q_ASSERT_SUCCEEDED(hr); + } + + ComPtr listener = sPriv->listener(); + if (!listener) { + qCWarning(QT_BT_WINDOWS) << Q_FUNC_INFO << "Could not obtain listener from server."; + return false; + } + + + HString serviceIdHString; + serviceId->AsString(serviceIdHString.GetAddressOf()); + Q_ASSERT_SUCCEEDED(hr); + const QString serviceIdString = QString::fromWCharArray(WindowsGetStringRawBuffer(serviceIdHString.Get(), nullptr)); + + //tell the server what service name our listener should have + //and start the real listener + bool result = sPriv->initiateActiveListening(serviceIdString); + if (!result) { + return false; + } + + result = writeSdpAttributes(); + if (!result) { + qCWarning(QT_BT_WINDOWS) << "Could not write SDP attributes."; + return false; + } + qCDebug(QT_BT_WINDOWS) << "SDP attributes written."; + + ComPtr serviceProvider2; + hr = serviceProvider.As(&serviceProvider2); + Q_ASSERT_SUCCEEDED(hr); + hr = serviceProvider2->StartAdvertisingWithRadioDiscoverability(listener.Get(), true); + if (FAILED(hr)) { + qCWarning(QT_BT_WINDOWS) << Q_FUNC_INFO << "Could not start advertising. Check your SDP data."; + return false; + } + + registered = true; + return true; +} + +bool QBluetoothServiceInfoPrivate::unregisterService() +{ + if (!registered) + return false; + + QBluetoothServerPrivate *sPriv = __fakeServerPorts.key(serverChannel()); + if (!sPriv) { + //QBluetoothServer::close() was called without prior call to unregisterService(). + //Now it is unregistered anyway. + registered = false; + return true; + } + + bool result = sPriv->deactivateActiveListening(); + if (!result) + return false; + + HRESULT hr; + hr = serviceProvider->StopAdvertising(); + Q_ASSERT_SUCCEEDED(hr); + + registered = false; + return true; +} + +bool QBluetoothServiceInfoPrivate::writeSdpAttributes() +{ + if (!serviceProvider) + return false; + + ComPtr writer; + HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_DataWriter).Get(), + &writer); + Q_ASSERT_SUCCEEDED(hr); + ComPtr> rawAttributes; + hr = serviceProvider->get_SdpRawAttributes(&rawAttributes); + Q_ASSERT_SUCCEEDED(hr); + const QList keys = attributes.keys(); + for (quint16 key : keys) { + // The SDP Class Id List and RFCOMM and L2CAP protocol descriptors are automatically + // generated by the RfcommServiceProvider. Do not specify it in the SDP raw attribute map. + if (key == QBluetoothServiceInfo::ServiceClassIds + || key == QBluetoothServiceInfo::ProtocolDescriptorList) + continue; + const QVariant attribute = attributes.value(key); + HRESULT hr; + ComPtr buffer = bufferFromAttribute(attribute); + if (!buffer) { + qCWarning(QT_BT_WINDOWS) << "Could not create buffer from attribute with id:" << key; + return false; + } + + // Other backends support a wrong structure in profile descriptor list. In order to make + // WinRT accept the list without breaking existing apps we have to repair this structure. + if (key == QBluetoothServiceInfo::BluetoothProfileDescriptorList) { + if (!repairProfileDescriptorListIfNeeded(buffer)) { + qCWarning(QT_BT_WINDOWS) << Q_FUNC_INFO << "Error while checking/repairing structure of profile descriptor list"; + return false; + } + } + + hr = writer->WriteBuffer(buffer.Get()); + Q_ASSERT_SUCCEEDED(hr); + + hr = writer->DetachBuffer(&buffer); + Q_ASSERT_SUCCEEDED(hr); + + boolean replaced; + hr = rawAttributes->Insert(key, buffer.Get(), &replaced); + Q_ASSERT_SUCCEEDED(hr); + Q_ASSERT(!replaced); + qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registered attribute" << QString::number(key, 16).rightJustified(4, QLatin1Char('0')) << "with value" << attribute; + } + return true; +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothsocket.cpp b/src/bluetooth/qbluetoothsocket.cpp new file mode 100644 index 0000000..e05d8a7 --- /dev/null +++ b/src/bluetooth/qbluetoothsocket.cpp @@ -0,0 +1,789 @@ +// Copyright (C) 2018 The Qt Company Ltd. +// Copyright (C) 2016 BlackBerry Limited. All rights reserved. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothsocket.h" +#if QT_CONFIG(bluez) +#include "qbluetoothsocket_bluez_p.h" +#include "qbluetoothsocket_bluezdbus_p.h" +#include "bluez/bluez5_helper_p.h" +#elif defined(QT_ANDROID_BLUETOOTH) +#include "qbluetoothsocket_android_p.h" +#elif defined(QT_WINRT_BLUETOOTH) +#include "qbluetoothsocket_winrt_p.h" +#elif defined(QT_OSX_BLUETOOTH) +#include "qbluetoothsocket_macos_p.h" +#else +#include "qbluetoothsocket_dummy_p.h" +#endif + +#include "qbluetoothservicediscoveryagent.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT) + +/*! + \class QBluetoothSocket + \inmodule QtBluetooth + \brief The QBluetoothSocket class enables connection to a Bluetooth device + running a bluetooth server. + + \since 5.2 + + QBluetoothSocket supports two socket types, \l {QBluetoothServiceInfo::L2capProtocol}{L2CAP} and + \l {QBluetoothServiceInfo::RfcommProtocol}{RFCOMM}. + + \l {QBluetoothServiceInfo::L2capProtocol}{L2CAP} is a low level datagram-oriented Bluetooth socket. + Android does not support \l {QBluetoothServiceInfo::L2capProtocol}{L2CAP} for socket + connections. + + \l {QBluetoothServiceInfo::RfcommProtocol}{RFCOMM} is a reliable, stream-oriented socket. RFCOMM + sockets emulate an RS-232 serial port. + + To create a connection to a Bluetooth service, create a socket of the appropriate type and call + connectToService() passing the Bluetooth address and port number. QBluetoothSocket will emit + the connected() signal when the connection is established. + + If the \l {QBluetoothServiceInfo::Protocol}{Protocol} is not supported on a platform, calling + \l connectToService() will emit a \l {QBluetoothSocket::SocketError::UnsupportedProtocolError}{UnsupportedProtocolError} error. + + \note QBluetoothSocket does not support synchronous read and write operations. Functions such + as \l waitForReadyRead() and \l waitForBytesWritten() are not implemented. I/O operations should be + performed using \l readyRead(), \l read() and \l write(). + + On iOS, this class cannot be used because the platform does not expose + an API which may permit access to QBluetoothSocket related features. + + \note On macOS Monterey (12) the socket data flow is paused when a + modal dialogue is executing, or an event tracking mode is entered (for + example by long-pressing a Window close button). This may change in the + future releases of macOS. +*/ + +/*! + \enum QBluetoothSocket::SocketState + + This enum describes the state of the Bluetooth socket. + + \value UnconnectedState Socket is not connected. + \value ServiceLookupState Socket is querying connection parameters. + \value ConnectingState Socket is attempting to connect to a device. + \value ConnectedState Socket is connected to a device. + \value BoundState Socket is bound to a local address and port. + \value ClosingState Socket is connected and will be closed once all pending data is + written to the socket. + \value ListeningState Socket is listening for incoming connections. +*/ + +/*! + \enum QBluetoothSocket::SocketError + + This enum describes Bluetooth socket error types. + + \value UnknownSocketError An unknown error has occurred. + \value NoSocketError No error. Used for testing. + \value HostNotFoundError Could not find the remote host. + \value ServiceNotFoundError Could not find the service UUID on remote host. + \value NetworkError Attempt to read or write from socket returned an error + \value UnsupportedProtocolError The \l {QBluetoothServiceInfo::Protocol}{Protocol} is not + supported on this platform. + \value OperationError An operation was attempted while the socket was in a state + that did not permit it. + \value [since 5.10] RemoteHostClosedError The remote host closed the connection. + \value [since 6.4] MissingPermissionsError The operating system requests + permissions which were not + granted by the user. +*/ + +/*! + \fn void QBluetoothSocket::connected() + + This signal is emitted when a connection is established. + + \sa QBluetoothSocket::SocketState::ConnectedState, stateChanged() +*/ + +/*! + \fn void QBluetoothSocket::disconnected() + + This signal is emitted when the socket is disconnected. + + \sa QBluetoothSocket::SocketState::UnconnectedState, stateChanged() +*/ + +/*! + \fn void QBluetoothSocket::errorOccurred(QBluetoothSocket::SocketError error) + + This signal is emitted when an \a error occurs. + + \sa error() + \since 6.2 +*/ + +/*! + \fn QBluetoothSocket::stateChanged(QBluetoothSocket::SocketState state) + + This signal is emitted when the socket state changes to \a state. + + \sa connected(), disconnected(), state(), QBluetoothSocket::SocketState +*/ + +/*! + \fn void QBluetoothSocket::abort() + + Aborts the current connection and resets the socket. Unlike disconnectFromService(), this + function immediately closes the socket, discarding any pending data in the write buffer. + + \note On Android, aborting the socket requires asynchronous interaction with Android threads. + Therefore the associated \l disconnected() and \l stateChanged() signals are delayed + until the threads have finished the closure. + + \sa disconnectFromService(), close() +*/ + +/*! + \fn void QBluetoothSocket::close() + + Disconnects the socket's connection with the device. + + \note On Android, closing the socket requires asynchronous interaction with Android threads. + Therefore the associated \l disconnected() and \l stateChanged() signals are delayed + until the threads have finished the closure. + +*/ + +/*! + \fn void QBluetoothSocket::disconnectFromService() + + Attempts to close the socket. If there is pending data waiting to be written QBluetoothSocket + will enter ClosingState and wait until all data has been written. Eventually, it will enter + UnconnectedState and emit the disconnected() signal. + + \sa connectToService() +*/ + +/*! + \fn QString QBluetoothSocket::localName() const + + Returns the name of the local device. + + Although some platforms may differ the socket must generally be connected to guarantee + the return of a valid name. In particular, this is true when dealing with platforms + that support multiple local Bluetooth adapters. +*/ + +/*! + \fn QBluetoothAddress QBluetoothSocket::localAddress() const + + Returns the address of the local device. + + Although some platforms may differ the socket must generally be connected to guarantee + the return of a valid address. In particular, this is true when dealing with platforms + that support multiple local Bluetooth adapters. +*/ + +/*! + \fn quint16 QBluetoothSocket::localPort() const + + Returns the port number of the local socket if available, otherwise returns 0. + Although some platforms may differ the socket must generally be connected to guarantee + the return of a valid port number. + + On Android and \macos, this feature is not supported and returns 0. +*/ + +/*! + \fn QString QBluetoothSocket::peerName() const + + Returns the name of the peer device. +*/ + +/*! + \fn QBluetoothAddress QBluetoothSocket::peerAddress() const + + Returns the address of the peer device. +*/ + +/*! + \fn quint16 QBluetoothSocket::peerPort() const + + Return the port number of the peer socket if available, otherwise returns 0. + On Android, this feature is not supported. +*/ + +/*! + \fn qint64 QBluetoothSocket::readData(char *data, qint64 maxSize) + + \reimp +*/ + +/*! + \fn qint64 QBluetoothSocket::writeData(const char *data, qint64 maxSize) + + \reimp +*/ + +static QBluetoothSocketBasePrivate *createSocketPrivate() +{ +#if QT_CONFIG(bluez) + if (bluetoothdVersion() >= QVersionNumber(5, 46)) { + qCDebug(QT_BT) << "Using Bluetooth dbus socket implementation"; + return new QBluetoothSocketPrivateBluezDBus(); + } else { + qCDebug(QT_BT) << "Using Bluetooth raw socket implementation"; + return new QBluetoothSocketPrivateBluez(); + } +#elif defined(QT_ANDROID_BLUETOOTH) + return new QBluetoothSocketPrivateAndroid(); +#elif defined(QT_WINRT_BLUETOOTH) + return new QBluetoothSocketPrivateWinRT(); +#elif defined(QT_OSX_BLUETOOTH) + return new QBluetoothSocketPrivateDarwin(); +#else + return new QBluetoothSocketPrivateDummy(); +#endif +} + +/*! + Constructs a Bluetooth socket of \a socketType type, with \a parent. +*/ +QBluetoothSocket::QBluetoothSocket(QBluetoothServiceInfo::Protocol socketType, QObject *parent) +: QIODevice(parent) +{ + d_ptr = createSocketPrivate(); + d_ptr->q_ptr = this; + + Q_D(QBluetoothSocketBase); + d->ensureNativeSocket(socketType); + + setOpenMode(QIODevice::NotOpen); +} + +/*! + Constructs a Bluetooth socket with \a parent. +*/ +QBluetoothSocket::QBluetoothSocket(QObject *parent) + : QIODevice(parent) +{ + d_ptr = createSocketPrivate(); + d_ptr->q_ptr = this; + setOpenMode(QIODevice::NotOpen); +} + +#if QT_CONFIG(bluez) + +/*! + \internal +*/ +QBluetoothSocket::QBluetoothSocket(QBluetoothSocketBasePrivate *dPrivate, + QBluetoothServiceInfo::Protocol socketType, + QObject *parent) + : QIODevice(parent) +{ + d_ptr = dPrivate; + d_ptr->q_ptr = this; + + Q_D(QBluetoothSocketBase); + d->ensureNativeSocket(socketType); + + setOpenMode(QIODevice::NotOpen); +} + +#endif + +/*! + Destroys the Bluetooth socket. +*/ +QBluetoothSocket::~QBluetoothSocket() +{ + delete d_ptr; + d_ptr = nullptr; +} + +/*! + \reimp +*/ +bool QBluetoothSocket::isSequential() const +{ + return true; +} + +/*! + Returns the number of incoming bytes that are waiting to be read. + + \sa bytesToWrite(), read() +*/ +qint64 QBluetoothSocket::bytesAvailable() const +{ + Q_D(const QBluetoothSocketBase); + return QIODevice::bytesAvailable() + d->bytesAvailable(); +} + +/*! + Returns the number of bytes that are waiting to be written. The bytes are written when control + goes back to the event loop. +*/ +qint64 QBluetoothSocket::bytesToWrite() const +{ + Q_D(const QBluetoothSocketBase); + return d->bytesToWrite(); +} + +/*! + Attempts to connect to the service described by \a service. + + The socket is opened in the given \a openMode. The \l socketType() is ignored + if \a service specifies a differing \l QBluetoothServiceInfo::socketProtocol(). + + The socket first enters ConnectingState and attempts to connect to the device providing + \a service. If a connection is established, QBluetoothSocket enters ConnectedState and + emits connected(). + + At any point, the socket can emit errorOccurred() to signal that an error occurred. + + Note that most platforms require a pairing prior to connecting to the remote device. Otherwise + the connection process may fail. + + On Android, only RFCOMM connections are possible. This function ignores any socket protocol indicator + and assumes RFCOMM. + + \sa state(), disconnectFromService() +*/ +void QBluetoothSocket::connectToService(const QBluetoothServiceInfo &service, OpenMode openMode) +{ + Q_D(QBluetoothSocketBase); + d->connectToService(service, openMode); +} + +/*! + \fn void QBluetoothSocket::connectToService(const QBluetoothAddress &address, QBluetoothUuid::ServiceClassUuid uuid, OpenMode mode = ReadWrite) + + \internal + + Exists to avoid QTBUG-65831. +*/ + +/*! + Attempts to make a connection to the service identified by \a uuid on the device with address + \a address. + + The socket is opened in the given \a openMode. + + For BlueZ, the socket first enters the \l ServiceLookupState and queries the connection parameters for + \a uuid. If the service parameters are successfully retrieved the socket enters + ConnectingState, and attempts to connect to \a address. If a connection is established, + QBluetoothSocket enters \l ConnectedState and emits connected(). + + On Android, the service connection can directly be established + using the UUID of the remote service. Therefore the platform does not require + the \l ServiceLookupState and \l socketType() is always set to + \l QBluetoothServiceInfo::RfcommProtocol. + + At any point, the socket can emit errorOccurred() to signal that an error occurred. + + Note that most platforms require a pairing prior to connecting to the remote device. Otherwise + the connection process may fail. + + \sa state(), disconnectFromService() +*/ +void QBluetoothSocket::connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid, OpenMode openMode) +{ + Q_D(QBluetoothSocketBase); + d->connectToService(address, uuid, openMode); +} + +/*! + Attempts to make a connection with \a address on the given \a port. + + The socket is opened in the given \a openMode. + + The socket first enters ConnectingState, and attempts to connect to \a address. If a + connection is established, QBluetoothSocket enters ConnectedState and emits connected(). + + At any point, the socket can emit errorOccurred() to signal that an error occurred. + + On Android and BlueZ (version 5.46 or above), a connection to a service can not be established using a port. + Calling this function will emit a \l {QBluetoothSocket::SocketError::ServiceNotFoundError}{ServiceNotFoundError}. + + Note that most platforms require a pairing prior to connecting to the remote device. Otherwise + the connection process may fail. + + \sa state(), disconnectFromService() +*/ +void QBluetoothSocket::connectToService(const QBluetoothAddress &address, quint16 port, OpenMode openMode) +{ + Q_D(QBluetoothSocketBase); + d->connectToService(address, port, openMode); +} + +/*! + Returns the socket type. The socket automatically adjusts to the protocol + offered by the remote service. + + Android only support \l{QBluetoothServiceInfo::RfcommProtocol}{RFCOMM} + based sockets. +*/ +QBluetoothServiceInfo::Protocol QBluetoothSocket::socketType() const +{ + Q_D(const QBluetoothSocketBase); + return d->socketType; +} + +/*! + Returns the current state of the socket. +*/ +QBluetoothSocket::SocketState QBluetoothSocket::state() const +{ + Q_D(const QBluetoothSocketBase); + return d->state; +} + +/*! + Returns the last error. +*/ +QBluetoothSocket::SocketError QBluetoothSocket::error() const +{ + Q_D(const QBluetoothSocketBase); + return d->socketError; +} + +/*! + Returns a user displayable text string for the error. + */ +QString QBluetoothSocket::errorString() const +{ + Q_D(const QBluetoothSocketBase); + return d->errorString; +} + +/*! + Sets the preferred security parameter for the connection attempt to + \a flags. This value is incorporated when calling \l connectToService(). + Therefore it is required to reconnect to change this parameter for an + existing connection. + + On Bluez this property is set to QBluetooth::Security::Authorization by default. + + On \macos, this value is ignored as the platform does not permit access + to the security parameter of the socket. By default the platform prefers + secure/encrypted connections though and therefore this function always + returns \l QBluetooth::Security::Secure. + + Android only supports two levels of security (secure and non-secure). + If this flag is set to \l QBluetooth::Security::NoSecurity the socket + object will not employ any authentication or encryption. Any other + security flag combination will trigger a secure Bluetooth connection. + This flag is set to \l QBluetooth::Security::Secure by default. + + \note A secure connection requires a pairing between the two devices. On + some platforms, the pairing is automatically initiated during the establishment + of the connection. Other platforms require the application to manually trigger + the pairing before attempting to connect. + + \sa preferredSecurityFlags() + + \since 5.6 +*/ +void QBluetoothSocket::setPreferredSecurityFlags(QBluetooth::SecurityFlags flags) +{ +#ifdef QT_OSX_BLUETOOTH + return; // not supported on macOS. +#endif + Q_D(QBluetoothSocketBase); + if (d->secFlags != flags) + d->secFlags = flags; +} + +/*! + Returns the security parameters used for the initial connection + attempt. + + The security parameters may be renegotiated between the two parties + during or after the connection has been established. If such a change happens + it is not reflected in the value of this flag. + + On \macos, this flag is always set to \l QBluetooth::Security::Secure. + + \sa setPreferredSecurityFlags() + + \since 5.6 +*/ +QBluetooth::SecurityFlags QBluetoothSocket::preferredSecurityFlags() const +{ +#if QT_OSX_BLUETOOTH + // not supported on macOS - platform always uses encryption + return QBluetooth::Security::Secure; +#else + Q_D(const QBluetoothSocketBase); + return d->secFlags; +#endif // QT_OSX_BLUETOOTH +} + +/*! + Sets the socket state to \a state. +*/ +void QBluetoothSocket::setSocketState(QBluetoothSocket::SocketState state) +{ + Q_D(QBluetoothSocketBase); + const SocketState old = d->state; + if (state == old) + return; + + d->state = state; + if(old != d->state) + emit stateChanged(state); + if (state == QBluetoothSocket::SocketState::ConnectedState) { + emit connected(); + } else if ((old == QBluetoothSocket::SocketState::ConnectedState + || old == QBluetoothSocket::SocketState::ClosingState) + && state == QBluetoothSocket::SocketState::UnconnectedState) { + emit disconnected(); + } + if (state == SocketState::ListeningState){ +#ifdef QT_OSX_BLUETOOTH + qCWarning(QT_BT) << "listening socket is not supported by IOBluetooth"; +#endif + // TODO: look at this, is this really correct? + // if we're a listening socket we can't handle connects? + if (d->readNotifier) { + d->readNotifier->setEnabled(false); + } + } +} + +/*! + Returns true if you can read at least one line from the device + */ + +bool QBluetoothSocket::canReadLine() const +{ + Q_D(const QBluetoothSocketBase); + return d->canReadLine() || QIODevice::canReadLine(); +} + +/*! + Sets the type of error that last occurred to \a error_. +*/ +void QBluetoothSocket::setSocketError(QBluetoothSocket::SocketError error_) +{ + Q_D(QBluetoothSocketBase); + d->socketError = error_; + emit errorOccurred(error_); +} + +/*! + Start device discovery for \a service and open the socket with \a openMode. If the socket + is created with a service uuid device address, use service discovery to find the + port number to connect to. +*/ + +void QBluetoothSocket::doDeviceDiscovery(const QBluetoothServiceInfo &service, OpenMode openMode) +{ + Q_D(QBluetoothSocketBase); + + setSocketState(QBluetoothSocket::SocketState::ServiceLookupState); + qCDebug(QT_BT) << "Starting Bluetooth service discovery"; + + if(d->discoveryAgent) { + d->discoveryAgent->stop(); + delete d->discoveryAgent; + } + + d->discoveryAgent = new QBluetoothServiceDiscoveryAgent(this); + d->discoveryAgent->setRemoteAddress(service.device().address()); + + //qDebug() << "Got agent"; + + connect(d->discoveryAgent, &QBluetoothServiceDiscoveryAgent::serviceDiscovered, + this, &QBluetoothSocket::serviceDiscovered); + connect(d->discoveryAgent, &QBluetoothServiceDiscoveryAgent::finished, + this, &QBluetoothSocket::discoveryFinished); + + d->openMode = openMode; + + QList filterUuids = service.serviceClassUuids(); + if(!service.serviceUuid().isNull()) + filterUuids.append(service.serviceUuid()); + + if (!filterUuids.isEmpty()) + d->discoveryAgent->setUuidFilter(filterUuids); + + // we have to ID the service somehow + Q_ASSERT(!d->discoveryAgent->uuidFilter().isEmpty()); + + qCDebug(QT_BT) << "UUID filter" << d->discoveryAgent->uuidFilter(); + + d->discoveryAgent->start(QBluetoothServiceDiscoveryAgent::FullDiscovery); +} + +void QBluetoothSocket::serviceDiscovered(const QBluetoothServiceInfo &service) +{ + Q_D(QBluetoothSocketBase); + qCDebug(QT_BT) << "FOUND SERVICE!" << service; + if (service.protocolServiceMultiplexer() > 0 || service.serverChannel() > 0) { + connectToService(service, d->openMode); + d->discoveryAgent->deleteLater(); + d->discoveryAgent = nullptr; +#ifdef QT_WINRT_BLUETOOTH + } else if (!service.attribute(0xBEEF).isNull() + && !service.attribute(0xBEF0).isNull()) { + connectToService(service, d->openMode); + d->discoveryAgent->deleteLater(); + d->discoveryAgent = nullptr; +#endif + } else { + qCDebug(QT_BT) << "Could not find port/psm for potential remote service"; + } +} + +void QBluetoothSocket::discoveryFinished() +{ + qCDebug(QT_BT) << "Socket discovery finished"; + Q_D(QBluetoothSocketBase); + if (d->discoveryAgent){ + qCDebug(QT_BT) << "Didn't find any"; + d->errorString = tr("Service cannot be found"); + setSocketError(SocketError::ServiceNotFoundError); + setSocketState(QBluetoothSocket::SocketState::UnconnectedState); + d->discoveryAgent->deleteLater(); + d->discoveryAgent = nullptr; + } +} + +void QBluetoothSocket::abort() +{ + if (state() == SocketState::UnconnectedState) + return; + + Q_D(QBluetoothSocketBase); + setOpenMode(QIODevice::NotOpen); + + if (state() == SocketState::ServiceLookupState && d->discoveryAgent) { + d->discoveryAgent->disconnect(); + d->discoveryAgent->stop(); + d->discoveryAgent = nullptr; + } + + setSocketState(SocketState::ClosingState); + d->abort(); +} + +void QBluetoothSocket::disconnectFromService() +{ + close(); +} + +QString QBluetoothSocket::localName() const +{ + Q_D(const QBluetoothSocketBase); + return d->localName(); +} + +QBluetoothAddress QBluetoothSocket::localAddress() const +{ + Q_D(const QBluetoothSocketBase); + return d->localAddress(); +} + +quint16 QBluetoothSocket::localPort() const +{ + Q_D(const QBluetoothSocketBase); + return d->localPort(); +} + +QString QBluetoothSocket::peerName() const +{ + Q_D(const QBluetoothSocketBase); + return d->peerName(); +} + +QBluetoothAddress QBluetoothSocket::peerAddress() const +{ + Q_D(const QBluetoothSocketBase); + return d->peerAddress(); +} + +quint16 QBluetoothSocket::peerPort() const +{ + Q_D(const QBluetoothSocketBase); + return d->peerPort(); +} + +qint64 QBluetoothSocket::writeData(const char *data, qint64 maxSize) +{ + Q_D(QBluetoothSocketBase); + + if (!data || maxSize <= 0) { + d_ptr->errorString = tr("Invalid data/data size"); + setSocketError(QBluetoothSocket::SocketError::OperationError); + return -1; + } + + return d->writeData(data, maxSize); +} + +qint64 QBluetoothSocket::readData(char *data, qint64 maxSize) +{ + Q_D(QBluetoothSocketBase); + return d->readData(data, maxSize); +} + +void QBluetoothSocket::close() +{ + if (state() == SocketState::UnconnectedState) + return; + + Q_D(QBluetoothSocketBase); + setOpenMode(QIODevice::NotOpen); + + if (state() == SocketState::ServiceLookupState && d->discoveryAgent) { + d->discoveryAgent->disconnect(); + d->discoveryAgent->stop(); + d->discoveryAgent = nullptr; + } + + setSocketState(SocketState::ClosingState); + + d->close(); +} + +/*! + \fn bool QBluetoothSocket::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType, SocketState socketState, OpenMode openMode) + + Sets the socket to use \a socketDescriptor with a type of \a socketType, + which is in state \a socketState, and mode \a openMode. + + The socket descriptor is owned by the QBluetoothSocket instance and may + be closed once finished. + + Returns \c true on success. +*/ + +// ### Qt 7 consider making this function private. The qbluetoothsocket_bluez backend is the +// the only backend providing publicly accessible support for this. Other backends implement +// similarly named, but private, overload +bool QBluetoothSocket::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType, + SocketState socketState, OpenMode openMode) +{ + Q_D(QBluetoothSocketBase); + return d->setSocketDescriptor(socketDescriptor, socketType, socketState, openMode); +} + +/*! + Returns the platform-specific socket descriptor, if available. + This function returns -1 if the descriptor is not available or an error has occurred. +*/ + +int QBluetoothSocket::socketDescriptor() const +{ + Q_D(const QBluetoothSocketBase); + return d->socket; +} + +QT_END_NAMESPACE + +#include "moc_qbluetoothsocket.cpp" diff --git a/src/bluetooth/qbluetoothsocket.h b/src/bluetooth/qbluetoothsocket.h new file mode 100644 index 0000000..53aa9f2 --- /dev/null +++ b/src/bluetooth/qbluetoothsocket.h @@ -0,0 +1,157 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QBLUETOOTHSOCKET_H +#define QBLUETOOTHSOCKET_H + +#include + +#include +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + + +class QBluetoothSocketBasePrivate; + +class Q_BLUETOOTH_EXPORT QBluetoothSocket : public QIODevice +{ + Q_OBJECT + + Q_DECLARE_PRIVATE(QBluetoothSocketBase) + + friend class QBluetoothServer; + friend class QBluetoothServerPrivate; + friend class QBluetoothSocketPrivateDarwin; + friend class QBluetoothSocketPrivateAndroid; + friend class QBluetoothSocketPrivateBluez; + friend class QBluetoothSocketPrivateBluezDBus; + friend class QBluetoothSocketPrivateDummy; + friend class QBluetoothSocketPrivateWin; + friend class QBluetoothSocketPrivateWinRT; + +public: + + enum class SocketState { + UnconnectedState, + ServiceLookupState, + ConnectingState, + ConnectedState, + BoundState, + ClosingState, + ListeningState + }; + Q_ENUM(SocketState) + + enum class SocketError { + NoSocketError, + UnknownSocketError, + RemoteHostClosedError, + HostNotFoundError, + ServiceNotFoundError, + NetworkError, + UnsupportedProtocolError, + OperationError, + MissingPermissionsError + }; + Q_ENUM(SocketError) + + explicit QBluetoothSocket(QBluetoothServiceInfo::Protocol socketType, QObject *parent = nullptr); // create socket of type socketType + explicit QBluetoothSocket(QObject *parent = nullptr); // create a blank socket + virtual ~QBluetoothSocket(); + + void abort(); + + void close() override; + + bool isSequential() const override; + + qint64 bytesAvailable() const override; + qint64 bytesToWrite() const override; + + bool canReadLine() const override; + + void connectToService(const QBluetoothServiceInfo &service, OpenMode openMode = ReadWrite); + void connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid, OpenMode openMode = ReadWrite); + void connectToService(const QBluetoothAddress &address, quint16 port, OpenMode openMode = ReadWrite); + inline void connectToService(const QBluetoothAddress &address, QBluetoothUuid::ServiceClassUuid uuid, + OpenMode mode = ReadWrite) + { + connectToService(address, QBluetoothUuid(uuid), mode); + } + void disconnectFromService(); + + //bool flush(); + //bool isValid() const; + + QString localName() const; + QBluetoothAddress localAddress() const; + quint16 localPort() const; + + QString peerName() const; + QBluetoothAddress peerAddress() const; + quint16 peerPort() const; + //QBluetoothServiceInfo peerService() const; + + //qint64 readBufferSize() const; + //void setReadBufferSize(qint64 size); + + bool setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType, + SocketState socketState = SocketState::ConnectedState, + OpenMode openMode = ReadWrite); + int socketDescriptor() const; + + QBluetoothServiceInfo::Protocol socketType() const; + SocketState state() const; + SocketError error() const; + QString errorString() const; + + //bool waitForConnected(int msecs = 30000); + //bool waitForDisconnected(int msecs = 30000); + //virtual bool waitForReadyRead(int msecs = 30000); + + void setPreferredSecurityFlags(QBluetooth::SecurityFlags flags); + QBluetooth::SecurityFlags preferredSecurityFlags() const; + +Q_SIGNALS: + void connected(); + void disconnected(); + void errorOccurred(QBluetoothSocket::SocketError error); + void stateChanged(QBluetoothSocket::SocketState state); + +protected: + qint64 readData(char *data, qint64 maxSize) override; + qint64 writeData(const char *data, qint64 maxSize) override; + + void setSocketState(SocketState state); + void setSocketError(SocketError error); + + void doDeviceDiscovery(const QBluetoothServiceInfo &service, OpenMode openMode); + +private Q_SLOTS: + void serviceDiscovered(const QBluetoothServiceInfo &service); + void discoveryFinished(); + + +protected: +#if QT_CONFIG(bluez) + //evil hack to enable QBluetoothServer on Bluez to set the desired d_ptr + explicit QBluetoothSocket(QBluetoothSocketBasePrivate *d, + QBluetoothServiceInfo::Protocol socketType, + QObject *parent = nullptr); +#endif + + QBluetoothSocketBasePrivate *d_ptr; + +private: + friend class QLowEnergyControllerPrivateBluez; +}; + + +QT_END_NAMESPACE + +#endif diff --git a/src/bluetooth/qbluetoothsocket_android.cpp b/src/bluetooth/qbluetoothsocket_android.cpp new file mode 100644 index 0000000..147d533 --- /dev/null +++ b/src/bluetooth/qbluetoothsocket_android.cpp @@ -0,0 +1,802 @@ +// Copyright (C) 2016 Lauri Laanmets (Proekspert AS) +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothsocket.h" +#include "qbluetoothsocket_android_p.h" +#include "qbluetoothaddress.h" +#include "qbluetoothdeviceinfo.h" +#include "qbluetoothserviceinfo.h" +#include "android/androidutils_p.h" +#include "android/jni_android_p.h" +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID) + +#define USE_FALLBACK true + +Q_BLUETOOTH_EXPORT bool useReverseUuidWorkAroundConnect = true; + +/* BluetoothSocket.connect() can block up to 10s. Therefore it must be + * in a separate thread. Unfortunately if BluetoothSocket.close() is + * called while connect() is still blocking the resulting behavior is not reliable. + * This may well be an Android platform bug. In any case, close() must + * be queued up until connect() has returned. + * + * The WorkerThread manages the connect() and close() calls. Interaction + * with the main thread happens via signals and slots. There is an accepted but + * undesirable side effect of this approach as the user may call connect() + * and close() and the socket would continue to successfully connect to + * the remote device just to immidiately close the physical connection again. + * + * WorkerThread and SocketConnectWorker are cleaned up via the threads + * finished() signal. + */ + +class SocketConnectWorker : public QObject +{ + Q_OBJECT +public: + SocketConnectWorker(const QJniObject& socket, + const QJniObject& targetUuid, + const QBluetoothUuid& qtTargetUuid) + : QObject(), + mSocketObject(socket), + mTargetUuid(targetUuid), + mQtTargetUuid(qtTargetUuid) + { + static int t = qRegisterMetaType(); + Q_UNUSED(t); + } + +signals: + void socketConnectDone(const QJniObject &socket); + void socketConnectFailed(const QJniObject &socket, + const QJniObject &targetUuid, + const QBluetoothUuid &qtUuid); +public slots: + void connectSocket() + { + QJniEnvironment env; + + qCDebug(QT_BT_ANDROID) << "Connecting socket"; + auto methodId = env.findMethod(mSocketObject.objectClass(), "connect", "()V"); + if (methodId) + env->CallVoidMethod(mSocketObject.object(), methodId); + if (!methodId || env.checkAndClearExceptions()) { + emit socketConnectFailed(mSocketObject, mTargetUuid, mQtTargetUuid); + QThread::currentThread()->quit(); + return; + } + + qCDebug(QT_BT_ANDROID) << "Socket connection established"; + emit socketConnectDone(mSocketObject); + } + + void closeSocket() + { + qCDebug(QT_BT_ANDROID) << "Executing queued closeSocket()"; + + mSocketObject.callMethod("close"); + QThread::currentThread()->quit(); + } + +private: + QJniObject mSocketObject; + QJniObject mTargetUuid; + // same as mTargetUuid above - just the Qt C++ version rather than jni uuid + QBluetoothUuid mQtTargetUuid; +}; + +class WorkerThread: public QThread +{ + Q_OBJECT +public: + WorkerThread() + : QThread(), workerPointer(0) + { + } + + // Runs in same thread as QBluetoothSocketPrivateAndroid + void setupWorker(QBluetoothSocketPrivateAndroid* d_ptr, const QJniObject& socketObject, + const QJniObject& uuidObject, bool useFallback, + const QBluetoothUuid& qtUuid = QBluetoothUuid()) + { + SocketConnectWorker* worker = new SocketConnectWorker( + socketObject, uuidObject, qtUuid); + worker->moveToThread(this); + + connect(this, &QThread::finished, worker, &QObject::deleteLater); + connect(this, &QThread::finished, this, &QObject::deleteLater); + connect(d_ptr, &QBluetoothSocketPrivateAndroid::connectJavaSocket, + worker, &SocketConnectWorker::connectSocket); + connect(d_ptr, &QBluetoothSocketPrivateAndroid::closeJavaSocket, + worker, &SocketConnectWorker::closeSocket); + connect(worker, &SocketConnectWorker::socketConnectDone, + d_ptr, &QBluetoothSocketPrivateAndroid::socketConnectSuccess); + if (useFallback) { + connect(worker, &SocketConnectWorker::socketConnectFailed, + d_ptr, &QBluetoothSocketPrivateAndroid::fallbackSocketConnectFailed); + } else { + connect(worker, &SocketConnectWorker::socketConnectFailed, + d_ptr, &QBluetoothSocketPrivateAndroid::defaultSocketConnectFailed); + } + + workerPointer = worker; + } + +private: + QPointer workerPointer; +}; + +QBluetoothSocketPrivateAndroid::QBluetoothSocketPrivateAndroid() + : + inputThread(0) +{ + secFlags = QBluetooth::Security::Secure; + adapter = getDefaultBluetoothAdapter(); + qRegisterMetaType(); + qRegisterMetaType(); +} + +QBluetoothSocketPrivateAndroid::~QBluetoothSocketPrivateAndroid() +{ + if (state != QBluetoothSocket::SocketState::UnconnectedState) + emit closeJavaSocket(); +} + +bool QBluetoothSocketPrivateAndroid::ensureNativeSocket(QBluetoothServiceInfo::Protocol type) +{ + socketType = type; + if (socketType == QBluetoothServiceInfo::RfcommProtocol) + return true; + + return false; +} + +/* + * Workaround for QTBUG-61392. If the underlying Android bug gets fixed, + * we need to consider restoring the non-reversed fallbackConnect from the repository. + */ +bool QBluetoothSocketPrivateAndroid::fallBackReversedConnect(const QBluetoothUuid &uuid) +{ + Q_Q(QBluetoothSocket); + + qCWarning(QT_BT_ANDROID) << "Falling back to reverse uuid workaround."; + const QBluetoothUuid reverse = reverseUuid(uuid); + if (reverse.isNull()) + return false; + + QString tempUuid = reverse.toString(QUuid::WithoutBraces); + + QJniEnvironment env; + const QJniObject inputString = QJniObject::fromString(tempUuid); + const QJniObject uuidObject = QJniObject::callStaticMethod( + QtJniTypes::Traits::className(), "fromString", + inputString.object()); + + if (secFlags == QBluetooth::SecurityFlags(QBluetooth::Security::NoSecurity)) { + qCDebug(QT_BT_ANDROID) << "Connecting via insecure rfcomm"; + socketObject = remoteDevice.callMethod( + "createInsecureRfcommSocketToServiceRecord", + uuidObject.object()); + } else { + qCDebug(QT_BT_ANDROID) << "Connecting via secure rfcomm"; + socketObject = remoteDevice.callMethod( + "createRfcommSocketToServiceRecord", + uuidObject.object()); + } + + if (!socketObject.isValid()) { + remoteDevice = QJniObject(); + errorString = QBluetoothSocket::tr("Cannot connect to %1", + "%1 = uuid").arg(reverse.toString()); + q->setSocketError(QBluetoothSocket::SocketError::ServiceNotFoundError); + q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState); + return false; + } + + WorkerThread *workerThread = new WorkerThread(); + workerThread->setupWorker(this, socketObject, uuidObject, USE_FALLBACK); + workerThread->start(); + emit connectJavaSocket(); + + return true; +} + +/* + * The call order during a connectToServiceHelper() is as follows: + * + * 1. call connectToServiceHelper() + * 2. wait for execution of SocketConnectThread::run() + * 3. if threaded connect succeeds call socketConnectSuccess() via signals + * -> done + * 4. if threaded connect fails call defaultSocketConnectFailed() via signals + * 5. call fallBackReversedConnect() + * -> if failure entire connectToServiceHelper() fails + * Note: This fallback can be disabled with private API boolean + * 6. if threaded connect on one of above fallbacks succeeds call socketConnectSuccess() + * via signals + * -> done + * 7. if threaded connect on fallback channel fails call fallbackSocketConnectFailed() + * -> complete failure of entire connectToServiceHelper() + * */ +void QBluetoothSocketPrivateAndroid::connectToServiceHelper(const QBluetoothAddress &address, + const QBluetoothUuid &uuid, + QIODevice::OpenMode openMode) +{ + Q_Q(QBluetoothSocket); + Q_UNUSED(openMode); + + qCDebug(QT_BT_ANDROID) << "connectToServiceHelper()" << address.toString() << uuid.toString(); + + if (!ensureAndroidPermission(QBluetoothPermission::Access)) { + qCWarning(QT_BT_ANDROID) << "Bluetooth socket connect failed due to missing permissions"; + errorString = QBluetoothSocket::tr( + "Bluetooth socket connect failed due to missing permissions."); + q->setSocketError(QBluetoothSocket::SocketError::MissingPermissionsError); + q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState); + return; + } + + q->setSocketState(QBluetoothSocket::SocketState::ConnectingState); + + if (!adapter.isValid()) { + qCWarning(QT_BT_ANDROID) << "Device does not support Bluetooth"; + errorString = QBluetoothSocket::tr("Device does not support Bluetooth"); + q->setSocketError(QBluetoothSocket::SocketError::NetworkError); + q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState); + return; + } + + const int state = adapter.callMethod("getState"); + if (state != 12 ) { //BluetoothAdapter.STATE_ON + qCWarning(QT_BT_ANDROID) << "Bluetooth device offline"; + errorString = QBluetoothSocket::tr("Device is powered off"); + q->setSocketError(QBluetoothSocket::SocketError::NetworkError); + q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState); + return; + } + + QJniEnvironment env; + QJniObject inputString = QJniObject::fromString(address.toString()); + remoteDevice = adapter.callMethod("getRemoteDevice", + inputString.object()); + if (!remoteDevice.isValid()) { + errorString = QBluetoothSocket::tr("Cannot access address %1", "%1 = Bt address e.g. 11:22:33:44:55:66").arg(address.toString()); + q->setSocketError(QBluetoothSocket::SocketError::HostNotFoundError); + q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState); + return; + } + + //cut leading { and trailing } {xxx-xxx} + const QString tempUuid = uuid.toString(QUuid::WithoutBraces); + + inputString = QJniObject::fromString(tempUuid); + const QJniObject uuidObject = QJniObject::callStaticMethod( + QtJniTypes::Traits::className(), "fromString", + inputString.object()); + + if (secFlags == QBluetooth::SecurityFlags(QBluetooth::Security::NoSecurity)) { + qCDebug(QT_BT_ANDROID) << "Connecting via insecure rfcomm"; + socketObject = remoteDevice.callMethod( + "createInsecureRfcommSocketToServiceRecord", + uuidObject.object()); + } else { + qCDebug(QT_BT_ANDROID) << "Connecting via secure rfcomm"; + socketObject = remoteDevice.callMethod( + "createRfcommSocketToServiceRecord", + uuidObject.object()); + } + + if (!socketObject.isValid()) { + remoteDevice = QJniObject(); + errorString = QBluetoothSocket::tr("Cannot connect to %1 on %2", + "%1 = uuid, %2 = Bt address").arg(uuid.toString()).arg(address.toString()); + q->setSocketError(QBluetoothSocket::SocketError::ServiceNotFoundError); + q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState); + return; + } + + WorkerThread *workerThread = new WorkerThread(); + workerThread->setupWorker(this, socketObject, uuidObject, !USE_FALLBACK, uuid); + workerThread->start(); + emit connectJavaSocket(); +} + +void QBluetoothSocketPrivateAndroid::connectToService( + const QBluetoothServiceInfo &service, QIODevice::OpenMode openMode) +{ + Q_Q(QBluetoothSocket); + + if (q->state() != QBluetoothSocket::SocketState::UnconnectedState + && q->state() != QBluetoothSocket::SocketState::ServiceLookupState) { + qCWarning(QT_BT_ANDROID) << "QBluetoothSocketPrivateAndroid::connectToService called on busy socket"; + errorString = QBluetoothSocket::tr("Trying to connect while connection is in progress"); + q->setSocketError(QBluetoothSocket::SocketError::OperationError); + return; + } + + // Workaround for QTBUG-75035 + /* Not all Android devices publish or discover the SPP uuid for serial services. + * Also, Android does not permit the detection of the protocol used by a serial + * Bluetooth connection. + * + * Therefore, QBluetoothServiceDiscoveryAgentPrivate::populateDiscoveredServices() + * may have to guess what protocol a potential custom uuid uses. The guessing works + * reasonably well as long as the SDP discovery finds the SPP uuid. Otherwise + * the SPP and rfcomm protocol info is missing in \a service. + * + * Android only supports RFCOMM (no L2CP). We assume (in favor of user experience) + * that a non-RFCOMM protocol implies a missing SPP uuid during discovery but the user + * still wanting to connect with the given \a service instance. + */ + + auto protocol = service.socketProtocol(); + switch (protocol) { + case QBluetoothServiceInfo::L2capProtocol: + case QBluetoothServiceInfo::UnknownProtocol: + qCWarning(QT_BT_ANDROID) << "Changing socket protocol to RFCOMM"; + protocol = QBluetoothServiceInfo::RfcommProtocol; + break; + case QBluetoothServiceInfo::RfcommProtocol: + break; + } + + if (!ensureNativeSocket(protocol)) { + errorString = QBluetoothSocket::tr("Socket type not supported"); + q->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError); + return; + } + connectToServiceHelper(service.device().address(), service.serviceUuid(), openMode); +} + +void QBluetoothSocketPrivateAndroid::connectToService( + const QBluetoothAddress &address, const QBluetoothUuid &uuid, + QIODevice::OpenMode openMode) +{ + Q_Q(QBluetoothSocket); + + if (q->state() != QBluetoothSocket::SocketState::UnconnectedState) { + qCWarning(QT_BT_ANDROID) << "QBluetoothSocketPrivateAndroid::connectToService called on busy socket"; + errorString = QBluetoothSocket::tr("Trying to connect while connection is in progress"); + q->setSocketError(QBluetoothSocket::SocketError::OperationError); + return; + } + + if (q->socketType() == QBluetoothServiceInfo::UnknownProtocol) { + qCWarning(QT_BT_ANDROID) << "QBluetoothSocketPrivateAndroid::connectToService cannot " + "connect with 'UnknownProtocol' (type provided by given service)"; + errorString = QBluetoothSocket::tr("Socket type not supported"); + q->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError); + return; + } + + if (!ensureNativeSocket(q->socketType())) { + errorString = QBluetoothSocket::tr("Socket type not supported"); + q->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError); + return; + } + connectToServiceHelper(address, uuid, openMode); +} + +void QBluetoothSocketPrivateAndroid::connectToService( + const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode) +{ + Q_UNUSED(port); + Q_UNUSED(openMode); + Q_UNUSED(address); + + Q_Q(QBluetoothSocket); + + errorString = tr("Connecting to port is not supported"); + q->setSocketError(QBluetoothSocket::SocketError::ServiceNotFoundError); + qCWarning(QT_BT_ANDROID) << "Connecting to port is not supported"; +} + +void QBluetoothSocketPrivateAndroid::socketConnectSuccess(const QJniObject &socket) +{ + Q_Q(QBluetoothSocket); + QJniEnvironment env; + + // test we didn't get a success from a previous connect + // which was cleaned up late + if (socket != socketObject) + return; + + if (inputThread) { + inputThread->deleteLater(); + inputThread = 0; + } + + inputStream = socketObject.callMethod("getInputStream"); + outputStream = socketObject.callMethod("getOutputStream"); + + if (!inputStream.isValid() || !outputStream.isValid()) { + + emit closeJavaSocket(); + socketObject = inputStream = outputStream = remoteDevice = QJniObject(); + + + errorString = QBluetoothSocket::tr("Obtaining streams for service failed"); + q->setSocketError(QBluetoothSocket::SocketError::NetworkError); + q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState); + return; + } + + inputThread = new InputStreamThread(this); + QObject::connect(inputThread, SIGNAL(dataAvailable()), + q, SIGNAL(readyRead()), Qt::QueuedConnection); + QObject::connect(inputThread, SIGNAL(errorOccurred(int)), this, SLOT(inputThreadError(int)), + Qt::QueuedConnection); + + if (!inputThread->run()) { + //close socket again + emit closeJavaSocket(); + + socketObject = inputStream = outputStream = remoteDevice = QJniObject(); + + delete inputThread; + inputThread = 0; + + errorString = QBluetoothSocket::tr("Input stream thread cannot be started"); + q->setSocketError(QBluetoothSocket::SocketError::NetworkError); + q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState); + return; + } + + // only unbuffered behavior supported at this stage + q->setOpenMode(QIODevice::ReadWrite|QIODevice::Unbuffered); + + q->setSocketState(QBluetoothSocket::SocketState::ConnectedState); +} + +void QBluetoothSocketPrivateAndroid::defaultSocketConnectFailed( + const QJniObject &socket, const QJniObject &targetUuid, + const QBluetoothUuid &qtTargetUuid) +{ + Q_UNUSED(targetUuid); + Q_Q(QBluetoothSocket); + + // test we didn't get a fail from a previous connect + // which was cleaned up late - should be same socket + if (socket != socketObject) + return; + + if (!useReverseUuidWorkAroundConnect || !fallBackReversedConnect(qtTargetUuid)) { + errorString = QBluetoothSocket::tr("Connection to service failed"); + socketObject = remoteDevice = QJniObject(); + q->setSocketError(QBluetoothSocket::SocketError::ServiceNotFoundError); + q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState); + qCWarning(QT_BT_ANDROID) << "Socket connect workaround failed"; + } +} + +void QBluetoothSocketPrivateAndroid::fallbackSocketConnectFailed( + const QJniObject &socket, const QJniObject &targetUuid) +{ + Q_UNUSED(targetUuid); + Q_Q(QBluetoothSocket); + + // test we didn't get a fail from a previous connect + // which was cleaned up late - should be same socket + if (socket != socketObject) + return; + + qCWarning(QT_BT_ANDROID) << "Socket connect via workaround failed."; + errorString = QBluetoothSocket::tr("Connection to service failed"); + socketObject = remoteDevice = QJniObject(); + + q->setSocketError(QBluetoothSocket::SocketError::ServiceNotFoundError); + q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState); +} + +void QBluetoothSocketPrivateAndroid::abort() +{ + if (state == QBluetoothSocket::SocketState::UnconnectedState) + return; + + if (socketObject.isValid()) { + QJniEnvironment env; + + /* + * BluetoothSocket.close() triggers an abort of the input stream + * thread because inputStream.read() throws IOException + * In turn the thread stops and throws an error which sets + * new state, error and emits relevant signals. + * See QBluetoothSocketPrivateAndroid::inputThreadError() for details + */ + + if (inputThread) + inputThread->prepareForClosure(); + + emit closeJavaSocket(); + + inputStream = outputStream = socketObject = remoteDevice = QJniObject(); + + if (inputThread) { + // inputThread exists hence we had a successful connect + // which means inputThread is responsible for setting Unconnected + + //don't delete here as signals caused by Java Thread are still + //going to be emitted + //delete occurs in inputThreadError() + inputThread = 0; + } else { + // inputThread doesn't exist hence + // we abort in the middle of connect(). WorkerThread will do + // close() without further feedback. Therefore we have to set + // Unconnected (now) in advance + Q_Q(QBluetoothSocket); + q->setOpenMode(QIODevice::NotOpen); + q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState); + emit q->readChannelFinished(); + } + } +} + +QString QBluetoothSocketPrivateAndroid::localName() const +{ + if (!ensureAndroidPermission(QBluetoothPermission::Access)) { + qCWarning(QT_BT_ANDROID) << "Bluetooth socket localName() failed due to" + "missing permissions"; + } else if (adapter.isValid()) { + return adapter.callMethod("getName").toString(); + } + + return QString(); +} + +QBluetoothAddress QBluetoothSocketPrivateAndroid::localAddress() const +{ + QString result; + + if (!ensureAndroidPermission(QBluetoothPermission::Access)) { + qCWarning(QT_BT_ANDROID) << "Bluetooth socket localAddress() failed due to" + "missing permissions"; + } else if (adapter.isValid()) { + result = adapter.callMethod("getAddress").toString(); + } + + return QBluetoothAddress(result); +} + +quint16 QBluetoothSocketPrivateAndroid::localPort() const +{ + // Impossible to get channel number with current Android API (Levels 5 to 19) + return 0; +} + +QString QBluetoothSocketPrivateAndroid::peerName() const +{ + if (!remoteDevice.isValid()) + return QString(); + + return remoteDevice.callMethod("getName").toString(); +} + +QBluetoothAddress QBluetoothSocketPrivateAndroid::peerAddress() const +{ + if (!remoteDevice.isValid()) + return QBluetoothAddress(); + + const QString address = remoteDevice.callMethod("getAddress").toString(); + return QBluetoothAddress(address); +} + +quint16 QBluetoothSocketPrivateAndroid::peerPort() const +{ + // Impossible to get channel number with current Android API (Levels 5 to 13) + return 0; +} + +qint64 QBluetoothSocketPrivateAndroid::writeData(const char *data, qint64 maxSize) +{ + //TODO implement buffered behavior (so far only unbuffered) + Q_Q(QBluetoothSocket); + if (state != QBluetoothSocket::SocketState::ConnectedState || !outputStream.isValid()) { + qCWarning(QT_BT_ANDROID) << "Socket::writeData: " << state << outputStream.isValid(); + errorString = QBluetoothSocket::tr("Cannot write while not connected"); + q->setSocketError(QBluetoothSocket::SocketError::OperationError); + return -1; + } + + QJniEnvironment env; + jbyteArray nativeData = env->NewByteArray((qint32)maxSize); + env->SetByteArrayRegion(nativeData, 0, (qint32)maxSize, reinterpret_cast(data)); + auto methodId = env.findMethod(outputStream.objectClass(), + "write", + "([BII)V"); + if (methodId) + env->CallVoidMethod(outputStream.object(), methodId, nativeData, 0, (qint32)maxSize); + env->DeleteLocalRef(nativeData); + + if (!methodId || env.checkAndClearExceptions()) { + qCWarning(QT_BT_ANDROID) << "Error while writing"; + errorString = QBluetoothSocket::tr("Error during write on socket."); + q->setSocketError(QBluetoothSocket::SocketError::NetworkError); + return -1; + } + + emit q->bytesWritten(maxSize); + return maxSize; +} + +qint64 QBluetoothSocketPrivateAndroid::readData(char *data, qint64 maxSize) +{ + Q_Q(QBluetoothSocket); + if (state != QBluetoothSocket::SocketState::ConnectedState || !inputThread) { + qCWarning(QT_BT_ANDROID) << "Socket::readData: " << state << inputThread ; + errorString = QBluetoothSocket::tr("Cannot read while not connected"); + q->setSocketError(QBluetoothSocket::SocketError::OperationError); + return -1; + } + + return inputThread->readData(data, maxSize); +} + +void QBluetoothSocketPrivateAndroid::inputThreadError(int errorCode) +{ + Q_Q(QBluetoothSocket); + + if (errorCode != -1) { //magic error which is expected and can be ignored + errorString = QBluetoothSocket::tr("Network error during read"); + q->setSocketError(QBluetoothSocket::SocketError::NetworkError); + } + + //finally we can delete the InputStreamThread + InputStreamThread *client = qobject_cast(sender()); + if (client) + client->deleteLater(); + + if (socketObject.isValid()) { + //triggered when remote side closed the socket + //cleanup internal objects + //if it was call to local close()/abort() the objects are cleaned up already + + emit closeJavaSocket(); + + inputStream = outputStream = remoteDevice = socketObject = QJniObject(); + if (inputThread) { + // deleted already above (client->deleteLater()) + inputThread = 0; + } + } + + q->setOpenMode(QIODevice::NotOpen); + q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState); + emit q->readChannelFinished(); +} + +void QBluetoothSocketPrivateAndroid::close() +{ + /* This function is called by QBluetoothSocket::close and softer version + QBluetoothSocket::disconnectFromService() which difference I do not quite fully understand. + Anyways we end up in Android "close" function call. + */ + abort(); +} + +bool QBluetoothSocketPrivateAndroid::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType, + QBluetoothSocket::SocketState socketState, QBluetoothSocket::OpenMode openMode) +{ + Q_UNUSED(socketDescriptor); + Q_UNUSED(socketType); + Q_UNUSED(socketState); + Q_UNUSED(openMode); + qCWarning(QT_BT_ANDROID) << "No socket descriptor support on Android."; + return false; +} + +bool QBluetoothSocketPrivateAndroid::setSocketDescriptor(const QJniObject &socket, QBluetoothServiceInfo::Protocol socketType_, + QBluetoothSocket::SocketState socketState, QBluetoothSocket::OpenMode openMode) +{ + Q_Q(QBluetoothSocket); + + if (q->state() != QBluetoothSocket::SocketState::UnconnectedState || !socket.isValid()) + return false; + + if (!ensureNativeSocket(socketType_)) + return false; + + socketObject = socket; + + inputStream = socketObject.callMethod("getInputStream"); + outputStream = socketObject.callMethod("getOutputStream"); + + if (!inputStream.isValid() || !outputStream.isValid()) { + + //close socket again + socketObject.callMethod("close"); + + socketObject = inputStream = outputStream = remoteDevice = QJniObject(); + + + errorString = QBluetoothSocket::tr("Obtaining streams for service failed"); + q->setSocketError(QBluetoothSocket::SocketError::NetworkError); + q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState); + return false; + } + + remoteDevice = socketObject.callMethod("getRemoteDevice"); + + if (inputThread) { + inputThread->deleteLater(); + inputThread = 0; + } + inputThread = new InputStreamThread(this); + QObject::connect(inputThread, SIGNAL(dataAvailable()), + q, SIGNAL(readyRead()), Qt::QueuedConnection); + QObject::connect(inputThread, SIGNAL(errorOccurred(int)), this, SLOT(inputThreadError(int)), + Qt::QueuedConnection); + inputThread->run(); + + // WorkerThread manages all sockets for us + // When we come through here the socket was already connected by + // server socket listener (see QBluetoothServer) + // Therefore we only use WorkerThread to potentially close it later on + WorkerThread *workerThread = new WorkerThread(); + workerThread->setupWorker(this, socketObject, QJniObject(), !USE_FALLBACK); + workerThread->start(); + + q->setOpenMode(openMode | QIODevice::Unbuffered); + q->setSocketState(socketState); + + return true; +} + +qint64 QBluetoothSocketPrivateAndroid::bytesAvailable() const +{ + //We cannot access buffer directly as it is part of different thread + if (inputThread) + return inputThread->bytesAvailable(); + + return 0; +} + +qint64 QBluetoothSocketPrivateAndroid::bytesToWrite() const +{ + return 0; // nothing because always unbuffered +} + +/* + * This function is part of a workaround for QTBUG-61392 + * + * Returns null uuid if the given \a serviceUuid is not a uuid + * derived from the Bluetooth base uuid. + */ +QBluetoothUuid QBluetoothSocketPrivateAndroid::reverseUuid(const QBluetoothUuid &serviceUuid) +{ + if (serviceUuid.isNull()) + return QBluetoothUuid(); + + bool isBaseUuid = false; + serviceUuid.toUInt32(&isBaseUuid); + if (isBaseUuid) + return serviceUuid; + + const QUuid::Id128Bytes original = serviceUuid.toBytes(); + QUuid::Id128Bytes reversed; + for (int i = 0; i < 16; i++) + reversed.data[15-i] = original.data[i]; + return QBluetoothUuid{reversed}; +} + +bool QBluetoothSocketPrivateAndroid::canReadLine() const +{ + // We cannot access buffer directly as it is part of different thread + if (inputThread) + return inputThread->canReadLine(); + + return false; +} + +QT_END_NAMESPACE + +#include diff --git a/src/bluetooth/qbluetoothsocket_android_p.h b/src/bluetooth/qbluetoothsocket_android_p.h new file mode 100644 index 0000000..a2cbbda --- /dev/null +++ b/src/bluetooth/qbluetoothsocket_android_p.h @@ -0,0 +1,110 @@ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + + +#ifndef QBLUETOOTHSOCKET_ANDROID_P_H +#define QBLUETOOTHSOCKET_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 "qbluetoothsocketbase_p.h" + +#include +#include +#include "android/inputstreamthread_p.h" +#include + +QT_BEGIN_NAMESPACE + +class QBluetoothSocketPrivateAndroid final : public QBluetoothSocketBasePrivate +{ + Q_OBJECT + friend class QBluetoothServerPrivate; + +public: + QBluetoothSocketPrivateAndroid(); + ~QBluetoothSocketPrivateAndroid() override; + + //On Android we connect using the uuid not the port + void connectToServiceHelper(const QBluetoothAddress &address, const QBluetoothUuid &uuid, + QIODevice::OpenMode openMode) override; + + void connectToService(const QBluetoothServiceInfo &service, + QIODevice::OpenMode openMode) override; + void connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid, + QIODevice::OpenMode openMode) override; + void connectToService(const QBluetoothAddress &address, quint16 port, + QIODevice::OpenMode openMode) override; + + bool fallBackReversedConnect(const QBluetoothUuid &uuid); + + bool ensureNativeSocket(QBluetoothServiceInfo::Protocol type) override; + + QString localName() const override; + QBluetoothAddress localAddress() const override; + quint16 localPort() const override; + + QString peerName() const override; + QBluetoothAddress peerAddress() const override; + quint16 peerPort() const override; + + void abort() override; + void close() override; + + qint64 writeData(const char *data, qint64 maxSize) override; + qint64 readData(char *data, qint64 maxSize) override; + + bool setSocketDescriptor(const QJniObject &socket, QBluetoothServiceInfo::Protocol socketType, + QBluetoothSocket::SocketState socketState = QBluetoothSocket::SocketState::ConnectedState, + QBluetoothSocket::OpenMode openMode = QBluetoothSocket::ReadWrite) override; + + bool setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType, + QBluetoothSocket::SocketState socketState = QBluetoothSocket::SocketState::ConnectedState, + QBluetoothSocket::OpenMode openMode = QBluetoothSocket::ReadWrite) override; + + qint64 bytesAvailable() const override; + bool canReadLine() const override; + qint64 bytesToWrite() const override; + + static QBluetoothUuid reverseUuid(const QBluetoothUuid &serviceUuid); + + QJniObject adapter; + QJniObject socketObject; + QJniObject remoteDevice; + QJniObject inputStream; + QJniObject outputStream; + InputStreamThread *inputThread; + +public slots: + void socketConnectSuccess(const QJniObject &socket); + void defaultSocketConnectFailed(const QJniObject & socket, + const QJniObject &targetUuid, + const QBluetoothUuid &qtTargetUuid); + void fallbackSocketConnectFailed(const QJniObject &socket, + const QJniObject &targetUuid); + void inputThreadError(int errorCode); + +signals: + void connectJavaSocket(); + void closeJavaSocket(); + +}; + +// QTBUG-61392 related +// Private API to disable the silent behavior to reverse a remote service's +// UUID. In rare cases the workaround behavior might not be desirable as +// it may lead to connects to incorrect services. +extern bool useReverseUuidWorkAroundConnect; + +QT_END_NAMESPACE + +#endif // QBLUETOOTHSOCKET_ANDROID_P_H diff --git a/src/bluetooth/qbluetoothsocket_bluez.cpp b/src/bluetooth/qbluetoothsocket_bluez.cpp new file mode 100644 index 0000000..7e45f29 --- /dev/null +++ b/src/bluetooth/qbluetoothsocket_bluez.cpp @@ -0,0 +1,644 @@ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothsocket.h" +#include "qbluetoothsocket_bluez_p.h" +#include "qbluetoothdeviceinfo.h" + +#include "bluez/objectmanager_p.h" +#include +#include "bluez/bluez_data_p.h" + +#include +#include + +#include + +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ) + +QBluetoothSocketPrivateBluez::QBluetoothSocketPrivateBluez() + : QBluetoothSocketBasePrivate() +{ + secFlags = QBluetooth::Security::Authorization; +} + +QBluetoothSocketPrivateBluez::~QBluetoothSocketPrivateBluez() +{ + delete readNotifier; + readNotifier = nullptr; + delete connectWriteNotifier; + connectWriteNotifier = nullptr; + + // If the socket wasn't closed/aborted make sure we free the socket file descriptor + if (socket != -1) + QT_CLOSE(socket); +} + +bool QBluetoothSocketPrivateBluez::ensureNativeSocket(QBluetoothServiceInfo::Protocol type) +{ + if (socket != -1) { + if (socketType == type) + return true; + + delete readNotifier; + readNotifier = nullptr; + delete connectWriteNotifier; + connectWriteNotifier = nullptr; + QT_CLOSE(socket); + } + + socketType = type; + + switch (type) { + case QBluetoothServiceInfo::L2capProtocol: + socket = ::socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); + break; + case QBluetoothServiceInfo::RfcommProtocol: + socket = ::socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); + break; + default: + socket = -1; + } + + if (socket == -1) + return false; + + int flags = fcntl(socket, F_GETFL, 0); + fcntl(socket, F_SETFL, flags | O_NONBLOCK); + + Q_Q(QBluetoothSocket); + readNotifier = new QSocketNotifier(socket, QSocketNotifier::Read); + QObject::connect(readNotifier, SIGNAL(activated(QSocketDescriptor)), this, SLOT(_q_readNotify())); + connectWriteNotifier = new QSocketNotifier(socket, QSocketNotifier::Write, q); + QObject::connect(connectWriteNotifier, SIGNAL(activated(QSocketDescriptor)), this, SLOT(_q_writeNotify())); + + connectWriteNotifier->setEnabled(false); + readNotifier->setEnabled(false); + + + return true; +} + +void QBluetoothSocketPrivateBluez::connectToServiceHelper(const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode) +{ + Q_Q(QBluetoothSocket); + int result = -1; + + if (socket == -1 && !ensureNativeSocket(socketType)) { + errorString = QBluetoothSocket::tr("Unknown socket error"); + q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError); + return; + } + + // apply preferred security level + // ignore QBluetooth::Security::Authentication -> not used anymore by kernel + struct bt_security security; + memset(&security, 0, sizeof(security)); + + if (secFlags & QBluetooth::Security::Authorization) + security.level = BT_SECURITY_LOW; + if (secFlags & QBluetooth::Security::Encryption) + security.level = BT_SECURITY_MEDIUM; + if (secFlags & QBluetooth::Security::Secure) + security.level = BT_SECURITY_HIGH; + + if (setsockopt(socket, SOL_BLUETOOTH, BT_SECURITY, + &security, sizeof(security)) != 0) { + qCWarning(QT_BT_BLUEZ) << "Failed to set socket option, closing socket for safety" << errno; + qCWarning(QT_BT_BLUEZ) << "Error: " << qt_error_string(errno); + errorString = QBluetoothSocket::tr("Cannot set connection security level"); + q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError); + return; + } + + if (socketType == QBluetoothServiceInfo::RfcommProtocol) { + sockaddr_rc addr; + + memset(&addr, 0, sizeof(addr)); + addr.rc_family = AF_BLUETOOTH; + addr.rc_channel = port; + + convertAddress(address.toUInt64(), addr.rc_bdaddr.b); + + connectWriteNotifier->setEnabled(true); + readNotifier->setEnabled(true); + + result = ::connect(socket, (sockaddr *)&addr, sizeof(addr)); + } else if (socketType == QBluetoothServiceInfo::L2capProtocol) { + sockaddr_l2 addr; + + memset(&addr, 0, sizeof(addr)); + addr.l2_family = AF_BLUETOOTH; + // This is an ugly hack but the socket class does what's needed already. + // For L2CP GATT we need a channel rather than a socket and the LE address type + // We don't want to make this public API offering for now especially since + // only Linux (of all platforms supported by this library) supports this type + // of socket. + +#if QT_CONFIG(bluez) && !defined(QT_BLUEZ_NO_BTLE) + if (lowEnergySocketType) { + addr.l2_cid = htobs(port); + addr.l2_bdaddr_type = lowEnergySocketType; + } else { + addr.l2_psm = htobs(port); + } +#else + addr.l2_psm = htobs(port); +#endif + + convertAddress(address.toUInt64(), addr.l2_bdaddr.b); + + connectWriteNotifier->setEnabled(true); + readNotifier->setEnabled(true); + + result = ::connect(socket, (sockaddr *)&addr, sizeof(addr)); + } + + if (result >= 0 || (result == -1 && errno == EINPROGRESS)) { + connecting = true; + q->setSocketState(QBluetoothSocket::SocketState::ConnectingState); + q->setOpenMode(openMode); + } else { + errorString = qt_error_string(errno); + q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError); + } +} + +void QBluetoothSocketPrivateBluez::connectToService( + const QBluetoothServiceInfo &service, QIODevice::OpenMode openMode) +{ + Q_Q(QBluetoothSocket); + + if (q->state() != QBluetoothSocket::SocketState::UnconnectedState + && q->state() != QBluetoothSocket::SocketState::ServiceLookupState) { + qCWarning(QT_BT_BLUEZ) << "QBluetoothSocketPrivateBluez::connectToService called on busy socket"; + errorString = QBluetoothSocket::tr("Trying to connect while connection is in progress"); + q->setSocketError(QBluetoothSocket::SocketError::OperationError); + return; + } + + // we are checking the service protocol and not socketType() + // socketType will change in ensureNativeSocket() + if (service.socketProtocol() == QBluetoothServiceInfo::UnknownProtocol) { + qCWarning(QT_BT_BLUEZ) << "QBluetoothSocket::connectToService cannot " + "connect with 'UnknownProtocol' (type provided by given service)"; + errorString = QBluetoothSocket::tr("Socket type not supported"); + q->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError); + return; + } + + if (service.protocolServiceMultiplexer() > 0) { + Q_ASSERT(service.socketProtocol() == QBluetoothServiceInfo::L2capProtocol); + + if (!ensureNativeSocket(QBluetoothServiceInfo::L2capProtocol)) { + errorString = QBluetoothSocket::tr("Unknown socket error"); + q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError); + return; + } + connectToServiceHelper(service.device().address(), service.protocolServiceMultiplexer(), + openMode); + } else if (service.serverChannel() > 0) { + Q_ASSERT(service.socketProtocol() == QBluetoothServiceInfo::RfcommProtocol); + + if (!ensureNativeSocket(QBluetoothServiceInfo::RfcommProtocol)) { + errorString = QBluetoothSocket::tr("Unknown socket error"); + q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError); + return; + } + connectToServiceHelper(service.device().address(), service.serverChannel(), openMode); + } else { + // try doing service discovery to see if we can find the socket + if (service.serviceUuid().isNull() + && !service.serviceClassUuids().contains(QBluetoothUuid::ServiceClassUuid::SerialPort)) { + qCWarning(QT_BT_BLUEZ) << "No port, no PSM, and no UUID provided. Unable to connect"; + return; + } + qCDebug(QT_BT_BLUEZ) << "Need a port/psm, doing discovery"; + q->doDeviceDiscovery(service, openMode); + } +} + +void QBluetoothSocketPrivateBluez::connectToService( + const QBluetoothAddress &address, const QBluetoothUuid &uuid, + QIODevice::OpenMode openMode) +{ + Q_Q(QBluetoothSocket); + + if (q->state() != QBluetoothSocket::SocketState::UnconnectedState) { + qCWarning(QT_BT_BLUEZ) << "QBluetoothSocketPrivateBluez::connectToService called on busy socket"; + errorString = QBluetoothSocket::tr("Trying to connect while connection is in progress"); + q->setSocketError(QBluetoothSocket::SocketError::OperationError); + return; + } + + if (q->socketType() == QBluetoothServiceInfo::UnknownProtocol) { + qCWarning(QT_BT_BLUEZ) << "QBluetoothSocketPrivateBluez::connectToService cannot " + "connect with 'UnknownProtocol' (type provided by given service)"; + errorString = QBluetoothSocket::tr("Socket type not supported"); + q->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError); + return; + } + + QBluetoothServiceInfo service; + QBluetoothDeviceInfo device(address, QString(), QBluetoothDeviceInfo::MiscellaneousDevice); + service.setDevice(device); + service.setServiceUuid(uuid); + q->doDeviceDiscovery(service, openMode); +} + +void QBluetoothSocketPrivateBluez::connectToService( + const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode) +{ + Q_Q(QBluetoothSocket); + + if (q->socketType() == QBluetoothServiceInfo::UnknownProtocol) { + qCWarning(QT_BT_BLUEZ) << "QBluetoothSocketPrivateBluez::connectToService cannot " + "connect with 'UnknownProtocol' (type provided by given service)"; + errorString = QBluetoothSocket::tr("Socket type not supported"); + q->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError); + return; + } + + if (q->state() != QBluetoothSocket::SocketState::UnconnectedState) { + qCWarning(QT_BT_BLUEZ) << "QBluetoothSocketPrivateBluez::connectToService called on busy socket"; + errorString = QBluetoothSocket::tr("Trying to connect while connection is in progress"); + q->setSocketError(QBluetoothSocket::SocketError::OperationError); + return; + } + connectToServiceHelper(address, port, openMode); +} + +void QBluetoothSocketPrivateBluez::_q_writeNotify() +{ + Q_Q(QBluetoothSocket); + if (connecting && state == QBluetoothSocket::SocketState::ConnectingState){ + int errorno, len; + len = sizeof(errorno); + ::getsockopt(socket, SOL_SOCKET, SO_ERROR, &errorno, (socklen_t*)&len); + if(errorno) { + errorString = qt_error_string(errorno); + q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError); + return; + } + + q->setSocketState(QBluetoothSocket::SocketState::ConnectedState); + + connectWriteNotifier->setEnabled(false); + connecting = false; + } + else { + if (txBuffer.size() == 0) { + connectWriteNotifier->setEnabled(false); + return; + } + + char buf[1024]; + + const auto size = txBuffer.read(buf, 1024); + const auto writtenBytes = qt_safe_write(socket, buf, size); + if (writtenBytes < 0) { + switch (errno) { + case EAGAIN: + txBuffer.ungetBlock(buf, size); + break; + default: + // every other case returns error + errorString = QBluetoothSocket::tr("Network Error: %1").arg(qt_error_string(errno)) ; + q->setSocketError(QBluetoothSocket::SocketError::NetworkError); + break; + } + } else { + if (writtenBytes < size) { + // add remainder back to buffer + char* remainder = buf + writtenBytes; + txBuffer.ungetBlock(remainder, size - writtenBytes); + } + if (writtenBytes > 0) + emit q->bytesWritten(writtenBytes); + } + + if (txBuffer.size()) { + connectWriteNotifier->setEnabled(true); + } + else if (state == QBluetoothSocket::SocketState::ClosingState) { + connectWriteNotifier->setEnabled(false); + this->close(); + } + } +} + +void QBluetoothSocketPrivateBluez::_q_readNotify() +{ + Q_Q(QBluetoothSocket); + char *writePointer = rxBuffer.reserve(QPRIVATELINEARBUFFER_BUFFERSIZE); +// qint64 readFromDevice = q->readData(writePointer, QPRIVATELINEARBUFFER_BUFFERSIZE); + const auto readFromDevice = ::read(socket, writePointer, QPRIVATELINEARBUFFER_BUFFERSIZE); + rxBuffer.chop(QPRIVATELINEARBUFFER_BUFFERSIZE - (readFromDevice < 0 ? 0 : readFromDevice)); + if(readFromDevice <= 0){ + int errsv = errno; + readNotifier->setEnabled(false); + connectWriteNotifier->setEnabled(false); + errorString = qt_error_string(errsv); + qCWarning(QT_BT_BLUEZ) << Q_FUNC_INFO << socket << "error:" << readFromDevice << errorString; + if (errsv == EHOSTDOWN) + q->setSocketError(QBluetoothSocket::SocketError::HostNotFoundError); + else if (errsv == ECONNRESET) + q->setSocketError(QBluetoothSocket::SocketError::RemoteHostClosedError); + else + q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError); + + q->disconnectFromService(); + } + else { + emit q->readyRead(); + } +} + +void QBluetoothSocketPrivateBluez::abort() +{ + delete readNotifier; + readNotifier = nullptr; + delete connectWriteNotifier; + connectWriteNotifier = nullptr; + + // We don't transition through Closing for abort, so + // we don't call disconnectFromService or + // QBluetoothSocket::close + QT_CLOSE(socket); + socket = -1; + + Q_Q(QBluetoothSocket); + + q->setOpenMode(QIODevice::NotOpen); + q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState); + emit q->readChannelFinished(); +} + +QString QBluetoothSocketPrivateBluez::localName() const +{ + const QBluetoothAddress address = localAddress(); + if (address.isNull()) + return QString(); + + QBluetoothLocalDevice device(address); + return device.name(); +} + +QBluetoothAddress QBluetoothSocketPrivateBluez::localAddress() const +{ + if (socketType == QBluetoothServiceInfo::RfcommProtocol) { + sockaddr_rc addr; + socklen_t addrLength = sizeof(addr); + + if (::getsockname(socket, reinterpret_cast(&addr), &addrLength) == 0) + return QBluetoothAddress(convertAddress(addr.rc_bdaddr.b)); + } else if (socketType == QBluetoothServiceInfo::L2capProtocol) { + sockaddr_l2 addr; + socklen_t addrLength = sizeof(addr); + + if (::getsockname(socket, reinterpret_cast(&addr), &addrLength) == 0) + return QBluetoothAddress(convertAddress(addr.l2_bdaddr.b)); + } + + return QBluetoothAddress(); +} + +quint16 QBluetoothSocketPrivateBluez::localPort() const +{ + if (socketType == QBluetoothServiceInfo::RfcommProtocol) { + sockaddr_rc addr; + socklen_t addrLength = sizeof(addr); + + if (::getsockname(socket, reinterpret_cast(&addr), &addrLength) == 0) + return addr.rc_channel; + } else if (socketType == QBluetoothServiceInfo::L2capProtocol) { + sockaddr_l2 addr; + socklen_t addrLength = sizeof(addr); + + if (::getsockname(socket, reinterpret_cast(&addr), &addrLength) == 0) + return addr.l2_psm; + } + + return 0; +} + +QString QBluetoothSocketPrivateBluez::peerName() const +{ + quint64 bdaddr; + + if (socketType == QBluetoothServiceInfo::RfcommProtocol) { + sockaddr_rc addr; + socklen_t addrLength = sizeof(addr); + + if (::getpeername(socket, reinterpret_cast(&addr), &addrLength) < 0) + return QString(); + + convertAddress(addr.rc_bdaddr.b, &bdaddr); + } else if (socketType == QBluetoothServiceInfo::L2capProtocol) { + sockaddr_l2 addr; + socklen_t addrLength = sizeof(addr); + + if (::getpeername(socket, reinterpret_cast(&addr), &addrLength) < 0) + return QString(); + + convertAddress(addr.l2_bdaddr.b, &bdaddr); + } else { + qCWarning(QT_BT_BLUEZ) << "peerName() called on socket of unknown type"; + return QString(); + } + + const QString peerAddress = QBluetoothAddress(bdaddr).toString(); + + initializeBluez5(); + OrgFreedesktopDBusObjectManagerInterface manager( + QStringLiteral("org.bluez"), QStringLiteral("/"), QDBusConnection::systemBus()); + QDBusPendingReply reply = manager.GetManagedObjects(); + reply.waitForFinished(); + if (reply.isError()) + return QString(); + + ManagedObjectList managedObjectList = reply.value(); + for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); + it != managedObjectList.constEnd(); ++it) { + const InterfaceList &ifaceList = it.value(); + + for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); + ++jt) { + const QString &iface = jt.key(); + const QVariantMap &ifaceValues = jt.value(); + + if (iface == QStringLiteral("org.bluez.Device1")) { + if (ifaceValues.value(QStringLiteral("Address")).toString() == peerAddress) + return ifaceValues.value(QStringLiteral("Alias")).toString(); + } + } + } + return QString(); +} + +QBluetoothAddress QBluetoothSocketPrivateBluez::peerAddress() const +{ + if (socketType == QBluetoothServiceInfo::RfcommProtocol) { + sockaddr_rc addr; + socklen_t addrLength = sizeof(addr); + + if (::getpeername(socket, reinterpret_cast(&addr), &addrLength) == 0) + return QBluetoothAddress(convertAddress(addr.rc_bdaddr.b)); + } else if (socketType == QBluetoothServiceInfo::L2capProtocol) { + sockaddr_l2 addr; + socklen_t addrLength = sizeof(addr); + + if (::getpeername(socket, reinterpret_cast(&addr), &addrLength) == 0) + return QBluetoothAddress(convertAddress(addr.l2_bdaddr.b)); + } + + return QBluetoothAddress(); +} + +quint16 QBluetoothSocketPrivateBluez::peerPort() const +{ + if (socketType == QBluetoothServiceInfo::RfcommProtocol) { + sockaddr_rc addr; + socklen_t addrLength = sizeof(addr); + + if (::getpeername(socket, reinterpret_cast(&addr), &addrLength) == 0) + return addr.rc_channel; + } else if (socketType == QBluetoothServiceInfo::L2capProtocol) { + sockaddr_l2 addr; + socklen_t addrLength = sizeof(addr); + + if (::getpeername(socket, reinterpret_cast(&addr), &addrLength) == 0) + return addr.l2_psm; + } + + return 0; +} + +qint64 QBluetoothSocketPrivateBluez::writeData(const char *data, qint64 maxSize) +{ + Q_Q(QBluetoothSocket); + + if (state != QBluetoothSocket::SocketState::ConnectedState) { + errorString = QBluetoothSocket::tr("Cannot write while not connected"); + q->setSocketError(QBluetoothSocket::SocketError::OperationError); + return -1; + } + + if (q->openMode() & QIODevice::Unbuffered) { + auto sz = ::qt_safe_write(socket, data, maxSize); + if (sz < 0) { + switch (errno) { + case EAGAIN: + sz = 0; + break; + default: + errorString = QBluetoothSocket::tr("Network Error: %1").arg(qt_error_string(errno)); + q->setSocketError(QBluetoothSocket::SocketError::NetworkError); + } + } + + if (sz > 0) + emit q->bytesWritten(sz); + + return sz; + } + else { + + if(!connectWriteNotifier) + return -1; + + if(txBuffer.size() == 0) { + connectWriteNotifier->setEnabled(true); + QMetaObject::invokeMethod(this, "_q_writeNotify", Qt::QueuedConnection); + } + + char *txbuf = txBuffer.reserve(maxSize); + memcpy(txbuf, data, maxSize); + + return maxSize; + } +} + +qint64 QBluetoothSocketPrivateBluez::readData(char *data, qint64 maxSize) +{ + Q_Q(QBluetoothSocket); + + if (state != QBluetoothSocket::SocketState::ConnectedState) { + errorString = QBluetoothSocket::tr("Cannot read while not connected"); + q->setSocketError(QBluetoothSocket::SocketError::OperationError); + return -1; + } + + if (!rxBuffer.isEmpty()) + return rxBuffer.read(data, maxSize); + + return 0; +} + +void QBluetoothSocketPrivateBluez::close() +{ + // If we have pending data on the write buffer, wait until it has been written, + // after which this close() will be called again + if (txBuffer.size() > 0) + connectWriteNotifier->setEnabled(true); + else + abort(); +} + +bool QBluetoothSocketPrivateBluez::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType_, + QBluetoothSocket::SocketState socketState, QBluetoothSocket::OpenMode openMode) +{ + Q_Q(QBluetoothSocket); + delete readNotifier; + readNotifier = nullptr; + delete connectWriteNotifier; + connectWriteNotifier = nullptr; + + socketType = socketType_; + if (socket != -1) + QT_CLOSE(socket); + + socket = socketDescriptor; + + // ensure that O_NONBLOCK is set on new connections. + int flags = fcntl(socket, F_GETFL, 0); + if (!(flags & O_NONBLOCK)) + fcntl(socket, F_SETFL, flags | O_NONBLOCK); + + readNotifier = new QSocketNotifier(socket, QSocketNotifier::Read); + QObject::connect(readNotifier, SIGNAL(activated(QSocketDescriptor)), this, SLOT(_q_readNotify())); + connectWriteNotifier = new QSocketNotifier(socket, QSocketNotifier::Write, q); + QObject::connect(connectWriteNotifier, SIGNAL(activated(QSocketDescriptor)), this, SLOT(_q_writeNotify())); + + q->setOpenMode(openMode); + q->setSocketState(socketState); + + return true; +} + +qint64 QBluetoothSocketPrivateBluez::bytesAvailable() const +{ + return rxBuffer.size(); +} + +qint64 QBluetoothSocketPrivateBluez::bytesToWrite() const +{ + return txBuffer.size(); +} + +bool QBluetoothSocketPrivateBluez::canReadLine() const +{ + return rxBuffer.canReadLine(); +} + +QT_END_NAMESPACE + +#include "moc_qbluetoothsocket_bluez_p.cpp" diff --git a/src/bluetooth/qbluetoothsocket_bluez_p.h b/src/bluetooth/qbluetoothsocket_bluez_p.h new file mode 100644 index 0000000..4f679b7 --- /dev/null +++ b/src/bluetooth/qbluetoothsocket_bluez_p.h @@ -0,0 +1,72 @@ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QBLUETOOTHSOCKET_BLUEZ_H +#define QBLUETOOTHSOCKET_BLUEZ_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 "qbluetoothsocketbase_p.h" + +QT_BEGIN_NAMESPACE + +class QBluetoothSocketPrivateBluez final: public QBluetoothSocketBasePrivate +{ + Q_OBJECT + +public: + QBluetoothSocketPrivateBluez(); + ~QBluetoothSocketPrivateBluez() override; + + void connectToServiceHelper(const QBluetoothAddress &address, + quint16 port, + QIODevice::OpenMode openMode) override; + + void connectToService(const QBluetoothServiceInfo &service, + QIODevice::OpenMode openMode) override; + void connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid, + QIODevice::OpenMode openMode) override; + void connectToService(const QBluetoothAddress &address, quint16 port, + QIODevice::OpenMode openMode) override; + + bool ensureNativeSocket(QBluetoothServiceInfo::Protocol type) override; + + QString localName() const override; + QBluetoothAddress localAddress() const override; + quint16 localPort() const override; + + QString peerName() const override; + QBluetoothAddress peerAddress() const override; + quint16 peerPort() const override; + + void abort() override; + void close() override; + + qint64 writeData(const char *data, qint64 maxSize) override; + qint64 readData(char *data, qint64 maxSize) override; + + bool setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType, + QBluetoothSocket::SocketState socketState = QBluetoothSocket::SocketState::ConnectedState, + QBluetoothSocket::OpenMode openMode = QBluetoothSocket::ReadWrite) override; + + qint64 bytesAvailable() const override; + bool canReadLine() const override; + qint64 bytesToWrite() const override; + +private slots: + void _q_readNotify(); + void _q_writeNotify(); +}; + +QT_END_NAMESPACE + +#endif // QBLUETOOTHSOCKET_BLUEZ_H diff --git a/src/bluetooth/qbluetoothsocket_bluezdbus.cpp b/src/bluetooth/qbluetoothsocket_bluezdbus.cpp new file mode 100644 index 0000000..6413296 --- /dev/null +++ b/src/bluetooth/qbluetoothsocket_bluezdbus.cpp @@ -0,0 +1,593 @@ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothsocket.h" +#include "qbluetoothsocket_bluezdbus_p.h" + +#include "bluez/bluez_data_p.h" +#include "bluez/bluez5_helper_p.h" +#include "bluez/adapter1_bluez5_p.h" +#include "bluez/device1_bluez5_p.h" +#include "bluez/objectmanager_p.h" +#include "bluez/profile1_p.h" +#include "bluez/profile1context_p.h" +#include "bluez/profilemanager1_p.h" + +#include +#include + +#include +#include + +#include + +#include + +QT_BEGIN_NAMESPACE + +using namespace Qt::StringLiterals; + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ) + +QBluetoothSocketPrivateBluezDBus::QBluetoothSocketPrivateBluezDBus() +{ + secFlags = QBluetooth::Security::NoSecurity; + + profileManager = new OrgBluezProfileManager1Interface( + QStringLiteral("org.bluez"), + QStringLiteral("/org/bluez"), + QDBusConnection::systemBus(), + this); +} + +QBluetoothSocketPrivateBluezDBus::~QBluetoothSocketPrivateBluezDBus() +{ +} + +bool QBluetoothSocketPrivateBluezDBus::ensureNativeSocket(QBluetoothServiceInfo::Protocol type) +{ + switch (type) { + case QBluetoothServiceInfo::UnknownProtocol: + break; + case QBluetoothServiceInfo::RfcommProtocol: + case QBluetoothServiceInfo::L2capProtocol: + socketType = type; + return true; + } + + return false; +} + +void QBluetoothSocketPrivateBluezDBus::connectToServiceHelper( + const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode) +{ + // TODO Remove when Bluez4 support dropped + // Only used by QBluetoothSocketPrivateBluez + Q_UNUSED(openMode); + Q_UNUSED(address); + Q_UNUSED(port); +} + +static QString findRemoteDevicePath(const QBluetoothAddress &address) +{ + OrgFreedesktopDBusObjectManagerInterface manager(QStringLiteral("org.bluez"), + QStringLiteral("/"), + QDBusConnection::systemBus()); + + bool ok = false; + const QString adapterPath = findAdapterForAddress(QBluetoothAddress(), &ok); + if (!ok) + return QString(); + + auto reply = manager.GetManagedObjects(); + reply.waitForFinished(); + if (reply.isError()) + return QString(); + + ManagedObjectList objectList = reply.value(); + for (ManagedObjectList::const_iterator it = objectList.constBegin(); + it != objectList.constEnd(); ++it) { + const QDBusObjectPath &path = it.key(); + const InterfaceList &ifaceList = it.value(); + + for (InterfaceList::const_iterator ifaceIter = ifaceList.constBegin(); + ifaceIter != ifaceList.constEnd(); ++ifaceIter) { + if (ifaceIter.key() == QStringLiteral("org.bluez.Device1")) { + if (path.path().indexOf(adapterPath) != 0) + continue; // devices whose path does not start with same path we skip + + OrgBluezDevice1Interface device(QStringLiteral("org.bluez"), + path.path(), QDBusConnection::systemBus()); + if (device.adapter().path() != adapterPath) + continue; + + const QBluetoothAddress btAddress(device.address()); + if (btAddress.isNull() || btAddress != address) + continue; + + return path.path(); + } + } + } + + return QString(); +} + +void QBluetoothSocketPrivateBluezDBus::connectToServiceHelper( + const QBluetoothAddress &address, const QBluetoothUuid &uuid, + QIODevice::OpenMode openMode) +{ + Q_Q(QBluetoothSocket); + + int i = 0; + bool success = false; + profileUuid = uuid.toString(QUuid::WithoutBraces); + + if (profileContext) { + qCDebug(QT_BT_BLUEZ) << "Profile context still active. close socket first."; + q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError); + return; + } + + + profileContext = new OrgBluezProfile1ContextInterface(this); + connect(profileContext, &OrgBluezProfile1ContextInterface::newConnection, + this, &QBluetoothSocketPrivateBluezDBus::remoteConnected); + + for (i = 0; i < 10 && !success; i++) { + // profile registration might fail in case other service uses same path + // try 10 times and otherwise abort + + profilePath = u"/qt/btsocket/%1%2/%3"_s. + arg(sanitizeNameForDBus(QCoreApplication::applicationName())). + arg(QCoreApplication::applicationPid()). + arg(QRandomGenerator::global()->generate()); + + success = QDBusConnection::systemBus().registerObject( + profilePath, profileContext, QDBusConnection::ExportAllSlots); + } + + if (!success) { + // we could not register the profile + qCWarning(QT_BT_BLUEZ) << "Cannot export serial client profile on DBus"; + + delete profileContext; + profileContext = nullptr; + + errorString = QBluetoothSocket::tr("Cannot export profile on DBus"); + q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError); + + return; + } + + QVariantMap profileOptions; + profileOptions.insert(QStringLiteral("Role"), QStringLiteral("client")); + profileOptions.insert(QStringLiteral("Service"), profileUuid); + profileOptions.insert(QStringLiteral("Name"), + QStringLiteral("QBluetoothSocket-%1").arg(QCoreApplication::applicationPid())); + + // TODO support more profile parameter + // profileOptions.insert(QStringLiteral("Channel"), 0); + + qCDebug(QT_BT_BLUEZ) << "Registering client profile on" << profilePath << "with options:"; + qCDebug(QT_BT_BLUEZ) << profileOptions; + QDBusPendingReply<> reply = profileManager->RegisterProfile( + QDBusObjectPath(profilePath), + profileUuid, + profileOptions); + reply.waitForFinished(); + if (reply.isError()) { + qCWarning(QT_BT_BLUEZ) << "Client profile registration failed:" + << reply.error().message(); + + QDBusConnection::systemBus().unregisterObject(profilePath); + errorString = QBluetoothSocket::tr("Cannot register profile on DBus"); + q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError); + return; + } + + remoteDevicePath = findRemoteDevicePath(address); + if (remoteDevicePath.isEmpty()) { + qCWarning(QT_BT_BLUEZ) << "Unknown remote device:" << address + << "Try device discovery first"; + clearSocket(); + + errorString = QBluetoothSocket::tr("Cannot find remote device"); + q->setSocketError(QBluetoothSocket::SocketError::HostNotFoundError); + return; + } + + OrgBluezDevice1Interface device(QStringLiteral("org.bluez"), remoteDevicePath, + QDBusConnection::systemBus()); + reply = device.ConnectProfile(profileUuid); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, &QDBusPendingCallWatcher::finished, + this, &QBluetoothSocketPrivateBluezDBus::connectToServiceReplyHandler); + + q->setOpenMode(openMode); + q->setSocketState(QBluetoothSocket::SocketState::ConnectingState); +} + +void QBluetoothSocketPrivateBluezDBus::connectToServiceReplyHandler( + QDBusPendingCallWatcher *watcher) +{ + Q_Q(QBluetoothSocket); + + QDBusPendingReply<> reply = *watcher; + if (reply.isError()) { + qCWarning(QT_BT_BLUEZ) << "Cannot connect to profile/service."; + + clearSocket(); + + errorString = QBluetoothSocket::tr("Cannot connect to remote profile"); + q->setSocketError(QBluetoothSocket::SocketError::HostNotFoundError); + } + watcher->deleteLater(); +} + +void QBluetoothSocketPrivateBluezDBus::connectToService( + const QBluetoothServiceInfo &service, QIODevice::OpenMode openMode) +{ + Q_Q(QBluetoothSocket); + QBluetoothUuid targetService; + + targetService = service.serviceUuid(); + if (targetService.isNull()) { + // Do we have serialport service class? + if (service.serviceClassUuids().contains(QBluetoothUuid::ServiceClassUuid::SerialPort)) + targetService = QBluetoothUuid::ServiceClassUuid::SerialPort; + } + + if (targetService.isNull()) { + qCWarning(QT_BT_BLUEZ) << "Cannot find appropriate serviceUuid" + << "or SerialPort service class uuid"; + errorString = QBluetoothSocket::tr("Missing serviceUuid or Serial Port service class uuid"); + q->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError); + return; + } + + if (service.socketProtocol() != QBluetoothServiceInfo::Protocol::UnknownProtocol) + socketType = service.socketProtocol(); + qCDebug(QT_BT_BLUEZ) << "Socket protocol used:" << socketType; + + connectToService(service.device().address(), targetService, openMode); +} + +void QBluetoothSocketPrivateBluezDBus::connectToService( + const QBluetoothAddress &address, const QBluetoothUuid &uuid, QIODevice::OpenMode openMode) +{ + Q_Q(QBluetoothSocket); + + if (address.isNull()) { + qCWarning(QT_BT_BLUEZ) << "Invalid address to remote address passed."; + errorString = QBluetoothSocket::tr("Invalid Bluetooth address passed to connectToService()"); + q->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError); + return; + } + + if (uuid.isNull()) { + qCWarning(QT_BT_BLUEZ) << "Cannot find appropriate serviceUuid" + << "or SerialPort service class uuid"; + errorString = QBluetoothSocket::tr("Missing serviceUuid or Serial Port service class uuid"); + q->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError); + return; + } + + if (q->state() != QBluetoothSocket::SocketState::UnconnectedState) { + qCWarning(QT_BT_BLUEZ) << "QBluetoothSocketPrivateBluezDBus::connectToService called on busy socket"; + errorString = QBluetoothSocket::tr("Trying to connect while connection is in progress"); + q->setSocketError(QBluetoothSocket::SocketError::OperationError); + return; + } + + if (q->socketType() == QBluetoothServiceInfo::UnknownProtocol) { + qCWarning(QT_BT_BLUEZ) << "QBluetoothSocketPrivateBluezDBus::connectToService cannot " + "connect with 'UnknownProtocol' (type provided by given service)"; + errorString = QBluetoothSocket::tr("Socket type not supported"); + q->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError); + return; + } + + if (!ensureNativeSocket(q->socketType())) { + errorString = QBluetoothSocket::tr("Socket type not supported"); + q->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError); + return; + } + connectToServiceHelper(address, uuid, openMode); +} + +void QBluetoothSocketPrivateBluezDBus::connectToService( + const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode) +{ + + Q_UNUSED(port); + Q_UNUSED(address); + Q_UNUSED(openMode); + Q_Q(QBluetoothSocket); + + errorString = tr("Connecting to port is not supported via Bluez DBus"); + q->setSocketError(QBluetoothSocket::SocketError::ServiceNotFoundError); + qCWarning(QT_BT_BLUEZ) << "Connecting to port is not supported (Uuid required)"; +} + +void QBluetoothSocketPrivateBluezDBus::abort() +{ + if (localSocket) { + localSocket->close(); + // delayed disconnected signal emission when localSocket closes + } else { + Q_Q(QBluetoothSocket); + + clearSocket(); + q->setOpenMode(QIODevice::NotOpen); + q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState); + emit q->readChannelFinished(); + } +} + +QString QBluetoothSocketPrivateBluezDBus::localName() const +{ + bool ok = false; + const QString adapterPath = findAdapterForAddress(QBluetoothAddress(), &ok); + if (!ok) + return QString(); + + OrgBluezAdapter1Interface adapter(QStringLiteral("org.bluez"), adapterPath, + QDBusConnection::systemBus()); + return QString(adapter.alias()); +} + +QBluetoothAddress QBluetoothSocketPrivateBluezDBus::localAddress() const +{ + bool ok = false; + const QString adapterPath = findAdapterForAddress(QBluetoothAddress(), &ok); + if (!ok) + return QBluetoothAddress(); + + OrgBluezAdapter1Interface adapter(QStringLiteral("org.bluez"), adapterPath, + QDBusConnection::systemBus()); + return QBluetoothAddress(adapter.address()); +} + +quint16 QBluetoothSocketPrivateBluezDBus::localPort() const +{ + int descriptor = -1; + + if (localSocket) + descriptor = int(localSocket->socketDescriptor()); + if (descriptor == -1) + return 0; + + if (socketType == QBluetoothServiceInfo::RfcommProtocol) { + sockaddr_rc addr; + socklen_t addrLength = sizeof(addr); + + if (::getsockname(descriptor, reinterpret_cast(&addr), &addrLength) == 0) + return (addr.rc_channel); + } else if (socketType == QBluetoothServiceInfo::L2capProtocol) { + sockaddr_l2 addr; + socklen_t addrLength = sizeof(addr); + + if (::getsockname(descriptor, reinterpret_cast(&addr), &addrLength) == 0) + return addr.l2_psm; + } + + return 0; +} + +QString QBluetoothSocketPrivateBluezDBus::peerName() const +{ + if (remoteDevicePath.isEmpty()) + return QString(); + + OrgBluezDevice1Interface device(QStringLiteral("org.bluez"), remoteDevicePath, + QDBusConnection::systemBus()); + return device.alias(); +} + +QBluetoothAddress QBluetoothSocketPrivateBluezDBus::peerAddress() const +{ + if (remoteDevicePath.isEmpty()) + return QBluetoothAddress(); + + OrgBluezDevice1Interface device(QStringLiteral("org.bluez"), remoteDevicePath, + QDBusConnection::systemBus()); + return QBluetoothAddress(device.address()); +} + +quint16 QBluetoothSocketPrivateBluezDBus::peerPort() const +{ + int descriptor = -1; + + if (localSocket) + descriptor = int(localSocket->socketDescriptor()); + if (descriptor == -1) + return 0; + + if (socketType == QBluetoothServiceInfo::RfcommProtocol) { + sockaddr_rc addr; + socklen_t addrLength = sizeof(addr); + + if (::getpeername(descriptor, reinterpret_cast(&addr), &addrLength) == 0) + return addr.rc_channel; + } else if (socketType == QBluetoothServiceInfo::L2capProtocol) { + sockaddr_l2 addr; + socklen_t addrLength = sizeof(addr); + + if (::getpeername(descriptor, reinterpret_cast(&addr), &addrLength) == 0) + return addr.l2_psm; + } + + return 0; +} + +qint64 QBluetoothSocketPrivateBluezDBus::writeData(const char *data, qint64 maxSize) +{ + Q_UNUSED(data); + Q_UNUSED(maxSize); + + Q_Q(QBluetoothSocket); + + if (state != QBluetoothSocket::SocketState::ConnectedState) { + errorString = QBluetoothSocket::tr("Cannot write while not connected"); + q->setSocketError(QBluetoothSocket::SocketError::OperationError); + return -1; + } + + if (localSocket) + return localSocket->write(data, maxSize); + + return -1; +} + +qint64 QBluetoothSocketPrivateBluezDBus::readData(char *data, qint64 maxSize) +{ + Q_UNUSED(data); + Q_UNUSED(maxSize); + + Q_Q(QBluetoothSocket); + + if (state != QBluetoothSocket::SocketState::ConnectedState) { + errorString = QBluetoothSocket::tr("Cannot read while not connected"); + q->setSocketError(QBluetoothSocket::SocketError::OperationError); + return -1; + } + + if (localSocket) + return localSocket->read(data, maxSize); + + return -1; +} + +void QBluetoothSocketPrivateBluezDBus::close() +{ + abort(); +} + +bool QBluetoothSocketPrivateBluezDBus::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType, + QBluetoothSocket::SocketState socketState, QBluetoothSocket::OpenMode openMode) +{ + Q_UNUSED(socketDescriptor); + Q_UNUSED(socketType); + Q_UNUSED(socketState); + Q_UNUSED(openMode); + return false; +} + +qint64 QBluetoothSocketPrivateBluezDBus::bytesAvailable() const +{ + if (localSocket) + return localSocket->bytesAvailable(); + + return 0; +} + +bool QBluetoothSocketPrivateBluezDBus::canReadLine() const +{ + if (localSocket) + return localSocket->canReadLine(); + + return false; +} + +qint64 QBluetoothSocketPrivateBluezDBus::bytesToWrite() const +{ + if (localSocket) + return localSocket->bytesToWrite(); + + return 0; +} + +void QBluetoothSocketPrivateBluezDBus::remoteConnected(const QDBusUnixFileDescriptor &fd) +{ + Q_Q(QBluetoothSocket); + + int descriptor = ::dup(fd.fileDescriptor()); + localSocket = new QLocalSocket(this); + bool success = localSocket->setSocketDescriptor( + descriptor, QLocalSocket::ConnectedState, q->openMode()); + if (!success || !localSocket->isValid()) { + q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState); + delete localSocket; + localSocket = nullptr; + } else { + connect(localSocket, &QLocalSocket::readyRead, + q, &QBluetoothSocket::readyRead); + connect(localSocket, &QLocalSocket::stateChanged, + this, &QBluetoothSocketPrivateBluezDBus::socketStateChanged); + connect(localSocket, &QLocalSocket::bytesWritten, + q, &QBluetoothSocket::bytesWritten); + + socket = descriptor; + q->setSocketState(QBluetoothSocket::SocketState::ConnectedState); + } +} + +void QBluetoothSocketPrivateBluezDBus::socketStateChanged(QLocalSocket::LocalSocketState newState) +{ + Q_Q(QBluetoothSocket); + + switch (newState) { + case QLocalSocket::ClosingState: + q->setSocketState(QBluetoothSocket::SocketState::ClosingState); + break; + case QLocalSocket::UnconnectedState: + clearSocket(); + q->setOpenMode(QIODevice::NotOpen); + q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState); + emit q->readChannelFinished(); + break; + default: + // ConnectingState and ConnectedState not mapped + // (already set at the time when the socket is created) + break; + } +} + +void QBluetoothSocketPrivateBluezDBus::clearSocket() +{ + Q_Q(QBluetoothSocket); + + if (profilePath.isEmpty()) + return; + + qCDebug(QT_BT_BLUEZ) << "Clearing profile called for" << profilePath; + + if (localSocket) { + localSocket->close(); + localSocket->deleteLater(); + localSocket = nullptr; + } + + socket = -1; + + if (q->state() == QBluetoothSocket::SocketState::ConnectedState) { + OrgBluezDevice1Interface device(QStringLiteral("org.bluez"), remoteDevicePath, + QDBusConnection::systemBus()); + auto reply = device.DisconnectProfile(profileUuid); + reply.waitForFinished(); + if (reply.isError()) { + qCWarning(QT_BT_BLUEZ) << "Disconnect profile failed:" + << reply.error().message(); + } + } + + QDBusPendingReply<> reply = profileManager->UnregisterProfile(QDBusObjectPath(profilePath)); + reply.waitForFinished(); + if (reply.isError()) + qCWarning(QT_BT_BLUEZ) << "Unregister profile:" << reply.error().message(); + + QDBusConnection::systemBus().unregisterObject(profilePath); + + if (profileContext) { + delete profileContext; + profileContext = nullptr; + } + + remoteDevicePath.clear(); + profileUuid.clear(); + profilePath.clear(); +} +QT_END_NAMESPACE + +#include "moc_qbluetoothsocket_bluezdbus_p.cpp" diff --git a/src/bluetooth/qbluetoothsocket_bluezdbus_p.h b/src/bluetooth/qbluetoothsocket_bluezdbus_p.h new file mode 100644 index 0000000..ad2191f --- /dev/null +++ b/src/bluetooth/qbluetoothsocket_bluezdbus_p.h @@ -0,0 +1,98 @@ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QBLUETOOTHSOCKET_BLUEZDBUS_H +#define QBLUETOOTHSOCKET_BLUEZDBUS_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 "qbluetoothsocketbase_p.h" + +#include + +#include +#include + +class OrgBluezProfileManager1Interface; + +QT_BEGIN_NAMESPACE + +class QLocalSocket; +class OrgBluezProfile1ContextInterface; + +class QBluetoothSocketPrivateBluezDBus final: public QBluetoothSocketBasePrivate +{ + Q_OBJECT + +public: + QBluetoothSocketPrivateBluezDBus(); + ~QBluetoothSocketPrivateBluezDBus() override; + + void connectToServiceHelper(const QBluetoothAddress &address, + quint16 port, + QIODevice::OpenMode openMode) override; + void connectToServiceHelper(const QBluetoothAddress &address, + const QBluetoothUuid &uuid, + QIODevice::OpenMode openMode); + + void connectToService(const QBluetoothServiceInfo &service, + QIODevice::OpenMode openMode) override; + void connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid, + QIODevice::OpenMode openMode) override; + void connectToService(const QBluetoothAddress &address, quint16 port, + QIODevice::OpenMode openMode) override; + + bool ensureNativeSocket(QBluetoothServiceInfo::Protocol type) override; + + QString localName() const override; + QBluetoothAddress localAddress() const override; + quint16 localPort() const override; + + QString peerName() const override; + QBluetoothAddress peerAddress() const override; + quint16 peerPort() const override; + + void abort() override; + void close() override; + + qint64 writeData(const char *data, qint64 maxSize) override; + qint64 readData(char *data, qint64 maxSize) override; + + bool setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType, + QBluetoothSocket::SocketState socketState = QBluetoothSocket::SocketState::ConnectedState, + QBluetoothSocket::OpenMode openMode = QBluetoothSocket::ReadWrite) override; + + qint64 bytesAvailable() const override; + bool canReadLine() const override; + qint64 bytesToWrite() const override; + +public slots: + void connectToServiceReplyHandler(QDBusPendingCallWatcher *); + +private: + void remoteConnected(const QDBusUnixFileDescriptor &fd); + void socketStateChanged(QLocalSocket::LocalSocketState newState); + + void clearSocket(); + +private: + OrgBluezProfileManager1Interface *profileManager = nullptr; + OrgBluezProfile1ContextInterface *profileContext = nullptr; + QString remoteDevicePath; + QString profileUuid; + QString profilePath; + QLocalSocket *localSocket = nullptr; +}; + +QT_END_NAMESPACE + +#endif // QBLUETOOTHSOCKET_BLUEZDBUS_H diff --git a/src/bluetooth/qbluetoothsocket_dummy.cpp b/src/bluetooth/qbluetoothsocket_dummy.cpp new file mode 100644 index 0000000..efe670b --- /dev/null +++ b/src/bluetooth/qbluetoothsocket_dummy.cpp @@ -0,0 +1,172 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothsocket.h" +#include "qbluetoothsocket_dummy_p.h" +#ifndef QT_IOS_BLUETOOTH +#include "dummy/dummy_helper_p.h" +#endif + +QT_BEGIN_NAMESPACE + +QBluetoothSocketPrivateDummy::QBluetoothSocketPrivateDummy() +{ + secFlags = QBluetooth::Security::NoSecurity; +#ifndef QT_IOS_BLUETOOTH + printDummyWarning(); +#endif +} + +QBluetoothSocketPrivateDummy::~QBluetoothSocketPrivateDummy() +{ +} + +bool QBluetoothSocketPrivateDummy::ensureNativeSocket(QBluetoothServiceInfo::Protocol type) +{ + socketType = type; + return false; +} + +void QBluetoothSocketPrivateDummy::connectToServiceHelper(const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode) +{ + Q_UNUSED(openMode); + Q_UNUSED(address); + Q_UNUSED(port); +} + +void QBluetoothSocketPrivateDummy::connectToService( + const QBluetoothServiceInfo &service, QIODevice::OpenMode openMode) +{ + Q_UNUSED(service); + Q_UNUSED(openMode); + + Q_Q(QBluetoothSocket); + + qWarning() << "Using non-functional QBluetoothSocketPrivateDummy"; + errorString = QBluetoothSocket::tr("Socket type not supported"); + q->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError); +} + +void QBluetoothSocketPrivateDummy::connectToService( + const QBluetoothAddress &address, const QBluetoothUuid &uuid, QIODevice::OpenMode openMode) +{ + Q_UNUSED(address); + Q_UNUSED(uuid); + Q_UNUSED(openMode); + + Q_Q(QBluetoothSocket); + + qWarning() << "Using non-functional QBluetoothSocketPrivateDummy"; + errorString = QBluetoothSocket::tr("Socket type not supported"); + q->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError); +} + +void QBluetoothSocketPrivateDummy::connectToService( + const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode) +{ + Q_UNUSED(address); + Q_UNUSED(port); + Q_UNUSED(openMode); + + Q_Q(QBluetoothSocket); + + qWarning() << "Using non-functional QBluetoothSocketPrivateDummy"; + errorString = QBluetoothSocket::tr("Socket type not supported"); + q->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError); +} + +void QBluetoothSocketPrivateDummy::abort() +{ +} + +QString QBluetoothSocketPrivateDummy::localName() const +{ + return QString(); +} + +QBluetoothAddress QBluetoothSocketPrivateDummy::localAddress() const +{ + return QBluetoothAddress(); +} + +quint16 QBluetoothSocketPrivateDummy::localPort() const +{ + return 0; +} + +QString QBluetoothSocketPrivateDummy::peerName() const +{ + return QString(); +} + +QBluetoothAddress QBluetoothSocketPrivateDummy::peerAddress() const +{ + return QBluetoothAddress(); +} + +quint16 QBluetoothSocketPrivateDummy::peerPort() const +{ + return 0; +} + +qint64 QBluetoothSocketPrivateDummy::writeData(const char *data, qint64 maxSize) +{ + Q_UNUSED(data); + Q_UNUSED(maxSize); + + Q_Q(QBluetoothSocket); + + if (state != QBluetoothSocket::SocketState::ConnectedState) { + errorString = QBluetoothSocket::tr("Cannot write while not connected"); + q->setSocketError(QBluetoothSocket::SocketError::OperationError); + return -1; + } + return -1; +} + +qint64 QBluetoothSocketPrivateDummy::readData(char *data, qint64 maxSize) +{ + Q_UNUSED(data); + Q_UNUSED(maxSize); + + Q_Q(QBluetoothSocket); + + if (state != QBluetoothSocket::SocketState::ConnectedState) { + errorString = QBluetoothSocket::tr("Cannot read while not connected"); + q->setSocketError(QBluetoothSocket::SocketError::OperationError); + return -1; + } + + return -1; +} + +void QBluetoothSocketPrivateDummy::close() +{ +} + +bool QBluetoothSocketPrivateDummy::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType, + QBluetoothSocket::SocketState socketState, QBluetoothSocket::OpenMode openMode) +{ + Q_UNUSED(socketDescriptor); + Q_UNUSED(socketType); + Q_UNUSED(socketState); + Q_UNUSED(openMode); + return false; +} + +qint64 QBluetoothSocketPrivateDummy::bytesAvailable() const +{ + return 0; +} + +bool QBluetoothSocketPrivateDummy::canReadLine() const +{ + return false; +} + +qint64 QBluetoothSocketPrivateDummy::bytesToWrite() const +{ + return 0; +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothsocket_dummy_p.h b/src/bluetooth/qbluetoothsocket_dummy_p.h new file mode 100644 index 0000000..3780441 --- /dev/null +++ b/src/bluetooth/qbluetoothsocket_dummy_p.h @@ -0,0 +1,72 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QBLUETOOTHSOCKET_DUMMY_H +#define QBLUETOOTHSOCKET_DUMMY_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 "qbluetoothsocket.h" +#include "qbluetoothsocketbase_p.h" +#include + +QT_BEGIN_NAMESPACE + +class QBluetoothSocketPrivateDummy final : public QBluetoothSocketBasePrivate +{ + Q_OBJECT + friend class QBluetoothServerPrivate; + +public: + QBluetoothSocketPrivateDummy(); + ~QBluetoothSocketPrivateDummy() override; + + void connectToServiceHelper(const QBluetoothAddress &address, + quint16 port, + QIODevice::OpenMode openMode) override; + + void connectToService(const QBluetoothServiceInfo &service, + QIODevice::OpenMode openMode) override; + void connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid, + QIODevice::OpenMode openMode) override; + void connectToService(const QBluetoothAddress &address, quint16 port, + QIODevice::OpenMode openMode) override; + + bool ensureNativeSocket(QBluetoothServiceInfo::Protocol type) override; + + QString localName() const override; + QBluetoothAddress localAddress() const override; + quint16 localPort() const override; + + QString peerName() const override; + QBluetoothAddress peerAddress() const override; + quint16 peerPort() const override; + + void abort() override; + void close() override; + + qint64 writeData(const char *data, qint64 maxSize) override; + qint64 readData(char *data, qint64 maxSize) override; + + bool setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType, + QBluetoothSocket::SocketState socketState = QBluetoothSocket::SocketState::ConnectedState, + QBluetoothSocket::OpenMode openMode = QBluetoothSocket::ReadWrite) override; + + qint64 bytesAvailable() const override; + bool canReadLine() const override; + qint64 bytesToWrite() const override; +}; + +QT_END_NAMESPACE + +#endif // QBLUETOOTHSOCKET_DUMMY_H + diff --git a/src/bluetooth/qbluetoothsocket_macos.mm b/src/bluetooth/qbluetoothsocket_macos.mm new file mode 100644 index 0000000..aabf179 --- /dev/null +++ b/src/bluetooth/qbluetoothsocket_macos.mm @@ -0,0 +1,531 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothservicediscoveryagent.h" +// The order is important (the first header contains +// the base class for a private socket) - workaround for +// dependencies problem. +#include "qbluetoothsocketbase_p.h" +#include "qbluetoothsocket_macos_p.h" + +#include "darwin/btrfcommchannel_p.h" +#include "darwin/btl2capchannel_p.h" +#include "qbluetoothlocaldevice.h" +#include "qbluetoothdeviceinfo.h" +#include "darwin/btutility_p.h" +#include "darwin/uistrings_p.h" +#include "qbluetoothsocket.h" + +#include +#include +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +namespace { + +using DarwinBluetooth::RetainPolicy; + +} // unnamed namespace + +QBluetoothSocketPrivateDarwin::QBluetoothSocketPrivateDarwin() + : writeChunk(std::numeric_limits::max()) +{ + q_ptr = nullptr; +} + +QBluetoothSocketPrivateDarwin::~QBluetoothSocketPrivateDarwin() +{ +} + +bool QBluetoothSocketPrivateDarwin::ensureNativeSocket(QBluetoothServiceInfo::Protocol type) +{ + // For now - very simplistic, we don't call it in this file, public class + // only calls it in a ctor, setting the protocol RFCOMM (in case of Android) + // or, indeed, doing, socket-related initialization in BlueZ backend. + Q_ASSERT(socketType == QBluetoothServiceInfo::UnknownProtocol); + socketType = type; + return type != QBluetoothServiceInfo::UnknownProtocol; +} + +QString QBluetoothSocketPrivateDarwin::localName() const +{ + const QBluetoothLocalDevice device; + return device.name(); +} + +QBluetoothAddress QBluetoothSocketPrivateDarwin::localAddress() const +{ + const QBluetoothLocalDevice device; + return device.address(); +} + +quint16 QBluetoothSocketPrivateDarwin::localPort() const +{ + return 0; +} + +QString QBluetoothSocketPrivateDarwin::peerName() const +{ + QT_BT_MAC_AUTORELEASEPOOL; + + NSString *nsName = nil; + if (socketType == QBluetoothServiceInfo::RfcommProtocol) { + if (rfcommChannel) + nsName = [rfcommChannel.getAs() peerName]; + } else if (socketType == QBluetoothServiceInfo::L2capProtocol) { + if (l2capChannel) + nsName = [l2capChannel.getAs() peerName]; + } + + if (nsName) + return QString::fromNSString(nsName); + + return QString(); +} + +QBluetoothAddress QBluetoothSocketPrivateDarwin::peerAddress() const +{ + BluetoothDeviceAddress addr = {}; + if (socketType == QBluetoothServiceInfo::RfcommProtocol) { + if (rfcommChannel) + addr = [rfcommChannel.getAs() peerAddress]; + } else if (socketType == QBluetoothServiceInfo::L2capProtocol) { + if (l2capChannel) + addr = [l2capChannel.getAs() peerAddress]; + } + + return DarwinBluetooth::qt_address(&addr); +} + +quint16 QBluetoothSocketPrivateDarwin::peerPort() const +{ + if (socketType == QBluetoothServiceInfo::RfcommProtocol) { + if (rfcommChannel) + return [rfcommChannel.getAs() getChannelID]; + } else if (socketType == QBluetoothServiceInfo::L2capProtocol) { + if (l2capChannel) + return [l2capChannel.getAs() getPSM]; + } + + return 0; +} + +void QBluetoothSocketPrivateDarwin::abort() +{ + // Can never be called while we're in connectToService: + Q_ASSERT_X(!isConnecting, Q_FUNC_INFO, "internal inconsistency - " + "still in connectToService()"); + + if (socketType == QBluetoothServiceInfo::RfcommProtocol) + rfcommChannel.reset(); + else if (socketType == QBluetoothServiceInfo::L2capProtocol) + l2capChannel.reset(); + + Q_ASSERT(q_ptr); + + q_ptr->setSocketState(QBluetoothSocket::SocketState::UnconnectedState); + emit q_ptr->readChannelFinished(); + +} + +void QBluetoothSocketPrivateDarwin::close() +{ + // Can never be called while we're in connectToService: + Q_ASSERT_X(!isConnecting, Q_FUNC_INFO, "internal inconsistency - " + "still in connectToService()"); + + if (!txBuffer.size()) + abort(); +} + + +qint64 QBluetoothSocketPrivateDarwin::writeData(const char *data, qint64 maxSize) +{ + Q_ASSERT_X(data, Q_FUNC_INFO, "invalid data (null)"); + Q_ASSERT_X(maxSize > 0, Q_FUNC_INFO, "invalid data size"); + + if (state != QBluetoothSocket::SocketState::ConnectedState) { + errorString = QCoreApplication::translate(SOCKET, SOC_NOWRITE); + q_ptr->setSocketError(QBluetoothSocket::SocketError::OperationError); + return -1; + } + + // We do not have a real socket API under the hood, + // IOBluetoothL2CAPChannel is buffered (writeAsync). + + if (!txBuffer.size()) + QMetaObject::invokeMethod(this, [this](){_q_writeNotify();}, Qt::QueuedConnection); + + char *dst = txBuffer.reserve(int(maxSize)); + std::copy(data, data + maxSize, dst); + + return maxSize; +} + +qint64 QBluetoothSocketPrivateDarwin::readData(char *data, qint64 maxSize) +{ + if (!data) + return 0; + + if (state != QBluetoothSocket::SocketState::ConnectedState) { + errorString = QCoreApplication::translate(SOCKET, SOC_NOREAD); + q_ptr->setSocketError(QBluetoothSocket::SocketError::OperationError); + return -1; + } + + if (!rxBuffer.isEmpty()) + return rxBuffer.read(data, int(maxSize)); + + return 0; +} + +qint64 QBluetoothSocketPrivateDarwin::bytesAvailable() const +{ + return rxBuffer.size(); +} + +bool QBluetoothSocketPrivateDarwin::canReadLine() const +{ + return rxBuffer.canReadLine(); +} + +qint64 QBluetoothSocketPrivateDarwin::bytesToWrite() const +{ + return txBuffer.size(); +} + +bool QBluetoothSocketPrivateDarwin::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType, + QBluetoothSocket::SocketState socketState, QIODevice::OpenMode openMode) +{ + Q_UNUSED(socketDescriptor); + Q_UNUSED(socketType); + Q_UNUSED(socketState); + Q_UNUSED(openMode); + + qCWarning(QT_BT_DARWIN) << "setting a socket descriptor is not supported by IOBluetooth"; + // Noop on macOS. + return false; +} + +void QBluetoothSocketPrivateDarwin::connectToServiceHelper(const QBluetoothAddress &address, quint16 port, + QIODevice::OpenMode openMode) +{ + Q_UNUSED(address); + Q_UNUSED(port); + Q_UNUSED(openMode); +} + +void QBluetoothSocketPrivateDarwin::connectToService(const QBluetoothServiceInfo &service, QIODevice::OpenMode openMode) +{ + Q_ASSERT(q_ptr); + + DarwinBluetooth::qt_test_iobluetooth_runloop(); + + if (state!= QBluetoothSocket::SocketState::UnconnectedState && state != QBluetoothSocket::SocketState::ServiceLookupState) { + qCWarning(QT_BT_DARWIN) << "called on a busy socket"; + errorString = QCoreApplication::translate(SOCKET, SOC_CONNECT_IN_PROGRESS); + q_ptr->setSocketError(QBluetoothSocket::SocketError::OperationError); + return; + } + + // Report this problem early, potentially avoid device discovery: + if (service.socketProtocol() == QBluetoothServiceInfo::UnknownProtocol) { + qCWarning(QT_BT_DARWIN) << Q_FUNC_INFO << "cannot connect with 'UnknownProtocol' type"; + errorString = QCoreApplication::translate(SOCKET, SOC_NETWORK_ERROR); + q_ptr->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError); + return; + } + + socketType = service.socketProtocol(); + + if (service.protocolServiceMultiplexer() > 0) { + connectToService(service.device().address(), + quint16(service.protocolServiceMultiplexer()), + openMode); + } else if (service.serverChannel() > 0) { + connectToService(service.device().address(), + quint16(service.serverChannel()), + openMode); + } else { + // Try service discovery. + if (service.serviceUuid().isNull()) { + qCWarning(QT_BT_DARWIN) << "No port, no PSM, and no " + "UUID provided, unable to connect"; + return; + } + + q_ptr->doDeviceDiscovery(service, openMode); + } +} + +void QBluetoothSocketPrivateDarwin::connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid, + QIODevice::OpenMode openMode) +{ + Q_ASSERT(q_ptr); + + DarwinBluetooth::qt_test_iobluetooth_runloop(); + + // Report this problem early, avoid device discovery: + if (socketType == QBluetoothServiceInfo::UnknownProtocol) { + qCWarning(QT_BT_DARWIN) << Q_FUNC_INFO << "cannot connect with 'UnknownProtocol' type"; + errorString = QCoreApplication::translate(SOCKET, SOC_NETWORK_ERROR); + q_ptr->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError); + return; + } + + if (state != QBluetoothSocket::SocketState::UnconnectedState) { + qCWarning(QT_BT_DARWIN) << "called on a busy socket"; + errorString = QCoreApplication::translate(SOCKET, SOC_CONNECT_IN_PROGRESS); + q_ptr->setSocketError(QBluetoothSocket::SocketError::OperationError); + return; + } + + QBluetoothDeviceInfo device(address, QString(), QBluetoothDeviceInfo::MiscellaneousDevice); + QBluetoothServiceInfo service; + service.setDevice(device); + service.setServiceUuid(uuid); + q_ptr->doDeviceDiscovery(service, openMode); +} + +void QBluetoothSocketPrivateDarwin::connectToService(const QBluetoothAddress &address, quint16 port, + QIODevice::OpenMode mode) +{ + Q_ASSERT(q_ptr); + + DarwinBluetooth::qt_test_iobluetooth_runloop(); + + if (socketType == QBluetoothServiceInfo::UnknownProtocol) { + qCWarning(QT_BT_DARWIN) << Q_FUNC_INFO << "cannot connect with 'UnknownProtocol' type"; + errorString = QCoreApplication::translate(SOCKET, SOC_NETWORK_ERROR); + q_ptr->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError); + return; + } + + Q_ASSERT_X(state == QBluetoothSocket::SocketState::ServiceLookupState || state == QBluetoothSocket::SocketState::UnconnectedState, + Q_FUNC_INFO, "invalid state"); + + q_ptr->setOpenMode(mode); + + socketError = QBluetoothSocket::SocketError::NoSocketError; + errorString.clear(); + rxBuffer.clear(); + txBuffer.clear(); + + IOReturn status = kIOReturnError; + // Setting socket state on q_ptr will emit a signal, + // we'd like to avoid any signal until this function completes. + const QBluetoothSocket::SocketState oldState = state; + // To prevent other connectToService calls (from QBluetoothSocket): + // and also avoid signals in delegate callbacks. + state = QBluetoothSocket::SocketState::ConnectingState; + // We're still inside this function: + isConnecting = true; + + // We'll later (or now) have to set an open mode on QBluetoothSocket. + openMode = mode; + + if (socketType == QBluetoothServiceInfo::RfcommProtocol) { + rfcommChannel.reset([[DarwinBTRFCOMMChannel alloc] initWithDelegate:this], RetainPolicy::noInitialRetain); + if (rfcommChannel) + status = [rfcommChannel.getAs() connectAsyncToDevice:address withChannelID:port]; + else + status = kIOReturnNoMemory; + } else if (socketType == QBluetoothServiceInfo::L2capProtocol) { + l2capChannel.reset([[DarwinBTL2CAPChannel alloc] initWithDelegate:this], RetainPolicy::noInitialRetain); + if (l2capChannel) + status = [l2capChannel.getAs() connectAsyncToDevice:address withPSM:port]; + else + status = kIOReturnNoMemory; + } + + // We're probably still connecting, but at least are leaving this function: + isConnecting = false; + + // QBluetoothSocket will change the state and also emit + // a signal later if required. + if (status == kIOReturnSuccess && socketError == QBluetoothSocket::SocketError::NoSocketError) { + if (state == QBluetoothSocket::SocketState::ConnectedState) { + // Callback 'channelOpenComplete' fired before + // connectToService finished: + state = oldState; + // Connected, setOpenMode on a QBluetoothSocket. + q_ptr->setOpenMode(openMode); + q_ptr->setSocketState(QBluetoothSocket::SocketState::ConnectedState); + if (rxBuffer.size()) // We also have some data already ... + emit q_ptr->readyRead(); + } else if (state == QBluetoothSocket::SocketState::UnconnectedState) { + // Even if we have some data, we can not read it if + // state != ConnectedState. + rxBuffer.clear(); + state = oldState; + q_ptr->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError); + } else { + // No error and we're connecting ... + state = oldState; + q_ptr->setSocketState(QBluetoothSocket::SocketState::ConnectingState); + } + } else { + state = oldState; + if (status != kIOReturnSuccess) + errorString = DarwinBluetooth::qt_error_string(status); + q_ptr->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError); + } +} + +void QBluetoothSocketPrivateDarwin::_q_writeNotify() +{ + Q_ASSERT_X(socketType == QBluetoothServiceInfo::L2capProtocol + || socketType == QBluetoothServiceInfo::RfcommProtocol, + Q_FUNC_INFO, "invalid socket type"); + Q_ASSERT_X(l2capChannel || rfcommChannel, Q_FUNC_INFO, + "invalid socket (no open channel)"); + Q_ASSERT_X(q_ptr, Q_FUNC_INFO, "invalid q_ptr (null)"); + + if (txBuffer.size()) { + const bool isL2CAP = socketType == QBluetoothServiceInfo::L2capProtocol; + writeChunk.resize(isL2CAP ? std::numeric_limits::max() : + [rfcommChannel.getAs() getMTU]); + + const auto size = txBuffer.read(writeChunk.data(), writeChunk.size()); + IOReturn status = kIOReturnError; + if (!isL2CAP) + status = [rfcommChannel.getAs() writeAsync:writeChunk.data() length:UInt16(size)]; + else + status = [l2capChannel.getAs() writeAsync:writeChunk.data() length:UInt16(size)]; + + if (status != kIOReturnSuccess) { + errorString = QCoreApplication::translate(SOCKET, SOC_NETWORK_ERROR); + q_ptr->setSocketError(QBluetoothSocket::SocketError::NetworkError); + return; + } else { + emit q_ptr->bytesWritten(size); + } + } + + if (!txBuffer.size() && state == QBluetoothSocket::SocketState::ClosingState) + close(); +} + +bool QBluetoothSocketPrivateDarwin::setRFCOMChannel(void *generic) +{ + // A special case "constructor": on OS X we do not have a real listening socket, + // instead a bluetooth server "listens" for channel open notifications and + // creates (if asked by a user later) a "socket" object + // for this connection. This function initializes + // a "socket" from such an external channel (reported by a notification). + auto channel = static_cast(generic); + // It must be a newborn socket! + Q_ASSERT_X(socketError == QBluetoothSocket::SocketError::NoSocketError + && state == QBluetoothSocket::SocketState::UnconnectedState && !rfcommChannel && !l2capChannel, + Q_FUNC_INFO, "unexpected socket state"); + + openMode = QIODevice::ReadWrite; + rfcommChannel.reset([[DarwinBTRFCOMMChannel alloc] initWithDelegate:this channel:channel], + RetainPolicy::noInitialRetain); + if (rfcommChannel) {// We do not handle errors, up to an external user. + q_ptr->setOpenMode(QIODevice::ReadWrite); + state = QBluetoothSocket::SocketState::ConnectedState; + socketType = QBluetoothServiceInfo::RfcommProtocol; + } + + return rfcommChannel; +} + +bool QBluetoothSocketPrivateDarwin::setL2CAPChannel(void *generic) +{ + // A special case "constructor": on OS X we do not have a real listening socket, + // instead a bluetooth server "listens" for channel open notifications and + // creates (if asked by a user later) a "socket" object + // for this connection. This function initializes + // a "socket" from such an external channel (reported by a notification). + auto channel = static_cast(generic); + + // It must be a newborn socket! + Q_ASSERT_X(socketError == QBluetoothSocket::SocketError::NoSocketError + && state == QBluetoothSocket::SocketState::UnconnectedState && !l2capChannel && !rfcommChannel, + Q_FUNC_INFO, "unexpected socket state"); + + openMode = QIODevice::ReadWrite; + l2capChannel.reset([[DarwinBTL2CAPChannel alloc] initWithDelegate:this channel:channel], RetainPolicy::noInitialRetain); + if (l2capChannel) {// We do not handle errors, up to an external user. + q_ptr->setOpenMode(QIODevice::ReadWrite); + state = QBluetoothSocket::SocketState::ConnectedState; + socketType = QBluetoothServiceInfo::L2capProtocol; + } + + return l2capChannel; +} + +void QBluetoothSocketPrivateDarwin::setChannelError(IOReturn errorCode) +{ + Q_UNUSED(errorCode); + + Q_ASSERT_X(q_ptr, Q_FUNC_INFO, "invalid q_ptr (null)"); + + if (isConnecting) { + // The delegate's method was called while we are still in + // connectToService ... will emit a moment later. + socketError = QBluetoothSocket::SocketError::UnknownSocketError; + } else { + q_ptr->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError); + } +} + +void QBluetoothSocketPrivateDarwin::channelOpenComplete() +{ + Q_ASSERT_X(q_ptr, Q_FUNC_INFO, "invalid q_ptr (null)"); + + if (!isConnecting) { + q_ptr->setOpenMode(openMode); + q_ptr->setSocketState(QBluetoothSocket::SocketState::ConnectedState); + } else { + state = QBluetoothSocket::SocketState::ConnectedState; + // We are still in connectToService, it'll care + // about signals! + } +} + +void QBluetoothSocketPrivateDarwin::channelClosed() +{ + Q_ASSERT_X(q_ptr, Q_FUNC_INFO, "invalid q_ptr (null)"); + + // Channel was closed by IOBluetooth and we can not write any data + // (thus close/abort probably will not work). + + if (!isConnecting) { + q_ptr->setOpenMode(QIODevice::NotOpen); + q_ptr->setSocketState(QBluetoothSocket::SocketState::UnconnectedState); + emit q_ptr->readChannelFinished(); + } else { + state = QBluetoothSocket::SocketState::UnconnectedState; + // We are still in connectToService and do not want + // to emit any signals yet. + } +} + +void QBluetoothSocketPrivateDarwin::readChannelData(void *data, std::size_t size) +{ + Q_ASSERT_X(data, Q_FUNC_INFO, "invalid data (null)"); + Q_ASSERT_X(size, Q_FUNC_INFO, "invalid data size (0)"); + Q_ASSERT_X(q_ptr, Q_FUNC_INFO, "invalid q_ptr (null)"); + + const char *src = static_cast(data); + char *dst = rxBuffer.reserve(int(size)); + std::copy(src, src + size, dst); + + if (!isConnecting) { + // If we're still in connectToService, do not emit. + emit q_ptr->readyRead(); + } // else connectToService must check and emit readyRead! +} + +void QBluetoothSocketPrivateDarwin::writeComplete() +{ + _q_writeNotify(); +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothsocket_macos_p.h b/src/bluetooth/qbluetoothsocket_macos_p.h new file mode 100644 index 0000000..139bca8 --- /dev/null +++ b/src/bluetooth/qbluetoothsocket_macos_p.h @@ -0,0 +1,117 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QBLUETOOTHSOCKET_OSX_P_H +#define QBLUETOOTHSOCKET_OSX_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_OSX_BLUETOOTH + +#include "qbluetoothsocketbase_p.h" +#include "qbluetoothserviceinfo.h" +#include "darwin/btdelegates_p.h" +#include "qbluetoothsocket.h" +#include "darwin/btraii_p.h" + +#ifndef QPRIVATELINEARBUFFER_BUFFERSIZE +#define QPRIVATELINEARBUFFER_BUFFERSIZE Q_INT64_C(16384) +#endif +// The order is important: bytearray before buffer: +#include +#include "qprivatelinearbuffer_p.h" + +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QBluetoothAddress; + +class QBluetoothSocketPrivateDarwin : public QBluetoothSocketBasePrivate, public DarwinBluetooth::ChannelDelegate +{ + friend class QBluetoothSocket; + friend class QBluetoothServer; + +public: + QBluetoothSocketPrivateDarwin(); + ~QBluetoothSocketPrivateDarwin(); + + // + bool ensureNativeSocket(QBluetoothServiceInfo::Protocol type) override; + + QString localName() const override; + QBluetoothAddress localAddress() const override; + quint16 localPort() const override; + + QString peerName() const override; + QBluetoothAddress peerAddress() const override; + quint16 peerPort() const override; + + void abort() override; + void close() override; + + qint64 writeData(const char *data, qint64 maxSize) override; + qint64 readData(char *data, qint64 maxSize) override; + + qint64 bytesAvailable() const override; + bool canReadLine() const override; + qint64 bytesToWrite() const override; + + bool setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType, + QBluetoothSocket::SocketState socketState, + QBluetoothSocket::OpenMode openMode) override; + + void connectToServiceHelper(const QBluetoothAddress &address, quint16 port, + QIODevice::OpenMode openMode) override; + void connectToService(const QBluetoothServiceInfo &service, + QIODevice::OpenMode openMode) override; + void connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid, + QIODevice::OpenMode openMode) override; + + void connectToService(const QBluetoothAddress &address, quint16 port, + QIODevice::OpenMode openMode) override; + + void _q_writeNotify(); + +private: + // Create a socket from an external source (without connectToService). + bool setRFCOMChannel(void *channel); + bool setL2CAPChannel(void *channel); + + // L2CAP and RFCOMM delegate + void setChannelError(IOReturn errorCode) override; + void channelOpenComplete() override; + void channelClosed() override; + void readChannelData(void *data, std::size_t size) override; + void writeComplete() override; + + QList writeChunk; + + using L2CAPChannel = DarwinBluetooth::ScopedPointer; + L2CAPChannel l2capChannel; + + using RFCOMMChannel = L2CAPChannel; + RFCOMMChannel rfcommChannel; + // A trick to deal with channel open too fast (synchronously). + bool isConnecting = false; +}; + +QT_END_NAMESPACE + +#endif + +#endif diff --git a/src/bluetooth/qbluetoothsocket_winrt.cpp b/src/bluetooth/qbluetoothsocket_winrt.cpp new file mode 100644 index 0000000..1d98f4f --- /dev/null +++ b/src/bluetooth/qbluetoothsocket_winrt.cpp @@ -0,0 +1,836 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothsocket_winrt_p.h" +#include "qbluetoothutils_winrt_p.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Devices::Bluetooth; +using namespace ABI::Windows::Devices::Bluetooth::Rfcomm; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::Networking; +using namespace ABI::Windows::Networking::Sockets; +using namespace ABI::Windows::Storage::Streams; + +typedef IAsyncOperationWithProgressCompletedHandler SocketReadCompletedHandler; +typedef IAsyncOperationWithProgress IAsyncBufferOperation; + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINDOWS) + +struct SocketGlobal +{ + SocketGlobal() + { + HRESULT hr; + hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(), + &bufferFactory); + Q_ASSERT_SUCCEEDED(hr); + } + + ComPtr bufferFactory; +}; +Q_GLOBAL_STATIC(SocketGlobal, g) + +#define READ_BUFFER_SIZE 65536 + +static inline QString qt_QStringFromHString(const HString &string) +{ + UINT32 length; + PCWSTR rawString = string.GetRawBuffer(&length); + if (length > INT_MAX) + length = INT_MAX; + return QString::fromWCharArray(rawString, int(length)); +} + +static qint64 writeIOStream(ComPtr stream, const char *data, qint64 len) +{ + ComPtr tempBuffer; + if (len > UINT32_MAX) { + qCWarning(QT_BT_WINDOWS) << "writeIOStream can only write up to" << UINT32_MAX << "bytes."; + len = UINT32_MAX; + } + quint32 ulen = static_cast(len); + HRESULT hr = g->bufferFactory->Create(ulen, &tempBuffer); + Q_ASSERT_SUCCEEDED(hr); + hr = tempBuffer->put_Length(ulen); + Q_ASSERT_SUCCEEDED(hr); + ComPtr byteArrayAccess; + hr = tempBuffer.As(&byteArrayAccess); + Q_ASSERT_SUCCEEDED(hr); + byte *bytes; + hr = byteArrayAccess->Buffer(&bytes); + Q_ASSERT_SUCCEEDED(hr); + memcpy(bytes, data, ulen); + ComPtr> op; + hr = stream->WriteAsync(tempBuffer.Get(), &op); + RETURN_IF_FAILED("Failed to write to stream", return -1); + UINT32 bytesWritten; + hr = QWinRTFunctions::await(op, &bytesWritten); + RETURN_IF_FAILED("Failed to write to stream", return -1); + return bytesWritten; +} + +class SocketWorker : public QObject +{ + Q_OBJECT +public: + SocketWorker() + { + } + + ~SocketWorker() + { + } + void close() + { + m_shuttingDown = true; + if (m_readOp) { + onReadyRead(m_readOp.Get(), Canceled); + ComPtr info; + HRESULT hr = m_readOp.As(&info); + Q_ASSERT_SUCCEEDED(hr); + if (info) { + hr = info->Cancel(); + Q_ASSERT_SUCCEEDED(hr); + hr = info->Close(); + Q_ASSERT_SUCCEEDED(hr); + } + m_readOp.Reset(); + } + } + +signals: + void newDataReceived(const QList &data); + void socketErrorOccured(QBluetoothSocket::SocketError error); + +public slots: + Q_INVOKABLE void notifyAboutNewData() + { + const QList newData = std::move(m_pendingData); + m_pendingData.clear(); + emit newDataReceived(newData); + } + +public: + void startReading() + { + ComPtr tempBuffer; + HRESULT hr = g->bufferFactory->Create(READ_BUFFER_SIZE, &tempBuffer); + Q_ASSERT_SUCCEEDED(hr); + ComPtr stream; + hr = m_socket->get_InputStream(&stream); + Q_ASSERT_SUCCEEDED(hr); + hr = stream->ReadAsync(tempBuffer.Get(), READ_BUFFER_SIZE, InputStreamOptions_Partial, m_readOp.GetAddressOf()); + Q_ASSERT_SUCCEEDED(hr); + QPointer thisPtr(this); + hr = m_readOp->put_Completed( + Callback([thisPtr](IAsyncBufferOperation *asyncInfo, + AsyncStatus status) { + if (thisPtr) + return thisPtr->onReadyRead(asyncInfo, status); + return S_OK; + }).Get()); + Q_ASSERT_SUCCEEDED(hr); + } + + HRESULT onReadyRead(IAsyncBufferOperation *asyncInfo, AsyncStatus status) + { + if (m_shuttingDown) + return S_OK; + + if (asyncInfo == m_readOp.Get()) + m_readOp.Reset(); + else + Q_ASSERT(false); + + // A read in UnconnectedState will close the socket and return -1 and thus tell the caller, + // that the connection was closed. The socket cannot be closed here, as the subsequent read + // might fail then. + if (status == Error || status == Canceled) { + emit socketErrorOccured(QBluetoothSocket::SocketError::NetworkError); + return S_OK; + } + + ComPtr tempBuffer; + HRESULT hr = asyncInfo->GetResults(&tempBuffer); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to get read results buffer"); + emit socketErrorOccured(QBluetoothSocket::SocketError::UnknownSocketError); + return S_OK; + } + + UINT32 bufferLength; + hr = tempBuffer->get_Length(&bufferLength); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to get buffer length"); + emit socketErrorOccured(QBluetoothSocket::SocketError::UnknownSocketError); + return S_OK; + } + // A zero sized buffer length signals, that the remote host closed the connection. The socket + // cannot be closed though, as the following read might have socket descriptor -1 and thus and + // the closing of the socket won't be communicated to the caller. So only the error is set. The + // actual socket close happens inside of read. + if (!bufferLength) { + emit socketErrorOccured(QBluetoothSocket::SocketError::RemoteHostClosedError); + return S_OK; + } + + ComPtr byteArrayAccess; + hr = tempBuffer.As(&byteArrayAccess); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to get cast buffer"); + emit socketErrorOccured(QBluetoothSocket::SocketError::UnknownSocketError); + return S_OK; + } + byte *data; + hr = byteArrayAccess->Buffer(&data); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to access buffer data"); + emit socketErrorOccured(QBluetoothSocket::SocketError::UnknownSocketError); + return S_OK; + } + + QByteArray newData(reinterpret_cast(data), int(bufferLength)); + if (m_pendingData.isEmpty()) + QMetaObject::invokeMethod(this, "notifyAboutNewData", Qt::QueuedConnection); + m_pendingData << newData; + + UINT32 readBufferLength; + ComPtr stream; + hr = m_socket->get_InputStream(&stream); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to obtain input stream"); + emit socketErrorOccured(QBluetoothSocket::SocketError::UnknownSocketError); + return S_OK; + } + + // Reuse the stream buffer + hr = tempBuffer->get_Capacity(&readBufferLength); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to get buffer capacity"); + emit socketErrorOccured(QBluetoothSocket::SocketError::UnknownSocketError); + return S_OK; + } + hr = tempBuffer->put_Length(0); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to set buffer length"); + emit socketErrorOccured(QBluetoothSocket::SocketError::UnknownSocketError); + return S_OK; + } + + hr = stream->ReadAsync(tempBuffer.Get(), readBufferLength, InputStreamOptions_Partial, &m_readOp); + if (FAILED(hr)) { + qErrnoWarning(hr, "onReadyRead(): Could not read into socket stream buffer."); + emit socketErrorOccured(QBluetoothSocket::SocketError::UnknownSocketError); + return S_OK; + } + QPointer thisPtr(this); + hr = m_readOp->put_Completed( + Callback([thisPtr](IAsyncBufferOperation *asyncInfo, + AsyncStatus status) { + if (thisPtr) + return thisPtr->onReadyRead(asyncInfo, status); + return S_OK; + }).Get()); + if (FAILED(hr)) { + qErrnoWarning(hr, "onReadyRead(): Failed to set socket read callback."); + emit socketErrorOccured(QBluetoothSocket::SocketError::UnknownSocketError); + return S_OK; + } + return S_OK; + } + + void setSocket(ComPtr socket) { m_socket = socket; } + +private: + ComPtr m_socket; + QList m_pendingData; + bool m_shuttingDown = false; + + ComPtr> m_readOp; +}; + +QBluetoothSocketPrivateWinRT::QBluetoothSocketPrivateWinRT() + : m_worker(new SocketWorker()) +{ + mainThreadCoInit(this); + secFlags = QBluetooth::Security::NoSecurity; + connect(m_worker, &SocketWorker::newDataReceived, + this, &QBluetoothSocketPrivateWinRT::handleNewData, Qt::QueuedConnection); + connect(m_worker, &SocketWorker::socketErrorOccured, + this, &QBluetoothSocketPrivateWinRT::handleError, Qt::QueuedConnection); +} + +QBluetoothSocketPrivateWinRT::~QBluetoothSocketPrivateWinRT() +{ + abort(); + mainThreadCoUninit(this); +} + +bool QBluetoothSocketPrivateWinRT::ensureNativeSocket(QBluetoothServiceInfo::Protocol type) +{ + if (socket != -1) { + if (type == socketType) + return true; + m_socketObject = nullptr; + socket = -1; + } + socketType = type; + if (socketType != QBluetoothServiceInfo::RfcommProtocol) + return false; + + HRESULT hr; + hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_StreamSocket).Get(), &m_socketObject); + if (FAILED(hr) || !m_socketObject) { + qErrnoWarning(hr, "ensureNativeSocket: Could not create socket instance"); + return false; + } + socket = qintptr(m_socketObject.Get()); + m_worker->setSocket(m_socketObject); + + return true; +} + +void QBluetoothSocketPrivateWinRT::connectToService(Microsoft::WRL::ComPtr hostName, + const QString &serviceName, + QIODevice::OpenMode openMode) +{ + Q_Q(QBluetoothSocket); + + if (socket == -1 && !ensureNativeSocket(socketType)) { + errorString = QBluetoothSocket::tr("Unknown socket error"); + q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError); + return; + } + + HStringReference serviceNameReference(reinterpret_cast(serviceName.utf16())); + + HRESULT hr = m_socketObject->ConnectAsync(hostName.Get(), serviceNameReference.Get(), &m_connectOp); + if (hr == E_ACCESSDENIED) { + qErrnoWarning(hr, "QBluetoothSocketPrivateWinRT::connectToService: Unable to connect to bluetooth socket." + "Please check your manifest capabilities."); + q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState); + return; + } + Q_ASSERT_SUCCEEDED(hr); + + q->setSocketState(QBluetoothSocket::SocketState::ConnectingState); + requestedOpenMode = openMode; + hr = m_connectOp->put_Completed(Callback( + this, &QBluetoothSocketPrivateWinRT::handleConnectOpFinished).Get()); + RETURN_VOID_IF_FAILED("connectToHostByName: Could not register \"connectOp\" callback"); + return; +} + +void QBluetoothSocketPrivateWinRT::connectToServiceHelper(const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode) +{ + Q_Q(QBluetoothSocket); + + if (socket == -1 && !ensureNativeSocket(socketType)) { + errorString = QBluetoothSocket::tr("Unknown socket error"); + q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError); + return; + } + + const QString addressString = address.toString(); + HStringReference hostNameRef(reinterpret_cast(addressString.utf16())); + ComPtr hostNameFactory; + HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(), + &hostNameFactory); + Q_ASSERT_SUCCEEDED(hr); + ComPtr remoteHost; + hr = hostNameFactory->CreateHostName(hostNameRef.Get(), &remoteHost); + RETURN_VOID_IF_FAILED("QBluetoothSocketPrivateWinRT::connectToService: Could not create hostname."); + const QString portString = QString::number(port); + connectToService(remoteHost, portString, openMode); +} + +void QBluetoothSocketPrivateWinRT::connectToService( + const QBluetoothServiceInfo &service, QIODevice::OpenMode openMode) +{ + Q_Q(QBluetoothSocket); + + if (q->state() != QBluetoothSocket::SocketState::UnconnectedState + && q->state() != QBluetoothSocket::SocketState::ServiceLookupState) { + qCWarning(QT_BT_WINDOWS) << "QBluetoothSocket::connectToService called on busy socket"; + errorString = QBluetoothSocket::tr("Trying to connect while connection is in progress"); + q->setSocketError(QBluetoothSocket::SocketError::OperationError); + return; + } + + // we are checking the service protocol and not socketType() + // socketType will change in ensureNativeSocket() + if (service.socketProtocol() != QBluetoothServiceInfo::RfcommProtocol) { + errorString = QBluetoothSocket::tr("Socket type not supported"); + q->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError); + return; + } + + const QString connectionHostName = service.attribute(0xBEEF).toString(); + const QString connectionServiceName = service.attribute(0xBEF0).toString(); + if (service.protocolServiceMultiplexer() > 0) { + Q_ASSERT(service.socketProtocol() == QBluetoothServiceInfo::L2capProtocol); + + if (!ensureNativeSocket(QBluetoothServiceInfo::L2capProtocol)) { + errorString = QBluetoothSocket::tr("Unknown socket error"); + q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError); + return; + } + connectToServiceHelper(service.device().address(), + quint16(service.protocolServiceMultiplexer()), openMode); + } else if (!connectionHostName.isEmpty() && !connectionServiceName.isEmpty()) { + Q_ASSERT(service.socketProtocol() == QBluetoothServiceInfo::RfcommProtocol); + if (!ensureNativeSocket(QBluetoothServiceInfo::RfcommProtocol)) { + errorString = QBluetoothSocket::tr("Unknown socket error"); + q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError); + return; + } + HStringReference hostNameRef(reinterpret_cast(connectionHostName.utf16())); + ComPtr hostNameFactory; + HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(), + &hostNameFactory); + Q_ASSERT_SUCCEEDED(hr); + ComPtr remoteHost; + hr = hostNameFactory->CreateHostName(hostNameRef.Get(), &remoteHost); + connectToService(remoteHost, connectionServiceName, openMode); + } else if (service.serverChannel() > 0) { + Q_ASSERT(service.socketProtocol() == QBluetoothServiceInfo::RfcommProtocol); + + if (!ensureNativeSocket(QBluetoothServiceInfo::RfcommProtocol)) { + errorString = QBluetoothSocket::tr("Unknown socket error"); + q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError); + return; + } + connectToServiceHelper(service.device().address(), quint16(service.serverChannel()), + openMode); + } else { + // try doing service discovery to see if we can find the socket + if (service.serviceUuid().isNull() + && !service.serviceClassUuids().contains(QBluetoothUuid::ServiceClassUuid::SerialPort)) { + qCWarning(QT_BT_WINDOWS) << "No port, no PSM, and no UUID provided. Unable to connect"; + return; + } + qCDebug(QT_BT_WINDOWS) << "Need a port/psm, doing discovery"; + q->doDeviceDiscovery(service, openMode); + } +} + +void QBluetoothSocketPrivateWinRT::connectToService( + const QBluetoothAddress &address, const QBluetoothUuid &uuid, QIODevice::OpenMode openMode) +{ + Q_Q(QBluetoothSocket); + + if (q->state() != QBluetoothSocket::SocketState::UnconnectedState) { + qCWarning(QT_BT_WINDOWS) << "QBluetoothSocketPrivateWinRT::connectToService called on busy socket"; + errorString = QBluetoothSocket::tr("Trying to connect while connection is in progress"); + q->setSocketError(QBluetoothSocket::SocketError::OperationError); + return; + } + + if (q->socketType() != QBluetoothServiceInfo::RfcommProtocol) { + errorString = QBluetoothSocket::tr("Socket type not supported"); + q->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError); + return; + } + + QBluetoothServiceInfo service; + QBluetoothDeviceInfo device(address, QString(), QBluetoothDeviceInfo::MiscellaneousDevice); + service.setDevice(device); + service.setServiceUuid(uuid); + q->doDeviceDiscovery(service, openMode); +} + +void QBluetoothSocketPrivateWinRT::connectToService( + const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode) +{ + Q_Q(QBluetoothSocket); + + if (q->state() != QBluetoothSocket::SocketState::UnconnectedState) { + qCWarning(QT_BT_WINDOWS) << "QBluetoothSocketPrivateWinRT::connectToService called on busy socket"; + errorString = QBluetoothSocket::tr("Trying to connect while connection is in progress"); + q->setSocketError(QBluetoothSocket::SocketError::OperationError); + return; + } + + if (q->socketType() != QBluetoothServiceInfo::RfcommProtocol) { + errorString = QBluetoothSocket::tr("Socket type not supported"); + q->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError); + return; + } + + connectToServiceHelper(address, port, openMode); +} + +void QBluetoothSocketPrivateWinRT::abort() +{ + Q_Q(QBluetoothSocket); + if (state == QBluetoothSocket::SocketState::UnconnectedState) + return; + + disconnect(m_worker, &SocketWorker::newDataReceived, + this, &QBluetoothSocketPrivateWinRT::handleNewData); + disconnect(m_worker, &SocketWorker::socketErrorOccured, + this, &QBluetoothSocketPrivateWinRT::handleError); + m_worker->close(); + m_worker->deleteLater(); + + if (socket != -1) { + m_socketObject = nullptr; + socket = -1; + } + + const bool wasConnected = q->state() == QBluetoothSocket::SocketState::ConnectedState; + q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState); + if (wasConnected) { + q->setOpenMode(QIODevice::NotOpen); + emit q->readChannelFinished(); + } +} + +QString QBluetoothSocketPrivateWinRT::localName() const +{ + const QBluetoothAddress address = localAddress(); + if (address.isNull()) + return QString(); + + QBluetoothLocalDevice device(address); + return device.name(); +} + +static QString fromWinApiAddress(HString address) +{ + // WinAPI returns address with parentheses around it. We need to remove + // them to convert to QBluetoothAddress. + QString addressStr(qt_QStringFromHString(address)); + if (addressStr.startsWith(QLatin1Char('(')) && addressStr.endsWith(QLatin1Char(')'))) { + addressStr = addressStr.sliced(1, addressStr.size() - 2); + } + return addressStr; +} + +QBluetoothAddress QBluetoothSocketPrivateWinRT::localAddress() const +{ + if (!m_socketObject) + return QBluetoothAddress(); + + HRESULT hr; + ComPtr info; + hr = m_socketObject->get_Information(&info); + Q_ASSERT_SUCCEEDED(hr); + ComPtr localHost; + hr = info->get_LocalAddress(&localHost); + Q_ASSERT_SUCCEEDED(hr); + if (localHost) { + HString localAddress; + hr = localHost->get_CanonicalName(localAddress.GetAddressOf()); + Q_ASSERT_SUCCEEDED(hr); + return QBluetoothAddress(fromWinApiAddress(std::move(localAddress))); + } + return QBluetoothAddress(); +} + +quint16 QBluetoothSocketPrivateWinRT::localPort() const +{ + if (!m_socketObject) + return 0; + + HRESULT hr; + ComPtr info; + hr = m_socketObject->get_Information(&info); + Q_ASSERT_SUCCEEDED(hr); + HString localPortString; + hr = info->get_LocalPort(localPortString.GetAddressOf()); + Q_ASSERT_SUCCEEDED(hr); + bool ok = true; + const uint port = qt_QStringFromHString(localPortString).toUInt(&ok); + if (!ok || port > UINT16_MAX) { + qCWarning(QT_BT_WINDOWS) << "Unexpected local port"; + return 0; + } + return quint16(port); +} + +QString QBluetoothSocketPrivateWinRT::peerName() const +{ + if (!m_socketObject) + return QString(); + + HRESULT hr; + ComPtr info; + hr = m_socketObject->get_Information(&info); + Q_ASSERT_SUCCEEDED(hr); + ComPtr remoteHost; + hr = info->get_RemoteHostName(&remoteHost); + Q_ASSERT_SUCCEEDED(hr); + if (remoteHost) { + HString remoteHostName; + hr = remoteHost->get_DisplayName(remoteHostName.GetAddressOf()); + Q_ASSERT_SUCCEEDED(hr); + return qt_QStringFromHString(remoteHostName); + } + return {}; +} + +QBluetoothAddress QBluetoothSocketPrivateWinRT::peerAddress() const +{ + if (!m_socketObject) + return QBluetoothAddress(); + + HRESULT hr; + ComPtr info; + hr = m_socketObject->get_Information(&info); + Q_ASSERT_SUCCEEDED(hr); + ComPtr remoteHost; + hr = info->get_RemoteAddress(&remoteHost); + Q_ASSERT_SUCCEEDED(hr); + if (remoteHost) { + HString remoteAddress; + hr = remoteHost->get_CanonicalName(remoteAddress.GetAddressOf()); + Q_ASSERT_SUCCEEDED(hr); + return QBluetoothAddress(fromWinApiAddress(std::move(remoteAddress))); + } + return QBluetoothAddress(); +} + +quint16 QBluetoothSocketPrivateWinRT::peerPort() const +{ + if (!m_socketObject) + return 0; + + HRESULT hr; + ComPtr info; + hr = m_socketObject->get_Information(&info); + Q_ASSERT_SUCCEEDED(hr); + HString remotePortString; + hr = info->get_RemotePort(remotePortString.GetAddressOf()); + Q_ASSERT_SUCCEEDED(hr); + bool ok = true; + const uint port = qt_QStringFromHString(remotePortString).toUInt(&ok); + if (!ok || port > UINT16_MAX) { + qCWarning(QT_BT_WINDOWS) << "Unexpected remote port"; + return 0; + } + return quint16(port); +} + +qint64 QBluetoothSocketPrivateWinRT::writeData(const char *data, qint64 maxSize) +{ + Q_Q(QBluetoothSocket); + + if (state != QBluetoothSocket::SocketState::ConnectedState) { + errorString = QBluetoothSocket::tr("Cannot write while not connected"); + q->setSocketError(QBluetoothSocket::SocketError::OperationError); + return -1; + } + + ComPtr stream; + HRESULT hr; + hr = m_socketObject->get_OutputStream(&stream); + Q_ASSERT_SUCCEEDED(hr); + + qint64 bytesWritten = writeIOStream(stream, data, maxSize); + if (bytesWritten < 0) { + qCWarning(QT_BT_WINDOWS) << "Socket::writeData: " << state; + errorString = QBluetoothSocket::tr("Cannot read while not connected"); + q->setSocketError(QBluetoothSocket::SocketError::OperationError); + } + + emit q->bytesWritten(bytesWritten); + return bytesWritten; +} + +qint64 QBluetoothSocketPrivateWinRT::readData(char *data, qint64 maxSize) +{ + Q_Q(QBluetoothSocket); + + if (state != QBluetoothSocket::SocketState::ConnectedState) { + errorString = QBluetoothSocket::tr("Cannot read while not connected"); + q->setSocketError(QBluetoothSocket::SocketError::OperationError); + return -1; + } + + if (!rxBuffer.isEmpty()) { + if (maxSize > INT_MAX) + maxSize = INT_MAX; + return rxBuffer.read(data, int(maxSize)); + } + + return 0; +} + +void QBluetoothSocketPrivateWinRT::close() +{ + abort(); +} + +bool QBluetoothSocketPrivateWinRT::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType, + QBluetoothSocket::SocketState socketState, QBluetoothSocket::OpenMode openMode) +{ + Q_UNUSED(socketDescriptor); + Q_UNUSED(socketType); + Q_UNUSED(socketState); + Q_UNUSED(openMode); + qCWarning(QT_BT_WINDOWS) << "No socket descriptor support on WinRT."; + return false; +} + +bool QBluetoothSocketPrivateWinRT::setSocketDescriptor(ComPtr socketPtr, QBluetoothServiceInfo::Protocol socketType, + QBluetoothSocket::SocketState socketState, QBluetoothSocket::OpenMode openMode) +{ + Q_Q(QBluetoothSocket); + if (socketType != QBluetoothServiceInfo::RfcommProtocol || !socketPtr) + return false; + + m_socketObject = socketPtr; + socket = qintptr(m_socketObject.Get()); + m_worker->setSocket(m_socketObject); + q->setSocketState(socketState); + if (socketState == QBluetoothSocket::SocketState::ConnectedState) + m_worker->startReading(); + // QBluetoothSockets are unbuffered on Windows + q->setOpenMode(openMode | QIODevice::Unbuffered); + return true; +} + +qint64 QBluetoothSocketPrivateWinRT::bytesAvailable() const +{ + return rxBuffer.size(); +} + +qint64 QBluetoothSocketPrivateWinRT::bytesToWrite() const +{ + return 0; // nothing because always unbuffered +} + +bool QBluetoothSocketPrivateWinRT::canReadLine() const +{ + return rxBuffer.canReadLine(); +} + +void QBluetoothSocketPrivateWinRT::handleNewData(const QList &data) +{ + // Defer putting the data into the list until the next event loop iteration + // (where the readyRead signal is emitted as well) + QMetaObject::invokeMethod(this, "addToPendingData", Qt::QueuedConnection, + Q_ARG(QList, data)); +} + +void QBluetoothSocketPrivateWinRT::handleError(QBluetoothSocket::SocketError error) +{ + Q_Q(QBluetoothSocket); + switch (error) { + case QBluetoothSocket::SocketError::NetworkError: + errorString = QBluetoothSocket::tr("Network error"); + break; + case QBluetoothSocket::SocketError::RemoteHostClosedError: + errorString = QBluetoothSocket::tr("Remote host closed connection"); + break; + default: + errorString = QBluetoothSocket::tr("Unknown socket error"); + } + + q->setSocketError(error); + const bool wasConnected = q->state() == QBluetoothSocket::SocketState::ConnectedState; + q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState); + if (wasConnected) { + q->setOpenMode(QIODevice::NotOpen); + emit q->readChannelFinished(); + } +} + +void QBluetoothSocketPrivateWinRT::addToPendingData(const QList &data) +{ + Q_Q(QBluetoothSocket); + QMutexLocker locker(&m_readMutex); + m_pendingData.append(data); + for (const QByteArray &newData : data) { + char *writePointer = rxBuffer.reserve(newData.length()); + memcpy(writePointer, newData.data(), size_t(newData.length())); + } + locker.unlock(); + emit q->readyRead(); +} + +HRESULT QBluetoothSocketPrivateWinRT::handleConnectOpFinished(ABI::Windows::Foundation::IAsyncAction *action, ABI::Windows::Foundation::AsyncStatus status) +{ + Q_Q(QBluetoothSocket); + if (status != Completed || !m_connectOp) { // Protect against a late callback + errorString = QBluetoothSocket::tr("Unknown socket error"); + q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError); + q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState); + return S_OK; + } + + HRESULT hr = action->GetResults(); + switch (hr) { + + // A connection attempt failed because the connected party did not properly respond after a + // period of time, or established connection failed because connected host has failed to respond. + case HRESULT_FROM_WIN32(WSAETIMEDOUT): + errorString = QBluetoothSocket::tr("Connection timed out"); + q->setSocketError(QBluetoothSocket::SocketError::NetworkError); + q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState); + return S_OK; + // A socket operation was attempted to an unreachable host. + case HRESULT_FROM_WIN32(WSAEHOSTUNREACH): + errorString = QBluetoothSocket::tr("Host not reachable"); + q->setSocketError(QBluetoothSocket::SocketError::HostNotFoundError); + q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState); + return S_OK; + // No connection could be made because the target machine actively refused it. + case HRESULT_FROM_WIN32(WSAECONNREFUSED): + errorString = QBluetoothSocket::tr("Host refused connection"); + q->setSocketError(QBluetoothSocket::SocketError::HostNotFoundError); + q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState); + return S_OK; + default: + if (FAILED(hr)) { + errorString = QBluetoothSocket::tr("Unknown socket error"); + q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError); + q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState); + return S_OK; + } + } + + // The callback might be triggered several times if we do not cancel/reset it here + if (m_connectOp) { + ComPtr info; + hr = m_connectOp.As(&info); + Q_ASSERT_SUCCEEDED(hr); + if (info) { + hr = info->Cancel(); + Q_ASSERT_SUCCEEDED(hr); + hr = info->Close(); + Q_ASSERT_SUCCEEDED(hr); + } + m_connectOp.Reset(); + } + + // QBluetoothSockets are unbuffered on Windows + q->setOpenMode(requestedOpenMode | QIODevice::Unbuffered); + q->setSocketState(QBluetoothSocket::SocketState::ConnectedState); + m_worker->startReading(); + + return S_OK; +} + +QT_END_NAMESPACE + +#include "qbluetoothsocket_winrt.moc" diff --git a/src/bluetooth/qbluetoothsocket_winrt_p.h b/src/bluetooth/qbluetoothsocket_winrt_p.h new file mode 100644 index 0000000..4ba6c4f --- /dev/null +++ b/src/bluetooth/qbluetoothsocket_winrt_p.h @@ -0,0 +1,115 @@ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QBLUETOOTHSOCKET_WINRT_P_H +#define QBLUETOOTHSOCKET_WINRT_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 "qbluetoothsocket.h" +#include "qbluetoothsocketbase_p.h" +#include + +QT_FORWARD_DECLARE_CLASS(SocketWorker) + +namespace ABI { + namespace Windows { + namespace Networking { + struct IHostName; + } + } +} + +namespace Microsoft { + namespace WRL { + template class ComPtr; + } +} +QT_BEGIN_NAMESPACE + +class QBluetoothSocketPrivateWinRT final: public QBluetoothSocketBasePrivate +{ + Q_OBJECT + friend class QBluetoothServerPrivate; + +public: + QBluetoothSocketPrivateWinRT(); + ~QBluetoothSocketPrivateWinRT() override; + + void connectToServiceHelper(const QBluetoothAddress &address, + quint16 port, + QIODevice::OpenMode openMode) override; + + void connectToService(const QBluetoothServiceInfo &service, + QIODevice::OpenMode openMode) override; + void connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid, + QIODevice::OpenMode openMode) override; + void connectToService(const QBluetoothAddress &address, quint16 port, + QIODevice::OpenMode openMode) override; + + bool ensureNativeSocket(QBluetoothServiceInfo::Protocol type) override; + + QString localName() const override; + QBluetoothAddress localAddress() const override; + quint16 localPort() const override; + + QString peerName() const override; + QBluetoothAddress peerAddress() const override; + quint16 peerPort() const override; + + void abort() override; + void close() override; + + qint64 writeData(const char *data, qint64 maxSize) override; + qint64 readData(char *data, qint64 maxSize) override; + + bool setSocketDescriptor(Microsoft::WRL::ComPtr socket, + QBluetoothServiceInfo::Protocol socketType, + QBluetoothSocket::SocketState socketState = QBluetoothSocket::SocketState::ConnectedState, + QBluetoothSocket::OpenMode openMode = QBluetoothSocket::ReadWrite) override; + + bool setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType, + QBluetoothSocket::SocketState socketState = QBluetoothSocket::SocketState::ConnectedState, + QBluetoothSocket::OpenMode openMode = QBluetoothSocket::ReadWrite) override; + + qint64 bytesAvailable() const override; + bool canReadLine() const override; + qint64 bytesToWrite() const override; + + SocketWorker *m_worker; + + Microsoft::WRL::ComPtr m_socketObject; + Microsoft::WRL::ComPtr m_connectOp; + + QMutex m_readMutex; + + // Protected by m_readMutex. Written in addToPendingData (native callback) + QList m_pendingData; + + Q_INVOKABLE void addToPendingData(const QList &data); + +private slots: + void handleNewData(const QList &data); + void handleError(QBluetoothSocket::SocketError error); + +private: + void connectToService(Microsoft::WRL::ComPtr hostName, + const QString &serviceName, QIODevice::OpenMode openMode); + HRESULT handleConnectOpFinished(ABI::Windows::Foundation::IAsyncAction *action, + ABI::Windows::Foundation::AsyncStatus status); + + QIODevice::OpenMode requestedOpenMode = QIODevice::NotOpen; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/bluetooth/qbluetoothsocketbase.cpp b/src/bluetooth/qbluetoothsocketbase.cpp new file mode 100644 index 0000000..35cb595 --- /dev/null +++ b/src/bluetooth/qbluetoothsocketbase.cpp @@ -0,0 +1,20 @@ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothsocketbase_p.h" + +QT_BEGIN_NAMESPACE + +QBluetoothSocketBasePrivate::QBluetoothSocketBasePrivate(QObject *parent) : QObject(parent) +{ + +} + +QBluetoothSocketBasePrivate::~QBluetoothSocketBasePrivate() +{ + +} + +QT_END_NAMESPACE + +#include "moc_qbluetoothsocketbase_p.cpp" diff --git a/src/bluetooth/qbluetoothsocketbase_p.h b/src/bluetooth/qbluetoothsocketbase_p.h new file mode 100644 index 0000000..3b94cea --- /dev/null +++ b/src/bluetooth/qbluetoothsocketbase_p.h @@ -0,0 +1,166 @@ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QBLUETOOTHSOCKETBASEPRIVATE_P_H +#define QBLUETOOTHSOCKETBASEPRIVATE_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 + +#if defined(QT_ANDROID_BLUETOOTH) +#include +#endif + +#if defined(QT_WINRT_BLUETOOTH) +#include + +#include + +namespace ABI { + namespace Windows { + namespace Networking { + namespace Sockets { + struct IStreamSocket; + } + } + namespace Foundation { + struct IAsyncAction; + enum class AsyncStatus; + } + } +} +#endif // QT_WINRT_BLUETOOTH + +#ifndef QPRIVATELINEARBUFFER_BUFFERSIZE +#define QPRIVATELINEARBUFFER_BUFFERSIZE Q_INT64_C(16384) +#endif +#include "qprivatelinearbuffer_p.h" + +QT_FORWARD_DECLARE_CLASS(QSocketNotifier) +QT_FORWARD_DECLARE_CLASS(QBluetoothServiceDiscoveryAgent) + +QT_BEGIN_NAMESPACE + +class QBluetoothSocketBasePrivate : public QObject +{ + Q_OBJECT + +public: + explicit QBluetoothSocketBasePrivate(QObject *parent = nullptr); + virtual ~QBluetoothSocketBasePrivate(); + + virtual bool ensureNativeSocket(QBluetoothServiceInfo::Protocol type) = 0; + + virtual QString localName() const = 0; + virtual QBluetoothAddress localAddress() const = 0; + virtual quint16 localPort() const = 0; + + virtual QString peerName() const = 0; + virtual QBluetoothAddress peerAddress() const = 0; + virtual quint16 peerPort() const = 0; + + virtual void abort() = 0; + virtual void close() = 0; + + virtual qint64 writeData(const char *data, qint64 maxSize) = 0; + virtual qint64 readData(char *data, qint64 maxSize) = 0; + + virtual qint64 bytesAvailable() const = 0; + virtual bool canReadLine() const = 0; + virtual qint64 bytesToWrite() const = 0; + + virtual bool setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType, + QBluetoothSocket::SocketState socketState = QBluetoothSocket::SocketState::ConnectedState, + QBluetoothSocket::OpenMode openMode = QBluetoothSocket::ReadWrite) = 0; + + +#if defined(QT_ANDROID_BLUETOOTH) + virtual void connectToServiceHelper(const QBluetoothAddress &address, const QBluetoothUuid &uuid, + QIODevice::OpenMode openMode) = 0; +#else + virtual void connectToServiceHelper(const QBluetoothAddress &address, quint16 port, + QIODevice::OpenMode openMode) = 0; +#endif + virtual void connectToService(const QBluetoothServiceInfo &service, + QIODevice::OpenMode openMode) = 0; + virtual void connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid, + QIODevice::OpenMode openMode) = 0; + virtual void connectToService(const QBluetoothAddress &address, quint16 port, + QIODevice::OpenMode openMode) = 0; + +#ifdef QT_ANDROID_BLUETOOTH + virtual bool setSocketDescriptor(const QJniObject &socket, QBluetoothServiceInfo::Protocol socketType, + QBluetoothSocket::SocketState socketState = QBluetoothSocket::SocketState::ConnectedState, + QBluetoothSocket::OpenMode openMode = QBluetoothSocket::ReadWrite) = 0; +#elif defined(QT_WINRT_BLUETOOTH) + virtual bool setSocketDescriptor(Microsoft::WRL::ComPtr socket, + QBluetoothServiceInfo::Protocol socketType, + QBluetoothSocket::SocketState socketState = QBluetoothSocket::SocketState::ConnectedState, + QBluetoothSocket::OpenMode openMode = QBluetoothSocket::ReadWrite) = 0; +#endif + +public: + QPrivateLinearBuffer rxBuffer; + QPrivateLinearBuffer txBuffer; + int socket = -1; + QBluetoothServiceInfo::Protocol socketType = QBluetoothServiceInfo::UnknownProtocol; + QBluetoothSocket::SocketState state = QBluetoothSocket::SocketState::UnconnectedState; + QBluetoothSocket::SocketError socketError = QBluetoothSocket::SocketError::NoSocketError; + QSocketNotifier *readNotifier = nullptr; + QSocketNotifier *connectWriteNotifier = nullptr; + bool connecting = false; + + QBluetoothServiceDiscoveryAgent *discoveryAgent = nullptr; + QBluetoothSocket::OpenMode openMode; + QBluetooth::SecurityFlags secFlags; + + QString errorString; + +protected: + Q_DECLARE_PUBLIC(QBluetoothSocket) + QBluetoothSocket *q_ptr; + +#if QT_CONFIG(bluez) +public: + quint8 lowEnergySocketType = 0; +#endif +}; + +static inline void convertAddress(const quint64 from, quint8 (&to)[6]) +{ + to[0] = (from >> 0) & 0xff; + to[1] = (from >> 8) & 0xff; + to[2] = (from >> 16) & 0xff; + to[3] = (from >> 24) & 0xff; + to[4] = (from >> 32) & 0xff; + to[5] = (from >> 40) & 0xff; +} + +static inline quint64 convertAddress(const quint8 (&from)[6], quint64 *to = nullptr) +{ + const quint64 result = (quint64(from[0]) << 0) | + (quint64(from[1]) << 8) | + (quint64(from[2]) << 16) | + (quint64(from[3]) << 24) | + (quint64(from[4]) << 32) | + (quint64(from[5]) << 40); + if (to) + *to = result; + return result; +} + +QT_END_NAMESPACE + +#endif // QBLUETOOTHSOCKETBASE_P_H diff --git a/src/bluetooth/qbluetoothutils_winrt.cpp b/src/bluetooth/qbluetoothutils_winrt.cpp new file mode 100644 index 0000000..b146be1 --- /dev/null +++ b/src/bluetooth/qbluetoothutils_winrt.cpp @@ -0,0 +1,94 @@ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothutils_winrt_p.h" +#include +#include +#include + +#include +#include +#include +#include + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace winrt::Windows::Foundation::Metadata; +using namespace ABI::Windows::Storage::Streams; + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINDOWS) + +QByteArray byteArrayFromBuffer(const ComPtr &buffer, bool isWCharString) +{ + if (!buffer) { + qErrnoWarning("nullptr passed to byteArrayFromBuffer"); + return QByteArray(); + } + ComPtr byteAccess; + HRESULT hr = buffer.As(&byteAccess); + RETURN_IF_FAILED("Could not cast buffer", return QByteArray()) + char *data; + hr = byteAccess->Buffer(reinterpret_cast(&data)); + RETURN_IF_FAILED("Could not obtain buffer data", return QByteArray()) + UINT32 size; + hr = buffer->get_Length(&size); + RETURN_IF_FAILED("Could not obtain buffer size", return QByteArray()) + if (isWCharString) { + QString valueString = QString::fromUtf16(reinterpret_cast(data)).left(size / 2); + return valueString.toUtf8(); + } + return QByteArray(data, qint32(size)); +} + +static QSet successfulInits; +static QThread *mainThread = nullptr; + +void mainThreadCoInit(void* caller) +{ + Q_ASSERT(caller); + + if (QThread::currentThread() != QCoreApplication::instance()->thread()) { + qCWarning(QT_BT_WINDOWS) << "Main thread COM init tried from another thread"; + return; + } + + if (successfulInits.contains(caller)) { + qCWarning(QT_BT_WINDOWS) << "Multiple COM inits by same object"; + return; + } + + Q_ASSERT_X(!mainThread || mainThread == QThread::currentThread(), + __FUNCTION__, "QCoreApplication's thread has changed!"); + + // This executes in main thread which may run Gui => use apartment threaded + if (!SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED))) { + qCWarning(QT_BT_WINDOWS) << "Unexpected COM initialization result"; + return; + } + successfulInits.insert(caller); + if (!mainThread) + mainThread = QThread::currentThread(); +} + +void mainThreadCoUninit(void* caller) +{ + Q_ASSERT(caller); + + if (!successfulInits.contains(caller)) { + qCWarning(QT_BT_WINDOWS) << "COM uninitialization without initialization"; + return; + } + + if (QThread::currentThread() != mainThread) { + qCWarning(QT_BT_WINDOWS) << "Main thread COM uninit tried from another thread"; + return; + } + + CoUninitialize(); + successfulInits.remove(caller); + +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothutils_winrt_p.h b/src/bluetooth/qbluetoothutils_winrt_p.h new file mode 100644 index 0000000..9e1d475 --- /dev/null +++ b/src/bluetooth/qbluetoothutils_winrt_p.h @@ -0,0 +1,55 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QBLUETOOTHUTILS_WINRT_P_H +#define QBLUETOOTHUTILS_WINRT_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. +// + +// Workaround for Windows SDK bug. +// See https://github.com/microsoft/Windows.UI.Composition-Win32-Samples/issues/47 + #include +#include +namespace winrt::impl +{ + template + auto wait_for(Async const& async, Windows::Foundation::TimeSpan const& timeout); +} + +#include +#include + +#include + +namespace ABI { + namespace Windows { + namespace Storage { + namespace Streams { + struct IBuffer; + } + } + } +} + +QT_BEGIN_NAMESPACE + +using NativeBuffer = ABI::Windows::Storage::Streams::IBuffer; +QByteArray byteArrayFromBuffer(const Microsoft::WRL::ComPtr &buffer, + bool isWCharString = false); + +// The calls to Co(Un)init must be balanced +void mainThreadCoInit(void* caller); +void mainThreadCoUninit(void* caller); + +QT_END_NAMESPACE + +#endif // QBLUETOOTHSOCKET_WINRT_P_H diff --git a/src/bluetooth/qbluetoothuuid.cpp b/src/bluetooth/qbluetoothuuid.cpp new file mode 100644 index 0000000..5eefde4 --- /dev/null +++ b/src/bluetooth/qbluetoothuuid.cpp @@ -0,0 +1,1050 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qbluetoothuuid.h" +#include "qbluetoothservicediscoveryagent.h" + +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +QT_IMPL_METATYPE_EXTERN(QBluetoothUuid) + +// Bluetooth base UUID 00000000-0000-1000-8000-00805F9B34FB +// these defines represent the above UUID +// static inline constexpr const uint data1Reference = 0x00000000; +static inline constexpr const ushort data2Reference = 0x0000; +static inline constexpr const ushort data3Reference = 0x1000; +static inline constexpr const unsigned char data4Reference[] { 0x80, 0x00, 0x00, 0x80, + 0x5f, 0x9b, 0x34, 0xfb }; + +void registerQBluetoothUuid() +{ + qRegisterMetaType(); +} +Q_CONSTRUCTOR_FUNCTION(registerQBluetoothUuid) + +/*! + \class QBluetoothUuid + \inmodule QtBluetooth + \brief The QBluetoothUuid class generates a UUID for each Bluetooth + service. + + \since 5.2 +*/ + +/*! + \enum QBluetoothUuid::ProtocolUuid + + This enum is a convienience type for Bluetooth protocol UUIDs. Values of this type will be + implicitly converted into a QBluetoothUuid when necessary. + + \value Sdp SDP protocol UUID + \value Udp UDP protocol UUID + \value Rfcomm RFCOMM protocol UUID + \value Tcp TCP protocol UUID + \value TcsBin Telephony Control Specification UUID + \value TcsAt Telephony Control Specification AT UUID + \value Att Attribute protocol UUID + \value Obex OBEX protocol UUID + \value Ip IP protocol UUID + \value Ftp FTP protocol UUID + \value Http HTTP protocol UUID + \value Wsp WSP UUID + \value Bnep Bluetooth Network Encapsulation Protocol UUID + \value Upnp Extended Service Discovery Profile UUID + \value Hidp Human Interface Device Profile UUID + \value HardcopyControlChannel Hardcopy Cable Replacement Profile UUID + \value HardcopyDataChannel Hardcopy Cable Replacement Profile UUID + \value HardcopyNotification Hardcopy Cable Replacement Profile UUID + \value Avctp Audio/Video Control Transport Protocol UUID + \value Avdtp Audio/Video Distribution Transport Protocol UUID + \value Cmtp Common ISDN Access Profile + \value UdiCPlain UDI protocol UUID + \value McapControlChannel Multi-Channel Adaptation Protocol UUID + \value McapDataChannel Multi-Channel Adaptation Protocol UUID + \value L2cap L2CAP protocol UUID + + \sa QBluetoothServiceInfo::ProtocolDescriptorList +*/ + +/*! + \enum QBluetoothUuid::ServiceClassUuid + + This enum is a convienience type for Bluetooth service class and profile UUIDs. Values of this type will be + implicitly converted into a QBluetoothUuid when necessary. Some UUIDs refer to service class ids, others to profile + ids and some can be used as both. In general, profile UUIDs shall only be used in a + \l QBluetoothServiceInfo::BluetoothProfileDescriptorList attribute and service class UUIDs shall only be used + in a \l QBluetoothServiceInfo::ServiceClassIds attribute. If the UUID is marked as profile and service class UUID + it can be used as a value for either of the above service attributes. Such a dual use has historical reasons + but is no longer permissible for newer UUIDs. + + The list below explicitly states as what type each UUID shall be used. Bluetooth Low Energy related values + starting with 0x18 were introduced by Qt 5.4 + + \value ServiceDiscoveryServer Service discovery server UUID (service) + \value BrowseGroupDescriptor Browser group descriptor (service) + \value PublicBrowseGroup Public browse group service class. Services which have the public + browse group in their \l {QBluetoothServiceInfo::BrowseGroupList}{browse group list} + are discoverable by the remote devices. + \value SerialPort Serial Port Profile UUID (service & profile) + \value LANAccessUsingPPP LAN Access Profile UUID (service & profile) + \value DialupNetworking Dial-up Networking Profile UUID (service & profile) + \value IrMCSync Synchronization Profile UUID (service & profile) + \value ObexObjectPush OBEX object push service UUID (service & profile) + \value OBEXFileTransfer File Transfer Profile (FTP) UUID (service & profile) + \value IrMCSyncCommand Synchronization Profile UUID (profile) + \value Headset Headset Profile (HSP) UUID (service & profile) + \value AudioSource Advanced Audio Distribution Profile (A2DP) UUID (service) + \value AudioSink Advanced Audio Distribution Profile (A2DP) UUID (service) + \value AV_RemoteControlTarget Audio/Video Remote Control Profile (AVRCP) UUID (service) + \value AdvancedAudioDistribution Advanced Audio Distribution Profile (A2DP) UUID (profile) + \value AV_RemoteControl Audio/Video Remote Control Profile (AVRCP) UUID (service & profile) + \value AV_RemoteControlController Audio/Video Remote Control Profile UUID (service) + \value HeadsetAG Headset Profile (HSP) UUID (service) + \value PANU Personal Area Networking Profile (PAN) UUID (service & profile) + \value NAP Personal Area Networking Profile (PAN) UUID (service & profile) + \value GN Personal Area Networking Profile (PAN) UUID (service & profile) + \value DirectPrinting Basic Printing Profile (BPP) UUID (service) + \value ReferencePrinting Related to Basic Printing Profile (BPP) UUID (service) + \value BasicImage Basic Imaging Profile (BIP) UUID (profile) + \value ImagingResponder Basic Imaging Profile (BIP) UUID (service) + \value ImagingAutomaticArchive Basic Imaging Profile (BIP) UUID (service) + \value ImagingReferenceObjects Basic Imaging Profile (BIP) UUID (service) + \value Handsfree Hands-Free Profile (HFP) UUID (service & profile) + \value HandsfreeAudioGateway Hands-Free Audio Gateway (HFP) UUID (service) + \value DirectPrintingReferenceObjectsService Basic Printing Profile (BPP) UUID (service) + \value ReflectedUI Basic Printing Profile (BPP) UUID (service) + \value BasicPrinting Basic Printing Profile (BPP) UUID (profile) + \value PrintingStatus Basic Printing Profile (BPP) UUID (service) + \value HumanInterfaceDeviceService Human Interface Device (HID) UUID (service & profile) + \value HardcopyCableReplacement Hardcopy Cable Replacement Profile (HCRP) (profile) + \value HCRPrint Hardcopy Cable Replacement Profile (HCRP) (service) + \value HCRScan Hardcopy Cable Replacement Profile (HCRP) (service) + \value SIMAccess SIM Access Profile (SAP) UUID (service and profile) + \value PhonebookAccessPCE Phonebook Access Profile (PBAP) UUID (service) + \value PhonebookAccessPSE Phonebook Access Profile (PBAP) UUID (service) + \value PhonebookAccess Phonebook Access Profile (PBAP) (profile) + \value HeadsetHS Headset Profile (HSP) UUID (service) + \value MessageAccessServer Message Access Profile (MAP) UUID (service) + \value MessageNotificationServer Message Access Profile (MAP) UUID (service) + \value MessageAccessProfile Message Access Profile (MAP) UUID (profile) + \value GNSS Global Navigation Satellite System UUID (profile) + \value GNSSServer Global Navigation Satellite System Server (UUID) (service) + \value Display3D 3D Synchronization Display UUID (service) + \value Glasses3D 3D Synchronization Glasses UUID (service) + \value Synchronization3D 3D Synchronization UUID (profile) + \value MPSProfile Multi-Profile Specification UUID (profile) + \value MPSService Multi-Profile Specification UUID (service) + \value PnPInformation Device Identification (DID) UUID (service & profile) + \value GenericNetworking Generic networking UUID (service) + \value GenericFileTransfer Generic file transfer UUID (service) + \value GenericAudio Generic audio UUID (service) + \value GenericTelephony Generic telephone UUID (service) + \value VideoSource Video Distribution Profile (VDP) UUID (service) + \value VideoSink Video Distribution Profile (VDP) UUID (service) + \value VideoDistribution Video Distribution Profile (VDP) UUID (profile) + \value HDP Health Device Profile (HDP) UUID (profile) + \value HDPSource Health Device Profile Source (HDP) UUID (service) + \value HDPSink Health Device Profile Sink (HDP) UUID (service) + \value GenericAccess Generic access service for Bluetooth Low Energy devices UUID (service). + It contains generic information about the device. All available Characteristics are readonly. + \value GenericAttribute + \value ImmediateAlert Immediate Alert UUID (service). The service exposes a control point to allow a peer + device to cause the device to immediately alert. + \value LinkLoss Link Loss UUID (service). The service defines behavior when a link is lost between two devices. + \value TxPower Transmission Power UUID (service). The service exposes a device’s current + transmit power level when in a connection. + \value CurrentTimeService Current Time UUID (service). The service defines how the current time can be exposed using + the Generic Attribute Profile (GATT). + \value ReferenceTimeUpdateService Reference Time update UUID (service). The service defines how a client can request + an update from a reference time source from a time server. + \value NextDSTChangeService Next DST change UUID (service). The service defines how the information about an + upcoming DST change can be exposed. + \value Glucose Glucose UUID (service). The service exposes glucose and other data from a glucose sensor + for use in consumer and professional healthcare applications. + \value HealthThermometer Health Thermometer UUID (service). The Health Thermometer service exposes temperature + and other data from a thermometer intended for healthcare and fitness applications. + \value DeviceInformation Device Information UUID (service). The Device Information Service exposes manufacturer + and/or vendor information about a device. + \value HeartRate Heart Rate UUID (service). The service exposes the heart rate and other data from a + Heart Rate Sensor intended for fitness applications. + \value PhoneAlertStatusService Phone Alert Status UUID (service). The service exposes the phone alert status when + in a connection. + \value BatteryService Battery UUID (service). The Battery Service exposes the state of a battery within a device. + \value BloodPressure Blood Pressure UUID (service). The service exposes blood pressure and other data from a blood pressure + monitor intended for healthcare applications. + \value AlertNotificationService Alert Notification UUID (service). The Alert Notification service exposes alert + information on a device. + \value HumanInterfaceDevice Human Interface UUID (service). The service exposes the HID reports and other HID data + intended for HID Hosts and HID Devices. + \value ScanParameters Scan Parameters UUID (service). The Scan Parameters Service enables a GATT Server device + to expose a characteristic for the GATT Client to write its scan interval and scan window + on the GATT Server device. + \value RunningSpeedAndCadence Runnung Speed and Cadence UUID (service). The service exposes speed, cadence and other + data from a Running Speed and Cadence Sensor intended for fitness applications. + \value CyclingSpeedAndCadence Cycling Speed and Cadence UUID (service). The service exposes speed-related and + cadence-related data from a Cycling Speed and Cadence sensor intended for fitness + applications. + \value CyclingPower Cycling Speed UUID (service). The service exposes power- and force-related data and + optionally speed- and cadence-related data from a Cycling Power + sensor intended for sports and fitness applications. + \value LocationAndNavigation Location Navigation UUID (service). The service exposes location and navigation-related + data from a Location and Navigation sensor intended for outdoor activity applications. + \value EnvironmentalSensing Environmental sensor UUID (service). The service exposes data from an environmental sensor + for sports and fitness applications. + \value BodyComposition Body composition UUID (service). The service exposes data about the body composition intended + for consumer healthcare applications. + \value UserData User Data UUID (service). The User Data service provides user-related data such as name, + gender or weight in sports and fitness environments. + \value WeightScale Weight Scale UUID (service). The Weight Scale service exposes weight-related data from + a scale for consumer healthcare, sports and fitness applications. + \value BondManagement Bond Management UUID (service). The Bond Management service enables user to manage the + storage of bond information on Bluetooth devices. + \value ContinuousGlucoseMonitoring Continuous Glucose Monitoring UUID (service). The Continuous Glucose Monitoring service + exposes glucose data from a monitoring sensor for use in healthcare applications. +*/ + +/*! + \enum QBluetoothUuid::CharacteristicType + \since 5.4 + + This enum is a convienience type for Bluetooth low energy service characteristics class UUIDs. Values of this type + will be implicitly converted into a QBluetoothUuid when necessary. The detailed type descriptions can be found + on \l{https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicsHome.aspx}{bluetooth.org}. + + \value AerobicHeartRateLowerLimit The lower limit of the heart rate where the user improves his endurance while + exercising. + \value AerobicHeartRateUpperLimit The upper limit of the heart rate where the user improves his endurance while + exercising. + \value AerobicThreshold This characteristic states the first metabolic threshold. + \value Age This characteristic states the age of the user. + \value AnaerobicHeartRateLowerLimit The lower limit of the heart rate where the user enhances his anaerobic + tolerance while exercising. + \value AnaerobicHeartRateUpperLimit The upper limit of the heart rate where the user enhances his anaerobic + tolerance while exercising. + \value AnaerobicThreshold This characteristic states the second metabolic threshold. + \value AlertCategoryID Categories of alerts/messages. + \value AlertCategoryIDBitMask Categories of alerts/messages. + \value AlertLevel The level of an alert a device is to sound. + If this level is changed while the alert is being sounded, + the new level should take effect. + \value AlertNotificationControlPoint Control point of the Alert Notification server. + Client can write the command here to request the several + functions toward the server. + \value AlertStatus The Alert Status characteristic defines the Status of alert. + \value ApparentWindDirection The characteristic exposes the apparent wind direction. The apparent wind is + experienced by an observer in motion. This characteristic states the direction + of the wind with an angle measured clockwise relative to the observers heading. + \value ApparentWindSpeed The characteristic exposes the apparent wind speed in meters per second. + The apparent wind is experienced by an observer in motion. + \value Appearance The external appearance of this device. The values are composed + of a category (10-bits) and sub-categories (6-bits). + \value BarometricPressureTrend This characteristic exposes the trend the barometric pressure is taking. + \value BatteryLevel The current charge level of a battery. 100% represents fully charged + while 0% represents fully discharged. + \value BloodPressureFeature The Blood Pressure Feature characteristic is used to describe the supported + features of the Blood Pressure Sensor. + \value BloodPressureMeasurement The Blood Pressure Measurement characteristic is a variable length structure + containing a Flags field, a Blood Pressure Measurement Compound Value field, + and contains additional fields such as Time Stamp, Pulse Rate and User ID + as determined by the contents of the Flags field. + \value BodyCompositionFeature This characteristic describes the available features in the \l BodyCompositionMeasurement + characteristic. + \value BodyCompositionMeasurement This characteristic describes the body composition such as muscle percentage + or the body water mass. + \value BodySensorLocation The Body Sensor Location characteristic describes the location of a sensor on + the body (e.g.: chest, finger or hand). + \value BootKeyboardInputReport The Boot Keyboard Input Report characteristic is used to transfer fixed format + and length Input Report data between a HID Host operating in Boot Protocol Mode + and a HID Service corresponding to a boot keyboard. + \value BootKeyboardOutputReport The Boot Keyboard Output Report characteristic is used to transfer fixed format + and length Output Report data between a HID Host operating in Boot Protocol Mode + and a HID Service corresponding to a boot keyboard. + \value BootMouseInputReport The Boot Mouse Input Report characteristic is used to transfer fixed format and + length Input Report data between a HID Host operating in Boot Protocol Mode and + a HID Service corresponding to a boot mouse. + \value CSCFeature The CSC (Cycling Speed and Cadence) Feature characteristic is used to describe + the supported features of the Server. + \value CSCMeasurement The CSC Measurement characteristic (CSC refers to Cycling Speed and Cadence) + is a variable length structure containing a Flags field and, based on the contents + of the Flags field, may contain one or more additional fields as shown in the tables + below. + \value CurrentTime The Current Time characteristic shows the same information as the \l ExactTime256 + characteristic and information on timezone, DST and the method of update employed. + \value CyclingPowerControlPoint The Cycling Power Control Point characteristic is used to request a specific function + to be executed on the receiving device. + \value CyclingPowerFeature The CP Feature characteristic is used to report a list of features supported by + the device. + \value CyclingPowerMeasurement The Cycling Power Measurement characteristic is a variable length structure containing + a Flags field, an Instantaneous Power field and, based on the contents of the Flags + field, may contain one or more additional fields as shown in the table below. + \value CyclingPowerVector The Cycling Power Vector characteristic is a variable length structure containing + a Flags fieldand based on the contents of the Flags field, may contain one or more + additional fields as shown in the table below. + \value DatabaseChangeIncrement + \value DateOfBirth This characteristic states the user's date of birth. + \value DateOfThresholdAssessment + \value DateTime The Date Time characteristic is used to represent time. + \value DayDateTime The Day Date Time characteristic presents the date, time and day of the week. + \value DayOfWeek The Day of Week characteristic describes the day of the week (Monday - Sunday). + \value DescriptorValueChanged This characteristic is related to the Environmental Sensing Service. + \value DeviceName The Device Name characteristic contains the name of the device. + \value DewPoint This characteristic states the dew point in degree Celsius. + \value DSTOffset The DST Offset characteristic describes the offset employed by daylight-saving time. + \value Elevation The Elevation characteristic states the elevation above/below sea level. + \value EmailAddress This characteristic states the email of the user. + \value ExactTime256 The Exact Time 256 characteristic describes the data, day and time + with an accuracy of 1/256th of a second. + \value FatBurnHeartRateLowerLimit The lower limit of the heart rate where the user maximizes the fat burn while exercising. + \value FatBurnHeartRateUpperLimit The upper limit of the heart rate where the user maximizes the fat burn while exercising. + \value FirmwareRevisionString The value of this characteristic is a UTF-8 string representing the firmware revision + for the firmware within the device. + \value FirstName This characteristic exposes the user's first name. + \value FiveZoneHeartRateLimits This characteristic contains the limits between the heart rate zones for the + 5-zone heart rate definition. + \value Gender This characteristic states the user's gender. + \value GlucoseFeature The Glucose Feature characteristic is used to describe the supported features + of the Server. When read, the Glucose Feature characteristic returns a value + that is used by a Client to determine the supported features of the Server. + \value GlucoseMeasurement The Glucose Measurement characteristic is a variable length structure containing + a Flags field, a Sequence Number field, a Base Time field and, based upon the contents + of the Flags field, may contain a Time Offset field, Glucose Concentration field, + Type-Sample Location field and a Sensor Status Annunciation field. + \value GlucoseMeasurementContext + \value GustFactor The characteristic states a factor of wind speed increase between average wind speed in + maximum gust speed. + \value HardwareRevisionString The value of this characteristic is a UTF-8 string representing the hardware revision + for the hardware within the device. + \value MaximumRecommendedHeartRate This characteristic exposes the maximum recommended heart rate that limits exertion. + \value HeartRateControlPoint + \value HeartRateMax This characteristic states the maximum heart rate a user can reach in beats per minute. + \value HeartRateMeasurement + \value HeatIndex This characteristic provides a heat index in degree Celsius. + \value Height This characteristic states the user's height. + \value HIDControlPoint The HID Control Point characteristic is a control-point attribute that defines the + HID Commands when written. + \value HIDInformation The HID Information Characteristic returns the HID attributes when read. + \value HipCircumference This characteristic states the user's hip circumference in meters. + \value Humidity The characteristic states the humidity in percent. + \value IEEE1107320601RegulatoryCertificationDataList The value of the characteristic is an opaque structure listing + various regulatory and/or certification compliance items to which the device + claims adherence. + \value IntermediateCuffPressure This characteristic has the same format as the Blood Pressure Measurement + characteristic. + \value IntermediateTemperature The Intermediate Temperature characteristic has the same format as the + Temperature Measurement characteristic. + \value Irradiance This characteristic states the power of electromagnetic radiation in watt per square meter. + \value Language This characteristic contains the language definition based on ISO639-1. + \value LastName This characteristic states the user's last name. + \value LNControlPoint The LN Control Point characteristic is used to request a specific function + to be executed on the receiving device. + \value LNFeature The LN Feature characteristic is used to report a list of features supported + by the device. + \value LocalTimeInformation + \value LocationAndSpeed The Location and Speed characteristic is a variable length structure containing + a Flags field and, based on the contents of the Flags field, may contain a combination + of data fields. + \value MagneticDeclination The characteristic contains the angle on the horizontal plane between the direction of + the (Geographic) True North and the Magnetic North, measured clockwise from True North + to Magnetic North. + \value MagneticFluxDensity2D This characteristic states the magnetic flux density on an x and y axis. + \value MagneticFluxDensity3D This characteristic states the magnetic flux density on an x, y and z axis. + \value ManufacturerNameString The value of this characteristic is a UTF-8 string representing the name of the + manufacturer of the device. + \value MeasurementInterval The Measurement Interval characteristic defines the time between measurements. + \value ModelNumberString The value of this characteristic is a UTF-8 string representing the model number + assigned by the device vendor. + \value Navigation The Navigation characteristic is a variable length structure containing a Flags field, + a Bearing field, a Heading field and, based on the contents of the Flags field. + \value NewAlert This characteristic defines the category of the alert and how many new alerts of + that category have occurred in the server device. + \value PeripheralPreferredConnectionParameters + \value PeripheralPrivacyFlag + \value PnPID The PnP_ID characteristic returns its value when read using the GATT Characteristic + Value Read procedure. + \value PollenConcentration The characteristic exposes the pollen concentration count per cubic meter. + \value PositionQuality The Position Quality characteristic is a variable length structure containing a + Flags field and at least one of the optional data. + \value Pressure The Pressure characteristic states the value of a pressure sensor. + \value ProtocolMode The Protocol Mode characteristic is used to expose the current protocol mode of + the HID Service with which it is associated, or to set the desired protocol + mode of the HID Service. + \value Rainfall This characteristic exposes the rainfall in meters. + \value ReconnectionAddress The Information included in this page is informative. The normative descriptions + are contained in the applicable specification. + \value RecordAccessControlPoint This control point is used with a service to provide basic management functionality + for the Glucose Sensor patient record database. + \value ReferenceTimeInformation + \value Report The Report characteristic is used to exchange data between a HID Device and a HID Host. + \value ReportMap Only a single instance of this characteristic exists as part of a HID Service. + \value RestingHeartRate This characteristic exposes the lowest heart rate a user can reach. + \value RingerControlPoint The Ringer Control Point characteristic defines the Control Point of Ringer. + \value RingerSetting The Ringer Setting characteristic defines the Setting of the Ringer. + \value RSCFeature The RSC (Running Speed and Cadence) Feature characteristic is used to describe the + supported features of the Server. + \value RSCMeasurement RSC refers to Running Speed and Cadence. + \value SCControlPoint The SC Control Point characteristic is used to request a specific function to be + executed on the receiving device. + \value ScanIntervalWindow The Scan Interval Window characteristic is used to store the scan parameters of + the GATT Client. + \value ScanRefresh The Scan Refresh characteristic is used to notify the Client that the Server + requires the Scan Interval Window characteristic to be written with the latest + values upon notification. + \value SensorLocation The Sensor Location characteristic is used to expose the location of the sensor. + \value SerialNumberString The value of this characteristic is a variable-length UTF-8 string representing + the serial number for a particular instance of the device. + \value ServiceChanged + \value SoftwareRevisionString The value of this characteristic is a UTF-8 string representing the software + revision for the software within the device. + \value SportTypeForAerobicAnaerobicThresholds This characteristic is used to preset the various Aerobic and Anaerobic + threshold characteristics based on the to-be-performed sport type. + \value SupportedNewAlertCategory Category that the server supports for new alert. + \value SupportedUnreadAlertCategory Category that the server supports for unread alert. + \value SystemID If the system ID is based of a Bluetooth Device Address with a Company Identifier + (OUI) is 0x123456 and the Company Assigned Identifier is 0x9ABCDE, then the System + Identifier is required to be 0x123456FFFE9ABCDE. + \value Temperature The value of this characteristic states the temperature in degree Celsius. + \value TemperatureMeasurement The Temperature Measurement characteristic is a variable length structure containing + a Flags field, a Temperature Measurement Value field and, based upon the contents of + the Flags field, optionally a Time Stamp field and/or a Temperature Type field. + \value TemperatureType The Temperature Type characteristic is an enumeration that indicates where the + temperature was measured. + \value ThreeZoneHeartRateLimits This characteristic contains the limits between the heart rate zones for the + 3-zone heart rate definition. + \value TimeAccuracy + \value TimeSource + \value TimeUpdateControlPoint + \value TimeUpdateState + \value TimeWithDST + \value TimeZone + \value TrueWindDirection The characteristic states the direction of the wind with an angle measured clockwise + relative to (Geographic) True North. A wind coming from the east is given as 90 degrees. + \value TrueWindSpeed The characteristic states the wind speed in meters per seconds. + \value TwoZoneHeartRateLimits This characteristic contains the limits between the heart rate zones for the + 2-zone heart rate definition. + \value TxPowerLevel The value of the characteristic is a signed 8 bit integer that has a fixed point + exponent of 0. + \value UnreadAlertStatus This characteristic shows how many numbers of unread alerts exist in the specific + category in the device. + \value UserControlPoint + \value UserIndex This characteristic states the index of the user. + \value UVIndex This characteristic exposes the UV index. + \value VO2Max This characteristic exposes the maximum Oxygen uptake of a user. + \value WaistCircumference This characteristic states the user's waist circumference in meters. + \value Weight This characteristic exposes the user's weight in kilograms. + \value WeightMeasurement This characteristic provides weight related data such as BMI or the user's weight. + \value WeightScaleFeature This characteristic describes the available data in the \l WeightMeasurement + characteristic. + \value WindChill This characteristic states the wind chill in degree Celsius +*/ + +/*! + \enum QBluetoothUuid::DescriptorType + \since 5.4 + + Descriptors are attributes that describe Bluetooth Low Energy characteristic values. + + This enum is a convienience type for descriptor class UUIDs. Values of this type + will be implicitly converted into a QBluetoothUuid when necessary. The detailed type specifications + can be found on \l{https://developer.bluetooth.org/gatt/descriptors/Pages/DescriptorsHomePage.aspx}{bluetooth.org}. + + \value CharacteristicExtendedProperties Descriptor defines additional Characteristic Properties. + The existence of this descriptor is indicated by the + \l QLowEnergyCharacteristic::ExtendedProperty flag. + \value CharacteristicUserDescription Descriptor provides a textual user description for a characteristic value. + \value ClientCharacteristicConfiguration Descriptor defines how the characteristic may be configured by a specific client. + \value ServerCharacteristicConfiguration Descriptor defines how the characteristic descriptor is associated with may be + configured for the server. + \value CharacteristicPresentationFormat Descriptor defines the format of the Characteristic Value. + \value CharacteristicAggregateFormat Descriptor defines the format of an aggregated Characteristic Value. + \value ValidRange descriptor is used for defining the range of a characteristics. + Two mandatory fields are contained (upper and lower bounds) which define the range. + \value ExternalReportReference Allows a HID Host to map information from the Report Map characteristic value for + Input Report, Output Report or Feature Report data to the Characteristic UUID of + external service characteristics used to transfer the associated data. + \value ReportReference Mapping information in the form of a Report ID and Report Type which maps the + current parent characteristic to the Report ID(s) and Report Type (s) defined + within the Report Map characteristic. + \value EnvironmentalSensingConfiguration Descriptor defines how multiple trigger settings descriptors are combined. Therefore + this descriptor works together with the \l EnvironmentalSensingTriggerSetting descriptor + to define the conditions under which the associated characteristic value can be notified. + \value EnvironmentalSensingMeasurement Descriptor defines the additional information for the environmental sensing server + such as the intended application, sampling functions or measurement period and uncertainty. + \value EnvironmentalSensingTriggerSetting Descriptor defines under which conditions an environmental sensing server (ESS) should + trigger notifications. Examples of such conditions are certain thresholds being reached + or timers having expired. This implies that the ESS characteristic supports notifications. + \value UnknownDescriptorType The descriptor type is unknown. +*/ + +/*! + \fn QBluetoothUuid::QBluetoothUuid() + + Constructs a new null Bluetooth UUID. +*/ + +/*! + \fn QBluetoothUuid::QBluetoothUuid(ProtocolUuid uuid) + + Constructs a new Bluetooth UUID from the protocol \a uuid. +*/ + +/*! + \fn QBluetoothUuid::QBluetoothUuid(ServiceClassUuid uuid) + + Constructs a new Bluetooth UUID from the service class \a uuid. +*/ + +/*! + \fn QBluetoothUuid::QBluetoothUuid(CharacteristicType uuid) + + Constructs a new Bluetooth UUID from the characteristic type \a uuid. + \since 5.4 +*/ + +/*! + \fn QBluetoothUuid::QBluetoothUuid(DescriptorType uuid) + + Constructs a new Bluetooth UUID from the descriptor type \a uuid. + \since 5.4 +*/ + +/*! + \fn QBluetoothUuid::QBluetoothUuid(quint16 uuid) + + Constructs a new Bluetooth UUID from the 16 bit \a uuid. +*/ + +/*! + \fn QBluetoothUuid::QBluetoothUuid(quint32 uuid) + + Constructs a new Bluetooth UUID from the 32 bit \a uuid. +*/ + +/*! + \fn QBluetoothUuid::QBluetoothUuid(QUuid::Id128Bytes uuid, QSysInfo::Endian order) + \since 6.6 + + Constructs a new Bluetooth UUID from the 128 bit \a uuid represented + by the integral \a uuid parameter and respecting the byte order \a order. +*/ + +/*! + \fn quint128 QBluetoothUuid::toUInt128(QSysInfo::Endian order) const + + Returns the 128 bit representation of this UUID in byte order \a order. + + \note In Qt versions prior to 6.6, the \a order argument was not present, + and the function was hard-coded to return in big-endian order. +*/ +#ifndef QT_SUPPORTS_INT128 // otherwise falls back to QUuid::toUint128() +quint128 QBluetoothUuid::toUInt128(QSysInfo::Endian order) const noexcept +{ + quint128 r; + const auto bytes = toBytes(order); + static_assert(sizeof(quint128) == sizeof(decltype(bytes))); + memcpy(&r, bytes.data, sizeof(quint128)); + return r; +} +#endif // !QT_SUPPORTS_INT128 + +/*! + \fn QBluetoothUuid::QBluetoothUuid(quint128 uuid, QSysInfo::Endian order) + + Constructs a new Bluetooth UUID from a 128 bit \a uuid. + + \note In Qt versions prior to 6.6, the \a order argument was not present, + and the function was hard-coded to big-endian order. +*/ + +/*! + \fn QBluetoothUuid::QBluetoothUuid(const QUuid &uuid) + + Constructs a new Bluetooth UUID that is a copy of \a uuid. +*/ + +/*! + Returns the minimum size in bytes that this UUID can be represented in. For non-null UUIDs 2, + 4 or 16 is returned. 0 is returned for null UUIDs. + + \sa isNull(), toUInt16(), toUInt32() +*/ +int QBluetoothUuid::minimumSize() const +{ + if (data2 == data2Reference && data3 == data3Reference + && memcmp(data4, data4Reference, 8) == 0) { + // 16 or 32 bit Bluetooth UUID + if (data1 & 0xFFFF0000) + return 4; + else + return 2; + } + + if (isNull()) + return 0; + + return 16; +} + +/*! + Returns the 16 bit representation of this UUID. If \a ok is passed, it is set to true if the + conversion is possible, otherwise it is set to false. The return value is undefined if \a ok is + set to false. +*/ +quint16 QBluetoothUuid::toUInt16(bool *ok) const +{ + if (data1 & 0xFFFF0000 || data2 != data2Reference || data3 != data3Reference + || memcmp(data4, data4Reference, 8) != 0) { + // not convertable to 16 bit Bluetooth UUID. + if (ok) + *ok = false; + return 0; + } + + if (ok) + *ok = true; + + return data1; +} + +/*! + Returns the 32 bit representation of this UUID. If \a ok is passed, it is set to true if the + conversion is possible, otherwise it is set to false. The return value is undefined if \a ok is + set to false. +*/ +quint32 QBluetoothUuid::toUInt32(bool *ok) const +{ + if (data2 != data2Reference || data3 != data3Reference + || memcmp(data4, data4Reference, 8) != 0) { + // not convertable to 32 bit Bluetooth UUID. + if (ok) + *ok = false; + return 0; + } + + if (ok) + *ok = true; + + return data1; +} + +/*! + Returns a human-readable and translated name for the given service class + represented by \a uuid. + + \sa QBluetoothUuid::ServiceClassUuid + \since Qt 5.4 + */ +QString QBluetoothUuid::serviceClassToString(QBluetoothUuid::ServiceClassUuid uuid) +{ + switch (uuid) { + case QBluetoothUuid::ServiceClassUuid::ServiceDiscoveryServer: return QBluetoothServiceDiscoveryAgent::tr("Service Discovery"); + case QBluetoothUuid::ServiceClassUuid::BrowseGroupDescriptor: return QBluetoothServiceDiscoveryAgent::tr("Browse Group Descriptor"); + case QBluetoothUuid::ServiceClassUuid::PublicBrowseGroup: return QBluetoothServiceDiscoveryAgent::tr("Public Browse Group"); + case QBluetoothUuid::ServiceClassUuid::SerialPort: return QBluetoothServiceDiscoveryAgent::tr("Serial Port Profile"); + case QBluetoothUuid::ServiceClassUuid::LANAccessUsingPPP: return QBluetoothServiceDiscoveryAgent::tr("LAN Access Profile"); + case QBluetoothUuid::ServiceClassUuid::DialupNetworking: return QBluetoothServiceDiscoveryAgent::tr("Dial-Up Networking"); + case QBluetoothUuid::ServiceClassUuid::IrMCSync: return QBluetoothServiceDiscoveryAgent::tr("Synchronization"); + case QBluetoothUuid::ServiceClassUuid::ObexObjectPush: return QBluetoothServiceDiscoveryAgent::tr("Object Push"); + case QBluetoothUuid::ServiceClassUuid::OBEXFileTransfer: return QBluetoothServiceDiscoveryAgent::tr("File Transfer"); + case QBluetoothUuid::ServiceClassUuid::IrMCSyncCommand: return QBluetoothServiceDiscoveryAgent::tr("Synchronization Command"); + case QBluetoothUuid::ServiceClassUuid::Headset: return QBluetoothServiceDiscoveryAgent::tr("Headset"); + case QBluetoothUuid::ServiceClassUuid::AudioSource: return QBluetoothServiceDiscoveryAgent::tr("Audio Source"); + case QBluetoothUuid::ServiceClassUuid::AudioSink: return QBluetoothServiceDiscoveryAgent::tr("Audio Sink"); + case QBluetoothUuid::ServiceClassUuid::AV_RemoteControlTarget: return QBluetoothServiceDiscoveryAgent::tr("Audio/Video Remote Control Target"); + case QBluetoothUuid::ServiceClassUuid::AdvancedAudioDistribution: return QBluetoothServiceDiscoveryAgent::tr("Advanced Audio Distribution"); + case QBluetoothUuid::ServiceClassUuid::AV_RemoteControl: return QBluetoothServiceDiscoveryAgent::tr("Audio/Video Remote Control"); + case QBluetoothUuid::ServiceClassUuid::AV_RemoteControlController: return QBluetoothServiceDiscoveryAgent::tr("Audio/Video Remote Control Controller"); + case QBluetoothUuid::ServiceClassUuid::HeadsetAG: return QBluetoothServiceDiscoveryAgent::tr("Headset AG"); + case QBluetoothUuid::ServiceClassUuid::PANU: return QBluetoothServiceDiscoveryAgent::tr("Personal Area Networking (PANU)"); + case QBluetoothUuid::ServiceClassUuid::NAP: return QBluetoothServiceDiscoveryAgent::tr("Personal Area Networking (NAP)"); + case QBluetoothUuid::ServiceClassUuid::GN: return QBluetoothServiceDiscoveryAgent::tr("Personal Area Networking (GN)"); + case QBluetoothUuid::ServiceClassUuid::DirectPrinting: return QBluetoothServiceDiscoveryAgent::tr("Basic Direct Printing (BPP)"); + case QBluetoothUuid::ServiceClassUuid::ReferencePrinting: return QBluetoothServiceDiscoveryAgent::tr("Basic Reference Printing (BPP)"); + case QBluetoothUuid::ServiceClassUuid::BasicImage: return QBluetoothServiceDiscoveryAgent::tr("Basic Imaging Profile"); + case QBluetoothUuid::ServiceClassUuid::ImagingResponder: return QBluetoothServiceDiscoveryAgent::tr("Basic Imaging Responder"); + case QBluetoothUuid::ServiceClassUuid::ImagingAutomaticArchive: return QBluetoothServiceDiscoveryAgent::tr("Basic Imaging Archive"); + case QBluetoothUuid::ServiceClassUuid::ImagingReferenceObjects: return QBluetoothServiceDiscoveryAgent::tr("Basic Imaging Ref Objects"); + case QBluetoothUuid::ServiceClassUuid::Handsfree: return QBluetoothServiceDiscoveryAgent::tr("Hands-Free"); + case QBluetoothUuid::ServiceClassUuid::HandsfreeAudioGateway: return QBluetoothServiceDiscoveryAgent::tr("Hands-Free AG"); + case QBluetoothUuid::ServiceClassUuid::DirectPrintingReferenceObjectsService: return QBluetoothServiceDiscoveryAgent::tr("Basic Printing RefObject Service"); + case QBluetoothUuid::ServiceClassUuid::ReflectedUI: return QBluetoothServiceDiscoveryAgent::tr("Basic Printing Reflected UI"); + case QBluetoothUuid::ServiceClassUuid::BasicPrinting: return QBluetoothServiceDiscoveryAgent::tr("Basic Printing"); + case QBluetoothUuid::ServiceClassUuid::PrintingStatus: return QBluetoothServiceDiscoveryAgent::tr("Basic Printing Status"); + case QBluetoothUuid::ServiceClassUuid::HumanInterfaceDeviceService: return QBluetoothServiceDiscoveryAgent::tr("Human Interface Device"); + case QBluetoothUuid::ServiceClassUuid::HardcopyCableReplacement: return QBluetoothServiceDiscoveryAgent::tr("Hardcopy Cable Replacement"); + case QBluetoothUuid::ServiceClassUuid::HCRPrint: return QBluetoothServiceDiscoveryAgent::tr("Hardcopy Cable Replacement Print"); + case QBluetoothUuid::ServiceClassUuid::HCRScan: return QBluetoothServiceDiscoveryAgent::tr("Hardcopy Cable Replacement Scan"); + case QBluetoothUuid::ServiceClassUuid::SIMAccess: return QBluetoothServiceDiscoveryAgent::tr("SIM Access Server"); + case QBluetoothUuid::ServiceClassUuid::PhonebookAccessPCE: return QBluetoothServiceDiscoveryAgent::tr("Phonebook Access PCE"); + case QBluetoothUuid::ServiceClassUuid::PhonebookAccessPSE: return QBluetoothServiceDiscoveryAgent::tr("Phonebook Access PSE"); + case QBluetoothUuid::ServiceClassUuid::PhonebookAccess: return QBluetoothServiceDiscoveryAgent::tr("Phonebook Access"); + case QBluetoothUuid::ServiceClassUuid::HeadsetHS: return QBluetoothServiceDiscoveryAgent::tr("Headset HS"); + case QBluetoothUuid::ServiceClassUuid::MessageAccessServer: return QBluetoothServiceDiscoveryAgent::tr("Message Access Server"); + case QBluetoothUuid::ServiceClassUuid::MessageNotificationServer: return QBluetoothServiceDiscoveryAgent::tr("Message Notification Server"); + case QBluetoothUuid::ServiceClassUuid::MessageAccessProfile: return QBluetoothServiceDiscoveryAgent::tr("Message Access"); + case QBluetoothUuid::ServiceClassUuid::GNSS: return QBluetoothServiceDiscoveryAgent::tr("Global Navigation Satellite System"); + case QBluetoothUuid::ServiceClassUuid::GNSSServer: return QBluetoothServiceDiscoveryAgent::tr("Global Navigation Satellite System Server"); + case QBluetoothUuid::ServiceClassUuid::Display3D: return QBluetoothServiceDiscoveryAgent::tr("3D Synchronization Display"); + case QBluetoothUuid::ServiceClassUuid::Glasses3D: return QBluetoothServiceDiscoveryAgent::tr("3D Synchronization Glasses"); + case QBluetoothUuid::ServiceClassUuid::Synchronization3D: return QBluetoothServiceDiscoveryAgent::tr("3D Synchronization"); + case QBluetoothUuid::ServiceClassUuid::MPSProfile: return QBluetoothServiceDiscoveryAgent::tr("Multi-Profile Specification (Profile)"); + case QBluetoothUuid::ServiceClassUuid::MPSService: return QBluetoothServiceDiscoveryAgent::tr("Multi-Profile Specification"); + case QBluetoothUuid::ServiceClassUuid::PnPInformation: return QBluetoothServiceDiscoveryAgent::tr("Device Identification"); + case QBluetoothUuid::ServiceClassUuid::GenericNetworking: return QBluetoothServiceDiscoveryAgent::tr("Generic Networking"); + case QBluetoothUuid::ServiceClassUuid::GenericFileTransfer: return QBluetoothServiceDiscoveryAgent::tr("Generic File Transfer"); + case QBluetoothUuid::ServiceClassUuid::GenericAudio: return QBluetoothServiceDiscoveryAgent::tr("Generic Audio"); + case QBluetoothUuid::ServiceClassUuid::GenericTelephony: return QBluetoothServiceDiscoveryAgent::tr("Generic Telephony"); + case QBluetoothUuid::ServiceClassUuid::VideoSource: return QBluetoothServiceDiscoveryAgent::tr("Video Source"); + case QBluetoothUuid::ServiceClassUuid::VideoSink: return QBluetoothServiceDiscoveryAgent::tr("Video Sink"); + case QBluetoothUuid::ServiceClassUuid::VideoDistribution: return QBluetoothServiceDiscoveryAgent::tr("Video Distribution"); + case QBluetoothUuid::ServiceClassUuid::HDP: return QBluetoothServiceDiscoveryAgent::tr("Health Device"); + case QBluetoothUuid::ServiceClassUuid::HDPSource: return QBluetoothServiceDiscoveryAgent::tr("Health Device Source"); + case QBluetoothUuid::ServiceClassUuid::HDPSink: return QBluetoothServiceDiscoveryAgent::tr("Health Device Sink"); + case QBluetoothUuid::ServiceClassUuid::GenericAccess: return QBluetoothServiceDiscoveryAgent::tr("Generic Access"); + case QBluetoothUuid::ServiceClassUuid::GenericAttribute: return QBluetoothServiceDiscoveryAgent::tr("Generic Attribute"); + case QBluetoothUuid::ServiceClassUuid::ImmediateAlert: return QBluetoothServiceDiscoveryAgent::tr("Immediate Alert"); + case QBluetoothUuid::ServiceClassUuid::LinkLoss: return QBluetoothServiceDiscoveryAgent::tr("Link Loss"); + case QBluetoothUuid::ServiceClassUuid::TxPower: return QBluetoothServiceDiscoveryAgent::tr("Tx Power"); + case QBluetoothUuid::ServiceClassUuid::CurrentTimeService: return QBluetoothServiceDiscoveryAgent::tr("Current Time Service"); + case QBluetoothUuid::ServiceClassUuid::ReferenceTimeUpdateService: return QBluetoothServiceDiscoveryAgent::tr("Reference Time Update Service"); + case QBluetoothUuid::ServiceClassUuid::NextDSTChangeService: return QBluetoothServiceDiscoveryAgent::tr("Next DST Change Service"); + case QBluetoothUuid::ServiceClassUuid::Glucose: return QBluetoothServiceDiscoveryAgent::tr("Glucose"); + case QBluetoothUuid::ServiceClassUuid::HealthThermometer: return QBluetoothServiceDiscoveryAgent::tr("Health Thermometer"); + case QBluetoothUuid::ServiceClassUuid::DeviceInformation: return QBluetoothServiceDiscoveryAgent::tr("Device Information"); + case QBluetoothUuid::ServiceClassUuid::HeartRate: return QBluetoothServiceDiscoveryAgent::tr("Heart Rate"); + case QBluetoothUuid::ServiceClassUuid::PhoneAlertStatusService: return QBluetoothServiceDiscoveryAgent::tr("Phone Alert Status Service"); + case QBluetoothUuid::ServiceClassUuid::BatteryService: return QBluetoothServiceDiscoveryAgent::tr("Battery Service"); + case QBluetoothUuid::ServiceClassUuid::BloodPressure: return QBluetoothServiceDiscoveryAgent::tr("Blood Pressure"); + case QBluetoothUuid::ServiceClassUuid::AlertNotificationService: return QBluetoothServiceDiscoveryAgent::tr("Alert Notification Service"); + case QBluetoothUuid::ServiceClassUuid::HumanInterfaceDevice: return QBluetoothServiceDiscoveryAgent::tr("Human Interface Device"); + case QBluetoothUuid::ServiceClassUuid::ScanParameters: return QBluetoothServiceDiscoveryAgent::tr("Scan Parameters"); + case QBluetoothUuid::ServiceClassUuid::RunningSpeedAndCadence: return QBluetoothServiceDiscoveryAgent::tr("Running Speed and Cadence"); + case QBluetoothUuid::ServiceClassUuid::CyclingSpeedAndCadence: return QBluetoothServiceDiscoveryAgent::tr("Cycling Speed and Cadence"); + case QBluetoothUuid::ServiceClassUuid::CyclingPower: return QBluetoothServiceDiscoveryAgent::tr("Cycling Power"); + case QBluetoothUuid::ServiceClassUuid::LocationAndNavigation: return QBluetoothServiceDiscoveryAgent::tr("Location and Navigation"); + case QBluetoothUuid::ServiceClassUuid::EnvironmentalSensing: return QBluetoothServiceDiscoveryAgent::tr("Environmental Sensing"); + case QBluetoothUuid::ServiceClassUuid::BodyComposition: return QBluetoothServiceDiscoveryAgent::tr("Body Composition"); + case QBluetoothUuid::ServiceClassUuid::UserData: return QBluetoothServiceDiscoveryAgent::tr("User Data"); + case QBluetoothUuid::ServiceClassUuid::WeightScale: return QBluetoothServiceDiscoveryAgent::tr("Weight Scale"); + //: Connection management (Bluetooth) + case QBluetoothUuid::ServiceClassUuid::BondManagement: return QBluetoothServiceDiscoveryAgent::tr("Bond Management"); + case QBluetoothUuid::ServiceClassUuid::ContinuousGlucoseMonitoring: return QBluetoothServiceDiscoveryAgent::tr("Continuous Glucose Monitoring"); + } + + return QString(); +} + + +/*! + Returns a human-readable and translated name for the given protocol + represented by \a uuid. + + \sa QBluetoothUuid::ProtocolUuid + + \since 5.4 + */ +QString QBluetoothUuid::protocolToString(QBluetoothUuid::ProtocolUuid uuid) +{ + switch (uuid) { + case QBluetoothUuid::ProtocolUuid::Sdp: return QBluetoothServiceDiscoveryAgent::tr("Service Discovery Protocol"); + case QBluetoothUuid::ProtocolUuid::Udp: return QBluetoothServiceDiscoveryAgent::tr("User Datagram Protocol"); + case QBluetoothUuid::ProtocolUuid::Rfcomm: return QBluetoothServiceDiscoveryAgent::tr("Radio Frequency Communication"); + case QBluetoothUuid::ProtocolUuid::Tcp: return QBluetoothServiceDiscoveryAgent::tr("Transmission Control Protocol"); + case QBluetoothUuid::ProtocolUuid::TcsBin: return QBluetoothServiceDiscoveryAgent::tr("Telephony Control Specification - Binary"); + case QBluetoothUuid::ProtocolUuid::TcsAt: return QBluetoothServiceDiscoveryAgent::tr("Telephony Control Specification - AT"); + case QBluetoothUuid::ProtocolUuid::Att: return QBluetoothServiceDiscoveryAgent::tr("Attribute Protocol"); + case QBluetoothUuid::ProtocolUuid::Obex: return QBluetoothServiceDiscoveryAgent::tr("Object Exchange Protocol"); + case QBluetoothUuid::ProtocolUuid::Ip: return QBluetoothServiceDiscoveryAgent::tr("Internet Protocol"); + case QBluetoothUuid::ProtocolUuid::Ftp: return QBluetoothServiceDiscoveryAgent::tr("File Transfer Protocol"); + case QBluetoothUuid::ProtocolUuid::Http: return QBluetoothServiceDiscoveryAgent::tr("Hypertext Transfer Protocol"); + case QBluetoothUuid::ProtocolUuid::Wsp: return QBluetoothServiceDiscoveryAgent::tr("Wireless Short Packet Protocol"); + case QBluetoothUuid::ProtocolUuid::Bnep: return QBluetoothServiceDiscoveryAgent::tr("Bluetooth Network Encapsulation Protocol"); + case QBluetoothUuid::ProtocolUuid::Upnp: return QBluetoothServiceDiscoveryAgent::tr("Extended Service Discovery Protocol"); + case QBluetoothUuid::ProtocolUuid::Hidp: return QBluetoothServiceDiscoveryAgent::tr("Human Interface Device Protocol"); + case QBluetoothUuid::ProtocolUuid::HardcopyControlChannel: return QBluetoothServiceDiscoveryAgent::tr("Hardcopy Control Channel"); + case QBluetoothUuid::ProtocolUuid::HardcopyDataChannel: return QBluetoothServiceDiscoveryAgent::tr("Hardcopy Data Channel"); + case QBluetoothUuid::ProtocolUuid::HardcopyNotification: return QBluetoothServiceDiscoveryAgent::tr("Hardcopy Notification"); + case QBluetoothUuid::ProtocolUuid::Avctp: return QBluetoothServiceDiscoveryAgent::tr("Audio/Video Control Transport Protocol"); + case QBluetoothUuid::ProtocolUuid::Avdtp: return QBluetoothServiceDiscoveryAgent::tr("Audio/Video Distribution Transport Protocol"); + case QBluetoothUuid::ProtocolUuid::Cmtp: return QBluetoothServiceDiscoveryAgent::tr("Common ISDN Access Protocol"); + case QBluetoothUuid::ProtocolUuid::UdiCPlain: return QBluetoothServiceDiscoveryAgent::tr("UdiCPlain"); + case QBluetoothUuid::ProtocolUuid::McapControlChannel: return QBluetoothServiceDiscoveryAgent::tr("Multi-Channel Adaptation Protocol - Control"); + case QBluetoothUuid::ProtocolUuid::McapDataChannel: return QBluetoothServiceDiscoveryAgent::tr("Multi-Channel Adaptation Protocol - Data"); + case QBluetoothUuid::ProtocolUuid::L2cap: return QBluetoothServiceDiscoveryAgent::tr("Layer 2 Control Protocol"); + } + + return QString(); +} + +/*! + Returns a human-readable and translated name for the given characteristic type + represented by \a uuid. + + \sa QBluetoothUuid::CharacteristicType + + \since 5.4 +*/ +QString QBluetoothUuid::characteristicToString(CharacteristicType uuid) +{ + switch (uuid) { + //: GAP: Generic Access Profile (Bluetooth) + case QBluetoothUuid::CharacteristicType::DeviceName: return QBluetoothServiceDiscoveryAgent::tr("GAP Device Name"); + //: GAP: Generic Access Profile (Bluetooth) + case QBluetoothUuid::CharacteristicType::Appearance: return QBluetoothServiceDiscoveryAgent::tr("GAP Appearance"); + case QBluetoothUuid::CharacteristicType::PeripheralPrivacyFlag: + //: GAP: Generic Access Profile (Bluetooth) + return QBluetoothServiceDiscoveryAgent::tr("GAP Peripheral Privacy Flag"); + case QBluetoothUuid::CharacteristicType::ReconnectionAddress: + //: GAP: Generic Access Profile (Bluetooth) + return QBluetoothServiceDiscoveryAgent::tr("GAP Reconnection Address"); + case QBluetoothUuid::CharacteristicType::PeripheralPreferredConnectionParameters: + return QBluetoothServiceDiscoveryAgent::tr("GAP Peripheral Preferred Connection Parameters"); + //: GATT: _G_eneric _Att_ribute Profile (Bluetooth) + case QBluetoothUuid::CharacteristicType::ServiceChanged: return QBluetoothServiceDiscoveryAgent::tr("GATT Service Changed"); + case QBluetoothUuid::CharacteristicType::AlertLevel: return QBluetoothServiceDiscoveryAgent::tr("Alert Level"); + case QBluetoothUuid::CharacteristicType::TxPowerLevel: return QBluetoothServiceDiscoveryAgent::tr("TX Power"); + case QBluetoothUuid::CharacteristicType::DateTime: return QBluetoothServiceDiscoveryAgent::tr("Date Time"); + case QBluetoothUuid::CharacteristicType::DayOfWeek: return QBluetoothServiceDiscoveryAgent::tr("Day Of Week"); + case QBluetoothUuid::CharacteristicType::DayDateTime: return QBluetoothServiceDiscoveryAgent::tr("Day Date Time"); + case QBluetoothUuid::CharacteristicType::ExactTime256: return QBluetoothServiceDiscoveryAgent::tr("Exact Time 256"); + case QBluetoothUuid::CharacteristicType::DSTOffset: return QBluetoothServiceDiscoveryAgent::tr("DST Offset"); + case QBluetoothUuid::CharacteristicType::TimeZone: return QBluetoothServiceDiscoveryAgent::tr("Time Zone"); + case QBluetoothUuid::CharacteristicType::LocalTimeInformation: + return QBluetoothServiceDiscoveryAgent::tr("Local Time Information"); + case QBluetoothUuid::CharacteristicType::TimeWithDST: return QBluetoothServiceDiscoveryAgent::tr("Time With DST"); + case QBluetoothUuid::CharacteristicType::TimeAccuracy: return QBluetoothServiceDiscoveryAgent::tr("Time Accuracy"); + case QBluetoothUuid::CharacteristicType::TimeSource: return QBluetoothServiceDiscoveryAgent::tr("Time Source"); + case QBluetoothUuid::CharacteristicType::ReferenceTimeInformation: + return QBluetoothServiceDiscoveryAgent::tr("Reference Time Information"); + case QBluetoothUuid::CharacteristicType::TimeUpdateControlPoint: + return QBluetoothServiceDiscoveryAgent::tr("Time Update Control Point"); + case QBluetoothUuid::CharacteristicType::TimeUpdateState: return QBluetoothServiceDiscoveryAgent::tr("Time Update State"); + case QBluetoothUuid::CharacteristicType::GlucoseMeasurement: return QBluetoothServiceDiscoveryAgent::tr("Glucose Measurement"); + case QBluetoothUuid::CharacteristicType::BatteryLevel: return QBluetoothServiceDiscoveryAgent::tr("Battery Level"); + case QBluetoothUuid::CharacteristicType::TemperatureMeasurement: + return QBluetoothServiceDiscoveryAgent::tr("Temperature Measurement"); + case QBluetoothUuid::CharacteristicType::TemperatureType: return QBluetoothServiceDiscoveryAgent::tr("Temperature Type"); + case QBluetoothUuid::CharacteristicType::IntermediateTemperature: + return QBluetoothServiceDiscoveryAgent::tr("Intermediate Temperature"); + case QBluetoothUuid::CharacteristicType::MeasurementInterval: return QBluetoothServiceDiscoveryAgent::tr("Measurement Interval"); + case QBluetoothUuid::CharacteristicType::BootKeyboardInputReport: return QBluetoothServiceDiscoveryAgent::tr("Boot Keyboard Input Report"); + case QBluetoothUuid::CharacteristicType::SystemID: return QBluetoothServiceDiscoveryAgent::tr("System ID"); + case QBluetoothUuid::CharacteristicType::ModelNumberString: return QBluetoothServiceDiscoveryAgent::tr("Model Number String"); + case QBluetoothUuid::CharacteristicType::SerialNumberString: return QBluetoothServiceDiscoveryAgent::tr("Serial Number String"); + case QBluetoothUuid::CharacteristicType::FirmwareRevisionString: return QBluetoothServiceDiscoveryAgent::tr("Firmware Revision String"); + case QBluetoothUuid::CharacteristicType::HardwareRevisionString: return QBluetoothServiceDiscoveryAgent::tr("Hardware Revision String"); + case QBluetoothUuid::CharacteristicType::SoftwareRevisionString: return QBluetoothServiceDiscoveryAgent::tr("Software Revision String"); + case QBluetoothUuid::CharacteristicType::ManufacturerNameString: return QBluetoothServiceDiscoveryAgent::tr("Manufacturer Name String"); + case QBluetoothUuid::CharacteristicType::IEEE1107320601RegulatoryCertificationDataList: + return QBluetoothServiceDiscoveryAgent::tr("IEEE 11073 20601 Regulatory Certification Data List"); + case QBluetoothUuid::CharacteristicType::CurrentTime: return QBluetoothServiceDiscoveryAgent::tr("Current Time"); + case QBluetoothUuid::CharacteristicType::ScanRefresh: return QBluetoothServiceDiscoveryAgent::tr("Scan Refresh"); + case QBluetoothUuid::CharacteristicType::BootKeyboardOutputReport: + return QBluetoothServiceDiscoveryAgent::tr("Boot Keyboard Output Report"); + case QBluetoothUuid::CharacteristicType::BootMouseInputReport: return QBluetoothServiceDiscoveryAgent::tr("Boot Mouse Input Report"); + case QBluetoothUuid::CharacteristicType::GlucoseMeasurementContext: + return QBluetoothServiceDiscoveryAgent::tr("Glucose Measurement Context"); + case QBluetoothUuid::CharacteristicType::BloodPressureMeasurement: + return QBluetoothServiceDiscoveryAgent::tr("Blood Pressure Measurement"); + case QBluetoothUuid::CharacteristicType::IntermediateCuffPressure: + return QBluetoothServiceDiscoveryAgent::tr("Intermediate Cuff Pressure"); + case QBluetoothUuid::CharacteristicType::HeartRateMeasurement: return QBluetoothServiceDiscoveryAgent::tr("Heart Rate Measurement"); + case QBluetoothUuid::CharacteristicType::BodySensorLocation: return QBluetoothServiceDiscoveryAgent::tr("Body Sensor Location"); + case QBluetoothUuid::CharacteristicType::HeartRateControlPoint: return QBluetoothServiceDiscoveryAgent::tr("Heart Rate Control Point"); + case QBluetoothUuid::CharacteristicType::AlertStatus: return QBluetoothServiceDiscoveryAgent::tr("Alert Status"); + case QBluetoothUuid::CharacteristicType::RingerControlPoint: return QBluetoothServiceDiscoveryAgent::tr("Ringer Control Point"); + case QBluetoothUuid::CharacteristicType::RingerSetting: return QBluetoothServiceDiscoveryAgent::tr("Ringer Setting"); + case QBluetoothUuid::CharacteristicType::AlertCategoryIDBitMask: + return QBluetoothServiceDiscoveryAgent::tr("Alert Category ID Bit Mask"); + case QBluetoothUuid::CharacteristicType::AlertCategoryID: return QBluetoothServiceDiscoveryAgent::tr("Alert Category ID"); + case QBluetoothUuid::CharacteristicType::AlertNotificationControlPoint: + return QBluetoothServiceDiscoveryAgent::tr("Alert Notification Control Point"); + case QBluetoothUuid::CharacteristicType::UnreadAlertStatus: return QBluetoothServiceDiscoveryAgent::tr("Unread Alert Status"); + case QBluetoothUuid::CharacteristicType::NewAlert: return QBluetoothServiceDiscoveryAgent::tr("New Alert"); + case QBluetoothUuid::CharacteristicType::SupportedNewAlertCategory: + return QBluetoothServiceDiscoveryAgent::tr("Supported New Alert Category"); + case QBluetoothUuid::CharacteristicType::SupportedUnreadAlertCategory: + return QBluetoothServiceDiscoveryAgent::tr("Supported Unread Alert Category"); + case QBluetoothUuid::CharacteristicType::BloodPressureFeature: return QBluetoothServiceDiscoveryAgent::tr("Blood Pressure Feature"); + //: HID: Human Interface Device Profile (Bluetooth) + case QBluetoothUuid::CharacteristicType::HIDInformation: return QBluetoothServiceDiscoveryAgent::tr("HID Information"); + case QBluetoothUuid::CharacteristicType::ReportMap: return QBluetoothServiceDiscoveryAgent::tr("Report Map"); + //: HID: Human Interface Device Profile (Bluetooth) + case QBluetoothUuid::CharacteristicType::HIDControlPoint: return QBluetoothServiceDiscoveryAgent::tr("HID Control Point"); + case QBluetoothUuid::CharacteristicType::Report: return QBluetoothServiceDiscoveryAgent::tr("Report"); + case QBluetoothUuid::CharacteristicType::ProtocolMode: return QBluetoothServiceDiscoveryAgent::tr("Protocol Mode"); + case QBluetoothUuid::CharacteristicType::ScanIntervalWindow: return QBluetoothServiceDiscoveryAgent::tr("Scan Interval Window"); + case QBluetoothUuid::CharacteristicType::PnPID: return QBluetoothServiceDiscoveryAgent::tr("PnP ID"); + case QBluetoothUuid::CharacteristicType::GlucoseFeature: return QBluetoothServiceDiscoveryAgent::tr("Glucose Feature"); + case QBluetoothUuid::CharacteristicType::RecordAccessControlPoint: + //: Glucose Sensor patient record database. + return QBluetoothServiceDiscoveryAgent::tr("Record Access Control Point"); + //: RSC: Running Speed and Cadence + case QBluetoothUuid::CharacteristicType::RSCMeasurement: return QBluetoothServiceDiscoveryAgent::tr("RSC Measurement"); + //: RSC: Running Speed and Cadence + case QBluetoothUuid::CharacteristicType::RSCFeature: return QBluetoothServiceDiscoveryAgent::tr("RSC Feature"); + case QBluetoothUuid::CharacteristicType::SCControlPoint: return QBluetoothServiceDiscoveryAgent::tr("SC Control Point"); + //: CSC: Cycling Speed and Cadence + case QBluetoothUuid::CharacteristicType::CSCMeasurement: return QBluetoothServiceDiscoveryAgent::tr("CSC Measurement"); + //: CSC: Cycling Speed and Cadence + case QBluetoothUuid::CharacteristicType::CSCFeature: return QBluetoothServiceDiscoveryAgent::tr("CSC Feature"); + case QBluetoothUuid::CharacteristicType::SensorLocation: return QBluetoothServiceDiscoveryAgent::tr("Sensor Location"); + case QBluetoothUuid::CharacteristicType::CyclingPowerMeasurement: + return QBluetoothServiceDiscoveryAgent::tr("Cycling Power Measurement"); + case QBluetoothUuid::CharacteristicType::CyclingPowerVector: return QBluetoothServiceDiscoveryAgent::tr("Cycling Power Vector"); + case QBluetoothUuid::CharacteristicType::CyclingPowerFeature: return QBluetoothServiceDiscoveryAgent::tr("Cycling Power Feature"); + case QBluetoothUuid::CharacteristicType::CyclingPowerControlPoint: + return QBluetoothServiceDiscoveryAgent::tr("Cycling Power Control Point"); + case QBluetoothUuid::CharacteristicType::LocationAndSpeed: return QBluetoothServiceDiscoveryAgent::tr("Location And Speed"); + case QBluetoothUuid::CharacteristicType::Navigation: return QBluetoothServiceDiscoveryAgent::tr("Navigation"); + case QBluetoothUuid::CharacteristicType::PositionQuality: return QBluetoothServiceDiscoveryAgent::tr("Position Quality"); + case QBluetoothUuid::CharacteristicType::LNFeature: return QBluetoothServiceDiscoveryAgent::tr("LN Feature"); + case QBluetoothUuid::CharacteristicType::LNControlPoint: return QBluetoothServiceDiscoveryAgent::tr("LN Control Point"); + case QBluetoothUuid::CharacteristicType::MagneticDeclination: + //: Angle between geographic and magnetic north + return QBluetoothServiceDiscoveryAgent::tr("Magnetic Declination"); + //: Above/below sea level + case QBluetoothUuid::CharacteristicType::Elevation: return QBluetoothServiceDiscoveryAgent::tr("Elevation"); + case QBluetoothUuid::CharacteristicType::Pressure: return QBluetoothServiceDiscoveryAgent::tr("Pressure"); + case QBluetoothUuid::CharacteristicType::Temperature: return QBluetoothServiceDiscoveryAgent::tr("Temperature"); + case QBluetoothUuid::CharacteristicType::Humidity: return QBluetoothServiceDiscoveryAgent::tr("Humidity"); + //: Wind speed while standing + case QBluetoothUuid::CharacteristicType::TrueWindSpeed: return QBluetoothServiceDiscoveryAgent::tr("True Wind Speed"); + case QBluetoothUuid::CharacteristicType::TrueWindDirection : return QBluetoothServiceDiscoveryAgent::tr("True Wind Direction"); + case QBluetoothUuid::CharacteristicType::ApparentWindSpeed: + //: Wind speed while observer is moving + return QBluetoothServiceDiscoveryAgent::tr("Apparent Wind Speed"); + case QBluetoothUuid::CharacteristicType::ApparentWindDirection: return QBluetoothServiceDiscoveryAgent::tr("Apparent Wind Direction"); + case QBluetoothUuid::CharacteristicType::GustFactor: + //: Factor by which wind gust is stronger than average wind + return QBluetoothServiceDiscoveryAgent::tr("Gust Factor"); + case QBluetoothUuid::CharacteristicType::PollenConcentration: return QBluetoothServiceDiscoveryAgent::tr("Pollen Concentration"); + case QBluetoothUuid::CharacteristicType::UVIndex: return QBluetoothServiceDiscoveryAgent::tr("UV Index"); + case QBluetoothUuid::CharacteristicType::Irradiance: return QBluetoothServiceDiscoveryAgent::tr("Irradiance"); + case QBluetoothUuid::CharacteristicType::Rainfall: return QBluetoothServiceDiscoveryAgent::tr("Rainfall"); + case QBluetoothUuid::CharacteristicType::WindChill: return QBluetoothServiceDiscoveryAgent::tr("Wind Chill"); + case QBluetoothUuid::CharacteristicType::HeatIndex: return QBluetoothServiceDiscoveryAgent::tr("Heat Index"); + case QBluetoothUuid::CharacteristicType::DewPoint: return QBluetoothServiceDiscoveryAgent::tr("Dew Point"); + case QBluetoothUuid::CharacteristicType::DescriptorValueChanged: + //: Environmental sensing related + return QBluetoothServiceDiscoveryAgent::tr("Descriptor Value Changed"); + case QBluetoothUuid::CharacteristicType::AerobicHeartRateLowerLimit: + return QBluetoothServiceDiscoveryAgent::tr("Aerobic Heart Rate Lower Limit"); + case QBluetoothUuid::CharacteristicType::AerobicHeartRateUpperLimit: + return QBluetoothServiceDiscoveryAgent::tr("Aerobic Heart Rate Upper Limit"); + case QBluetoothUuid::CharacteristicType::AerobicThreshold: return QBluetoothServiceDiscoveryAgent::tr("Aerobic Threshold"); + //: Age of person + case QBluetoothUuid::CharacteristicType::Age: return QBluetoothServiceDiscoveryAgent::tr("Age"); + case QBluetoothUuid::CharacteristicType::AnaerobicHeartRateLowerLimit: + return QBluetoothServiceDiscoveryAgent::tr("Anaerobic Heart Rate Lower Limit"); + case QBluetoothUuid::CharacteristicType::AnaerobicHeartRateUpperLimit: + return QBluetoothServiceDiscoveryAgent::tr("Anaerobic Heart Rate Upper Limit"); + case QBluetoothUuid::CharacteristicType::AnaerobicThreshold: return QBluetoothServiceDiscoveryAgent::tr("Anaerobic Threshold"); + case QBluetoothUuid::CharacteristicType::DateOfBirth: return QBluetoothServiceDiscoveryAgent::tr("Date Of Birth"); + case QBluetoothUuid::CharacteristicType::DateOfThresholdAssessment: return QBluetoothServiceDiscoveryAgent::tr("Date Of Threshold Assessment"); + case QBluetoothUuid::CharacteristicType::EmailAddress: return QBluetoothServiceDiscoveryAgent::tr("Email Address"); + case QBluetoothUuid::CharacteristicType::FatBurnHeartRateLowerLimit: + return QBluetoothServiceDiscoveryAgent::tr("Fat Burn Heart Rate Lower Limit"); + case QBluetoothUuid::CharacteristicType::FatBurnHeartRateUpperLimit: + return QBluetoothServiceDiscoveryAgent::tr("Fat Burn Heart Rate Upper Limit"); + case QBluetoothUuid::CharacteristicType::FirstName: return QBluetoothServiceDiscoveryAgent::tr("First Name"); + case QBluetoothUuid::CharacteristicType::FiveZoneHeartRateLimits: return QBluetoothServiceDiscoveryAgent::tr("5-Zone Heart Rate Limits"); + case QBluetoothUuid::CharacteristicType::Gender: return QBluetoothServiceDiscoveryAgent::tr("Gender"); + case QBluetoothUuid::CharacteristicType::HeartRateMax: return QBluetoothServiceDiscoveryAgent::tr("Heart Rate Maximum"); + //: Height of a person + case QBluetoothUuid::CharacteristicType::Height: return QBluetoothServiceDiscoveryAgent::tr("Height"); + case QBluetoothUuid::CharacteristicType::HipCircumference: return QBluetoothServiceDiscoveryAgent::tr("Hip Circumference"); + case QBluetoothUuid::CharacteristicType::LastName: return QBluetoothServiceDiscoveryAgent::tr("Last Name"); + case QBluetoothUuid::CharacteristicType::MaximumRecommendedHeartRate: + return QBluetoothServiceDiscoveryAgent::tr("Maximum Recommended Heart Rate"); + case QBluetoothUuid::CharacteristicType::RestingHeartRate: return QBluetoothServiceDiscoveryAgent::tr("Resting Heart Rate"); + case QBluetoothUuid::CharacteristicType::SportTypeForAerobicAnaerobicThresholds: + return QBluetoothServiceDiscoveryAgent::tr("Sport Type For Aerobic/Anaerobic Thresholds"); + case QBluetoothUuid::CharacteristicType::ThreeZoneHeartRateLimits: return QBluetoothServiceDiscoveryAgent::tr("3-Zone Heart Rate Limits"); + case QBluetoothUuid::CharacteristicType::TwoZoneHeartRateLimits: return QBluetoothServiceDiscoveryAgent::tr("2-Zone Heart Rate Limits"); + case QBluetoothUuid::CharacteristicType::VO2Max: return QBluetoothServiceDiscoveryAgent::tr("Oxygen Uptake"); + case QBluetoothUuid::CharacteristicType::WaistCircumference: return QBluetoothServiceDiscoveryAgent::tr("Waist Circumference"); + case QBluetoothUuid::CharacteristicType::Weight: return QBluetoothServiceDiscoveryAgent::tr("Weight"); + case QBluetoothUuid::CharacteristicType::DatabaseChangeIncrement: + //: Environmental sensing related + return QBluetoothServiceDiscoveryAgent::tr("Database Change Increment"); + case QBluetoothUuid::CharacteristicType::UserIndex: return QBluetoothServiceDiscoveryAgent::tr("User Index"); + case QBluetoothUuid::CharacteristicType::BodyCompositionFeature: return QBluetoothServiceDiscoveryAgent::tr("Body Composition Feature"); + case QBluetoothUuid::CharacteristicType::BodyCompositionMeasurement: return QBluetoothServiceDiscoveryAgent::tr("Body Composition Measurement"); + case QBluetoothUuid::CharacteristicType::WeightMeasurement: return QBluetoothServiceDiscoveryAgent::tr("Weight Measurement"); + case QBluetoothUuid::CharacteristicType::WeightScaleFeature: + return QBluetoothServiceDiscoveryAgent::tr("Weight Scale Feature"); + case QBluetoothUuid::CharacteristicType::UserControlPoint: return QBluetoothServiceDiscoveryAgent::tr("User Control Point"); + case QBluetoothUuid::CharacteristicType::MagneticFluxDensity2D: return QBluetoothServiceDiscoveryAgent::tr("Magnetic Flux Density 2D"); + case QBluetoothUuid::CharacteristicType::MagneticFluxDensity3D: return QBluetoothServiceDiscoveryAgent::tr("Magnetic Flux Density 3D"); + case QBluetoothUuid::CharacteristicType::Language: return QBluetoothServiceDiscoveryAgent::tr("Language"); + case QBluetoothUuid::CharacteristicType::BarometricPressureTrend: return QBluetoothServiceDiscoveryAgent::tr("Barometric Pressure Trend"); + } + + return QString(); +} + +/*! + Returns a human-readable and translated name for the given descriptor type + represented by \a uuid. + + \sa QBluetoothUuid::DescriptorType + + \since 5.4 +*/ +QString QBluetoothUuid::descriptorToString(QBluetoothUuid::DescriptorType uuid) +{ + switch (uuid) { + case QBluetoothUuid::DescriptorType::UnknownDescriptorType: + break; // returns {} below + case QBluetoothUuid::DescriptorType::CharacteristicExtendedProperties: + return QBluetoothServiceDiscoveryAgent::tr("Characteristic Extended Properties"); + case QBluetoothUuid::DescriptorType::CharacteristicUserDescription: + return QBluetoothServiceDiscoveryAgent::tr("Characteristic User Description"); + case QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration: + return QBluetoothServiceDiscoveryAgent::tr("Client Characteristic Configuration"); + case QBluetoothUuid::DescriptorType::ServerCharacteristicConfiguration: + return QBluetoothServiceDiscoveryAgent::tr("Server Characteristic Configuration"); + case QBluetoothUuid::DescriptorType::CharacteristicPresentationFormat: + return QBluetoothServiceDiscoveryAgent::tr("Characteristic Presentation Format"); + case QBluetoothUuid::DescriptorType::CharacteristicAggregateFormat: + return QBluetoothServiceDiscoveryAgent::tr("Characteristic Aggregate Format"); + case QBluetoothUuid::DescriptorType::ValidRange: + return QBluetoothServiceDiscoveryAgent::tr("Valid Range"); + case QBluetoothUuid::DescriptorType::ExternalReportReference: + return QBluetoothServiceDiscoveryAgent::tr("External Report Reference"); + case QBluetoothUuid::DescriptorType::ReportReference: + return QBluetoothServiceDiscoveryAgent::tr("Report Reference"); + case QBluetoothUuid::DescriptorType::EnvironmentalSensingConfiguration: + return QBluetoothServiceDiscoveryAgent::tr("Environmental Sensing Configuration"); + case QBluetoothUuid::DescriptorType::EnvironmentalSensingMeasurement: + return QBluetoothServiceDiscoveryAgent::tr("Environmental Sensing Measurement"); + case QBluetoothUuid::DescriptorType::EnvironmentalSensingTriggerSetting: + return QBluetoothServiceDiscoveryAgent::tr("Environmental Sensing Trigger Setting"); + } + + return QString(); +} + +/*! + \fn bool QBluetoothUuid::operator==(const QBluetoothUuid &a, const QBluetoothUuid &b) + \brief Returns \c true if \a a is equal to \a b, otherwise \c false. +*/ + +/*! + \fn bool QBluetoothUuid::operator!=(const QBluetoothUuid &a, const QBluetoothUuid &b) + \brief Returns \c true if \a a is not equal to \a b, otherwise \c false. +*/ + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug debug, const QBluetoothUuid &uuid) +{ + debug << uuid.toString(); + return debug; +} +#endif +QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothuuid.h b/src/bluetooth/qbluetoothuuid.h new file mode 100644 index 0000000..c19928c --- /dev/null +++ b/src/bluetooth/qbluetoothuuid.h @@ -0,0 +1,430 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QBLUETOOTHUUID_H +#define QBLUETOOTHUUID_H + +#include + +#include +#include +#include + +#include + +#if defined(Q_OS_DARWIN) || defined(Q_QDOC) +Q_FORWARD_DECLARE_OBJC_CLASS(CBUUID); +#endif + +QT_BEGIN_NAMESPACE + +#if !defined(QT_SUPPORTS_INT128) +struct quint128 +{ + quint8 data[16]; +}; +#endif + +class Q_BLUETOOTH_EXPORT QBluetoothUuid : public QUuid +{ +public: + enum class ProtocolUuid { + Sdp = 0x0001, + Udp = 0x0002, + Rfcomm = 0x0003, + Tcp = 0x0004, + TcsBin = 0x0005, + TcsAt = 0x0006, + Att = 0x0007, + Obex = 0x0008, + Ip = 0x0009, + Ftp = 0x000A, + Http = 0x000C, + Wsp = 0x000E, + Bnep = 0x000F, + Upnp = 0x0010, + Hidp = 0x0011, + HardcopyControlChannel = 0x0012, + HardcopyDataChannel = 0x0014, + HardcopyNotification = 0x0016, + Avctp = 0x0017, + Avdtp = 0x0019, + Cmtp = 0x001B, + UdiCPlain = 0x001D, + McapControlChannel = 0x001E, + McapDataChannel = 0x001F, + L2cap = 0x0100 + }; + + enum class ServiceClassUuid { + ServiceDiscoveryServer = 0x1000, + BrowseGroupDescriptor = 0x1001, + PublicBrowseGroup = 0x1002, + SerialPort = 0x1101, + LANAccessUsingPPP = 0x1102, + DialupNetworking = 0x1103, + IrMCSync = 0x1104, + ObexObjectPush = 0x1105, + OBEXFileTransfer = 0x1106, + IrMCSyncCommand = 0x1107, + Headset = 0x1108, + AudioSource = 0x110a, + AudioSink = 0x110b, + AV_RemoteControlTarget = 0x110c, + AdvancedAudioDistribution = 0x110d, + AV_RemoteControl = 0x110e, + AV_RemoteControlController = 0x110f, + HeadsetAG = 0x1112, + PANU = 0x1115, + NAP = 0x1116, + GN = 0x1117, + DirectPrinting = 0x1118, + ReferencePrinting = 0x1119, + BasicImage = 0x111a, + ImagingResponder = 0x111b, + ImagingAutomaticArchive = 0x111c, + ImagingReferenceObjects = 0x111d, + Handsfree = 0x111e, + HandsfreeAudioGateway = 0x111f, + DirectPrintingReferenceObjectsService = 0x1120, + ReflectedUI = 0x1121, + BasicPrinting = 0x1122, + PrintingStatus = 0x1123, + HumanInterfaceDeviceService = 0x1124, + HardcopyCableReplacement = 0x1125, + HCRPrint = 0x1126, + HCRScan = 0x1127, + SIMAccess = 0x112d, + PhonebookAccessPCE = 0x112e, + PhonebookAccessPSE = 0x112f, + PhonebookAccess = 0x1130, + HeadsetHS = 0x1131, + MessageAccessServer = 0x1132, + MessageNotificationServer = 0x1133, + MessageAccessProfile = 0x1134, + GNSS = 0x1135, + GNSSServer = 0x1136, + Display3D = 0x1137, + Glasses3D = 0x1138, + Synchronization3D = 0x1139, + MPSProfile = 0x113a, + MPSService = 0x113b, + PnPInformation = 0x1200, + GenericNetworking = 0x1201, + GenericFileTransfer = 0x1202, + GenericAudio = 0x1203, + GenericTelephony = 0x1204, + VideoSource = 0x1303, + VideoSink = 0x1304, + VideoDistribution = 0x1305, + HDP = 0x1400, + HDPSource = 0x1401, + HDPSink = 0x1402, + GenericAccess = 0x1800, + GenericAttribute = 0x1801, + ImmediateAlert = 0x1802, + LinkLoss = 0x1803, + TxPower = 0x1804, + CurrentTimeService = 0x1805, + ReferenceTimeUpdateService = 0x1806, + NextDSTChangeService = 0x1807, + Glucose = 0x1808, + HealthThermometer = 0x1809, + DeviceInformation = 0x180a, + HeartRate = 0x180d, + PhoneAlertStatusService = 0x180e, + BatteryService = 0x180f, + BloodPressure = 0x1810, + AlertNotificationService = 0x1811, + HumanInterfaceDevice = 0x1812, + ScanParameters = 0x1813, + RunningSpeedAndCadence = 0x1814, + CyclingSpeedAndCadence = 0x1816, + CyclingPower = 0x1818, + LocationAndNavigation = 0x1819, + EnvironmentalSensing = 0x181a, + BodyComposition = 0x181b, + UserData = 0x181c, + WeightScale = 0x181d, + BondManagement = 0x181e, + ContinuousGlucoseMonitoring = 0x181f + }; + + enum class CharacteristicType { + DeviceName = 0x2a00, + Appearance = 0x2a01, + PeripheralPrivacyFlag = 0x2a02, + ReconnectionAddress = 0x2a03, + PeripheralPreferredConnectionParameters = 0x2a04, + ServiceChanged = 0x2a05, + AlertLevel = 0x2a06, + TxPowerLevel = 0x2a07, + DateTime = 0x2a08, + DayOfWeek = 0x2a09, + DayDateTime = 0x2a0a, + /* 0x2a0b not defined */ + ExactTime256 = 0x2a0c, + DSTOffset = 0x2a0d, + TimeZone = 0x2a0e, + LocalTimeInformation = 0x2a0f, + /* 0x2a10 not defined */ + TimeWithDST = 0x2a11, + TimeAccuracy = 0x2a12, + TimeSource = 0x2a13, + ReferenceTimeInformation = 0x2a14, + /* 0x2a15 not defined */ + TimeUpdateControlPoint = 0x2a16, + TimeUpdateState = 0x2a17, + GlucoseMeasurement = 0x2a18, + BatteryLevel = 0x2a19, + /* 0x2a1a not defined */ + /* 0x2a1b not defined */ + TemperatureMeasurement = 0x2a1c, + TemperatureType = 0x2a1d, + IntermediateTemperature = 0x2a1e, + /* 0x2a1f not defined */ + /* 0x2a20 not defined */ + MeasurementInterval = 0x2a21, + BootKeyboardInputReport = 0x2a22, + SystemID = 0x2a23, + ModelNumberString = 0x2a24, + SerialNumberString = 0x2a25, + FirmwareRevisionString = 0x2a26, + HardwareRevisionString = 0x2a27, + SoftwareRevisionString = 0x2a28, + ManufacturerNameString = 0x2a29, + IEEE1107320601RegulatoryCertificationDataList = 0x2a2a, + CurrentTime = 0x2a2b, + MagneticDeclination = 0x2a2c, + /* 0x2a2d not defined */ + /* 0x2a2e not defined */ + /* 0x2a2f not defined */ + /* 0x2a30 not defined */ + ScanRefresh = 0x2a31, + BootKeyboardOutputReport = 0x2a32, + BootMouseInputReport = 0x2a33, + GlucoseMeasurementContext = 0x2a34, + BloodPressureMeasurement = 0x2a35, + IntermediateCuffPressure = 0x2a36, + HeartRateMeasurement = 0x2a37, + BodySensorLocation = 0x2a38, + HeartRateControlPoint = 0x2a39, + /* 0x2a3a not defined */ + /* 0x2a3b not defined */ + /* 0x2a3c not defined */ + /* 0x2a3d not defined */ + /* 0x2a3e not defined */ + AlertStatus = 0x2a3f, + RingerControlPoint = 0x2a40, + RingerSetting = 0x2a41, + AlertCategoryIDBitMask = 0x2a42, + AlertCategoryID = 0x2a43, + AlertNotificationControlPoint = 0x2a44, + UnreadAlertStatus = 0x2a45, + NewAlert = 0x2a46, + SupportedNewAlertCategory = 0x2a47, + SupportedUnreadAlertCategory = 0x2a48, + BloodPressureFeature = 0x2a49, + HIDInformation = 0x2a4a, + ReportMap = 0x2a4b, + HIDControlPoint = 0x2a4c, + Report = 0x2a4d, + ProtocolMode = 0x2a4e, + ScanIntervalWindow = 0x2a4f, + PnPID = 0x2a50, + GlucoseFeature = 0x2a51, + RecordAccessControlPoint = 0x2a52, + RSCMeasurement = 0x2a53, + RSCFeature = 0x2a54, + SCControlPoint = 0x2a55, + /* 0x2a56 not defined */ + /* 0x2a57 not defined */ + /* 0x2a58 not defined */ + /* 0x2a59 not defined */ + /* 0x2a5a not defined */ + CSCMeasurement = 0x2a5b, + CSCFeature = 0x2a5c, + SensorLocation = 0x2a5d, + /* 0x2a5e not defined */ + /* 0x2a5f not defined */ + /* 0x2a60 not defined */ + /* 0x2a61 not defined */ + /* 0x2a62 not defined */ + CyclingPowerMeasurement = 0x2a63, + CyclingPowerVector = 0x2a64, + CyclingPowerFeature = 0x2a65, + CyclingPowerControlPoint = 0x2a66, + LocationAndSpeed = 0x2a67, + Navigation = 0x2a68, + PositionQuality = 0x2a69, + LNFeature = 0x2a6a, + LNControlPoint = 0x2a6b, + Elevation = 0x2a6c, + Pressure = 0x2a6d, + Temperature = 0x2a6e, + Humidity = 0x2a6f, + TrueWindSpeed = 0x2a70, + TrueWindDirection = 0x2a71, + ApparentWindSpeed = 0x2a72, + ApparentWindDirection = 0x2a73, + GustFactor = 0x2a74, + PollenConcentration = 0x2a75, + UVIndex = 0x2a76, + Irradiance = 0x2a77, + Rainfall = 0x2a78, + WindChill = 0x2a79, + HeatIndex = 0x2a7a, + DewPoint = 0x2a7b, + /* 0x2a7c not defined */ + DescriptorValueChanged = 0x2a7d, + AerobicHeartRateLowerLimit = 0x2a7e, + AerobicThreshold = 0x2a7f, + Age = 0x2a80, + AnaerobicHeartRateLowerLimit = 0x2a81, + AnaerobicHeartRateUpperLimit = 0x2a82, + AnaerobicThreshold = 0x2a83, + AerobicHeartRateUpperLimit = 0x2a84, + DateOfBirth = 0x2a85, + DateOfThresholdAssessment = 0x2a86, + EmailAddress = 0x2a87, + FatBurnHeartRateLowerLimit = 0x2a88, + FatBurnHeartRateUpperLimit = 0x2a89, + FirstName = 0x2a8a, + FiveZoneHeartRateLimits = 0x2a8b, + Gender = 0x2a8c, + HeartRateMax = 0x2a8d, + Height = 0x2a8e, + HipCircumference = 0x2a8f, + LastName = 0x2a90, + MaximumRecommendedHeartRate = 0x2a91, + RestingHeartRate = 0x2a92, + SportTypeForAerobicAnaerobicThresholds = 0x2a93, + ThreeZoneHeartRateLimits = 0x2a94, + TwoZoneHeartRateLimits = 0x2a95, + VO2Max = 0x2a96, + WaistCircumference = 0x2a97, + Weight = 0x2a98, + DatabaseChangeIncrement = 0x2a99, + UserIndex = 0x2a9a, + BodyCompositionFeature = 0x2a9b, + BodyCompositionMeasurement = 0x2a9c, + WeightMeasurement = 0x2a9d, + WeightScaleFeature = 0x2a9e, + UserControlPoint = 0x2a9f, + MagneticFluxDensity2D = 0x2aa0, + MagneticFluxDensity3D = 0x2aa1, + Language = 0x2aa2, + BarometricPressureTrend = 0x2aa3 + }; + + enum class DescriptorType { + UnknownDescriptorType = 0x0, + CharacteristicExtendedProperties = 0x2900, + CharacteristicUserDescription = 0x2901, + ClientCharacteristicConfiguration = 0x2902, + ServerCharacteristicConfiguration = 0x2903, + CharacteristicPresentationFormat = 0x2904, + CharacteristicAggregateFormat = 0x2905, + ValidRange = 0x2906, + ExternalReportReference = 0x2907, + ReportReference = 0x2908, + /* 0x2909 not defined */ + /* 0x290a not defined */ + EnvironmentalSensingConfiguration = 0x290b, + EnvironmentalSensingMeasurement = 0x290c, + EnvironmentalSensingTriggerSetting = 0x290d + }; + + constexpr QBluetoothUuid() noexcept {}; + + // values below are based on Bluetooth BASE_UUID + constexpr QBluetoothUuid(ProtocolUuid uuid) noexcept + : QBluetoothUuid(static_cast(uuid)) {}; + constexpr QBluetoothUuid(ServiceClassUuid uuid) noexcept + : QBluetoothUuid(static_cast(uuid)) {}; + constexpr QBluetoothUuid(CharacteristicType uuid) noexcept + : QBluetoothUuid(static_cast(uuid)) {}; + constexpr QBluetoothUuid(DescriptorType uuid) noexcept + : QBluetoothUuid(static_cast(uuid)) {}; + explicit constexpr QBluetoothUuid(quint16 uuid) noexcept + : QBluetoothUuid(quint32{uuid}) {}; + explicit constexpr QBluetoothUuid(quint32 uuid) noexcept + : QUuid(uuid, 0x0, 0x1000, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb) {}; + // end of bluetooth-specific constructors; rest is essentially `using QUuid::QUuid;` + + using QUuid::QUuid; +#if QT_BLUETOOTH_REMOVED_SINCE(6, 6) + explicit QBluetoothUuid(quint128 uuid); +#endif + QT6_ONLY(QT_POST_CXX17_API_IN_EXPORTED_CLASS) // quint128 changes based on QT_SUPPORTS_INT128! + explicit QBluetoothUuid(quint128 uuid, QSysInfo::Endian order = QSysInfo::BigEndian) noexcept + : QUuid{fromBytes(&uuid, order)} {} +#if QT_BLUETOOTH_REMOVED_SINCE(6, 6) // actually 6.3 (cf. QUuid) + explicit QBluetoothUuid(const QString &uuid); +#endif + QBluetoothUuid(const QBluetoothUuid &uuid) = default; + QT_BLUETOOTH_INLINE_SINCE(6, 6) + QBluetoothUuid(QUuid QT6_ONLY(const &)uuid); + ~QBluetoothUuid() = default; + + QBluetoothUuid &operator=(const QBluetoothUuid &other) = default; + friend bool operator==(const QBluetoothUuid &a, const QBluetoothUuid &b) + { + return static_cast(a) == static_cast(b); + } + friend bool operator!=(const QBluetoothUuid &a, const QBluetoothUuid &b) { return !(a == b); } +#ifndef QT_NO_DEBUG_STREAM + friend Q_BLUETOOTH_EXPORT QDebug operator<<(QDebug debug, const QBluetoothUuid &uuid); +#if QT_BLUETOOTH_REMOVED_SINCE(6, 6) + static QDebug streamingOperator(QDebug debug, const QBluetoothUuid &uuid); +#endif +#endif + + int minimumSize() const; + + quint16 toUInt16(bool *ok = nullptr) const; + quint32 toUInt32(bool *ok = nullptr) const; + +#if QT_BLUETOOTH_REMOVED_SINCE(6, 6) + quint128 toUInt128() const; +#endif +#if defined(Q_QDOC) || !defined(QT_SUPPORTS_INT128) // otherwise falls back to QUuid::toUint128() + quint128 toUInt128(QSysInfo::Endian order = QSysInfo::BigEndian) const noexcept; +#endif + +#if defined(Q_OS_DARWIN) || defined(Q_QDOC) + static QBluetoothUuid fromCBUUID(CBUUID *cbUuid); + CBUUID *toCBUUID() const Q_DECL_NS_RETURNS_AUTORELEASED; +#endif + + static QString serviceClassToString(ServiceClassUuid uuid); + static QString protocolToString(ProtocolUuid uuid); + static QString characteristicToString(CharacteristicType uuid); + static QString descriptorToString(DescriptorType uuid); +}; + +#if QT_BLUETOOTH_INLINE_IMPL_SINCE(6, 6) +QBluetoothUuid::QBluetoothUuid(QUuid QT6_ONLY(const &)uuid) + : QUuid(uuid) +{ +} +#endif + + +#ifndef QT_NO_DATASTREAM +inline QDataStream &operator<<(QDataStream &s, const QBluetoothUuid &uuid) +{ + return s << static_cast(uuid); +} + +inline QDataStream &operator>>(QDataStream &s, QBluetoothUuid &uuid) +{ + return s >> static_cast(uuid); +} +#endif + +QT_END_NAMESPACE + +QT_DECL_METATYPE_EXTERN(QBluetoothUuid, Q_BLUETOOTH_EXPORT) + +#endif diff --git a/src/bluetooth/qbluetoothuuid_darwin.mm b/src/bluetooth/qbluetoothuuid_darwin.mm new file mode 100644 index 0000000..056a266 --- /dev/null +++ b/src/bluetooth/qbluetoothuuid_darwin.mm @@ -0,0 +1,46 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "darwin/btutility_p.h" + +#include "qbluetoothuuid.h" + +QT_BEGIN_NAMESPACE + +/*! + \brief Constructs a new QBluetoothUuid, containing a copy of the \a cbUuid CBUUID. + + \note this function is only available on Apple platforms. + + \since 6.6 + \ingroup platform-type-conversions +*/ +QBluetoothUuid QBluetoothUuid::fromCBUUID(CBUUID *cbUuid) +{ + if (!cbUuid) + return {}; + + return DarwinBluetooth::qt_uuid(cbUuid); +} + +/*! + \brief Creates a CBUUID from a QBluetoothUuid. + + The resulting CBUUID is autoreleased. + + \note this function is only available on Apple platforms. + + \since 6.6 + \ingroup platform-type-conversions +*/ + +CBUUID *QBluetoothUuid::toCBUUID() const +{ + const auto cbUuidGuard = DarwinBluetooth::cb_uuid(*this); + // cb_uuid returns a strong reference (RAII object). Let + // it do its job and release, but we return auto-released + // CBUUID, as documented. + return [[cbUuidGuard.data() retain] autorelease]; +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/qleadvertiser_bluez.cpp b/src/bluetooth/qleadvertiser_bluez.cpp new file mode 100644 index 0000000..422bb14 --- /dev/null +++ b/src/bluetooth/qleadvertiser_bluez.cpp @@ -0,0 +1,437 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qleadvertiser_bluez_p.h" + +#include "bluez/bluez_data_p.h" +#include "bluez/hcimanager_p.h" +#include "qbluetoothsocketbase_p.h" + +#include + +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ) + +QLeAdvertiser::~QLeAdvertiser() + = default; + +struct AdvParams { + quint16 minInterval; + quint16 maxInterval; + quint8 type; + quint8 ownAddrType; + quint8 directAddrType; + bdaddr_t directAddr; + quint8 channelMap; + quint8 filterPolicy; +} __attribute__ ((packed)); + +struct AdvData { + quint8 length; + quint8 data[31]; +}; + +struct WhiteListParams { + quint8 addrType; + bdaddr_t addr; +}; + + +template +static QByteArray byteArrayFromStruct(const T &data) +{ + return QByteArray(reinterpret_cast(&data), sizeof data); +} + +QLeAdvertiserBluez::QLeAdvertiserBluez(const QLowEnergyAdvertisingParameters ¶ms, + const QLowEnergyAdvertisingData &advertisingData, + const QLowEnergyAdvertisingData &scanResponseData, + std::shared_ptr hciManager, QObject *parent) + : QLeAdvertiser(params, advertisingData, scanResponseData, parent), m_hciManager(hciManager) +{ + Q_ASSERT(m_hciManager); + connect(m_hciManager.get(), &HciManager::commandCompleted, this, + &QLeAdvertiserBluez::handleCommandCompleted); +} + +QLeAdvertiserBluez::~QLeAdvertiserBluez() +{ + disconnect(m_hciManager.get(), &HciManager::commandCompleted, this, + &QLeAdvertiserBluez::handleCommandCompleted); + doStopAdvertising(); +} + +void QLeAdvertiserBluez::doStartAdvertising() +{ + if (!m_hciManager->monitorEvent(HciManager::HciEvent::EVT_CMD_COMPLETE)) { + handleError(); + return; + } + + m_sendPowerLevel = advertisingData().includePowerLevel() + || scanResponseData().includePowerLevel(); + if (m_sendPowerLevel) + queueReadTxPowerLevelCommand(); + else + queueAdvertisingCommands(); + sendNextCommand(); +} + +void QLeAdvertiserBluez::doStopAdvertising() +{ + toggleAdvertising(false); + sendNextCommand(); +} + +void QLeAdvertiserBluez::queueCommand(QBluezConst::OpCodeCommandField ocf, const QByteArray &data) +{ + m_pendingCommands << Command(ocf, data); +} + +void QLeAdvertiserBluez::sendNextCommand() +{ + if (m_pendingCommands.isEmpty()) { + // TODO: Unmonitor event. + return; + } + const Command &c = m_pendingCommands.first(); + if (!m_hciManager->sendCommand(QBluezConst::OgfLinkControl, c.ocf, c.data)) { + handleError(); + return; + } +} + +void QLeAdvertiserBluez::queueAdvertisingCommands() +{ + toggleAdvertising(false); // Stop advertising first, in case it's currently active. + setWhiteList(); + setAdvertisingParams(); + setAdvertisingData(); + setScanResponseData(); + toggleAdvertising(true); +} + +void QLeAdvertiserBluez::queueReadTxPowerLevelCommand() +{ + // Spec v4.2, Vol 2, Part E, 7.8.6 + queueCommand(QBluezConst::OcfLeReadTxPowerLevel, QByteArray()); +} + +void QLeAdvertiserBluez::toggleAdvertising(bool enable) +{ + // Spec v4.2, Vol 2, Part E, 7.8.9 + queueCommand(QBluezConst::OcfLeSetAdvEnable, QByteArray(1, enable)); +} + +void QLeAdvertiserBluez::setAdvertisingParams() +{ + // Spec v4.2, Vol 2, Part E, 7.8.5 + // or Spec v5.3, Vol 4, Part E, 7.8.5 + AdvParams params; + static_assert(sizeof params == 15, "unexpected struct size"); + using namespace std; + memset(¶ms, 0, sizeof params); + setAdvertisingInterval(params); + params.type = parameters().mode(); + params.filterPolicy = parameters().filterPolicy(); + if (params.filterPolicy != QLowEnergyAdvertisingParameters::IgnoreWhiteList + && advertisingData().discoverability() == QLowEnergyAdvertisingData::DiscoverabilityLimited) { + qCWarning(QT_BT_BLUEZ) << "limited discoverability is incompatible with " + "using a white list; disabling filtering"; + params.filterPolicy = QLowEnergyAdvertisingParameters::IgnoreWhiteList; + } + params.ownAddrType = QLowEnergyController::PublicAddress; // TODO: Make configurable. + + // TODO: For ADV_DIRECT_IND. + // params.directAddrType = xxx; + // params.direct_bdaddr = xxx; + + params.channelMap = 0x7; // All channels. + + const QByteArray paramsData = byteArrayFromStruct(params); + qCDebug(QT_BT_BLUEZ) << "advertising parameters:" << paramsData.toHex(); + queueCommand(QBluezConst::OcfLeSetAdvParams, paramsData); +} + +static quint16 forceIntoRange(quint16 val, quint16 min, quint16 max) +{ + return qMin(qMax(val, min), max); +} + +void QLeAdvertiserBluez::setAdvertisingInterval(AdvParams ¶ms) +{ + const double multiplier = 0.625; + const quint16 minVal = parameters().minimumInterval() / multiplier; + const quint16 maxVal = parameters().maximumInterval() / multiplier; + Q_ASSERT(minVal <= maxVal); + const quint16 specMinimum = + parameters().mode() == QLowEnergyAdvertisingParameters::AdvScanInd + || parameters().mode() == QLowEnergyAdvertisingParameters::AdvNonConnInd ? 0xa0 : 0x20; + const quint16 specMaximum = 0x4000; + params.minInterval = qToLittleEndian(forceIntoRange(minVal, specMinimum, specMaximum)); + params.maxInterval = qToLittleEndian(forceIntoRange(maxVal, specMinimum, specMaximum)); + Q_ASSERT(params.minInterval <= params.maxInterval); +} + +void QLeAdvertiserBluez::setPowerLevel(AdvData &advData) +{ + if (m_sendPowerLevel) { + advData.data[advData.length++] = 2; + advData.data[advData.length++]= 0xa; + advData.data[advData.length++] = m_powerLevel; + } +} + +void QLeAdvertiserBluez::setFlags(AdvData &advData) +{ + // TODO: Discoverability flags are incompatible with ADV_DIRECT_IND + quint8 flags = 0; + if (advertisingData().discoverability() == QLowEnergyAdvertisingData::DiscoverabilityLimited) + flags |= 0x1; + else if (advertisingData().discoverability() == QLowEnergyAdvertisingData::DiscoverabilityGeneral) + flags |= 0x2; + flags |= 0x4; // "BR/EDR not supported". Otherwise clients might try to connect over Bluetooth classic. + if (flags) { + advData.data[advData.length++] = 2; + advData.data[advData.length++] = 0x1; + advData.data[advData.length++] = flags; + } +} + +template static quint8 servicesType(bool dataComplete); +template<> quint8 servicesType(bool dataComplete) +{ + return dataComplete ? 0x3 : 0x2; +} +template<> quint8 servicesType(bool dataComplete) +{ + return dataComplete ? 0x5 : 0x4; +} +template<> quint8 servicesType(bool dataComplete) +{ + return dataComplete ? 0x7 : 0x6; +} + +template +static void addServicesData(AdvData &data, const QList &services) +{ + if (services.isEmpty()) + return; + constexpr auto sizeofT = static_cast(sizeof(T)); // signed is more convenient + const qsizetype spaceAvailable = sizeof data.data - data.length; + // Determine how many services will be set, space may limit the number + const qsizetype maxServices = (std::min)((spaceAvailable - 2) / sizeofT, services.size()); + if (maxServices <= 0) { + qCWarning(QT_BT_BLUEZ) << "services data does not fit into advertising data packet"; + return; + } + const bool dataComplete = maxServices == services.size(); + if (!dataComplete) { + qCWarning(QT_BT_BLUEZ) << "only" << maxServices << "out of" << services.size() + << "services fit into the advertising data"; + } + data.data[data.length++] = 1 + maxServices * sizeofT; + data.data[data.length++] = servicesType(dataComplete); + for (qsizetype i = 0; i < maxServices; ++i) { + memcpy(data.data + data.length, &services.at(i), sizeofT); + data.length += sizeofT; + } +} + +void QLeAdvertiserBluez::setServicesData(const QLowEnergyAdvertisingData &src, AdvData &dest) +{ + QList services16; + QList services32; + QList services128; + const QList services = src.services(); + for (const QBluetoothUuid &service : services) { + bool ok; + const quint16 service16 = service.toUInt16(&ok); + if (ok) { + services16 << qToLittleEndian(service16); + continue; + } + const quint32 service32 = service.toUInt32(&ok); + if (ok) { + services32 << qToLittleEndian(service32); + continue; + } + + // QUuid::toBytes() is defaults to Big-Endian + services128 << service.toBytes(QSysInfo::LittleEndian); + } + addServicesData(dest, services16); + addServicesData(dest, services32); + addServicesData(dest, services128); +} + +void QLeAdvertiserBluez::setManufacturerData(const QLowEnergyAdvertisingData &src, AdvData &dest) +{ + if (src.manufacturerId() == QLowEnergyAdvertisingData::invalidManufacturerId()) + return; + + const QByteArray manufacturerData = src.manufacturerData(); + if (dest.length >= sizeof dest.data - 1 - 1 - 2 - manufacturerData.size()) { + qCWarning(QT_BT_BLUEZ) << "manufacturer data does not fit into advertising data packet"; + return; + } + + dest.data[dest.length++] = manufacturerData.size() + 1 + 2; + dest.data[dest.length++] = 0xff; + putBtData(src.manufacturerId(), dest.data + dest.length); + dest.length += sizeof(quint16); + std::memcpy(dest.data + dest.length, manufacturerData.data(), manufacturerData.size()); + dest.length += manufacturerData.size(); +} + +void QLeAdvertiserBluez::setLocalNameData(const QLowEnergyAdvertisingData &src, AdvData &dest) +{ + if (src.localName().isEmpty()) + return; + if (dest.length >= sizeof dest.data - 3) { + qCWarning(QT_BT_BLUEZ) << "local name does not fit into advertising data"; + return; + } + + const QByteArray localNameUtf8 = src.localName().toUtf8(); + const qsizetype fullSize = localNameUtf8.size() + 1 + 1; + const qsizetype size = (std::min)(fullSize, qsizetype(sizeof dest.data - dest.length)); + const bool isComplete = size == fullSize; + dest.data[dest.length++] = size - 1; + const int dataType = isComplete ? 0x9 : 0x8; + dest.data[dest.length++] = dataType; + std::memcpy(dest.data + dest.length, localNameUtf8, size - 2); + dest.length += size - 2; +} + +void QLeAdvertiserBluez::setData(bool isScanResponseData) +{ + // Spec v4.2, Vol 3, Part C, 11 and Supplement, Part 1 + AdvData theData; + static_assert(sizeof theData == 32, "unexpected struct size"); + theData.length = 0; + + const QLowEnergyAdvertisingData &sourceData = isScanResponseData + ? scanResponseData() : advertisingData(); + + if (const QByteArray rawData = sourceData.rawData(); !rawData.isEmpty()) { + theData.length = (std::min)(qsizetype(sizeof theData.data), rawData.size()); + std::memcpy(theData.data, rawData.data(), theData.length); + } else { + if (sourceData.includePowerLevel()) + setPowerLevel(theData); + if (!isScanResponseData) + setFlags(theData); + + // Insert new constant-length data here. + + setLocalNameData(sourceData, theData); + setServicesData(sourceData, theData); + setManufacturerData(sourceData, theData); + } + + std::memset(theData.data + theData.length, 0, sizeof theData.data - theData.length); + const QByteArray dataToSend = byteArrayFromStruct(theData); + + if (!isScanResponseData) { + qCDebug(QT_BT_BLUEZ) << "advertising data:" << dataToSend.toHex(); + queueCommand(QBluezConst::OcfLeSetAdvData, dataToSend); + } else if ((parameters().mode() == QLowEnergyAdvertisingParameters::AdvScanInd + || parameters().mode() == QLowEnergyAdvertisingParameters::AdvInd) + && theData.length > 0) { + qCDebug(QT_BT_BLUEZ) << "scan response data:" << dataToSend.toHex(); + queueCommand(QBluezConst::OcfLeSetScanResponseData, dataToSend); + } +} + +void QLeAdvertiserBluez::setAdvertisingData() +{ + // Spec v4.2, Vol 2, Part E, 7.8.7 + setData(false); +} + +void QLeAdvertiserBluez::setScanResponseData() +{ + // Spec v4.2, Vol 2, Part E, 7.8.8 + setData(true); +} + +void QLeAdvertiserBluez::setWhiteList() +{ + // Spec v4.2, Vol 2, Part E, 7.8.15-16 + if (parameters().filterPolicy() == QLowEnergyAdvertisingParameters::IgnoreWhiteList) + return; + queueCommand(QBluezConst::OcfLeClearWhiteList, QByteArray()); + const QList whiteListInfos + = parameters().whiteList(); + for (const auto &addressInfo : whiteListInfos) { + WhiteListParams commandParam; + static_assert(sizeof commandParam == 7, "unexpected struct size"); + commandParam.addrType = addressInfo.type; + convertAddress(addressInfo.address.toUInt64(), commandParam.addr.b); + queueCommand(QBluezConst::OcfLeAddToWhiteList, byteArrayFromStruct(commandParam)); + } +} + +void QLeAdvertiserBluez::handleCommandCompleted(quint16 opCode, quint8 status, + const QByteArray &data) +{ + if (m_pendingCommands.isEmpty()) + return; + const QBluezConst::OpCodeCommandField ocf = QBluezConst::OpCodeCommandField(ocfFromOpCode(opCode)); + const Command currentCmd = m_pendingCommands.first(); + if (currentCmd.ocf != ocf) + return; // Not one of our commands. + m_pendingCommands.takeFirst(); + if (status != 0) { + qCDebug(QT_BT_BLUEZ) << "command" << ocf + << "failed with status" << (HciManager::HciError)status + << "status code" << status; + if (ocf == QBluezConst::OcfLeSetAdvEnable && status == 0xc && currentCmd.data == QByteArray(1, '\0')) { + // we ignore OcfLeSetAdvEnable if it tries to disable an active advertisement + // it seems the platform often automatically turns off advertisements + // subsequently the explicit stopAdvertisement call fails when re-issued + qCDebug(QT_BT_BLUEZ) << "Advertising disable failed, ignoring"; + sendNextCommand(); + return; + } + if (ocf == QBluezConst::OcfLeReadTxPowerLevel) { + qCDebug(QT_BT_BLUEZ) << "reading power level failed, leaving it out of the " + "advertising data"; + m_sendPowerLevel = false; + } else { + handleError(); + return; + } + } else { + qCDebug(QT_BT_BLUEZ) << "command" << ocf << "executed successfully"; + } + + switch (ocf) { + case QBluezConst::OcfLeReadTxPowerLevel: + if (m_sendPowerLevel) { + m_powerLevel = data.at(0); + qCDebug(QT_BT_BLUEZ) << "TX power level is" << m_powerLevel; + } + queueAdvertisingCommands(); + break; + default: + break; + } + + sendNextCommand(); +} + +void QLeAdvertiserBluez::handleError() +{ + m_pendingCommands.clear(); + // TODO: Unmonitor event + emit errorOccurred(); +} + +QT_END_NAMESPACE + +#include "moc_qleadvertiser_bluez_p.cpp" diff --git a/src/bluetooth/qleadvertiser_bluez_p.h b/src/bluetooth/qleadvertiser_bluez_p.h new file mode 100644 index 0000000..5bb5d96 --- /dev/null +++ b/src/bluetooth/qleadvertiser_bluez_p.h @@ -0,0 +1,117 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QLEADVERTISER_BLUEZ_P_H +#define QLEADVERTISER_BLUEZ_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 "qlowenergyadvertisingdata.h" +#include "qlowenergyadvertisingparameters.h" + +QT_REQUIRE_CONFIG(bluez); + +#include "bluez/bluez_data_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +class QLeAdvertiser : public QObject +{ + Q_OBJECT +public: + void startAdvertising() { doStartAdvertising(); } + void stopAdvertising() { doStopAdvertising(); } + +signals: + void errorOccurred(); + +public: + QLeAdvertiser(const QLowEnergyAdvertisingParameters ¶ms, + const QLowEnergyAdvertisingData &advData, + const QLowEnergyAdvertisingData &responseData, QObject *parent) + : QObject(parent), m_params(params), m_advData(advData), m_responseData(responseData) {} + ~QLeAdvertiser() override; + +protected: + const QLowEnergyAdvertisingParameters ¶meters() const { return m_params; } + const QLowEnergyAdvertisingData &advertisingData() const { return m_advData; } + const QLowEnergyAdvertisingData &scanResponseData() const { return m_responseData; } + +private: + virtual void doStartAdvertising() = 0; + virtual void doStopAdvertising() = 0; + + const QLowEnergyAdvertisingParameters m_params; + const QLowEnergyAdvertisingData m_advData; + const QLowEnergyAdvertisingData m_responseData; +}; + +struct AdvData; +struct AdvParams; +class HciManager; + +class QLeAdvertiserBluez : public QLeAdvertiser +{ + Q_OBJECT +public: + QLeAdvertiserBluez(const QLowEnergyAdvertisingParameters ¶ms, + const QLowEnergyAdvertisingData &advertisingData, + const QLowEnergyAdvertisingData &scanResponseData, + std::shared_ptr hciManager, + QObject *parent = nullptr); + ~QLeAdvertiserBluez() override; + +private: + void doStartAdvertising() override; + void doStopAdvertising() override; + + void setPowerLevel(AdvData &advData); + void setFlags(AdvData &advData); + void setServicesData(const QLowEnergyAdvertisingData &src, AdvData &dest); + void setManufacturerData(const QLowEnergyAdvertisingData &src, AdvData &dest); + void setLocalNameData(const QLowEnergyAdvertisingData &src, AdvData &dest); + + void queueCommand(QBluezConst::OpCodeCommandField ocf, const QByteArray &advertisingData); + void sendNextCommand(); + void queueAdvertisingCommands(); + void queueReadTxPowerLevelCommand(); + void toggleAdvertising(bool enable); + void setAdvertisingParams(); + void setAdvertisingInterval(AdvParams ¶ms); + void setData(bool isScanResponseData); + void setAdvertisingData(); + void setScanResponseData(); + void setWhiteList(); + + void handleCommandCompleted(quint16 opCode, quint8 status, const QByteArray &advertisingData); + void handleError(); + + std::shared_ptr m_hciManager; + + struct Command { + Command() {} + Command(QBluezConst::OpCodeCommandField ocf, const QByteArray &data) : ocf(ocf), data(data) { } + QBluezConst::OpCodeCommandField ocf; + QByteArray data; + }; + QList m_pendingCommands; + + quint8 m_powerLevel; + bool m_sendPowerLevel; +}; + +QT_END_NAMESPACE + +#endif // Include guard. diff --git a/src/bluetooth/qleadvertiser_bluezdbus.cpp b/src/bluetooth/qleadvertiser_bluezdbus.cpp new file mode 100644 index 0000000..78e95a7 --- /dev/null +++ b/src/bluetooth/qleadvertiser_bluezdbus.cpp @@ -0,0 +1,229 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qleadvertiser_bluezdbus_p.h" +#include "bluez/leadvertisement1_p.h" +#include "bluez/leadvertisingmanager1_p.h" +#include "bluez/bluez5_helper_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ) + +using namespace Qt::StringLiterals; + +// The advertisement dbus object path is freely definable, use as prefix +static constexpr auto advObjectPathTemplate{"/qt/btle/advertisement/%1%2/%3"_L1}; +static constexpr auto bluezService{"org.bluez"_L1}; +static constexpr auto bluezErrorFailed{"org.bluez.Error.Failed"_L1}; + +// From bluez API documentation +static constexpr auto advDataTXPower{"tx-power"_L1}; +static constexpr auto advDataTypePeripheral{"peripheral"_L1}; +static constexpr auto advDataTypeBroadcast{"broadcast"_L1}; +static constexpr quint16 advDataMinIntervalMs{20}; +static constexpr quint16 advDataMaxIntervalMs{10485}; + + +QLeDBusAdvertiser::QLeDBusAdvertiser(const QLowEnergyAdvertisingParameters ¶ms, + const QLowEnergyAdvertisingData &advertisingData, + const QLowEnergyAdvertisingData &scanResponseData, + const QString &hostAdapterPath, + QObject* parent) + : QObject(parent), + m_advParams(params), + m_advData(advertisingData), + m_advObjectPath(QString(advObjectPathTemplate). + arg(sanitizeNameForDBus(QCoreApplication::applicationName())). + arg(QCoreApplication::applicationPid()). + arg(QRandomGenerator::global()->generate())), + m_advDataDBus(new OrgBluezLEAdvertisement1Adaptor(this)), + m_advManager(new OrgBluezLEAdvertisingManager1Interface(bluezService, hostAdapterPath, + QDBusConnection::systemBus(), this)) +{ + // Bluez DBus API doesn't allow distinguishing between advertisement and scan response data; + // consolidate the two if they differ. + // Union of service UUIDs: + if (scanResponseData.services() != advertisingData.services()) { + QList services = advertisingData.services(); + for (const auto &service: scanResponseData.services()) { + if (!services.contains(service)) + services.append(service); + } + m_advData.setServices(services); + } + // Scan response is given precedence with rest of the data + if (!scanResponseData.localName().isEmpty()) + m_advData.setLocalName(scanResponseData.localName()); + if (scanResponseData.manufacturerId() != QLowEnergyAdvertisingData::invalidManufacturerId()) { + m_advData.setManufacturerData(scanResponseData.manufacturerId(), + scanResponseData.manufacturerData()); + } + if (scanResponseData.includePowerLevel()) + m_advData.setIncludePowerLevel(true); + + setDataForDBus(); +} + +QLeDBusAdvertiser::~QLeDBusAdvertiser() +{ + stopAdvertising(); +} + +// This function parses the advertising data provided by the application and +// populates the dbus adaptor with it. DBus will ask the data from the adaptor when +// the advertisement is later registered (started) +void QLeDBusAdvertiser::setDataForDBus() +{ + setAdvertisingParamsForDBus(); + setAdvertisementDataForDBus(); +} + +void QLeDBusAdvertiser::setAdvertisingParamsForDBus() +{ + // Whitelist and filter policy + if (!m_advParams.whiteList().isEmpty()) + qCWarning(QT_BT_BLUEZ) << "White lists and filter policies not supported, ignoring"; + + // Legacy advertising mode mapped to GAP role (peripheral vs broadcast) + switch (m_advParams.mode()) + { + case QLowEnergyAdvertisingParameters::AdvScanInd: + case QLowEnergyAdvertisingParameters::AdvNonConnInd: + m_advDataDBus->setType(advDataTypeBroadcast); + break; + case QLowEnergyAdvertisingParameters::AdvInd: + default: + m_advDataDBus->setType(advDataTypePeripheral); + } + + // Advertisement interval (min max in milliseconds). Ensure the values fit the range bluez + // allows. The max >= min is guaranteed by QLowEnergyAdvertisingParameters::setInterval(). + // Note: Bluez reads these values but at the time of this writing it marks this feature + // as 'experimental' + m_advDataDBus->setMinInterval(qBound(advDataMinIntervalMs, + quint16(m_advParams.minimumInterval()), + advDataMaxIntervalMs)); + m_advDataDBus->setMaxInterval(qBound(advDataMinIntervalMs, + quint16(m_advParams.maximumInterval()), + advDataMaxIntervalMs)); +} + +void QLeDBusAdvertiser::setAdvertisementDataForDBus() +{ + // We don't calculate the advertisement length to guard for too long advertisements. + // There isn't adequate control and visibility on the advertisement for that. + // - We don't know the max length (legacy or extended advertising) + // - Bluez may truncate some of the fields on its own, making calculus here imprecise + // - Scan response may or may not be used to offload some of the data + + // Include the power level if requested and dbus supports it + const auto supportedIncludes = m_advManager->supportedIncludes(); + if (m_advData.includePowerLevel() && supportedIncludes.contains(advDataTXPower)) + m_advDataDBus->setIncludes({advDataTXPower}); + + // Set the application provided name (valid to be empty). + // For clarity: bluez also has "local-name" system include that could be set if no local + // name is provided. However that would require that the LocalName DBus property would + // not exist. Existing LocalName property when 'local-name' is included leads to an + // advertisement error. + m_advDataDBus->setLocalName(m_advData.localName()); + + // Service UUIDs + if (!m_advData.services().isEmpty()) { + QStringList serviceUUIDList; + for (const auto& service: m_advData.services()) + serviceUUIDList << service.toString(QUuid::StringFormat::WithoutBraces); + m_advDataDBus->setServiceUUIDs(serviceUUIDList); + } + + // Manufacturer data + if (m_advData.manufacturerId() != QLowEnergyAdvertisingData::invalidManufacturerId()) { + m_advDataDBus->setManufacturerData({ + {m_advData.manufacturerId(), QDBusVariant(m_advData.manufacturerData())}}); + } + + // Discoverability + if (m_advDataDBus->type() == advDataTypePeripheral) { + m_advDataDBus->setDiscoverable(m_advData.discoverability() + != QLowEnergyAdvertisingData::DiscoverabilityNone); + } else { + qCDebug(QT_BT_BLUEZ) << "Ignoring advertisement discoverability in broadcast mode"; + } + + // Raw data + if (!m_advData.rawData().isEmpty()) + qCWarning(QT_BT_BLUEZ) << "Raw advertisement data not supported, ignoring"; +} + +void QLeDBusAdvertiser::startAdvertising() +{ + qCDebug(QT_BT_BLUEZ) << "Start advertising" << m_advObjectPath << "on" << m_advManager->path(); + if (m_advertising) { + qCWarning(QT_BT_BLUEZ) << "Start tried while already advertising"; + return; + } + + if (!QDBusConnection::systemBus().registerObject(m_advObjectPath, m_advDataDBus, + QDBusConnection::ExportAllContents)) { + qCWarning(QT_BT_BLUEZ) << "Advertisement dbus object registration failed"; + emit errorOccurred(); + return; + } + + // Register the advertisement which starts the actual advertising. + // We use call watcher here instead of waitForFinished() because DBus will + // call back our advertisement object (to read data) in this same thread => would block + auto reply = m_advManager->RegisterAdvertisement(QDBusObjectPath(m_advObjectPath), {}); + QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this); + + QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, + [this](QDBusPendingCallWatcher* watcher){ + QDBusPendingReply<> reply = *watcher; + if (reply.isError()) { + qCWarning(QT_BT_BLUEZ) << "Advertisement registration failed" << reply.error(); + if (reply.error().name() == bluezErrorFailed) + qCDebug(QT_BT_BLUEZ) << "Advertisement could've been too large"; + QDBusConnection::systemBus().unregisterObject(m_advObjectPath); + emit errorOccurred(); + } else { + qCDebug(QT_BT_BLUEZ) << "Advertisement started successfully"; + m_advertising = true; + } + watcher->deleteLater(); + }); +} + +void QLeDBusAdvertiser::stopAdvertising() +{ + if (!m_advertising) + return; + + m_advertising = false; + auto reply = m_advManager->UnregisterAdvertisement(QDBusObjectPath(m_advObjectPath)); + reply.waitForFinished(); + if (reply.isError()) + qCWarning(QT_BT_BLUEZ) << "Error in unregistering advertisement" << reply.error(); + else + qCDebug(QT_BT_BLUEZ) << "Advertisement unregistered successfully"; + QDBusConnection::systemBus().unregisterObject(m_advObjectPath); +} + +// Called by Bluez when the advertisement has been removed (org.bluez.LEAdvertisement1.Release) +void QLeDBusAdvertiser::Release() +{ + qCDebug(QT_BT_BLUEZ) << "Advertisement" << m_advObjectPath << "released" + << (m_advertising ? "unexpectedly" : ""); + if (m_advertising) { + // If we are advertising, it means the Release is unsolicited + // and handled as an advertisement error. No need to call UnregisterAdvertisement + m_advertising = false; + QDBusConnection::systemBus().unregisterObject(m_advObjectPath); + emit errorOccurred(); + } +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/qleadvertiser_bluezdbus_p.h b/src/bluetooth/qleadvertiser_bluezdbus_p.h new file mode 100644 index 0000000..5a11988 --- /dev/null +++ b/src/bluetooth/qleadvertiser_bluezdbus_p.h @@ -0,0 +1,66 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QLEADVERTISER_BLUEZDBUS_P_H +#define QLEADVERTISER_BLUEZDBUS_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 "qlowenergyadvertisingdata.h" +#include "qlowenergyadvertisingparameters.h" + +QT_REQUIRE_CONFIG(bluez); + +#include + +class OrgBluezLEAdvertisement1Adaptor; +class OrgBluezLEAdvertisingManager1Interface; + +QT_BEGIN_NAMESPACE + +class QLeDBusAdvertiser : public QObject +{ + Q_OBJECT + +public: + QLeDBusAdvertiser(const QLowEnergyAdvertisingParameters ¶ms, + const QLowEnergyAdvertisingData &advertisingData, + const QLowEnergyAdvertisingData &scanResponseData, + const QString &hostAdapterPath, + QObject* parent = nullptr); + ~QLeDBusAdvertiser() override; + + void startAdvertising(); + void stopAdvertising(); + + Q_INVOKABLE void Release(); + +signals: + void errorOccurred(); + +private: + void setDataForDBus(); + void setAdvertisingParamsForDBus(); + void setAdvertisementDataForDBus(); + +private: + const QLowEnergyAdvertisingParameters m_advParams; + QLowEnergyAdvertisingData m_advData; + const QString m_advObjectPath; + OrgBluezLEAdvertisement1Adaptor* const m_advDataDBus; + OrgBluezLEAdvertisingManager1Interface* const m_advManager; + bool m_advertising = false; +}; + +QT_END_NAMESPACE + +#endif // QLEADVERTISER_BLUEZDBUS_P_H diff --git a/src/bluetooth/qlowenergyadvertisingdata.cpp b/src/bluetooth/qlowenergyadvertisingdata.cpp new file mode 100644 index 0000000..90cf452 --- /dev/null +++ b/src/bluetooth/qlowenergyadvertisingdata.cpp @@ -0,0 +1,273 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qlowenergyadvertisingdata.h" + +#include + +QT_BEGIN_NAMESPACE + +class QLowEnergyAdvertisingDataPrivate : public QSharedData +{ +public: + QLowEnergyAdvertisingDataPrivate() + : manufacturerId(QLowEnergyAdvertisingData::invalidManufacturerId()) + , discoverability(QLowEnergyAdvertisingData::DiscoverabilityNone) + , includePowerLevel(false) + { + } + + QString localName; + QByteArray manufacturerData; + QByteArray rawData; + QList services; + quint16 manufacturerId; + QLowEnergyAdvertisingData::Discoverability discoverability; + bool includePowerLevel; +}; + +/*! + \since 5.7 + \class QLowEnergyAdvertisingData + \brief The QLowEnergyAdvertisingData class represents the data to be broadcast during + Bluetooth Low Energy advertising. + \inmodule QtBluetooth + \ingroup shared + + This data can include the device name, GATT services offered by the device, and so on. + The data set via this class will be used when advertising is started by calling + \l QLowEnergyController::startAdvertising(). Objects of this class can represent an + Advertising Data packet or a Scan Response packet. + \note The actual data packets sent over the advertising channel cannot contain more than 31 + bytes. If the variable-length data set via this class exceeds that limit, it will + be left out of the packet or truncated, depending on the type. + On Android, advertising will fail if advertising data is larger than 31 bytes. + On Bluez DBus backend the advertising length limit and the behavior when it is exceeded + is up to BlueZ; it may for example support extended advertising. For the most + predictable behavior keep the advertising data short. + + \sa QLowEnergyAdvertisingParameters + \sa QLowEnergyController::startAdvertising() +*/ + +/*! + \enum QLowEnergyAdvertisingData::Discoverability + + The discoverability of the advertising device as defined by the Generic Access Profile. + + \value DiscoverabilityNone + The advertising device does not wish to be discoverable by scanning devices. + \value DiscoverabilityLimited + The advertising device wishes to be discoverable with a high priority. Note that this mode + is not compatible with using a white list. The value of + \l QLowEnergyAdvertisingParameters::filterPolicy() is always assumed to be + \l QLowEnergyAdvertisingParameters::IgnoreWhiteList when limited discoverability + is used. + \value DiscoverabilityGeneral + The advertising device wishes to be discoverable by scanning devices. + */ + +/*! + Creates a new object of this class. All values are initialized to their defaults + according to the Bluetooth Low Energy specification. + */ +QLowEnergyAdvertisingData::QLowEnergyAdvertisingData() : d(new QLowEnergyAdvertisingDataPrivate) +{ +} + +/*! Constructs a new object of this class that is a copy of \a other. */ +QLowEnergyAdvertisingData::QLowEnergyAdvertisingData(const QLowEnergyAdvertisingData &other) + : d(other.d) +{ +} + +/*! Destroys this object. */ +QLowEnergyAdvertisingData::~QLowEnergyAdvertisingData() +{ +} + +/*! Makes this object a copy of \a other and returns the new value of this object. */ +QLowEnergyAdvertisingData &QLowEnergyAdvertisingData::operator=(const QLowEnergyAdvertisingData &other) +{ + d = other.d; + return *this; +} + +/*! + Specifies that \a name should be broadcast as the name of the device. If the full name does not + fit into the advertising data packet, an abbreviated name is sent, as described by the + Bluetooth Low Energy specification. + + On Android, the local name cannot be changed. Android always uses the device name. + If this local name is not empty, the Android implementation includes the device name + in the advertisement packet; otherwise the device name is omitted from the advertisement + packet. + + \sa localName() + */ +void QLowEnergyAdvertisingData::setLocalName(const QString &name) +{ + d->localName = name; +} + +/*! + Returns the name of the local device that is to be advertised. + + \sa setLocalName() + */ +QString QLowEnergyAdvertisingData::localName() const +{ + return d->localName; +} + +/*! + Sets the manufacturer id and data. The \a id parameter is a company identifier as assigned + by the Bluetooth SIG. The \a data parameter is an arbitrary value. + */ +void QLowEnergyAdvertisingData::setManufacturerData(quint16 id, const QByteArray &data) +{ + d->manufacturerId = id; + d->manufacturerData = data; +} + +/*! + Returns the manufacturer id. + The default is \l QLowEnergyAdvertisingData::invalidManufacturerId(), which means + the data will not be advertised. + */ +quint16 QLowEnergyAdvertisingData::manufacturerId() const +{ + return d->manufacturerId; +} + +/*! + Returns the manufacturer data. The default is an empty byte array. + */ +QByteArray QLowEnergyAdvertisingData::manufacturerData() const +{ + return d->manufacturerData; +} + +/*! + Specifies whether to include the device's transmit power level in the advertising data. If + \a doInclude is \c true, the data will be included, otherwise it will not. + */ +void QLowEnergyAdvertisingData::setIncludePowerLevel(bool doInclude) +{ + d->includePowerLevel = doInclude; +} + +/*! + Returns whether to include the device's transmit power level in the advertising data. + The default is \c false. + */ +bool QLowEnergyAdvertisingData::includePowerLevel() const +{ + return d->includePowerLevel; +} + +/*! + Sets the discoverability type of the advertising device to \a mode. + \note Discoverability information can only appear in an actual advertising data packet. If + this object acts as scan response data, a call to this function will have no effect + on the scan response sent. + */ +void QLowEnergyAdvertisingData::setDiscoverability(QLowEnergyAdvertisingData::Discoverability mode) +{ + d->discoverability = mode; +} + +/*! + Returns the discoverability mode of the advertising device. + The default is \l DiscoverabilityNone. + */ +QLowEnergyAdvertisingData::Discoverability QLowEnergyAdvertisingData::discoverability() const +{ + return d->discoverability; +} + +/*! + Specifies that the service UUIDs in \a services should be advertised. + If the entire list does not fit into the packet, an incomplete list is sent as specified + by the Bluetooth Low Energy specification. + */ +void QLowEnergyAdvertisingData::setServices(const QList &services) +{ + d->services = services; +} + +/*! + Returns the list of service UUIDs to be advertised. + By default, this list is empty. + */ +QList QLowEnergyAdvertisingData::services() const +{ + return d->services; +} + +/*! + Sets the data to be advertised to \a data. If the value is not an empty byte array, it will + be sent as-is as the advertising data and all other data in this object will be ignored. + This can be used to send non-standard data. + \note If \a data is longer than 31 bytes, it will be truncated. It is the caller's responsibility + to ensure that \a data is well-formed. + + Providing the raw advertising data is not supported on BlueZ DBus backend as BlueZ does not + support it. This may change in a future release. + */ +void QLowEnergyAdvertisingData::setRawData(const QByteArray &data) +{ + d->rawData = data; +} + +/*! + Returns the user-supplied raw data to be advertised. The default is an empty byte array. + */ +QByteArray QLowEnergyAdvertisingData::rawData() const +{ + return d->rawData; +} + +/*! + \fn void QLowEnergyAdvertisingData::swap(QLowEnergyAdvertisingData &other) + Swaps this object with \a other. + */ + +/*! + \brief Returns \c true if \a a and \a b are equal with respect to their public state, + otherwise returns \c false. + \internal + */ +bool QLowEnergyAdvertisingData::equals(const QLowEnergyAdvertisingData &a, + const QLowEnergyAdvertisingData &b) +{ + if (a.d == b.d) + return true; + return a.discoverability() == b.discoverability() + && a.includePowerLevel() == b.includePowerLevel() && a.localName() == b.localName() + && a.manufacturerData() == b.manufacturerData() + && a.manufacturerId() == b.manufacturerId() && a.services() == b.services() + && a.rawData() == b.rawData(); +} + +/*! + \fn bool QLowEnergyAdvertisingData::operator!=(const QLowEnergyAdvertisingData &data1, + const QLowEnergyAdvertisingData &data2) + \brief Returns \c true if \a data1 and \a data2 are not equal with respect to their + public state, otherwise returns \c false. + */ + +/*! + \fn bool QLowEnergyAdvertisingData::operator==(const QLowEnergyAdvertisingData &data1, + const QLowEnergyAdvertisingData &data2) + \brief Returns \c true if \a data1 and \a data2 are equal with respect to their public + state, otherwise returns \c false. + */ + +/*! + \fn static quint16 QLowEnergyAdvertisingData::invalidManufacturerId(); + Returns an invalid manufacturer id. If this value is set as the manufacturer id + (which it is by default), no manufacturer data will be present in the advertising data. + */ + +QT_END_NAMESPACE diff --git a/src/bluetooth/qlowenergyadvertisingdata.h b/src/bluetooth/qlowenergyadvertisingdata.h new file mode 100644 index 0000000..600bd21 --- /dev/null +++ b/src/bluetooth/qlowenergyadvertisingdata.h @@ -0,0 +1,68 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QLOWENERGYADVERTISINGDATA_H +#define QLOWENERGYADVERTISINGDATA_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QLowEnergyAdvertisingDataPrivate; + +class Q_BLUETOOTH_EXPORT QLowEnergyAdvertisingData +{ +public: + QLowEnergyAdvertisingData(); + QLowEnergyAdvertisingData(const QLowEnergyAdvertisingData &other); + ~QLowEnergyAdvertisingData(); + + QLowEnergyAdvertisingData &operator=(const QLowEnergyAdvertisingData &other); + friend bool operator==(const QLowEnergyAdvertisingData &a, const QLowEnergyAdvertisingData &b) + { + return equals(a, b); + } + friend bool operator!=(const QLowEnergyAdvertisingData &a, const QLowEnergyAdvertisingData &b) + { + return !equals(a, b); + } + + void setLocalName(const QString &name); + QString localName() const; + + static quint16 invalidManufacturerId() { return 0xffff; } + void setManufacturerData(quint16 id, const QByteArray &data); + quint16 manufacturerId() const; + QByteArray manufacturerData() const; + + void setIncludePowerLevel(bool doInclude); + bool includePowerLevel() const; + + enum Discoverability { + DiscoverabilityNone, DiscoverabilityLimited, DiscoverabilityGeneral + }; + void setDiscoverability(Discoverability mode); + Discoverability discoverability() const; + + void setServices(const QList &services); + QList services() const; + + // TODO: BR/EDR capability flag? + + void setRawData(const QByteArray &data); + QByteArray rawData() const; + + void swap(QLowEnergyAdvertisingData &other) noexcept { d.swap(other.d); } + +private: + static bool equals(const QLowEnergyAdvertisingData &a, const QLowEnergyAdvertisingData &b); + QSharedDataPointer d; +}; + +Q_DECLARE_SHARED(QLowEnergyAdvertisingData) + +QT_END_NAMESPACE + +#endif // Include guard diff --git a/src/bluetooth/qlowenergyadvertisingparameters.cpp b/src/bluetooth/qlowenergyadvertisingparameters.cpp new file mode 100644 index 0000000..b092303 --- /dev/null +++ b/src/bluetooth/qlowenergyadvertisingparameters.cpp @@ -0,0 +1,296 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qlowenergyadvertisingparameters.h" + +QT_BEGIN_NAMESPACE + +class QLowEnergyAdvertisingParametersPrivate : public QSharedData +{ +public: + QLowEnergyAdvertisingParametersPrivate() + : filterPolicy(QLowEnergyAdvertisingParameters::IgnoreWhiteList) + , mode(QLowEnergyAdvertisingParameters::AdvInd) + , minInterval(1280) + , maxInterval(1280) + { + } + + QList whiteList; + QLowEnergyAdvertisingParameters::FilterPolicy filterPolicy; + QLowEnergyAdvertisingParameters::Mode mode; + int minInterval; + int maxInterval; +}; + +/*! + \since 5.7 + \class QLowEnergyAdvertisingParameters + \brief The QLowEnergyAdvertisingParameters class represents the parameters used for + Bluetooth Low Energy advertising. + \inmodule QtBluetooth + \ingroup shared + + When running the advertising procedure, a number of parameters can be configured, such as + how fast to advertise or which clients, if any, can connect to the advertising device. + These parameters are set via this class, and their values will be used when advertising + is started by calling \l QLowEnergyController::startAdvertising(). + + \sa QLowEnergyAdvertisingData + \sa QLowEnergyController::startAdvertising() +*/ + +/*! + \enum QLowEnergyAdvertisingParameters::Mode + + Specifies in which way to advertise. + \value AdvInd + For non-directed, connectable advertising. Advertising is not directed to + one specific device and a device seeing the advertisement can connect to the + advertising device or send scan requests. + \value AdvScanInd + For non-directed, scannable advertising. Advertising is not directed to + one specific device and a device seeing the advertisement can send a scan + request to the advertising device, but cannot connect to it. + \value AdvNonConnInd + For non-directed, non-connectable advertising. Advertising is not directed to + one specific device. A device seeing the advertisement cannot connect to the + advertising device, nor can it send a scan request. This mode thus implies + pure broadcasting. +*/ + +/*! + \enum QLowEnergyAdvertisingParameters::FilterPolicy + + Specifies the semantics of the white list. + \value IgnoreWhiteList + The value of the white list is ignored, that is, no filtering takes place for + either scan or connection requests when using undirected advertising. + \value UseWhiteListForScanning + The white list is used when handling scan requests, but is ignored for connection + requests. + \value UseWhiteListForConnecting + The white list is used when handling connection requests, but is ignored for scan + requests. + \value UseWhiteListForScanningAndConnecting + The white list is used for both connection and scan requests. + + \sa QLowEnergyAdvertisingParameters::whiteList() +*/ + +/*! + \class QLowEnergyAdvertisingParameters::AddressInfo + \inmodule QtBluetooth + \since 5.7 + + \brief The QLowEnergyAdvertisingParameters::AddressInfo defines the elements of a white list. + + A list of QLowEnergyAdvertisingParameters::AddressInfo instances is passed to + \l QLowEnergyAdvertisingParameters::setWhiteList(). White lists are used to + restrict the devices which have the permission to interact with the peripheral. + The permitted type of interaction is defined by + \l QLowEnergyAdvertisingParameters::FilterPolicy. + + \sa QLowEnergyAdvertisingParameters::whiteList() +*/ + +/*! + \variable QLowEnergyAdvertisingParameters::AddressInfo::address + + This is the Bluetooth address of a remote device. +*/ + +/*! + \variable QLowEnergyAdvertisingParameters::AddressInfo::type + + The type of the address (public or private). + The \l AddressInfo default constructor initialises this value to + \l QLowEnergyController::PublicAddress. +*/ + +/*! + \fn QLowEnergyAdvertisingParameters::AddressInfo::AddressInfo(const QBluetoothAddress &addr, QLowEnergyController::RemoteAddressType type) + + Constructs a new AddressInfo instance. \a addr represents the Bluetooth address of + the remote device and \a type the nature of the address. +*/ + +/*! + \fn QLowEnergyAdvertisingParameters::AddressInfo::AddressInfo() + + Constructs a default constructed AddressInfo instance. + + By default the \l AddressInfo::type member is set to + \l QLowEnergyController::PublicAddress and the \l AddressInfo::address + member has a null address. +*/ + +/*! + Constructs a new object of this class. All values are initialized to their defaults + according to the Bluetooth Low Energy specification. + */ +QLowEnergyAdvertisingParameters::QLowEnergyAdvertisingParameters() + : d(new QLowEnergyAdvertisingParametersPrivate) +{ +} + +/*! Constructs a new object of this class that is a copy of \a other. */ +QLowEnergyAdvertisingParameters::QLowEnergyAdvertisingParameters(const QLowEnergyAdvertisingParameters &other) + : d(other.d) +{ +} + +/*! Destroys this object. */ +QLowEnergyAdvertisingParameters::~QLowEnergyAdvertisingParameters() +{ +} + +/*! Makes this object a copy of \a other and returns the new value of this object. */ +QLowEnergyAdvertisingParameters &QLowEnergyAdvertisingParameters::operator=(const QLowEnergyAdvertisingParameters &other) +{ + d = other.d; + return *this; +} + +/*! Sets the advertising mode to \a mode. */ +void QLowEnergyAdvertisingParameters::setMode(QLowEnergyAdvertisingParameters::Mode mode) +{ + d->mode = mode; +} + +/*! + Returns the advertising mode. The default is \l QLowEnergyAdvertisingParameters::AdvInd. + */ +QLowEnergyAdvertisingParameters::Mode QLowEnergyAdvertisingParameters::mode() const +{ + return d->mode; +} + +/*! + Sets the white list that is potentially used for filtering scan and connection requests. + The \a whiteList parameter is the list of addresses to use for filtering, and \a policy + specifies how exactly to use \a whiteList. + + Whitelists are not supported on the BlueZ DBus backend as they are not supported by BlueZ. + */ +void QLowEnergyAdvertisingParameters::setWhiteList(const QList &whiteList, + FilterPolicy policy) +{ + d->whiteList = whiteList; + d->filterPolicy = policy; +} + +/*! + Returns the white list used for filtering scan and connection requests. + By default, this list is empty. + */ +QList QLowEnergyAdvertisingParameters::whiteList() const +{ + return d->whiteList; +} + +/*! + Returns the filter policy that determines how the white list is used. The default + is \l QLowEnergyAdvertisingParameters::IgnoreWhiteList. + */ +QLowEnergyAdvertisingParameters::FilterPolicy QLowEnergyAdvertisingParameters::filterPolicy() const +{ + return d->filterPolicy; +} + +/*! + Sets the advertising interval. This is a range that gives the controller an upper and a lower + bound for how often to send the advertising data. Both \a minimum and \a maximum are given + in milliseconds. + If \a maximum is smaller than \a minimum, it will be set to the value of \a minimum. + \note There are limits for the minimum and maximum interval; the exact values depend on + the mode. If they are exceeded, the lowest or highest possible value will be used, + respectively. + + Setting the advertising interval is supported on BlueZ DBus backend if its experimental + status is changed in later versions of BlueZ (or run in experimental mode). + + */ +void QLowEnergyAdvertisingParameters::setInterval(quint16 minimum, quint16 maximum) +{ + d->minInterval = minimum; + d->maxInterval = qMax(minimum, maximum); +} + +/*! + Returns the minimum advertising interval in milliseconds. The default is 1280. + */ +int QLowEnergyAdvertisingParameters::minimumInterval() const +{ + return d->minInterval; +} + +/*! + Returns the maximum advertising interval in milliseconds. The default is 1280. + */ +int QLowEnergyAdvertisingParameters::maximumInterval() const +{ + return d->maxInterval; +} + +/*! + \fn void QLowEnergyAdvertisingParameters::swap(QLowEnergyAdvertisingParameters &other) + Swaps this object with \a other. + */ + +/*! + \brief Returns \c true if \a a and \a b are equal with respect to their public state, + otherwise returns \c false. + \internal + */ +bool QLowEnergyAdvertisingParameters::equals(const QLowEnergyAdvertisingParameters &a, + const QLowEnergyAdvertisingParameters &b) +{ + if (a.d == b.d) + return true; + return a.filterPolicy() == b.filterPolicy() && a.minimumInterval() == b.minimumInterval() + && a.maximumInterval() == b.maximumInterval() && a.mode() == b.mode() + && a.whiteList() == b.whiteList(); +} + +bool QLowEnergyAdvertisingParameters::AddressInfo::equals( + const QLowEnergyAdvertisingParameters::AddressInfo &ai1, + const QLowEnergyAdvertisingParameters::AddressInfo &ai2) +{ + return ai1.address == ai2.address && ai1.type == ai2.type; +} + +/*! + \fn bool QLowEnergyAdvertisingParameters::operator!=( + const QLowEnergyAdvertisingParameters &a, + const QLowEnergyAdvertisingParameters &b) + \brief Returns \c true if \a a and \a b are not equal with respect to their public state, + otherwise returns \c false. + */ + +/*! + \fn bool QLowEnergyAdvertisingParameters::operator==( + const QLowEnergyAdvertisingParameters &a, + const QLowEnergyAdvertisingParameters &b) + \brief Returns \c true if \a a and \a b are equal with respect to their public state, + otherwise returns \c false. + */ + +/*! + \fn bool QLowEnergyAdvertisingParameters::AddressInfo::operator!=(const + QLowEnergyAdvertisingParameters::AddressInfo &a, const + QLowEnergyAdvertisingParameters::AddressInfo &b) + + \brief Returns \c true if \a a and \a b are not equal with respect to their public state, + otherwise returns \c false. + */ + +/*! + \fn bool QLowEnergyAdvertisingParameters::AddressInfo::operator==( + const QLowEnergyAdvertisingParameters::AddressInfo &a, + const QLowEnergyAdvertisingParameters::AddressInfo &b) + \brief Returns \c true if \a a and \a b are equal with respect to their public state, + otherwise returns \c false. + */ + +QT_END_NAMESPACE diff --git a/src/bluetooth/qlowenergyadvertisingparameters.h b/src/bluetooth/qlowenergyadvertisingparameters.h new file mode 100644 index 0000000..fe3ed1c --- /dev/null +++ b/src/bluetooth/qlowenergyadvertisingparameters.h @@ -0,0 +1,86 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QLOWENERGYADVERTISINGPARAMETERS_H +#define QLOWENERGYADVERTISINGPARAMETERS_H + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QLowEnergyAdvertisingParametersPrivate; + +class Q_BLUETOOTH_EXPORT QLowEnergyAdvertisingParameters +{ +public: + QLowEnergyAdvertisingParameters(); + QLowEnergyAdvertisingParameters(const QLowEnergyAdvertisingParameters &other); + ~QLowEnergyAdvertisingParameters(); + + QLowEnergyAdvertisingParameters &operator=(const QLowEnergyAdvertisingParameters &other); + friend bool operator==(const QLowEnergyAdvertisingParameters &a, + const QLowEnergyAdvertisingParameters &b) + { + return equals(a, b); + } + + friend bool operator!=(const QLowEnergyAdvertisingParameters &a, + const QLowEnergyAdvertisingParameters &b) + { + return !equals(a, b); + } + + enum Mode { AdvInd = 0x0, AdvScanInd = 0x2, AdvNonConnInd = 0x3 }; + void setMode(Mode mode); + Mode mode() const; + + class Q_BLUETOOTH_EXPORT AddressInfo + { + public: + AddressInfo(const QBluetoothAddress &addr, QLowEnergyController::RemoteAddressType t) + : address(addr), type(t) {} + AddressInfo() : type(QLowEnergyController::PublicAddress) {} + + QBluetoothAddress address; + QLowEnergyController::RemoteAddressType type; + friend bool operator==(const AddressInfo &a, const AddressInfo &b) { return equals(a, b); } + friend bool operator!=(const AddressInfo &a, const AddressInfo &b) { return !equals(a, b); } + + private: + static bool equals(const AddressInfo &a, const AddressInfo &b); + }; + + enum FilterPolicy { + IgnoreWhiteList = 0x00, + UseWhiteListForScanning = 0x01, + UseWhiteListForConnecting = 0x02, + UseWhiteListForScanningAndConnecting = 0x03, + }; + void setWhiteList(const QList &whiteList, FilterPolicy policy); + QList whiteList() const; + FilterPolicy filterPolicy() const; + + void setInterval(quint16 minimum, quint16 maximum); + int minimumInterval() const; + int maximumInterval() const; + + // TODO: own address type + // TODO: For ADV_DIRECT_IND: peer address + peer address type + + void swap(QLowEnergyAdvertisingParameters &other) noexcept { d.swap(other.d); } + +private: + static bool equals(const QLowEnergyAdvertisingParameters &a, + const QLowEnergyAdvertisingParameters &b); + QSharedDataPointer d; +}; + +Q_DECLARE_SHARED(QLowEnergyAdvertisingParameters) + +QT_END_NAMESPACE + +#endif // Include guard diff --git a/src/bluetooth/qlowenergycharacteristic.cpp b/src/bluetooth/qlowenergycharacteristic.cpp new file mode 100644 index 0000000..d71861c --- /dev/null +++ b/src/bluetooth/qlowenergycharacteristic.cpp @@ -0,0 +1,458 @@ +// Copyright (C) 2016 BlackBerry Limited. All rights reserved. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qlowenergycharacteristic.h" +#include "qlowenergyserviceprivate_p.h" +#include + +QT_BEGIN_NAMESPACE + +QT_IMPL_METATYPE_EXTERN(QLowEnergyCharacteristic) + +/*! + \class QLowEnergyCharacteristic + \inmodule QtBluetooth + \brief The QLowEnergyCharacteristic class stores information about a Bluetooth + Low Energy service characteristic. + + \since 5.4 + + QLowEnergyCharacteristic provides information about a Bluetooth Low Energy + service characteristic's name(), uuid(), value(), properties(), and + descriptors(). To obtain the characteristic's specification + and information, it is necessary to connect to the device using the + QLowEnergyService and QLowEnergyController classes. + + The characteristic value may be written via the \l QLowEnergyService instance + that manages the service to which this characteristic belongs. The + \l {QLowEnergyService::writeCharacteristic()} function writes the new value. + The \l {QLowEnergyService::characteristicWritten()} signal is emitted upon success. + The value() of this object is automatically updated accordingly. + + Characteristics may contain none, one or more descriptors. They can be individually + retrieved using the \l descriptor() function. The \l descriptors() function returns + all descriptors as a list. The general purpose of a descriptor is to add contextual + information to the characteristic. For example, the descriptor might provide + format or range information specifying how the characteristic's value is to be\ + interpreted. + + \sa QLowEnergyService, QLowEnergyDescriptor +*/ + +/*! + \enum QLowEnergyCharacteristic::PropertyType + + This enum describes the properties of a characteristic. + + \value Unknown The type is not known. + \value Broadcasting Allow for the broadcasting of Generic Attributes (GATT) characteristic values. + \value Read Allow the characteristic values to be read. + \value WriteNoResponse Allow characteristic values without responses to be written. + \value Write Allow for characteristic values to be written. + \value Notify Permits notification of characteristic values. + \value Indicate Permits indications of characteristic values. + \value WriteSigned Permits signed writes of the GATT characteristic values. + \value ExtendedProperty Additional characteristic properties are defined in the characteristic's + extended properties descriptor. + + It is not recommended to set both Notify and Indicate properties on the same characteristic + as the underlying Bluetooth stack behaviors differ from platform to platform. Please see + \l QLowEnergyCharacteristic::clientCharacteristicConfiguration + + + \sa properties() +*/ + +struct QLowEnergyCharacteristicPrivate +{ + QLowEnergyHandle handle; +}; + +/*! + Construct a new QLowEnergyCharacteristic. A default-constructed instance of + this class is always invalid. + + \sa isValid() +*/ +QLowEnergyCharacteristic::QLowEnergyCharacteristic(): + d_ptr(nullptr) +{ + +} + +/*! + Construct a new QLowEnergyCharacteristic that is a copy of \a other. + + The two copies continue to share the same underlying data which does not detach + upon write. +*/ +QLowEnergyCharacteristic::QLowEnergyCharacteristic(const QLowEnergyCharacteristic &other): + d_ptr(other.d_ptr) +{ + if (other.data) { + data = new QLowEnergyCharacteristicPrivate(); + data->handle = other.data->handle; + } +} + +/*! + \internal +*/ +QLowEnergyCharacteristic::QLowEnergyCharacteristic( + QSharedPointer p, QLowEnergyHandle handle): + d_ptr(p) +{ + data = new QLowEnergyCharacteristicPrivate(); + data->handle = handle; +} + +/*! + Destroys the QLowEnergyCharacteristic object. +*/ +QLowEnergyCharacteristic::~QLowEnergyCharacteristic() +{ + delete data; +} + +/*! + Returns the human-readable name of the characteristic. + + The name is based on the characteristic's \l uuid() which must have been + standardized. The complete list of characteristic types can be found + under \l {https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicsHome.aspx}{Bluetooth.org Characteristics}. + + The returned string is empty if the \l uuid() is unknown. + + \sa QBluetoothUuid::characteristicToString() +*/ +QString QLowEnergyCharacteristic::name() const +{ + return QBluetoothUuid::characteristicToString( + static_cast(uuid().toUInt16())); +} + +/*! + Returns the UUID of the characteristic if \l isValid() returns \c true; otherwise a + \l {QUuid::isNull()}{null} UUID. +*/ +QBluetoothUuid QLowEnergyCharacteristic::uuid() const +{ + if (d_ptr.isNull() || !data + || !d_ptr->characteristicList.contains(data->handle)) + return QBluetoothUuid(); + + return d_ptr->characteristicList[data->handle].uuid; +} + +/*! + Returns the properties of the characteristic. + + The properties define the access permissions for the characteristic. +*/ +QLowEnergyCharacteristic::PropertyTypes QLowEnergyCharacteristic::properties() const +{ + if (d_ptr.isNull() || !data + || !d_ptr->characteristicList.contains(data->handle)) + return QLowEnergyCharacteristic::Unknown; + + return d_ptr->characteristicList[data->handle].properties; +} + +/*! + Returns the cached value of the characteristic. + + If the characteristic's \l properties() permit writing of new values, + the value can be updated using \l QLowEnergyService::writeCharacteristic(). + + The cache is updated during the associated service's + \l {QLowEnergyService::discoverDetails()} {detail discovery}, a successful + \l {QLowEnergyService::readCharacteristic()}{read}/\l {QLowEnergyService::writeCharacteristic()}{write} + operation or when an update notification is received. + + The returned \l QByteArray always remains empty if the characteristic does not + have the \l {QLowEnergyCharacteristic::Read}{read permission}. In such cases only + the \l QLowEnergyService::characteristicChanged() or + \l QLowEnergyService::characteristicWritten() may provice information about the + value of this characteristic. +*/ +QByteArray QLowEnergyCharacteristic::value() const +{ + if (d_ptr.isNull() || !data + || !d_ptr->characteristicList.contains(data->handle)) + return QByteArray(); + + return d_ptr->characteristicList[data->handle].value; +} + +/*! + \internal + + Returns the handle of the characteristic's value attribute; + or \c 0 if the handle cannot be accessed on the platform or + if the characteristic is invalid. + + \note On \macos and iOS handles can differ from 0, but these + values have no special meaning outside of internal/private API. +*/ +QLowEnergyHandle QLowEnergyCharacteristic::handle() const +{ + if (d_ptr.isNull() || !data + || !d_ptr->characteristicList.contains(data->handle)) + return 0; + + return d_ptr->characteristicList[data->handle].valueHandle; +} + +/*! + Makes a copy of \a other and assigns it to this \l QLowEnergyCharacteristic object. + The two copies continue to share the same service and controller details. +*/ +QLowEnergyCharacteristic &QLowEnergyCharacteristic::operator=(const QLowEnergyCharacteristic &other) +{ + d_ptr = other.d_ptr; + + if (!other.data) { + if (data) { + delete data; + data = nullptr; + } + } else { + if (!data) + data = new QLowEnergyCharacteristicPrivate(); + + data->handle = other.data->handle; + } + return *this; +} + +/*! + \fn bool QLowEnergyCharacteristic::operator==(const QLowEnergyCharacteristic &a, + const QLowEnergyCharacteristic &b) + \brief Returns \c true if \a a is equal to \a b, otherwise \c false. + + Two \l QLowEnergyCharacteristic instances are considered to be equal if they refer to + the same characteristic on the same remote Bluetooth Low Energy device or both instances + have been default-constructed. + */ + +/*! + \fn bool QLowEnergyCharacteristic::operator!=(const QLowEnergyCharacteristic &a, + const QLowEnergyCharacteristic &b) + \brief Returns \c true if \a a and \a b are not equal; otherwise \c + false. + + Two QLowEnergyCharcteristic instances are considered to be equal if they refer to + the same characteristic on the same remote Bluetooth Low Energy device or both instances + have been default-constructed. + */ + +/*! + \brief Returns \c true if \a a is equal to \a b; otherwise \c false. + \internal + + Two \l QLowEnergyCharacteristic instances are considered to be equal if they refer to + the same characteristic on the same remote Bluetooth Low Energy device or both instances + have been default-constructed. + */ +bool QLowEnergyCharacteristic::equals(const QLowEnergyCharacteristic &a, + const QLowEnergyCharacteristic &b) +{ + if (a.d_ptr != b.d_ptr) + return false; + + if ((a.data && !b.data) || (!a.data && b.data)) + return false; + + if (!a.data) + return true; + + if (a.data->handle != b.data->handle) + return false; + + return true; +} + +/*! + Returns \c true if the QLowEnergyCharacteristic object is valid, otherwise returns \c false. + + An invalid characteristic object is not associated with any service (default-constructed) + or the associated service is no longer valid due to a disconnect from + the underlying Bluetooth Low Energy device, for example. Once the object is invalid + it cannot become valid anymore. + + \note If a \l QLowEnergyCharacteristic instance turns invalid due to a disconnect + from the underlying device, the information encapsulated by the current + instance remains as it was at the time of the disconnect. Therefore it can be + retrieved after the disconnect event. +*/ +bool QLowEnergyCharacteristic::isValid() const +{ + if (d_ptr.isNull() || !data) + return false; + + if (d_ptr->state == QLowEnergyService::InvalidService) + return false; + + return true; +} + +/*! + \internal + + Returns the handle of the characteristic or + \c 0 if the handle cannot be accessed on the platform or if the + characteristic is invalid. + + \note On \macos and iOS handles can differ from 0, but these + values have no special meaning outside of internal/private API. + + \sa isValid() + */ +QLowEnergyHandle QLowEnergyCharacteristic::attributeHandle() const +{ + if (d_ptr.isNull() || !data) + return 0; + + return data->handle; +} + +/*! + Returns the descriptor for \a uuid or an invalid \l QLowEnergyDescriptor instance. + + \sa descriptors() +*/ +QLowEnergyDescriptor QLowEnergyCharacteristic::descriptor(const QBluetoothUuid &uuid) const +{ + if (d_ptr.isNull() || !data) + return QLowEnergyDescriptor(); + + CharacteristicDataMap::const_iterator charIt = d_ptr->characteristicList.constFind(data->handle); + if (charIt != d_ptr->characteristicList.constEnd()) { + const QLowEnergyServicePrivate::CharData &charDetails = charIt.value(); + + DescriptorDataMap::const_iterator descIt = charDetails.descriptorList.constBegin(); + for ( ; descIt != charDetails.descriptorList.constEnd(); ++descIt) { + const QLowEnergyHandle descHandle = descIt.key(); + const QLowEnergyServicePrivate::DescData &descDetails = descIt.value(); + + if (descDetails.uuid == uuid) + return QLowEnergyDescriptor(d_ptr, data->handle, descHandle); + } + } + + return QLowEnergyDescriptor(); +} + +/*! + Returns the Client Characteristic Configuration Descriptor or an + invalid \l QLowEnergyDescriptor instance if no + Client Characteristic Configuration Descriptor exists. + + BTLE characteristics can support notifications and/or indications. + In both cases, the peripheral will inform the central on + each change of the characteristic's value. In the BTLE + attribute protocol, notification messages are not confirmed + by the central, while indications are confirmed. + Notifications are considered faster, but unreliable, while + indications are slower and more reliable. + + If a characteristic supports notification or indication, + these can be enabled by writing special bit patterns to the + Client Characteristic Configuration Descriptor. + For convenience, these bit patterns are provided as + \l QLowEnergyCharacteristic::CCCDDisable, + \l QLowEnergyCharacteristic::CCCDEnableNotification, and + \l QLowEnergyCharacteristic::CCCDEnableIndication. + + Enabling e.g. notification for a characteristic named + \c mycharacteristic in a service called \c myservice + could be done using the following code. + \code + auto cccd = mycharacteristic.clientCharacteristicConfiguration(); + if (!cccd.isValid()) { + // your error handling + return error; + } + myservice->writeDescriptor(cccd, QLowEnergyCharacteristic::CCCDEnableNotification); + \endcode + + \note + Calling \c characteristic.clientCharacteristicConfiguration() is equivalent to calling + \c characteristic.descriptor(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration). + + \note + It is not recommended to use both notifications and indications on the same characteristic. + This applies to both server-side when setting up the characteristics, as well as client-side + when enabling them. The bluetooth stack behavior differs from platform to platform and the + cross-platform behavior will likely be inconsistent. As an example a Bluez Linux client might + unconditionally try to enable both mechanisms if both are supported, whereas a macOS client + might unconditionally enable just the notifications. If both are needed consider creating two + separate characteristics. + + \since 6.2 + \sa descriptor() +*/ +QLowEnergyDescriptor QLowEnergyCharacteristic::clientCharacteristicConfiguration() const +{ + return descriptor(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration); +} + +/*! + Returns the list of descriptors belonging to this characteristic; otherwise + an empty list. + + \sa descriptor() +*/ +QList QLowEnergyCharacteristic::descriptors() const +{ + QList result; + + if (d_ptr.isNull() || !data + || !d_ptr->characteristicList.contains(data->handle)) + return result; + + QList descriptorKeys = d_ptr->characteristicList[data->handle]. + descriptorList.keys(); + + std::sort(descriptorKeys.begin(), descriptorKeys.end()); + + for (const QLowEnergyHandle descHandle : std::as_const(descriptorKeys)) { + QLowEnergyDescriptor descriptor(d_ptr, data->handle, descHandle); + result.append(descriptor); + } + + return result; +} + +/*! + \variable QLowEnergyCharacteristic::CCCDDisable + \since 6.2 + + Bit pattern to write into Client Characteristic Configuration Descriptor + to disable both notification and indication. + + \sa QLowEnergyCharacteristic::clientCharacteristicConfiguration +*/ +/*! + \variable QLowEnergyCharacteristic::CCCDEnableNotification + \since 6.2 + + Bit pattern to write into Client Characteristic Configuration Descriptor + to enable notification. + + \sa QLowEnergyCharacteristic::clientCharacteristicConfiguration +*/ +/*! + \variable QLowEnergyCharacteristic::CCCDEnableIndication + \since 6.2 + + Bit pattern to write into Client Characteristic Configuration Descriptor + to enable indication. + + \sa QLowEnergyCharacteristic::clientCharacteristicConfiguration +*/ +const QByteArray QLowEnergyCharacteristic::CCCDDisable = QByteArray::fromHex("0000"); +const QByteArray QLowEnergyCharacteristic::CCCDEnableNotification = QByteArray::fromHex("0100"); +const QByteArray QLowEnergyCharacteristic::CCCDEnableIndication = QByteArray::fromHex("0200"); + +QT_END_NAMESPACE diff --git a/src/bluetooth/qlowenergycharacteristic.h b/src/bluetooth/qlowenergycharacteristic.h new file mode 100644 index 0000000..8219c2d --- /dev/null +++ b/src/bluetooth/qlowenergycharacteristic.h @@ -0,0 +1,95 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2016 BlackBerry Limited all rights reserved +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QLOWENERGYCHARACTERISTIC_H +#define QLOWENERGYCHARACTERISTIC_H +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QBluetoothUuid; +class QLowEnergyServicePrivate; +struct QLowEnergyCharacteristicPrivate; +class Q_BLUETOOTH_EXPORT QLowEnergyCharacteristic +{ +public: + + enum PropertyType { + Unknown = 0x00, + Broadcasting = 0x01, + Read = 0x02, + WriteNoResponse = 0x04, + Write = 0x08, + Notify = 0x10, + Indicate = 0x20, + WriteSigned = 0x40, + ExtendedProperty = 0x80 + }; + Q_DECLARE_FLAGS(PropertyTypes, PropertyType) + + QLowEnergyCharacteristic(); + QLowEnergyCharacteristic(const QLowEnergyCharacteristic &other); + ~QLowEnergyCharacteristic(); + + QLowEnergyCharacteristic &operator=(const QLowEnergyCharacteristic &other); + friend bool operator==(const QLowEnergyCharacteristic &a, const QLowEnergyCharacteristic &b) + { + return equals(a, b); + } + friend bool operator!=(const QLowEnergyCharacteristic &a, const QLowEnergyCharacteristic &b) + { + return !equals(a, b); + } + + QString name() const; + + QBluetoothUuid uuid() const; + + QByteArray value() const; + + QLowEnergyCharacteristic::PropertyTypes properties() const; + + QLowEnergyDescriptor descriptor(const QBluetoothUuid &uuid) const; + QList descriptors() const; + + QLowEnergyDescriptor clientCharacteristicConfiguration() const; + + bool isValid() const; + + static const QByteArray CCCDDisable; + static const QByteArray CCCDEnableNotification; + static const QByteArray CCCDEnableIndication; + +private: + QLowEnergyHandle handle() const; + QLowEnergyHandle attributeHandle() const; + + QSharedPointer d_ptr; + + friend class QLowEnergyService; + friend class QLowEnergyControllerPrivate; + friend class QLowEnergyControllerPrivateAndroid; + friend class QLowEnergyControllerPrivateBluez; + friend class QLowEnergyControllerPrivateBluezDBus; + friend class QLowEnergyControllerPrivateCommon; + friend class QLowEnergyControllerPrivateDarwin; + friend class QLowEnergyControllerPrivateWinRT; + QLowEnergyCharacteristicPrivate *data = nullptr; + QLowEnergyCharacteristic(QSharedPointer p, + QLowEnergyHandle handle); + + static bool equals(const QLowEnergyCharacteristic &a, const QLowEnergyCharacteristic &b); +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QLowEnergyCharacteristic::PropertyTypes) + +QT_END_NAMESPACE + +QT_DECL_METATYPE_EXTERN(QLowEnergyCharacteristic, Q_BLUETOOTH_EXPORT) + +#endif // QLOWENERGYCHARACTERISTIC_H diff --git a/src/bluetooth/qlowenergycharacteristicdata.cpp b/src/bluetooth/qlowenergycharacteristicdata.cpp new file mode 100644 index 0000000..9c50e10 --- /dev/null +++ b/src/bluetooth/qlowenergycharacteristicdata.cpp @@ -0,0 +1,254 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qlowenergycharacteristicdata.h" + +#include "qlowenergydescriptordata.h" + +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT) + +struct QLowEnergyCharacteristicDataPrivate : public QSharedData +{ + QLowEnergyCharacteristicDataPrivate() + : properties(QLowEnergyCharacteristic::Unknown) + , minimumValueLength(0) + , maximumValueLength(INT_MAX) + {} + + QBluetoothUuid uuid; + QLowEnergyCharacteristic::PropertyTypes properties; + QList descriptors; + QByteArray value; + QBluetooth::AttAccessConstraints readConstraints; + QBluetooth::AttAccessConstraints writeConstraints; + int minimumValueLength; + int maximumValueLength; +}; + +/*! + \since 5.7 + \class QLowEnergyCharacteristicData + \brief The QLowEnergyCharacteristicData class is used to set up GATT service data. + \inmodule QtBluetooth + \ingroup shared + + An Object of this class provides a characteristic to be added to a + \l QLowEnergyServiceData object via \l QLowEnergyServiceData::addCharacteristic(). + + \sa QLowEnergyServiceData + \sa QLowEnergyController::addService +*/ + +/*! Creates a new invalid object of this class. */ +QLowEnergyCharacteristicData::QLowEnergyCharacteristicData() + : d(new QLowEnergyCharacteristicDataPrivate) +{ +} + +/*! Constructs a new object of this class that is a copy of \a other. */ +QLowEnergyCharacteristicData::QLowEnergyCharacteristicData(const QLowEnergyCharacteristicData &other) + : d(other.d) +{ +} + +/*! Destroys this object. */ +QLowEnergyCharacteristicData::~QLowEnergyCharacteristicData() +{ +} + +/*! Makes this object a copy of \a other and returns the new value of this object. */ +QLowEnergyCharacteristicData &QLowEnergyCharacteristicData::operator=(const QLowEnergyCharacteristicData &other) +{ + d = other.d; + return *this; +} + +/*! Returns the UUID of this characteristic. */ +QBluetoothUuid QLowEnergyCharacteristicData::uuid() const +{ + return d->uuid; +} + +/*! Sets the UUID of this characteristic to \a uuid. */ +void QLowEnergyCharacteristicData::setUuid(const QBluetoothUuid &uuid) +{ + d->uuid = uuid; +} + +/*! Returns the value of this characteristic. */ +QByteArray QLowEnergyCharacteristicData::value() const +{ + return d->value; +} + +/*! Sets the value of this characteristic to \a value. */ +void QLowEnergyCharacteristicData::setValue(const QByteArray &value) +{ + d->value = value; +} + +/*! Returns the properties of this characteristic. */ +QLowEnergyCharacteristic::PropertyTypes QLowEnergyCharacteristicData::properties() const +{ + return d->properties; +} + +/*! Sets the properties of this characteristic to \a properties. */ +void QLowEnergyCharacteristicData::setProperties(QLowEnergyCharacteristic::PropertyTypes properties) +{ + if ((properties & QLowEnergyCharacteristic::PropertyType::Notify) && + (properties & QLowEnergyCharacteristic::PropertyType::Indicate)) + qCWarning(QT_BT) << "Both NTF and IND properties set for characteristic" << d->uuid; + d->properties = properties; +} + +/*! Returns the descriptors of this characteristic. */ +QList QLowEnergyCharacteristicData::descriptors() const +{ + return d->descriptors; +} + +/*! + Sets the descriptors of this characteristic to \a descriptors. Only valid descriptors + are considered. + \sa addDescriptor() + */ +void QLowEnergyCharacteristicData::setDescriptors(const QList &descriptors) +{ + d->descriptors.clear(); + for (const QLowEnergyDescriptorData &desc : descriptors) + addDescriptor(desc); +} + +/*! + Adds \a descriptor to the list of descriptors of this characteristic, if it is valid. + \sa setDescriptors() + */ +void QLowEnergyCharacteristicData::addDescriptor(const QLowEnergyDescriptorData &descriptor) +{ + if (descriptor.isValid()) + d->descriptors << descriptor; + else + qCWarning(QT_BT) << "not adding invalid descriptor to characteristic"; +} + +/*! + Specifies that clients need to fulfill \a constraints to read the value of this characteristic. + */ +void QLowEnergyCharacteristicData::setReadConstraints(QBluetooth::AttAccessConstraints constraints) +{ + d->readConstraints = constraints; +} + +/*! + Returns the constraints needed for a client to read the value of this characteristic. + If \l properties() does not include \l QLowEnergyCharacteristic::Read, this value is irrelevant. + By default, there are no read constraints. + */ +QBluetooth::AttAccessConstraints QLowEnergyCharacteristicData::readConstraints() const +{ + return d->readConstraints; +} + +/*! + Specifies that clients need to fulfill \a constraints to write the value of this characteristic. + */ +void QLowEnergyCharacteristicData::setWriteConstraints(QBluetooth::AttAccessConstraints constraints) +{ + d->writeConstraints = constraints; +} + +/*! + Returns the constraints needed for a client to write the value of this characteristic. + If \l properties() does not include either of \l QLowEnergyCharacteristic::Write, + \l QLowEnergyCharacteristic::WriteNoResponse and \l QLowEnergyCharacteristic::WriteSigned, + this value is irrelevant. + By default, there are no write constraints. + */ +QBluetooth::AttAccessConstraints QLowEnergyCharacteristicData::writeConstraints() const +{ + return d->writeConstraints; +} + +/*! + Specifies \a minimum and \a maximum to be the smallest and largest length, respectively, + that the value of this characteristic can have. The unit is bytes. If \a minimum and + \a maximum are equal, the characteristic has a fixed-length value. + */ +void QLowEnergyCharacteristicData::setValueLength(int minimum, int maximum) +{ + d->minimumValueLength = minimum; + d->maximumValueLength = qMax(minimum, maximum); +} + +/*! + Returns the minimum length in bytes that the value of this characteristic can have. + The default is zero. + */ +int QLowEnergyCharacteristicData::minimumValueLength() const +{ + return d->minimumValueLength; +} + +/*! + Returns the maximum length in bytes that the value of this characteristic can have. + By default, there is no limit beyond the constraints of the data type. + */ +int QLowEnergyCharacteristicData::maximumValueLength() const +{ + return d->maximumValueLength; +} + +/*! + Returns true if and only if this characteristic is valid, that is, it has a non-null UUID. + */ +bool QLowEnergyCharacteristicData::isValid() const +{ + return !uuid().isNull(); +} + +/*! + \fn void QLowEnergyCharacteristicData::swap(QLowEnergyCharacteristicData &other) + Swaps this object with \a other. + */ + +/*! + \brief Returns \c true if \a a and \a b are equal with respect to their public state, + otherwise returns \c false. + \internal + */ +bool QLowEnergyCharacteristicData::equals(const QLowEnergyCharacteristicData &a, + const QLowEnergyCharacteristicData &b) +{ + return a.d == b.d + || (a.uuid() == b.uuid() && a.properties() == b.properties() + && a.descriptors() == b.descriptors() && a.value() == b.value() + && a.readConstraints() == b.readConstraints() + && a.writeConstraints() == b.writeConstraints() + && a.minimumValueLength() == b.maximumValueLength() + && a.maximumValueLength() == b.maximumValueLength()); +} + +/*! + \fn bool QLowEnergyCharacteristicData::operator==(const QLowEnergyCharacteristicData &a, + const QLowEnergyCharacteristicData &b) + \brief Returns \c true if \a a and \a b are equal with respect to their public state, + otherwise returns \c false. + */ + +/*! + \fn bool QLowEnergyCharacteristicData::operator!=(const QLowEnergyCharacteristicData &a, + const QLowEnergyCharacteristicData &b) + \brief Returns \c true if \a a and \a b are not equal with respect to their public state, + otherwise returns \c false. + */ + +QT_END_NAMESPACE diff --git a/src/bluetooth/qlowenergycharacteristicdata.h b/src/bluetooth/qlowenergycharacteristicdata.h new file mode 100644 index 0000000..e127fee --- /dev/null +++ b/src/bluetooth/qlowenergycharacteristicdata.h @@ -0,0 +1,69 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +#ifndef QLOWENERGYCHARACTERISTICDATA_H +#define QLOWENERGYCHARACTERISTICDATA_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QLowEnergyDescriptorData; +struct QLowEnergyCharacteristicDataPrivate; +class Q_BLUETOOTH_EXPORT QLowEnergyCharacteristicData +{ +public: + QLowEnergyCharacteristicData(); + QLowEnergyCharacteristicData(const QLowEnergyCharacteristicData &other); + ~QLowEnergyCharacteristicData(); + + QLowEnergyCharacteristicData &operator=(const QLowEnergyCharacteristicData &other); + friend bool operator==(const QLowEnergyCharacteristicData &a, + const QLowEnergyCharacteristicData &b) + { + return equals(a, b); + } + friend bool operator!=(const QLowEnergyCharacteristicData &a, + const QLowEnergyCharacteristicData &b) + { + return !equals(a, b); + } + + QBluetoothUuid uuid() const; + void setUuid(const QBluetoothUuid &uuid); + + QByteArray value() const; + void setValue(const QByteArray &value); + + QLowEnergyCharacteristic::PropertyTypes properties() const; + void setProperties(QLowEnergyCharacteristic::PropertyTypes properties); + + QList descriptors() const; + void setDescriptors(const QList &descriptors); + void addDescriptor(const QLowEnergyDescriptorData &descriptor); + + void setReadConstraints(QBluetooth::AttAccessConstraints constraints); + QBluetooth::AttAccessConstraints readConstraints() const; + + void setWriteConstraints(QBluetooth::AttAccessConstraints constraints); + QBluetooth::AttAccessConstraints writeConstraints() const; + + void setValueLength(int minimum, int maximum); + int minimumValueLength() const; + int maximumValueLength() const; + + bool isValid() const; + + void swap(QLowEnergyCharacteristicData &other) noexcept { d.swap(other.d); } + +private: + static bool equals(const QLowEnergyCharacteristicData &a, + const QLowEnergyCharacteristicData &b); + QSharedDataPointer d; +}; + +Q_DECLARE_SHARED(QLowEnergyCharacteristicData) + +QT_END_NAMESPACE + +#endif // Include guard. diff --git a/src/bluetooth/qlowenergyconnectionparameters.cpp b/src/bluetooth/qlowenergyconnectionparameters.cpp new file mode 100644 index 0000000..54eab42 --- /dev/null +++ b/src/bluetooth/qlowenergyconnectionparameters.cpp @@ -0,0 +1,212 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qlowenergyconnectionparameters.h" + +QT_BEGIN_NAMESPACE + +QT_IMPL_METATYPE_EXTERN(QLowEnergyConnectionParameters) + +class QLowEnergyConnectionParametersPrivate : public QSharedData +{ +public: + QLowEnergyConnectionParametersPrivate() + : minInterval(7.5) + , maxInterval(4000) + , latency(0) + , timeout(32000) + { + } + + double minInterval; + double maxInterval; + int latency; + int timeout; +}; + +/*! + \since 5.7 + \class QLowEnergyConnectionParameters + \brief The QLowEnergyConnectionParameters class is used when requesting or reporting + an update of the parameters of a Bluetooth LE connection. + + The connection parameters influence how often a master and a slave device synchronize + with each other. In general, a lower connection interval and latency means faster communication, + but also higher power consumption. How these criteria should be weighed against each other + is highly dependent on the concrete use case. + + Android only indirectly permits the adjustment of this parameter set. + The platform separates the connection parameters into three categories (hight, low & balanced + priority). Each category implies a predefined set of values for \l minimumInterval(), + \l maximumInterval() and \l latency(). Additionally, the value ranges of each category can vary + from one Android device to the next. Qt uses the \l minimumInterval() to determine the target + category as follows: + + \table + \header + \li minimumInterval() + \li Android priority + \row + \li interval < 30 + \li CONNECTION_PRIORITY_HIGH + \row + \li 30 <= interval <= 100 + \li CONNECTION_PRIORITY_BALANCED + \row + \li interval > 100 + \li CONNECTION_PRIORITY_LOW_POWER + \endtable + + The \l supervisionTimeout() cannot be changed on Android and is therefore ignored. + + + \inmodule QtBluetooth + \ingroup shared + + \sa QLowEnergyController::requestConnectionUpdate + \sa QLowEnergyController::connectionUpdated +*/ + + +/*! + Constructs a new object of this class. All values are initialized to valid defaults. + */ +QLowEnergyConnectionParameters::QLowEnergyConnectionParameters() + : d(new QLowEnergyConnectionParametersPrivate) +{ +} + +/*! Constructs a new object of this class that is a copy of \a other. */ +QLowEnergyConnectionParameters::QLowEnergyConnectionParameters(const QLowEnergyConnectionParameters &other) + : d(other.d) +{ +} + +/*! Destroys this object. */ +QLowEnergyConnectionParameters::~QLowEnergyConnectionParameters() +{ +} + +/*! Makes this object a copy of \a other and returns the new value of this object. */ +QLowEnergyConnectionParameters &QLowEnergyConnectionParameters::operator=(const QLowEnergyConnectionParameters &other) +{ + d = other.d; + return *this; +} + +/*! + Sets the range in which the connection interval should be. The actual value will be decided by + the controller. Both \a minimum and \a maximum are given in milliseconds. + If \a maximum is smaller than \a minimum, it will be set to the value of \a minimum. + The smallest possible connection interval is 7.5 milliseconds, the largest one is + 4000 milliseconds. + \sa minimumInterval(), maximumInterval() + */ +void QLowEnergyConnectionParameters::setIntervalRange(double minimum, double maximum) +{ + d->minInterval = minimum; + d->maxInterval = qMax(minimum, maximum); +} + +/*! + Returns the minimum connection interval in milliseconds. The default is 7.5. + \note If this object was emitted via \l QLowEnergyController::connectionUpdated(), then + this value is the same as \l maximumInterval() and refers to the actual + connection interval. + \sa setIntervalRange() + */ +double QLowEnergyConnectionParameters::minimumInterval() const +{ + return d->minInterval; +} + +/*! + Returns the maximum connection interval in milliseconds. The default is 4000. + \note If this object was emitted via \l QLowEnergyController::connectionUpdated(), then + this value is the same as \l minimumInterval() and refers to the actual + connection interval. + \sa setIntervalRange() + */ +double QLowEnergyConnectionParameters::maximumInterval() const +{ + return d->maxInterval; +} + +/*! + Sets the slave latency of the connection (that is, the number of connection events that a slave + device is allowed to ignore) to \a latency. The minimum value is 0, the maximum is 499. + \sa latency() + */ +void QLowEnergyConnectionParameters::setLatency(int latency) +{ + d->latency = latency; +} + +/*! + Returns the slave latency of the connection. + \sa setLatency() +*/ +int QLowEnergyConnectionParameters::latency() const +{ + return d->latency; +} + +/*! + Sets the link supervision timeout to \a timeout milliseconds. + There are several constraints on this value: It must be in the range [100,32000] and it must be + larger than (1 + \l latency()) * 2 * \l maximumInterval(). + + On Android, this timeout is not adjustable and therefore ignored. + + \sa supervisionTimeout() + */ +void QLowEnergyConnectionParameters::setSupervisionTimeout(int timeout) +{ + d->timeout = timeout; +} + +/*! + Returns the link supervision timeout of the connection in milliseconds. + \sa setSupervisionTimeout() +*/ +int QLowEnergyConnectionParameters::supervisionTimeout() const +{ + return d->timeout; +} + +/*! + \fn void QLowEnergyConnectionParameters::swap(QLowEnergyConnectionParameters &other) + Swaps this object with \a other. + */ + +/*! + \brief Returns \a true if \a a and \a b are equal with respect to their public state, + otherwise returns false. + \internal + */ +bool QLowEnergyConnectionParameters::equals(const QLowEnergyConnectionParameters &a, + const QLowEnergyConnectionParameters &b) +{ + if (a.d == b.d) + return true; + return a.minimumInterval() == b.minimumInterval() && a.maximumInterval() == b.maximumInterval() + && a.latency() == b.latency() && a.supervisionTimeout() == b.supervisionTimeout(); +} + +/*! + \fn bool QLowEnergyConnectionParameters::operator!=( + const QLowEnergyConnectionParameters &p1, + const QLowEnergyConnectionParameters &p2) + \brief Returns \c true if \a p1 and \a p2 are not equal with respect to their public state, + otherwise returns \c false. + */ + +/*! + \fn bool QLowEnergyConnectionParameters::operator==( + const QLowEnergyConnectionParameters &p1, + const QLowEnergyConnectionParameters &p2) + \brief Returns \c true if \a p1 and \a p2 are equal with respect to their public state, + otherwise returns \c false. + */ + +QT_END_NAMESPACE diff --git a/src/bluetooth/qlowenergyconnectionparameters.h b/src/bluetooth/qlowenergyconnectionparameters.h new file mode 100644 index 0000000..8a30e82 --- /dev/null +++ b/src/bluetooth/qlowenergyconnectionparameters.h @@ -0,0 +1,58 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QLOWENERGYCONNECTIONPARAMETERS_H +#define QLOWENERGYCONNECTIONPARAMETERS_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QLowEnergyConnectionParametersPrivate; + +class Q_BLUETOOTH_EXPORT QLowEnergyConnectionParameters +{ +public: + QLowEnergyConnectionParameters(); + QLowEnergyConnectionParameters(const QLowEnergyConnectionParameters &other); + ~QLowEnergyConnectionParameters(); + + QLowEnergyConnectionParameters &operator=(const QLowEnergyConnectionParameters &other); + friend bool operator==(const QLowEnergyConnectionParameters &a, + const QLowEnergyConnectionParameters &b) + { + return equals(a, b); + } + friend bool operator!=(const QLowEnergyConnectionParameters &a, + const QLowEnergyConnectionParameters &b) + { + return !equals(a, b); + } + + void setIntervalRange(double minimum, double maximum); + double minimumInterval() const; + double maximumInterval() const; + + void setLatency(int latency); + int latency() const; + + void setSupervisionTimeout(int timeout); + int supervisionTimeout() const; + + void swap(QLowEnergyConnectionParameters &other) noexcept { d.swap(other.d); } + +private: + static bool equals(const QLowEnergyConnectionParameters &a, + const QLowEnergyConnectionParameters &b); + QSharedDataPointer d; +}; + +Q_DECLARE_SHARED(QLowEnergyConnectionParameters) + +QT_END_NAMESPACE + +QT_DECL_METATYPE_EXTERN(QLowEnergyConnectionParameters, Q_BLUETOOTH_EXPORT) + +#endif // Include guard diff --git a/src/bluetooth/qlowenergycontroller.cpp b/src/bluetooth/qlowenergycontroller.cpp new file mode 100644 index 0000000..ec23f73 --- /dev/null +++ b/src/bluetooth/qlowenergycontroller.cpp @@ -0,0 +1,983 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qlowenergycontroller.h" + +#include "qlowenergycharacteristicdata.h" +#include "qlowenergyconnectionparameters.h" +#include "qlowenergydescriptordata.h" +#include "qlowenergyservicedata.h" + +#include +#include + + +#if QT_CONFIG(bluez) && !defined(QT_BLUEZ_NO_BTLE) +#include "bluez/bluez5_helper_p.h" +#include "qlowenergycontroller_bluezdbus_p.h" +#include "qlowenergycontroller_bluez_p.h" +#elif defined(QT_ANDROID_BLUETOOTH) +#include "qlowenergycontroller_android_p.h" +#include "android/androidutils_p.h" +#elif defined(QT_WINRT_BLUETOOTH) +#include "qtbluetoothglobal_p.h" +#include "qlowenergycontroller_winrt_p.h" +#elif defined(Q_OS_DARWIN) +#include "qlowenergycontroller_darwin_p.h" +#else +#include "qlowenergycontroller_dummy_p.h" +#endif + +#include + +QT_BEGIN_NAMESPACE + +QT_IMPL_METATYPE_EXTERN_TAGGED(QLowEnergyController::Error, QLowEnergyController__Error) +QT_IMPL_METATYPE_EXTERN_TAGGED(QLowEnergyController::ControllerState, + QLowEnergyController__ControllerState) +QT_IMPL_METATYPE_EXTERN_TAGGED(QLowEnergyController::RemoteAddressType, + QLowEnergyController__RemoteAddressType) +QT_IMPL_METATYPE_EXTERN_TAGGED(QLowEnergyController::Role, QLowEnergyController__Role) + +Q_DECLARE_LOGGING_CATEGORY(QT_BT) +#if defined(QT_ANDROID_BLUETOOTH) +Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID) +#endif + +/*! + \class QLowEnergyController + \inmodule QtBluetooth + \brief The QLowEnergyController class provides access to Bluetooth + Low Energy Devices. + + \since 5.4 + + QLowEnergyController acts as the entry point for Bluetooth Low Energy + development. + + Bluetooth Low Energy defines two types of devices; the peripheral and + the central. Each role performs a different task. The peripheral device + provides data which is utilized by central devices. An example might be a + humidity sensor which measures the moisture in a winter garden. A device + such as a mobile phone might read the sensor's value and display it to the user + in the greater context of all sensors in the same environment. In this case + the sensor is the peripheral device and the mobile phone acts as the + central device. + + A controller in the central role is created via the \l createCentral() factory method. + Such an object essentially acts as a placeholder towards a remote Low Energy peripheral + device, enabling features such as service discovery and state tracking. + + After having created a controller object in the central role, the first step is to establish + a connection via \l connectToDevice(). + Once the connection has been established, the controller's \l state() + changes to \l QLowEnergyController::ConnectedState and the \l connected() + signal is emitted. It is important to mention that some platforms such as + a BlueZ based Linux cannot maintain two connected instances of + \l QLowEnergyController to the same remote device. In such cases the second + call to \l connectToDevice() may fail. This limitation may disappear at some + stage in the future. The \l disconnectFromDevice() function is used to break + the existing connection. + + The second step after establishing the connection is to discover the services + offered by the remote peripheral device. This process is started via + \l discoverServices() and has finished once the \l discoveryFinished() signal + has been emitted. The discovered services can be enumerated via + \l services(). + + The last step is to create service objects. The \l createServiceObject() + function acts as factory for each service object and expects the service + UUID as parameter. The calling context should take ownership of the returned + \l QLowEnergyService instance. + + Any \l QLowEnergyService, \l QLowEnergyCharacteristic or + \l QLowEnergyDescriptor instance which is later created from this controller's + connection becomes invalid as soon as the controller disconnects from the + remote Bluetooth Low Energy device. + + A controller in the peripheral role is created via the \l createPeripheral() factory method. + Such an object acts as a peripheral device itself, enabling features such as advertising + services and allowing clients to get notified about changes to characteristic values. + + After having created a controller object in the peripheral role, the first step is to + populate the set of GATT services offered to client devices via calls to \l addService(). + Afterwards, one would call \l startAdvertising() to let the device broadcast some data + and, depending on the type of advertising being done, also listen for incoming connections + from GATT clients. + + \sa QLowEnergyService, QLowEnergyCharacteristic, QLowEnergyDescriptor + \sa QLowEnergyAdvertisingParameters, QLowEnergyAdvertisingData +*/ + +/*! + \enum QLowEnergyController::Error + + Indicates all possible error conditions found during the controller's + existence. + + \value NoError No error has occurred. + \value UnknownError An unknown error has occurred. + \value UnknownRemoteDeviceError The remote Bluetooth Low Energy device with the address passed to + the constructor of this class cannot be found. + \value NetworkError The attempt to read from or write to the + remote device failed. + \value InvalidBluetoothAdapterError The local Bluetooth device with the address passed to + the constructor of this class cannot be found or + there is no local Bluetooth device. + \value [since 5.5] ConnectionError The attempt to connect to the remote device failed. + \value [since 5.7] AdvertisingError The attempt to start advertising failed. + \value [since 5.10] RemoteHostClosedError The remote device closed the connection. + \value [since 5.14] AuthorizationError The local Bluetooth device closed the connection + due to insufficient authorization. + \value [since 6.4] MissingPermissionsError The operating system requests + permissions which were not + granted by the user. + \value [since 6.5] RssiReadError An attempt to read RSSI (received signal strength indicator) + of a remote device finished with error. +*/ + +/*! + \enum QLowEnergyController::ControllerState + + Indicates the state of the controller object. + + \value UnconnectedState The controller is not connected to a remote device. + \value ConnectingState The controller is attempting to connect to a remote device. + \value ConnectedState The controller is connected to a remote device. + \value DiscoveringState The controller is retrieving the list of services offered + by the remote device. + \value DiscoveredState The controller has discovered all services offered by the + remote device. + \value ClosingState The controller is about to be disconnected from the remote device. + \value [since 5.7] AdvertisingState The controller is currently advertising data. +*/ + +/*! + \enum QLowEnergyController::RemoteAddressType + + Indicates what type of Bluetooth address the remote device uses. + + \value PublicAddress The remote device uses a public Bluetooth address. + \value RandomAddress A random address is a Bluetooth Low Energy security feature. + Peripherals using such addresses may frequently change their + Bluetooth address. This information is needed when trying to + connect to a peripheral. + */ + +/*! + \enum QLowEnergyController::Role + + Indicates the role of the controller object. + + \value CentralRole + The controller acts as a client interacting with a remote device which is in the peripheral + role. The controller can initiate connections, discover services and + read and write characteristics. + \value PeripheralRole + The controller can be used to advertise services and handle incoming + connections and client requests, acting as a GATT server. A remote device connected to + the controller is in the central role. + + \sa QLowEnergyController::createCentral() + \sa QLowEnergyController::createPeripheral() + \since 5.7 + \note The peripheral role is not supported on Windows. In addition on Linux, handling the + "Signed Write" ATT command on the server side requires BlueZ 5 and kernel version 3.7 + or newer. + */ + + +/*! + \fn void QLowEnergyController::connected() + + This signal is emitted when the controller successfully connects to the remote + Low Energy device (if the controller is in the \l CentralRole) or if a remote Low Energy + device connected to the controller (if the controller is in the \l PeripheralRole). + On iOS, macOS, and Android this signal is not reliable if the controller is in the + \l PeripheralRole. On iOS and macOS the controller only guesses that some central + connected to our peripheral as soon as this central tries to write/read a + characteristic/descriptor. On Android the controller monitors all connected GATT + devices. On Linux BlueZ DBus peripheral backend the remote is considered connected + when it first reads/writes a characteristic or a descriptor. +*/ + +/*! + \fn void QLowEnergyController::mtuChanged(int mtu) + + This signal is emitted as a result of a successful MTU change. \a mtu + represents the new value. + + \note If the controller is in the \l PeripheralRole, the MTU value is negotiated + for each client/central device individually. Therefore this signal can be emitted + several times in a row for one or several devices. + + \sa mtu() +*/ + +/*! + \fn void QLowEnergyController::rssiRead(qint16 rssi) + + This signal is emitted after successful read of RSSI (received + signal strength indicator) for a connected remote device. + \a rssi parameter represents the new value. + + \sa readRssi() + \since 6.5 +*/ + +/*! + \fn void QLowEnergyController::disconnected() + + This signal is emitted when the controller disconnects from the remote + Low Energy device or vice versa. On iOS and macOS this signal is unreliable + if the controller is in the \l PeripheralRole. On Android the signal is emitted + when the last connected device is disconnected. On BlueZ DBus backend the controller + is considered disconnected when last client which has accessed the attributes has + disconnected. +*/ + +/*! + \fn void QLowEnergyController::stateChanged(ControllerState state) + + This signal is emitted when the controller's state changes. The new + \a state can also be retrieved via \l state(). + + \sa state() +*/ + +/*! + \fn void QLowEnergyController::errorOccurred(QLowEnergyController::Error newError) + + This signal is emitted when an error occurs. + The \a newError parameter describes the error that occurred. + + \sa error(), errorString() + \since 6.2 +*/ + +/*! + \fn void QLowEnergyController::serviceDiscovered(const QBluetoothUuid &newService) + + This signal is emitted each time a new service is discovered. The + \a newService parameter contains the UUID of the found service. + + This signal can only be emitted if the controller is in the \c CentralRole. + + \sa discoverServices(), discoveryFinished() +*/ + +/*! + \fn void QLowEnergyController::discoveryFinished() + + This signal is emitted when the running service discovery finishes. + The signal is not emitted if the discovery process finishes with + an error. + + This signal can only be emitted if the controller is in the \l CentralRole. + + \sa discoverServices(), error() +*/ + +/*! + \fn void QLowEnergyController::connectionUpdated(const QLowEnergyConnectionParameters &newParameters) + + This signal is emitted when the connection parameters change. This can happen as a result + of calling \l requestConnectionUpdate() or due to other reasons, for instance because + the other side of the connection requested new parameters. The new values can be retrieved + from \a newParameters. + + \since 5.7 + \sa requestConnectionUpdate() +*/ + + +void registerQLowEnergyControllerMetaType() +{ + static bool initDone = false; + if (!initDone) { + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + initDone = true; + } +} + +static QLowEnergyControllerPrivate *privateController( + QLowEnergyController::Role role, + const QBluetoothAddress& localDevice = QBluetoothAddress{}) +{ +#if QT_CONFIG(bluez) && !defined(QT_BLUEZ_NO_BTLE) + // Central role + // The minimum Bluez DBus version for central role is 5.42, otherwise we + // fall back to kernel ATT backend. Application can also force the choice + // with an environment variable (see bluetoothdVersion()) + // + // Peripheral role + // The DBus peripheral backend is the default, and for that we check the presence of + // the required DBus APIs and bluez version. The application may opt-out of the DBus + // peripheral role by setting the environment variable. The fall-back is the kernel ATT + // backend + // + // ### Qt 7 consider removing the non-dbus bluez (kernel ATT) support + + QString adapterPathWithPeripheralSupport; + if (role == QLowEnergyController::PeripheralRole + && bluetoothdVersion() >= QVersionNumber(5, 56) + && !qEnvironmentVariableIsSet("QT_BLUETOOTH_USE_KERNEL_PERIPHERAL")) { + adapterPathWithPeripheralSupport = adapterWithDBusPeripheralInterface(localDevice); + } + + if (role == QLowEnergyController::CentralRole + && bluetoothdVersion() >= QVersionNumber(5, 42)) { + qCDebug(QT_BT) << "Using BlueZ LE DBus API for central"; + return new QLowEnergyControllerPrivateBluezDBus(); + } else if (!adapterPathWithPeripheralSupport.isEmpty()) { + qCDebug(QT_BT) << "Using BlueZ LE DBus API for peripheral"; + return new QLowEnergyControllerPrivateBluezDBus(adapterPathWithPeripheralSupport); + } else { + qCDebug(QT_BT) << "Using BlueZ kernel ATT interface for" + << (role == QLowEnergyController::CentralRole ? "central" : "peripheral"); + return new QLowEnergyControllerPrivateBluez(); + } +#elif defined(QT_ANDROID_BLUETOOTH) + Q_UNUSED(role); + Q_UNUSED(localDevice); + return new QLowEnergyControllerPrivateAndroid(); +#elif defined(QT_WINRT_BLUETOOTH) + Q_UNUSED(role); + Q_UNUSED(localDevice); + return new QLowEnergyControllerPrivateWinRT(); +#elif defined(Q_OS_DARWIN) + Q_UNUSED(role); + Q_UNUSED(localDevice); + return new QLowEnergyControllerPrivateDarwin(); +#else + Q_UNUSED(role); + Q_UNUSED(localDevice); + return new QLowEnergyControllerPrivateCommon(); +#endif +} + +/*! + Constructs a new instance of this class with \a parent. + + The \a remoteDevice must contain the address of the + remote Bluetooth Low Energy device to which this object + should attempt to connect later on. + + The connection is established via \a localDevice. If \a localDevice + is invalid, the local default device is automatically selected. If + \a localDevice specifies a local device that is not a local Bluetooth + adapter, \l error() is set to \l InvalidBluetoothAdapterError once + \l connectToDevice() is called. + + \note This is only supported on BlueZ + */ +QLowEnergyController::QLowEnergyController( + const QBluetoothDeviceInfo &remoteDevice, + const QBluetoothAddress &localDevice, + QObject *parent) + : QObject(parent) +{ + d_ptr = privateController(CentralRole); + + Q_D(QLowEnergyController); + d->q_ptr = this; + d->role = CentralRole; + d->deviceUuid = remoteDevice.deviceUuid(); + d->remoteDevice = remoteDevice.address(); + + if (localDevice.isNull()) + d->localAdapter = QBluetoothLocalDevice().address(); + else + d->localAdapter = localDevice; + + d->addressType = QLowEnergyController::PublicAddress; + d->remoteName = remoteDevice.name(); + d->init(); +} + +/*! + Returns a new object of this class that is in the \l CentralRole and has the + parent object \a parent. + The \a remoteDevice refers to the device that a connection will be established to later. + + The controller uses the local default Bluetooth adapter for the connection management. + + \sa QLowEnergyController::CentralRole + \since 5.7 + */ +QLowEnergyController *QLowEnergyController::createCentral(const QBluetoothDeviceInfo &remoteDevice, + QObject *parent) +{ + return new QLowEnergyController(remoteDevice, QBluetoothAddress(), parent); +} + +/*! + Returns a new instance of this class with \a parent. + + The \a remoteDevice must contain the address of the remote Bluetooth Low + Energy device to which this object should attempt to connect later on. + + The connection is established via \a localDevice. If \a localDevice is invalid, + the local default device is automatically selected. If \a localDevice specifies + a local device that is not a local Bluetooth adapter, \l error() is set to + \l InvalidBluetoothAdapterError once \l connectToDevice() is called. + + Note that specifying the local device to be used for the connection is only + possible when using BlueZ. All other platforms do not support this feature. + + \since 5.14 + */ +QLowEnergyController *QLowEnergyController::createCentral(const QBluetoothDeviceInfo &remoteDevice, + const QBluetoothAddress &localDevice, + QObject *parent) +{ + return new QLowEnergyController(remoteDevice, localDevice, parent); +} + + +/*! + Returns a new object of this class that is in the \l PeripheralRole and has the + parent object \a parent. + Typically, the next steps are to add some services and finally + call \l startAdvertising() on the returned object. + + The controller uses the local default Bluetooth adapter for the connection management. + + \sa QLowEnergyController::PeripheralRole + \since 5.7 + */ +QLowEnergyController *QLowEnergyController::createPeripheral(QObject *parent) +{ + return new QLowEnergyController(QBluetoothAddress(), parent); +} + +/*! + Returns a new object of this class that is in the \l PeripheralRole and has the + parent object \a parent and is using \a localDevice. + Typically, the next steps are to add some services and finally + call \l startAdvertising() on the returned object. + + The peripheral is created on \a localDevice. If \a localDevice is invalid, + the local default device is automatically selected. If \a localDevice specifies + a local device that is not a local Bluetooth adapter, \l error() is set to + \l InvalidBluetoothAdapterError. + + Selecting \a localDevice is only supported on Linux. On other platform, + the parameter is ignored. + + \sa QLowEnergyController::PeripheralRole + \since 6.2 + */ +QLowEnergyController *QLowEnergyController::createPeripheral(const QBluetoothAddress &localDevice, + QObject *parent) +{ + return new QLowEnergyController(localDevice, parent); +} + +QLowEnergyController::QLowEnergyController(const QBluetoothAddress &localDevice, QObject *parent) + : QObject(parent) +{ + d_ptr = privateController(PeripheralRole, localDevice); + + Q_D(QLowEnergyController); + d->q_ptr = this; + d->role = PeripheralRole; + + if (localDevice.isNull()) + d->localAdapter = QBluetoothLocalDevice().address(); + else + d->localAdapter = localDevice; + + d->init(); +} + +/*! + Destroys the QLowEnergyController instance. + */ +QLowEnergyController::~QLowEnergyController() +{ + disconnectFromDevice(); //in case we were connected + delete d_ptr; +} + +/*! + Returns the address of the local Bluetooth adapter being used for the + communication. + + If this class instance was requested to use the default adapter + but there was no default adapter when creating this + class instance, the returned \l QBluetoothAddress will be null. + + \sa QBluetoothAddress::isNull() + */ +QBluetoothAddress QLowEnergyController::localAddress() const +{ + return d_ptr->localAdapter; +} + +/*! + Returns the address of the remote Bluetooth Low Energy device. + + For a controller in the \l CentralRole, this value will always be the one passed in when + the controller object was created. For a controller in the \l PeripheralRole, this value + is one of the currently connected client device addresses. This address will + be invalid if the controller is not currently in the \l ConnectedState. + */ +QBluetoothAddress QLowEnergyController::remoteAddress() const +{ + return d_ptr->remoteDevice; +} + +/*! + Returns the unique identifier of the remote Bluetooth Low Energy device. + + On macOS/iOS/tvOS CoreBluetooth does not expose/accept hardware addresses for + LE devices; instead developers are supposed to use unique 128-bit UUIDs, generated + by CoreBluetooth. These UUIDS will stay constant for the same central <-> peripheral + pair and we use them when connecting to a remote device. For a controller in the + \l CentralRole, this value will always be the one passed in when the controller + object was created. For a controller in the \l PeripheralRole, this value is invalid. + + \since 5.8 + */ +QBluetoothUuid QLowEnergyController::remoteDeviceUuid() const +{ + return d_ptr->deviceUuid; +} + +/*! + Returns the name of the remote Bluetooth Low Energy device, if the controller is in the + \l CentralRole. Otherwise the result is unspecified. + + \since 5.5 + */ +QString QLowEnergyController::remoteName() const +{ + return d_ptr->remoteName; +} + +/*! + Returns the current state of the controller. + + \sa stateChanged() + */ +QLowEnergyController::ControllerState QLowEnergyController::state() const +{ + return d_ptr->state; +} + +/*! + Returns the type of \l remoteAddress(). By default, this value is initialized + to \l PublicAddress. + + \sa setRemoteAddressType() + */ +QLowEnergyController::RemoteAddressType QLowEnergyController::remoteAddressType() const +{ + return d_ptr->addressType; +} + +/*! + Sets the remote address \a type. The type is required to connect + to the remote Bluetooth Low Energy device. + + This attribute is only required to be set on Linux/BlueZ systems with older + Linux kernels (v3.3 or lower), or if CAP_NET_ADMIN is not set for the executable. + The default value of the attribute is \l RandomAddress. + + \note All other platforms handle this flag transparently and therefore applications + can ignore it entirely. On Linux, the address type flag is not directly exposed + by BlueZ although some use cases do require this information. The only way to detect + the flag is via the Linux kernel's Bluetooth Management API (kernel + version 3.4+ required). This API requires CAP_NET_ADMIN capabilities though. If the + local QtBluetooth process has this capability set QtBluetooth will use the API. This + assumes that \l QBluetoothDeviceDiscoveryAgent was used prior to calling + \l QLowEnergyController::connectToDevice(). + */ +void QLowEnergyController::setRemoteAddressType( + QLowEnergyController::RemoteAddressType type) +{ + d_ptr->addressType = type; +} + +/*! + Connects to the remote Bluetooth Low Energy device. + + This function does nothing if the controller's \l state() + is not equal to \l UnconnectedState. The \l connected() signal is emitted + once the connection is successfully established. + + On Linux/BlueZ systems, it is not possible to connect to the same + remote device using two instances of this class. The second call + to this function may fail with an error. This limitation may + be removed in future releases. + + \sa disconnectFromDevice() + */ +void QLowEnergyController::connectToDevice() +{ + Q_D(QLowEnergyController); + + if (role() != CentralRole) { + qCWarning(QT_BT) << "Connection can only be established while in central role"; + return; + } + + if (!d->isValidLocalAdapter()) { + qCWarning(QT_BT) << "connectToDevice() LE controller has invalid adapter"; + d->setError(QLowEnergyController::InvalidBluetoothAdapterError); + return; + } + + if (state() != QLowEnergyController::UnconnectedState) + return; + + d->connectToDevice(); +} + +/*! + Disconnects from the remote device. + + Any \l QLowEnergyService, \l QLowEnergyCharacteristic or \l QLowEnergyDescriptor + instance that resulted from the current connection is automatically invalidated. + Once any of those objects become invalid they remain invalid even if this + controller object reconnects. + + This function does nothing if the controller is in the \l UnconnectedState. + + If the controller is in the peripheral role, it stops advertising and removes + all services which have previously been added via \l addService(). + To reuse the QLowEnergyController instance the application must re-add services + and restart the advertising mode by calling \l startAdvertising(). + + \sa connectToDevice() + */ +void QLowEnergyController::disconnectFromDevice() +{ + Q_D(QLowEnergyController); + + if (state() == QLowEnergyController::UnconnectedState) + return; + + d->invalidateServices(); + d->disconnectFromDevice(); +} + +/*! + Initiates the service discovery process. + + The discovery progress is indicated via the \l serviceDiscovered() signal. + The \l discoveryFinished() signal is emitted when the process has finished. + + If the controller instance is not connected or the controller has performed + the service discovery already this function will do nothing. + + \note Some platforms internally cache the service list of a device + which was discovered in the past. This can be problematic if the remote device + changed its list of services or their inclusion tree. If this behavior is a + problem, the best workaround is to temporarily turn Bluetooth off. This + causes a reset of the cache data. Currently Android exhibits such a + cache behavior. + */ +void QLowEnergyController::discoverServices() +{ + Q_D(QLowEnergyController); + + if (d->role != CentralRole) { + qCWarning(QT_BT) << "Cannot discover services in peripheral role"; + return; + } + if (d->state != QLowEnergyController::ConnectedState) + return; + + d->setState(QLowEnergyController::DiscoveringState); + d->discoverServices(); +} + +/*! + Returns the list of services offered by the remote device, if the controller is in + the \l CentralRole. Otherwise, the result is unspecified. + + The list contains all primary and secondary services. + + \sa createServiceObject() + */ +QList QLowEnergyController::services() const +{ + return d_ptr->serviceList.keys(); +} + +/*! + Creates an instance of the service represented by \a serviceUuid. + The \a serviceUuid parameter must have been obtained via + \l services(). + + The caller takes ownership of the returned pointer and may pass + a \a parent parameter as default owner. + + This function returns a null pointer if no service with + \a serviceUuid can be found on the remote device or the controller + is disconnected. + + This function can return instances for secondary services + too. The include relationships between services can be expressed + via \l QLowEnergyService::includedServices(). + + If this function is called multiple times using the same service UUID, + the returned \l QLowEnergyService instances share their internal + data. Therefore if one of the instances initiates the discovery + of the service details, the other instances automatically + transition into the discovery state too. + + \sa services() + */ +QLowEnergyService *QLowEnergyController::createServiceObject( + const QBluetoothUuid &serviceUuid, QObject *parent) +{ + Q_D(QLowEnergyController); + + QLowEnergyService *service = nullptr; + + ServiceDataMap::const_iterator it = d->serviceList.constFind(serviceUuid); + if (it != d->serviceList.constEnd()) { + const QSharedPointer &serviceData = it.value(); + + service = new QLowEnergyService(serviceData, parent); + } + + return service; +} + +/*! + Starts advertising the data given in \a advertisingData and \a scanResponseData, using + the parameters set in \a parameters. The controller has to be in the \l PeripheralRole. + If \a parameters indicates that the advertisement should be connectable, then this function + also starts listening for incoming client connections. + + Providing \a scanResponseData is not required, as it is not applicable for certain + configurations of \c parameters. \a advertisingData and \a scanResponseData are limited + to 31 byte user data. If, for example, several 128bit uuids are added to \a advertisingData, + the advertised packets may not contain all uuids. The existing limit may have caused the truncation + of uuids. In such cases \a scanResponseData may be used for additional information. + + On BlueZ DBus backend BlueZ decides if, and which data, to use in a scan response. Therefore + all advertisement data is recommended to set in the main \a advertisingData parameter. If both + advertisement and scan response data is set, the scan response data is given precedence. + + If this object is currently not in the \l UnconnectedState, nothing happens. + + \since 5.7 + \sa stopAdvertising() + */ +void QLowEnergyController::startAdvertising(const QLowEnergyAdvertisingParameters ¶meters, + const QLowEnergyAdvertisingData &advertisingData, + const QLowEnergyAdvertisingData &scanResponseData) +{ + Q_D(QLowEnergyController); + if (role() != PeripheralRole) { + qCWarning(QT_BT) << "Cannot start advertising in central role" << state(); + return; + } + if (state() != UnconnectedState) { + qCWarning(QT_BT) << "Cannot start advertising in state" << state(); + return; + } + d->startAdvertising(parameters, advertisingData, scanResponseData); +} + +/*! + Stops advertising, if this object is currently in the advertising state. + + The controller has to be in the \l PeripheralRole for this function to work. + It does not invalidate services which have previously been added via \l addService(). + + \since 5.7 + \sa startAdvertising() + */ +void QLowEnergyController::stopAdvertising() +{ + Q_D(QLowEnergyController); + if (state() != AdvertisingState) { + qCDebug(QT_BT) << "stopAdvertising called in state" << state(); + return; + } + d->stopAdvertising(); +} + +/*! + Constructs and returns a \l QLowEnergyService object with \a parent from \a service. + The controller must be in the \l PeripheralRole and in the \l UnconnectedState. The \a service + object must be valid. + + \note Once the peripheral instance is disconnected from the remote central device or + if \l disconnectFromDevice() is manually called, every service definition that was + previously added via this function is removed from the peripheral. Therefore this function + must be called again before re-advertising this peripheral controller instance. The described + behavior is connection specific and therefore not dependent on whether \l stopAdvertising() + was called. + + \since 5.7 + \sa stopAdvertising(), disconnectFromDevice(), QLowEnergyServiceData::addIncludedService + */ +QLowEnergyService *QLowEnergyController::addService(const QLowEnergyServiceData &service, + QObject *parent) +{ + if (role() != PeripheralRole) { + qCWarning(QT_BT) << "Services can only be added in the peripheral role"; + return nullptr; + } + if (state() != UnconnectedState) { + qCWarning(QT_BT) << "Services can only be added in unconnected state"; + return nullptr; + } + if (!service.isValid()) { + qCWarning(QT_BT) << "Not adding invalid service"; + return nullptr; + } + +#if defined(QT_ANDROID_BLUETOOTH) + if (!ensureAndroidPermission(QBluetoothPermission::Access)) { + qCWarning(QT_BT_ANDROID) << "addService() failed due to missing permissions"; + return nullptr; + } +#endif + + Q_D(QLowEnergyController); + QLowEnergyService *newService = d->addServiceHelper(service); + if (newService) + newService->setParent(parent); + + return newService; +} + + +/*! + Requests the controller to update the connection according to \a parameters. + If the request is successful, the \l connectionUpdated() signal will be emitted + with the actual new parameters. See the \l QLowEnergyConnectionParameters class for more + information on connection parameters. + + Android only indirectly permits the adjustment of this parameter set. + The connection parameters are separated into three categories (high, low & balanced priority). + Each category implies a pre-configured set of values for + \l QLowEnergyConnectionParameters::minimumInterval(), + \l QLowEnergyConnectionParameters::maximumInterval() and + \l QLowEnergyConnectionParameters::latency(). Although the connection request is an asynchronous + operation, Android does not provide a callback stating the result of the request. This is + an acknowledged Android bug. Due to this bug Android does not emit the \l connectionUpdated() + signal. + + \note Currently, this functionality is only implemented on Linux kernel backend and Android. + + \sa connectionUpdated() + \since 5.7 + */ +void QLowEnergyController::requestConnectionUpdate(const QLowEnergyConnectionParameters ¶meters) +{ + switch (state()) { + case ConnectedState: + case DiscoveredState: + case DiscoveringState: + d_ptr->requestConnectionUpdate(parameters); + break; + default: + qCWarning(QT_BT) << "Connection update request only possible in connected state"; + } +} + +/*! + Returns the last occurred error or \l NoError. +*/ +QLowEnergyController::Error QLowEnergyController::error() const +{ + return d_ptr->error; +} + +/*! + Returns a textual representation of the last occurred error. + The string is translated. +*/ +QString QLowEnergyController::errorString() const +{ + return d_ptr->errorString; +} + +/*! + Returns the role that this controller object is in. + + The role is determined when constructing a QLowEnergyController instance + using \l createCentral() or \l createPeripheral(). + + \since 5.7 + */ +QLowEnergyController::Role QLowEnergyController::role() const +{ + return d_ptr->role; +} + +/*! + Returns the MTU size. + + During connection setup, the ATT MTU size is negotiated. + This method provides the result of this negotiation. + It can be used to optimize packet sizes in some situations. + The maximum amount of data which can be transferred in a single + packet is \b {mtu-3} bytes. 3 bytes are required for the ATT + protocol header. + + Before the connection setup and MTU negotiation, the + default value of \c 23 will be returned. + + Not every platform exposes the MTU value. On those platforms (e.g. Linux) + this function always returns \c -1. + + If the controller is in the \l PeripheralRole, there might be several + central devices connected to it. In those cases this function returns + the MTU of the last connection that was negotiated. + + \since 6.2 + */ +int QLowEnergyController::mtu() const +{ + return d_ptr->mtu(); +} + +/*! + readRssi() reads RSSI (received signal strength indicator) for a connected remote device. + If the read was successful, the RSSI is then reported by rssiRead() signal. + + \note Prior to calling readRssi(), this controller must be connected to a peripheral. + This controller must be created using createCentral(). + + \note In case Bluetooth backend you are using does not support reading RSSI, + the errorOccurred() signal is emitted with an error code QLowEnergyController::RssiReadError. + At the moment platforms supporting reading RSSI include Android, iOS and macOS. + + \sa rssiRead(), connectToDevice(), state(), createCentral(), errorOccurred() + \since 6.5 +*/ +void QLowEnergyController::readRssi() +{ + if (role() != CentralRole) { + qCWarning(QT_BT, "Invalid role (peripheral), cannot read RSSI"); + return d_ptr->setError(RssiReadError); // This also emits. + } + + switch (state()) { + case UnconnectedState: + case ConnectingState: + case ClosingState: + qCWarning(QT_BT, "Cannot read RSSI while not in 'Connected' state, connect first"); + return d_ptr->setError(RssiReadError); // Will emit. + default: + d_ptr->readRssi(); + } +} + +QT_END_NAMESPACE + +#include "moc_qlowenergycontroller.cpp" diff --git a/src/bluetooth/qlowenergycontroller.h b/src/bluetooth/qlowenergycontroller.h new file mode 100644 index 0000000..0a42d9a --- /dev/null +++ b/src/bluetooth/qlowenergycontroller.h @@ -0,0 +1,149 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QLOWENERGYCONTROLLER_H +#define QLOWENERGYCONTROLLER_H + +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QLowEnergyAdvertisingParameters; +class QLowEnergyControllerPrivate; +class QLowEnergyServiceData; + +class Q_BLUETOOTH_EXPORT QLowEnergyController : public QObject +{ + Q_OBJECT +public: + enum Error { + NoError, + UnknownError, + UnknownRemoteDeviceError, + NetworkError, + InvalidBluetoothAdapterError, + ConnectionError, + AdvertisingError, + RemoteHostClosedError, + AuthorizationError, + MissingPermissionsError, + RssiReadError + }; + Q_ENUM(Error) + + enum ControllerState { + UnconnectedState = 0, + ConnectingState, + ConnectedState, + DiscoveringState, + DiscoveredState, + ClosingState, + AdvertisingState, + }; + Q_ENUM(ControllerState) + + enum RemoteAddressType { + PublicAddress = 0, + RandomAddress + }; + Q_ENUM(RemoteAddressType) + + enum Role { CentralRole, PeripheralRole }; + Q_ENUM(Role) + + static QLowEnergyController *createCentral(const QBluetoothDeviceInfo &remoteDevice, + QObject *parent = nullptr); + static QLowEnergyController *createCentral(const QBluetoothDeviceInfo &remoteDevice, + const QBluetoothAddress &localDevice, + QObject *parent = nullptr); + static QLowEnergyController *createPeripheral(const QBluetoothAddress &localDevice, + QObject *parent = nullptr); + static QLowEnergyController *createPeripheral(QObject *parent = nullptr); + + // TODO: Allow to set connection timeout (disconnect when no data has been exchanged for n seconds). + + ~QLowEnergyController(); + + QBluetoothAddress localAddress() const; + QBluetoothAddress remoteAddress() const; + QBluetoothUuid remoteDeviceUuid() const; + + QString remoteName() const; + + ControllerState state() const; + + // TODO Qt6 remove this property. It is not longer needed when using Bluez DBus backend + RemoteAddressType remoteAddressType() const; + void setRemoteAddressType(RemoteAddressType type); + + void connectToDevice(); + void disconnectFromDevice(); + + void discoverServices(); + QList services() const; + QLowEnergyService *createServiceObject(const QBluetoothUuid &service, QObject *parent = nullptr); + + void startAdvertising(const QLowEnergyAdvertisingParameters ¶meters, + const QLowEnergyAdvertisingData &advertisingData, + const QLowEnergyAdvertisingData &scanResponseData = QLowEnergyAdvertisingData()); + void stopAdvertising(); + + QLowEnergyService *addService(const QLowEnergyServiceData &service, QObject *parent = nullptr); + + void requestConnectionUpdate(const QLowEnergyConnectionParameters ¶meters); + + Error error() const; + QString errorString() const; + + Role role() const; + + int mtu() const; + void readRssi(); + +Q_SIGNALS: + void connected(); + void disconnected(); + void stateChanged(QLowEnergyController::ControllerState state); + void errorOccurred(QLowEnergyController::Error newError); + void mtuChanged(int mtu); + void rssiRead(qint16 rssi); + + void serviceDiscovered(const QBluetoothUuid &newService); + void discoveryFinished(); + void connectionUpdated(const QLowEnergyConnectionParameters ¶meters); + + +private: + // peripheral role ctor + explicit QLowEnergyController(const QBluetoothAddress &localDevice, QObject *parent = nullptr); + + // central role ctors + explicit QLowEnergyController(const QBluetoothDeviceInfo &remoteDevice, + const QBluetoothAddress &localDevice, + QObject *parent = nullptr); + + + Q_DECLARE_PRIVATE(QLowEnergyController) + QLowEnergyControllerPrivate *d_ptr; +}; + +QT_END_NAMESPACE + +QT_DECL_METATYPE_EXTERN_TAGGED(QLowEnergyController::Error, QLowEnergyController__Error, + Q_BLUETOOTH_EXPORT) +QT_DECL_METATYPE_EXTERN_TAGGED(QLowEnergyController::ControllerState, + QLowEnergyController__ControllerState, + Q_BLUETOOTH_EXPORT) +QT_DECL_METATYPE_EXTERN_TAGGED(QLowEnergyController::RemoteAddressType, + QLowEnergyController__RemoteAddressType, + Q_BLUETOOTH_EXPORT) +QT_DECL_METATYPE_EXTERN_TAGGED(QLowEnergyController::Role, QLowEnergyController__Role, + Q_BLUETOOTH_EXPORT) + +#endif // QLOWENERGYCONTROLLER_H diff --git a/src/bluetooth/qlowenergycontroller_android.cpp b/src/bluetooth/qlowenergycontroller_android.cpp new file mode 100644 index 0000000..b88a224 --- /dev/null +++ b/src/bluetooth/qlowenergycontroller_android.cpp @@ -0,0 +1,1285 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qlowenergycontroller_android_p.h" +#include "android/androidutils_p.h" +#include "android/jni_android_p.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID) + +// BT Core v5.3, 3.2.9, Vol 3, Part F +const int BTLE_MAX_ATTRIBUTE_VALUE_SIZE = 512; + +// Conversion: QBluetoothUuid -> java.util.UUID +static QJniObject javaUuidfromQtUuid(const QBluetoothUuid& uuid) +{ + // cut off leading and trailing brackets + const QString output = uuid.toString(QUuid::WithoutBraces); + + QJniObject javaString = QJniObject::fromString(output); + QJniObject javaUuid = QJniObject::callStaticMethod( + QtJniTypes::Traits::className(), "fromString", + javaString.object()); + + return javaUuid; +} + +QLowEnergyControllerPrivateAndroid::QLowEnergyControllerPrivateAndroid() + : QLowEnergyControllerPrivate(), + hub(0) +{ + registerQLowEnergyControllerMetaType(); +} + +QLowEnergyControllerPrivateAndroid::~QLowEnergyControllerPrivateAndroid() +{ + if (role == QLowEnergyController::PeripheralRole) { + if (hub) + hub->javaObject().callMethod("disconnectServer"); + } +} + +void QLowEnergyControllerPrivateAndroid::init() +{ + const bool isPeripheral = (role == QLowEnergyController::PeripheralRole); + + if (isPeripheral) { + qRegisterMetaType(); + hub = new LowEnergyNotificationHub(remoteDevice, isPeripheral, this); + // we only connect to the peripheral role specific signals + // TODO add connections as they get added later on + connect(hub, &LowEnergyNotificationHub::connectionUpdated, + this, &QLowEnergyControllerPrivateAndroid::connectionUpdated); + connect(hub, &LowEnergyNotificationHub::mtuChanged, + this, &QLowEnergyControllerPrivateAndroid::mtuChanged); + connect(hub, &LowEnergyNotificationHub::advertisementError, + this, &QLowEnergyControllerPrivateAndroid::advertisementError); + connect(hub, &LowEnergyNotificationHub::serverCharacteristicChanged, + this, &QLowEnergyControllerPrivateAndroid::serverCharacteristicChanged); + connect(hub, &LowEnergyNotificationHub::serverDescriptorWritten, + this, &QLowEnergyControllerPrivateAndroid::serverDescriptorWritten); + } else { + hub = new LowEnergyNotificationHub(remoteDevice, isPeripheral, this); + // we only connect to the central role specific signals + connect(hub, &LowEnergyNotificationHub::connectionUpdated, + this, &QLowEnergyControllerPrivateAndroid::connectionUpdated); + connect(hub, &LowEnergyNotificationHub::mtuChanged, + this, &QLowEnergyControllerPrivateAndroid::mtuChanged); + connect(hub, &LowEnergyNotificationHub::servicesDiscovered, + this, &QLowEnergyControllerPrivateAndroid::servicesDiscovered); + connect(hub, &LowEnergyNotificationHub::serviceDetailsDiscoveryFinished, + this, &QLowEnergyControllerPrivateAndroid::serviceDetailsDiscoveryFinished); + connect(hub, &LowEnergyNotificationHub::characteristicRead, + this, &QLowEnergyControllerPrivateAndroid::characteristicRead); + connect(hub, &LowEnergyNotificationHub::descriptorRead, + this, &QLowEnergyControllerPrivateAndroid::descriptorRead); + connect(hub, &LowEnergyNotificationHub::characteristicWritten, + this, &QLowEnergyControllerPrivateAndroid::characteristicWritten); + connect(hub, &LowEnergyNotificationHub::descriptorWritten, + this, &QLowEnergyControllerPrivateAndroid::descriptorWritten); + connect(hub, &LowEnergyNotificationHub::characteristicChanged, + this, &QLowEnergyControllerPrivateAndroid::characteristicChanged); + connect(hub, &LowEnergyNotificationHub::serviceError, + this, &QLowEnergyControllerPrivateAndroid::serviceError); + connect(hub, &LowEnergyNotificationHub::remoteRssiRead, + this, &QLowEnergyControllerPrivateAndroid::remoteRssiRead); + } +} + +void QLowEnergyControllerPrivateAndroid::connectToDevice() +{ + if (!hub) { + qCCritical(QT_BT_ANDROID) << "connectToDevice() LE controller has not been initialized"; + return; + } + + if (!ensureAndroidPermission(QBluetoothPermission::Access)) { + // This is unlikely to happen as a valid local adapter is a precondition + setError(QLowEnergyController::MissingPermissionsError); + qCWarning(QT_BT_ANDROID) << "connectToDevice() failed due to missing permissions"; + return; + } + + // required to pass unit test on default backend + if (remoteDevice.isNull()) { + qCWarning(QT_BT_ANDROID) << "Invalid/null remote device address"; + setError(QLowEnergyController::UnknownRemoteDeviceError); + return; + } + + setState(QLowEnergyController::ConnectingState); + + if (!hub->javaObject().isValid()) { + qCWarning(QT_BT_ANDROID) << "Cannot initiate QtBluetoothLE"; + setError(QLowEnergyController::ConnectionError); + setState(QLowEnergyController::UnconnectedState); + return; + } + + bool result = hub->javaObject().callMethod("connect"); + if (!result) { + setError(QLowEnergyController::ConnectionError); + setState(QLowEnergyController::UnconnectedState); + return; + } +} + +void QLowEnergyControllerPrivateAndroid::disconnectFromDevice() +{ + /* Catch an Android timeout bug. If the device is connecting but cannot + * physically connect it seems to ignore the disconnect call below. + * At least BluetoothGattCallback.onConnectionStateChange never + * arrives. The next BluetoothGatt.connect() works just fine though. + * */ + + QLowEnergyController::ControllerState oldState = state; + setState(QLowEnergyController::ClosingState); + + if (hub) { + if (role == QLowEnergyController::PeripheralRole) + hub->javaObject().callMethod("disconnectServer"); + else + hub->javaObject().callMethod("disconnect"); + } + + if (oldState == QLowEnergyController::ConnectingState) + setState(QLowEnergyController::UnconnectedState); +} + +void QLowEnergyControllerPrivateAndroid::discoverServices() +{ + // No need to check bluetooth permissions here as 'connected' is a precondition + + if (hub && hub->javaObject().callMethod("discoverServices")) { + qCDebug(QT_BT_ANDROID) << "Service discovery initiated"; + } else { + //revert to connected state + setError(QLowEnergyController::NetworkError); + setState(QLowEnergyController::ConnectedState); + } +} + +void QLowEnergyControllerPrivateAndroid::discoverServiceDetails( + const QBluetoothUuid &service, QLowEnergyService::DiscoveryMode mode) +{ + Q_UNUSED(mode); + if (!serviceList.contains(service)) { + qCWarning(QT_BT_ANDROID) << "Discovery of unknown service" << service.toString() + << "not possible"; + return; + } + + if (!hub) + return; + + QString tempUuid = service.toString(QUuid::WithoutBraces); + + QJniEnvironment env; + QJniObject uuid = QJniObject::fromString(tempUuid); + bool readAllValues = mode == QLowEnergyService::FullDiscovery; + bool result = hub->javaObject().callMethod("discoverServiceDetails", + uuid.object(), + readAllValues); + if (!result) { + QSharedPointer servicePrivate = + serviceList.value(service); + if (!servicePrivate.isNull()) { + servicePrivate->setError(QLowEnergyService::UnknownError); + servicePrivate->setState(QLowEnergyService::RemoteService); + } + qCWarning(QT_BT_ANDROID) << "Cannot discover details for" << service.toString(); + return; + } + + qCDebug(QT_BT_ANDROID) << "Discovery of" << service << "started"; +} + +void QLowEnergyControllerPrivateAndroid::writeCharacteristic( + const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QByteArray &newValue, + QLowEnergyService::WriteMode mode) +{ + //TODO don't ignore WriteWithResponse, right now we assume responses + Q_ASSERT(!service.isNull()); + + if (!service->characteristicList.contains(charHandle)) + return; + + QJniEnvironment env; + jbyteArray payload; + payload = env->NewByteArray(newValue.size()); + env->SetByteArrayRegion(payload, 0, newValue.size(), + (jbyte *)newValue.constData()); + + bool result = false; + if (hub) { + if (role == QLowEnergyController::CentralRole) { + qCDebug(QT_BT_ANDROID) << "Write characteristic with handle " << charHandle + << newValue.toHex() << "(service:" << service->uuid + << ", writeWithResponse:" << (mode == QLowEnergyService::WriteWithResponse) + << ", signed:" << (mode == QLowEnergyService::WriteSigned) << ")"; + result = hub->javaObject().callMethod("writeCharacteristic", + charHandle, payload, jint(mode)); + } else { // peripheral mode + qCDebug(QT_BT_ANDROID) << "Write server characteristic with handle " << charHandle + << newValue.toHex() << "(service:" << service->uuid; + + const auto &characteristic = characteristicForHandle(charHandle); + if (characteristic.isValid()) { + const QJniObject charUuid = javaUuidfromQtUuid(characteristic.uuid()); + result = hub->javaObject().callMethod( + "writeCharacteristic", + service->androidService.object(), + charUuid.object(), payload); + if (result) + service->characteristicList[charHandle].value = newValue; + } + } + } + + env->DeleteLocalRef(payload); + + if (!result) + service->setError(QLowEnergyService::CharacteristicWriteError); +} + +void QLowEnergyControllerPrivateAndroid::writeDescriptor( + const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descHandle, + const QByteArray &newValue) +{ + Q_ASSERT(!service.isNull()); + + QJniEnvironment env; + jbyteArray payload; + payload = env->NewByteArray(newValue.size()); + env->SetByteArrayRegion(payload, 0, newValue.size(), + (jbyte *)newValue.constData()); + + bool result = false; + if (hub) { + if (role == QLowEnergyController::CentralRole) { + qCDebug(QT_BT_ANDROID) << "Write descriptor with handle " << descHandle + << newValue.toHex() << "(service:" << service->uuid << ")"; + result = hub->javaObject().callMethod("writeDescriptor", + descHandle, payload); + } else { + const auto &characteristic = characteristicForHandle(charHandle); + const auto &descriptor = descriptorForHandle(descHandle); + if (characteristic.isValid() && descriptor.isValid()) { + qCDebug(QT_BT_ANDROID) << "Write descriptor" << descriptor.uuid() + << "(service:" << service->uuid + << "char: " << characteristic.uuid() << ")"; + const QJniObject charUuid = javaUuidfromQtUuid(characteristic.uuid()); + const QJniObject descUuid = javaUuidfromQtUuid(descriptor.uuid()); + result = hub->javaObject().callMethod( + "writeDescriptor", + service->androidService.object(), + charUuid.object(), descUuid.object(), + payload); + if (result) + service->characteristicList[charHandle].descriptorList[descHandle].value = newValue; + } + } + } + + env->DeleteLocalRef(payload); + + if (!result) + service->setError(QLowEnergyService::DescriptorWriteError); +} + +void QLowEnergyControllerPrivateAndroid::readCharacteristic( + const QSharedPointer service, + const QLowEnergyHandle charHandle) +{ + Q_ASSERT(!service.isNull()); + + if (!service->characteristicList.contains(charHandle)) + return; + + QJniEnvironment env; + bool result = false; + if (hub) { + qCDebug(QT_BT_ANDROID) << "Read characteristic with handle" + << charHandle << service->uuid; + result = hub->javaObject().callMethod("readCharacteristic", charHandle); + } + + if (!result) + service->setError(QLowEnergyService::CharacteristicReadError); +} + +void QLowEnergyControllerPrivateAndroid::readDescriptor( + const QSharedPointer service, + const QLowEnergyHandle /*charHandle*/, + const QLowEnergyHandle descriptorHandle) +{ + Q_ASSERT(!service.isNull()); + + QJniEnvironment env; + bool result = false; + if (hub) { + qCDebug(QT_BT_ANDROID) << "Read descriptor with handle" + << descriptorHandle << service->uuid; + result = hub->javaObject().callMethod("readDescriptor", descriptorHandle); + } + + if (!result) + service->setError(QLowEnergyService::DescriptorReadError); +} + +void QLowEnergyControllerPrivateAndroid::connectionUpdated( + QLowEnergyController::ControllerState newState, + QLowEnergyController::Error errorCode) +{ + qCDebug(QT_BT_ANDROID) << "Connection updated:" + << "error:" << errorCode + << "oldState:" << state + << "newState:" << newState; + + if (role == QLowEnergyController::PeripheralRole) + peripheralConnectionUpdated(newState, errorCode); + else + centralConnectionUpdated(newState, errorCode); +} + +void QLowEnergyControllerPrivateAndroid::mtuChanged(int mtu) +{ + Q_Q(QLowEnergyController); + qCDebug(QT_BT_ANDROID) << "MTU updated:" + << "mtu:" << mtu; + emit q->mtuChanged(mtu); +} + +void QLowEnergyControllerPrivateAndroid::remoteRssiRead(int rssi, bool success) +{ + Q_Q(QLowEnergyController); + if (success) { + // BT Core v5.3, 7.5.4, Vol 4, Part E + // The LE RSSI can take values -127..127 => narrowing to qint16 is safe + emit q->rssiRead(rssi); + } else { + qCDebug(QT_BT_ANDROID) << "Reading remote RSSI failed"; + setError(QLowEnergyController::RssiReadError); + } +} + +// called if server/peripheral +void QLowEnergyControllerPrivateAndroid::peripheralConnectionUpdated( + QLowEnergyController::ControllerState newState, + QLowEnergyController::Error errorCode) +{ + // Java errorCode can be larger than max QLowEnergyController::Error + if (errorCode > QLowEnergyController::AdvertisingError) + errorCode = QLowEnergyController::UnknownError; + + if (errorCode != QLowEnergyController::NoError) + setError(errorCode); + + const QLowEnergyController::ControllerState oldState = state; + setState(newState); + + // disconnect implies stop of advertisement + if (newState == QLowEnergyController::UnconnectedState) + stopAdvertising(); + + // The remote name and address may have changed + if (hub) { + remoteDevice = QBluetoothAddress( + hub->javaObject().callMethod("remoteAddress").toString()); + remoteName = hub->javaObject().callMethod("remoteName").toString(); + } + + Q_Q(QLowEnergyController); + // Emit (dis)connected if the connection state changes + if (oldState == QLowEnergyController::ConnectedState + && newState != QLowEnergyController::ConnectedState) { + emit q->disconnected(); + } else if (newState == QLowEnergyController::ConnectedState + && oldState != QLowEnergyController::ConnectedState) { + emit q->connected(); + } +} + +// called if client/central +void QLowEnergyControllerPrivateAndroid::centralConnectionUpdated( + QLowEnergyController::ControllerState newState, + QLowEnergyController::Error errorCode) +{ + Q_Q(QLowEnergyController); + + const QLowEnergyController::ControllerState oldState = state; + + if (errorCode != QLowEnergyController::NoError) { + // ConnectionError if transition from Connecting to Connected + if (oldState == QLowEnergyController::ConnectingState) { + setError(QLowEnergyController::ConnectionError); + /* There is a bug in Android, when connecting to an unconnectable + * device. The connection times out and Android sends error code + * 133 (doesn't exist) and STATE_CONNECTED. A subsequent disconnect() + * call never sends a STATE_DISCONNECTED either. + * As workaround we will trigger disconnect when we encounter + * error during connect attempt. This leaves the controller + * in a cleaner state. + * */ + newState = QLowEnergyController::UnconnectedState; + } + else + setError(errorCode); + } + + setState(newState); + if (newState == QLowEnergyController::UnconnectedState + && !(oldState == QLowEnergyController::UnconnectedState + || oldState == QLowEnergyController::ConnectingState)) { + + // Invalidate the services if the disconnect came from the remote end. + // Qtherwise we disconnected via QLowEnergyController::disconnectDevice() which + // triggered invalidation already + if (!serviceList.isEmpty()) { + Q_ASSERT(oldState != QLowEnergyController::ClosingState); + invalidateServices(); + } + emit q->disconnected(); + } else if (newState == QLowEnergyController::ConnectedState + && oldState != QLowEnergyController::ConnectedState ) { + emit q->connected(); + } +} + +void QLowEnergyControllerPrivateAndroid::servicesDiscovered( + QLowEnergyController::Error errorCode, const QString &foundServices) +{ + Q_Q(QLowEnergyController); + + if (errorCode == QLowEnergyController::NoError) { + //Android delivers all services in one go + const QStringList list = foundServices.split(QChar::Space, Qt::SkipEmptyParts); + for (const QString &entry : list) { + const QBluetoothUuid service(entry); + if (service.isNull()) + return; + + QLowEnergyServicePrivate *priv = new QLowEnergyServicePrivate(); + priv->uuid = service; + priv->setController(this); + + QSharedPointer pointer(priv); + serviceList.insert(service, pointer); + + emit q->serviceDiscovered(QBluetoothUuid(entry)); + } + + setState(QLowEnergyController::DiscoveredState); + emit q->discoveryFinished(); + } else { + setError(errorCode); + setState(QLowEnergyController::ConnectedState); + } +} + +void QLowEnergyControllerPrivateAndroid::serviceDetailsDiscoveryFinished( + const QString &serviceUuid, int startHandle, int endHandle) +{ + const QBluetoothUuid service(serviceUuid); + if (!serviceList.contains(service)) { + qCWarning(QT_BT_ANDROID) << "Discovery done of unknown service:" + << service.toString(); + return; + } + + //update service data + QSharedPointer pointer = + serviceList.value(service); + pointer->startHandle = startHandle; + pointer->endHandle = endHandle; + + if (hub && hub->javaObject().isValid()) { + QJniObject uuid = QJniObject::fromString(serviceUuid); + QJniObject javaIncludes = hub->javaObject().callMethod( + "includedServices", uuid.object()); + if (javaIncludes.isValid()) { + const QStringList list = javaIncludes.toString() + .split(QChar::Space, Qt::SkipEmptyParts); + for (const QString &entry : list) { + const QBluetoothUuid service(entry); + if (service.isNull()) + return; + + pointer->includedServices.append(service); + + // update the type of the included service + QSharedPointer otherService = + serviceList.value(service); + if (!otherService.isNull()) + otherService->type |= QLowEnergyService::IncludedService; + } + } + } + + qCDebug(QT_BT_ANDROID) << "Service" << serviceUuid << "discovered (start:" + << startHandle << "end:" << endHandle << ")" << pointer.data(); + + pointer->setState(QLowEnergyService::RemoteServiceDiscovered); +} + +void QLowEnergyControllerPrivateAndroid::characteristicRead( + const QBluetoothUuid &serviceUuid, int handle, + const QBluetoothUuid &charUuid, int properties, const QByteArray &data) +{ + if (!serviceList.contains(serviceUuid)) + return; + + QSharedPointer service = + serviceList.value(serviceUuid); + QLowEnergyHandle charHandle = handle; + + QLowEnergyServicePrivate::CharData &charDetails = + service->characteristicList[charHandle]; + + //Android uses same property value as Qt which is the Bluetooth LE standard + charDetails.properties = QLowEnergyCharacteristic::PropertyType(properties); + charDetails.uuid = charUuid; + charDetails.value = data; + //value handle always one larger than characteristics value handle + charDetails.valueHandle = charHandle + 1; + + if (service->state == QLowEnergyService::RemoteServiceDiscovered) { + QLowEnergyCharacteristic characteristic = characteristicForHandle(charHandle); + if (!characteristic.isValid()) { + qCWarning(QT_BT_ANDROID) << "characteristicRead: Cannot find characteristic"; + return; + } + emit service->characteristicRead(characteristic, data); + } +} + +void QLowEnergyControllerPrivateAndroid::descriptorRead( + const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid, + int descHandle, const QBluetoothUuid &descUuid, const QByteArray &data) +{ + if (!serviceList.contains(serviceUuid)) + return; + + QSharedPointer service = + serviceList.value(serviceUuid); + + bool entryUpdated = false; + + CharacteristicDataMap::iterator charIt = service->characteristicList.begin(); + for ( ; charIt != service->characteristicList.end(); ++charIt) { + QLowEnergyServicePrivate::CharData &charDetails = charIt.value(); + + if (charDetails.uuid != charUuid) + continue; + + // new entry created if it doesn't exist + QLowEnergyServicePrivate::DescData &descDetails = + charDetails.descriptorList[descHandle]; + descDetails.uuid = descUuid; + descDetails.value = data; + entryUpdated = true; + break; + } + + if (!entryUpdated) { + qCWarning(QT_BT_ANDROID) << "Cannot find/update descriptor" + << descUuid << charUuid << serviceUuid; + } else if (service->state == QLowEnergyService::RemoteServiceDiscovered){ + QLowEnergyDescriptor descriptor = descriptorForHandle(descHandle); + if (!descriptor.isValid()) { + qCWarning(QT_BT_ANDROID) << "descriptorRead: Cannot find descriptor"; + return; + } + emit service->descriptorRead(descriptor, data); + } +} + +void QLowEnergyControllerPrivateAndroid::characteristicWritten( + int charHandle, const QByteArray &data, QLowEnergyService::ServiceError errorCode) +{ + QSharedPointer service = + serviceForHandle(charHandle); + if (service.isNull()) + return; + + qCDebug(QT_BT_ANDROID) << "Characteristic write confirmation" << service->uuid + << charHandle << data.toHex() << errorCode; + + if (errorCode != QLowEnergyService::NoError) { + service->setError(errorCode); + return; + } + + QLowEnergyCharacteristic characteristic = characteristicForHandle(charHandle); + if (!characteristic.isValid()) { + qCWarning(QT_BT_ANDROID) << "characteristicWritten: Cannot find characteristic"; + return; + } + + // only update cache when property is readable. Otherwise it remains + // empty. + if (characteristic.properties() & QLowEnergyCharacteristic::Read) + updateValueOfCharacteristic(charHandle, data, false); + emit service->characteristicWritten(characteristic, data); +} + +void QLowEnergyControllerPrivateAndroid::descriptorWritten( + int descHandle, const QByteArray &data, QLowEnergyService::ServiceError errorCode) +{ + QSharedPointer service = + serviceForHandle(descHandle); + if (service.isNull()) + return; + + qCDebug(QT_BT_ANDROID) << "Descriptor write confirmation" << service->uuid + << descHandle << data.toHex() << errorCode; + + if (errorCode != QLowEnergyService::NoError) { + service->setError(errorCode); + return; + } + + QLowEnergyDescriptor descriptor = descriptorForHandle(descHandle); + if (!descriptor.isValid()) { + qCWarning(QT_BT_ANDROID) << "descriptorWritten: Cannot find descriptor"; + return; + } + + updateValueOfDescriptor(descriptor.characteristicHandle(), + descHandle, data, false); + emit service->descriptorWritten(descriptor, data); +} + +void QLowEnergyControllerPrivateAndroid::serverDescriptorWritten( + const QJniObject &jniDesc, const QByteArray &newValue) +{ + qCDebug(QT_BT_ANDROID) << "Server descriptor change notification" << newValue.toHex(); + + // retrieve service, char and desc uuids + const QJniObject jniChar = jniDesc.callMethod( + "getCharacteristic"); + if (!jniChar.isValid()) + return; + + const QJniObject jniService = + jniChar.callMethod("getService"); + if (!jniService.isValid()) + return; + + QJniObject jniUuid = jniService.callMethod("getUuid"); + const QBluetoothUuid serviceUuid(jniUuid.toString()); + if (serviceUuid.isNull()) + return; + + // TODO test if two service with same uuid exist + if (!localServices.contains(serviceUuid)) + return; + + jniUuid = jniChar.callMethod("getUuid"); + const QBluetoothUuid characteristicUuid(jniUuid.toString()); + if (characteristicUuid.isNull()) + return; + + jniUuid = jniDesc.callMethod("getUuid"); + const QBluetoothUuid descriptorUuid(jniUuid.toString()); + if (descriptorUuid.isNull()) + return; + + // find matching QLEDescriptor + auto servicePrivate = localServices.value(serviceUuid); + // TODO test if service contains two characteristics with same uuid + // or characteristic contains two descriptors with same uuid + const auto handleList = servicePrivate->characteristicList.keys(); + for (const auto charHandle: handleList) { + const auto &charData = servicePrivate->characteristicList.value(charHandle); + if (charData.uuid != characteristicUuid) + continue; + + const auto &descHandleList = charData.descriptorList.keys(); + for (const auto descHandle: descHandleList) { + const auto &descData = charData.descriptorList.value(descHandle); + if (descData.uuid != descriptorUuid) + continue; + + qCDebug(QT_BT_ANDROID) << "serverDescriptorChanged: Matching descriptor" + << descriptorUuid << "in char" << characteristicUuid + << "of service" << serviceUuid; + + servicePrivate->characteristicList[charHandle].descriptorList[descHandle].value = newValue; + + emit servicePrivate->descriptorWritten( + QLowEnergyDescriptor(servicePrivate, charHandle, descHandle), + newValue); + return; + } + } +} + +void QLowEnergyControllerPrivateAndroid::characteristicChanged( + int charHandle, const QByteArray &data) +{ + QSharedPointer service = + serviceForHandle(charHandle); + if (service.isNull()) + return; + + qCDebug(QT_BT_ANDROID) << "Characteristic change notification" << service->uuid + << charHandle << data.toHex() << "length:" << data.size(); + + QLowEnergyCharacteristic characteristic = characteristicForHandle(charHandle); + if (!characteristic.isValid()) { + qCWarning(QT_BT_ANDROID) << "characteristicChanged: Cannot find characteristic"; + return; + } + + // only update cache when property is readable. Otherwise it remains + // empty. + if (characteristic.properties() & QLowEnergyCharacteristic::Read) + updateValueOfCharacteristic(characteristic.attributeHandle(), + data, false); + emit service->characteristicChanged(characteristic, data); +} + +void QLowEnergyControllerPrivateAndroid::serverCharacteristicChanged( + const QJniObject &characteristic, const QByteArray &newValue) +{ + qCDebug(QT_BT_ANDROID) << "Server characteristic change notification" + << newValue.toHex() << "length:" << newValue.size(); + + // match characteristic to servicePrivate + QJniObject service = characteristic.callMethod( + "getService"); + if (!service.isValid()) + return; + + QJniObject jniUuid = service.callMethod("getUuid"); + QBluetoothUuid serviceUuid(jniUuid.toString()); + if (serviceUuid.isNull()) + return; + + // TODO test if two service with same uuid exist + if (!localServices.contains(serviceUuid)) + return; + + auto servicePrivate = localServices.value(serviceUuid); + + jniUuid = characteristic.callMethod("getUuid"); + QBluetoothUuid characteristicUuid(jniUuid.toString()); + if (characteristicUuid.isNull()) + return; + + QLowEnergyHandle foundHandle = 0; + const auto handleList = servicePrivate->characteristicList.keys(); + // TODO test if service contains two characteristics with same uuid + for (const auto handle: handleList) { + QLowEnergyServicePrivate::CharData &charData = servicePrivate->characteristicList[handle]; + if (charData.uuid != characteristicUuid) + continue; + + qCDebug(QT_BT_ANDROID) << "serverCharacteristicChanged: Matching characteristic" + << characteristicUuid << " on " << serviceUuid; + charData.value = newValue; + foundHandle = handle; + break; + } + + if (!foundHandle) + return; + + emit servicePrivate->characteristicChanged( + QLowEnergyCharacteristic(servicePrivate, foundHandle), newValue); +} + +void QLowEnergyControllerPrivateAndroid::serviceError( + int attributeHandle, QLowEnergyService::ServiceError errorCode) +{ + // ignore call if it isn't really an error + if (errorCode == QLowEnergyService::NoError) + return; + + QSharedPointer service = + serviceForHandle(attributeHandle); + Q_ASSERT(!service.isNull()); + + // ATM we don't really use attributeHandle but later on we might + // want to associate the error code with a char or desc + service->setError(errorCode); +} + +void QLowEnergyControllerPrivateAndroid::advertisementError(int errorCode) +{ + Q_Q(QLowEnergyController); + + switch (errorCode) + { + case 1: // AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE + errorString = QLowEnergyController::tr("Advertisement data is larger than 31 bytes"); + break; + case 2: // AdvertiseCallback.ADVERTISE_FAILED_FEATURE_UNSUPPORTED + errorString = QLowEnergyController::tr("Advertisement feature not supported on the platform"); + break; + case 3: // AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR + errorString = QLowEnergyController::tr("Error occurred trying to start advertising"); + break; + case 4: // AdvertiseCallback.ADVERTISE_FAILED_TOO_MANY_ADVERTISERS + errorString = QLowEnergyController::tr("Failed due to too many advertisers"); + break; + default: + errorString = QLowEnergyController::tr("Unknown advertisement error"); + break; + } + + error = QLowEnergyController::AdvertisingError; + emit q->errorOccurred(error); + + // not relevant states in peripheral mode + Q_ASSERT(state != QLowEnergyController::DiscoveredState); + Q_ASSERT(state != QLowEnergyController::DiscoveringState); + + switch (state) + { + case QLowEnergyController::UnconnectedState: + case QLowEnergyController::ConnectingState: + case QLowEnergyController::ConnectedState: + case QLowEnergyController::ClosingState: + // noop as remote is already connected or about to disconnect. + // when connection drops we reset to unconnected anyway + break; + + case QLowEnergyController::AdvertisingState: + setState(QLowEnergyController::UnconnectedState); + break; + default: + break; + } +} + +static QJniObject javaParcelUuidfromQtUuid(const QBluetoothUuid &uuid) +{ + QString output = uuid.toString(); + // cut off leading and trailing brackets + output = output.mid(1, output.size()-2); + + QJniObject javaString = QJniObject::fromString(output); + QJniObject parcelUuid = QJniObject::callStaticMethod( + QtJniTypes::Traits::className(), "fromString", + javaString.object()); + + return parcelUuid; +} + +static QJniObject createJavaAdvertiseData(const QLowEnergyAdvertisingData &data) +{ + QJniObject builder = QJniObject::construct(); + + // device name cannot be set but there is choice to show it or not + builder = builder.callMethod( + "setIncludeDeviceName", !data.localName().isEmpty()); + builder = builder.callMethod( + "setIncludeTxPowerLevel", data.includePowerLevel()); + const auto services = data.services(); + for (const auto &service : services) { + builder = builder.callMethod("addServiceUuid", + javaParcelUuidfromQtUuid(service).object()); + } + + if (!data.manufacturerData().isEmpty()) { + QJniEnvironment env; + const qint32 nativeSize = data.manufacturerData().size(); + jbyteArray nativeData = env->NewByteArray(nativeSize); + env->SetByteArrayRegion(nativeData, 0, nativeSize, + reinterpret_cast(data.manufacturerData().constData())); + builder = builder.callMethod( + "addManufacturerData", jint(data.manufacturerId()), nativeData); + env->DeleteLocalRef(nativeData); + + if (!builder.isValid()) { + qCWarning(QT_BT_ANDROID) << "Cannot set manufacturer id/data"; + } + } + + /*// TODO Qt vs Java API mismatch + -> Qt assumes rawData() is a global field + -> Android pairs rawData() per service uuid + if (!data.rawData().isEmpty()) { + QJniEnvironment env; + qint32 nativeSize = data.rawData().size(); + jbyteArray nativeData = env->NewByteArray(nativeSize); + env->SetByteArrayRegion(nativeData, 0, nativeSize, + reinterpret_cast(data.rawData().constData())); + builder = builder.callObjectMethod("addServiceData", + "(Landroid/os/ParcelUuid;[B])Landroid/bluetooth/le/AdvertiseData$Builder;", + data.rawData().object(), nativeData); + env->DeleteLocalRef(nativeData); + + if (env.checkAndClearExceptions()) { + qCWarning(QT_BT_ANDROID) << "Cannot set advertisement raw data"; + } + }*/ + + QJniObject javaAdvertiseData = builder.callMethod("build"); + return javaAdvertiseData; +} + +static QJniObject createJavaAdvertiseSettings(const QLowEnergyAdvertisingParameters ¶ms) +{ + QJniObject builder = QJniObject::construct(); + + bool connectable = false; + switch (params.mode()) + { + case QLowEnergyAdvertisingParameters::AdvInd: + connectable = true; + break; + case QLowEnergyAdvertisingParameters::AdvScanInd: + case QLowEnergyAdvertisingParameters::AdvNonConnInd: + connectable = false; + break; + // intentionally no default case + } + builder = builder.callMethod( + "setConnectable", connectable); + + /* TODO No Android API for further QLowEnergyAdvertisingParameters options + * Android TxPowerLevel, AdvertiseMode and Timeout not mappable to Qt + */ + + QJniObject javaAdvertiseSettings = builder.callMethod("build"); + return javaAdvertiseSettings; +} + + +void QLowEnergyControllerPrivateAndroid::startAdvertising(const QLowEnergyAdvertisingParameters ¶ms, + const QLowEnergyAdvertisingData &advertisingData, + const QLowEnergyAdvertisingData &scanResponseData) +{ + setState(QLowEnergyController::AdvertisingState); + + if (!ensureAndroidPermission(QBluetoothPermission::Access | QBluetoothPermission::Advertise)) { + qCWarning(QT_BT_ANDROID) << "startAdvertising() failed due to missing permissions"; + setError(QLowEnergyController::MissingPermissionsError); + setState(QLowEnergyController::UnconnectedState); + return; + } + + if (!hub || !hub->javaObject().isValid()) { + qCWarning(QT_BT_ANDROID) << "Cannot initiate QtBluetoothLEServer"; + setError(QLowEnergyController::AdvertisingError); + setState(QLowEnergyController::UnconnectedState); + return; + } + + // Pass on advertisingData, scanResponse & AdvertiseSettings + QJniObject jAdvertiseData = createJavaAdvertiseData(advertisingData); + QJniObject jScanResponse = createJavaAdvertiseData(scanResponseData); + QJniObject jAdvertiseSettings = createJavaAdvertiseSettings(params); + + const bool result = hub->javaObject().callMethod("startAdvertising", + jAdvertiseData.object(), + jScanResponse.object(), + jAdvertiseSettings.object()); + if (!result) { + setError(QLowEnergyController::AdvertisingError); + setState(QLowEnergyController::UnconnectedState); + } +} + +void QLowEnergyControllerPrivateAndroid::stopAdvertising() +{ + setState(QLowEnergyController::UnconnectedState); + hub->javaObject().callMethod("stopAdvertising"); +} + +void QLowEnergyControllerPrivateAndroid::requestConnectionUpdate(const QLowEnergyConnectionParameters ¶ms) +{ + // Android does not permit specification of specific latency or min/max + // connection intervals (see BluetoothGatt.requestConnectionPriority() + // In fact, each device manufacturer is permitted to change those values via a config + // file too. Therefore we can only make an approximated guess (see implementation below) + // In addition there is no feedback signal (known bug) from the hardware layer as per v24. + + // TODO recheck in later Android releases whether callback for + // BluetoothGatt.requestConnectionPriority() was added + + if (role != QLowEnergyController::CentralRole) { + qCWarning(QT_BT_ANDROID) << "On Android, connection requests only work for central role"; + return; + } + + const bool result = hub->javaObject().callMethod("requestConnectionUpdatePriority", + params.minimumInterval()); + if (!result) + qCWarning(QT_BT_ANDROID) << "Cannot set connection update priority"; +} + +/* + * Returns the Java char permissions based on the given characteristic data. + */ +static int setupCharPermissions(const QLowEnergyCharacteristicData &charData) +{ + int permission = 0; + if (charData.properties() & QLowEnergyCharacteristic::Read) { + if (int(charData.readConstraints()) == 0 // nothing is equivalent to simple read + || (charData.readConstraints() + & QBluetooth::AttAccessConstraint::AttAuthorizationRequired)) { + permission |= QJniObject::getStaticField( + QtJniTypes::Traits::className(), + "PERMISSION_READ"); + } + + if (charData.readConstraints() + & QBluetooth::AttAccessConstraint::AttAuthenticationRequired) { + permission |= QJniObject::getStaticField( + QtJniTypes::Traits::className(), + "PERMISSION_READ_ENCRYPTED"); + } + + if (charData.readConstraints() & QBluetooth::AttAccessConstraint::AttEncryptionRequired) { + permission |= QJniObject::getStaticField( + QtJniTypes::Traits::className(), + "PERMISSION_READ_ENCRYPTED_MITM"); + } + } + + if (charData.properties() & + (QLowEnergyCharacteristic::Write|QLowEnergyCharacteristic::WriteNoResponse) ) { + if (int(charData.writeConstraints()) == 0 // no flag is equivalent ti simple write + || (charData.writeConstraints() + & QBluetooth::AttAccessConstraint::AttAuthorizationRequired)) { + permission |= QJniObject::getStaticField( + QtJniTypes::Traits::className(), + "PERMISSION_WRITE"); + } + + if (charData.writeConstraints() + & QBluetooth::AttAccessConstraint::AttAuthenticationRequired) { + permission |= QJniObject::getStaticField( + QtJniTypes::Traits::className(), + "PERMISSION_WRITE_ENCRYPTED"); + } + + if (charData.writeConstraints() & QBluetooth::AttAccessConstraint::AttEncryptionRequired) { + permission |= QJniObject::getStaticField( + QtJniTypes::Traits::className(), + "PERMISSION_WRITE_ENCRYPTED_MITM"); + } + } + + if (charData.properties() & QLowEnergyCharacteristic::WriteSigned) { + if (charData.writeConstraints() & QBluetooth::AttAccessConstraint::AttEncryptionRequired) { + permission |= QJniObject::getStaticField( + QtJniTypes::Traits::className(), + "PERMISSION_WRITE_SIGNED_MITM"); + } else { + permission |= QJniObject::getStaticField( + QtJniTypes::Traits::className(), + "PERMISSION_WRITE_SIGNED"); + } + } + + return permission; +} + +/* + * Returns the Java desc permissions based on the given descriptor data. + */ +static int setupDescPermissions(const QLowEnergyDescriptorData &descData) +{ + int permissions = 0; + + if (descData.isReadable()) { + if (int(descData.readConstraints()) == 0 // empty is equivalent to simple read + || (descData.readConstraints() + & QBluetooth::AttAccessConstraint::AttAuthorizationRequired)) { + permissions |= QJniObject::getStaticField( + QtJniTypes::Traits::className(), + "PERMISSION_READ"); + } + + if (descData.readConstraints() + & QBluetooth::AttAccessConstraint::AttAuthenticationRequired) { + permissions |= QJniObject::getStaticField( + QtJniTypes::Traits::className(), + "PERMISSION_READ_ENCRYPTED"); + } + + if (descData.readConstraints() & QBluetooth::AttAccessConstraint::AttEncryptionRequired) { + permissions |= QJniObject::getStaticField( + QtJniTypes::Traits::className(), + "PERMISSION_READ_ENCRYPTED_MITM"); + } + } + + if (descData.isWritable()) { + if (int(descData.readConstraints()) == 0 // empty is equivalent to simple read + || (descData.readConstraints() + & QBluetooth::AttAccessConstraint::AttAuthorizationRequired)) { + permissions |= QJniObject::getStaticField( + QtJniTypes::Traits::className(), + "PERMISSION_WRITE"); + } + + if (descData.readConstraints() + & QBluetooth::AttAccessConstraint::AttAuthenticationRequired) { + permissions |= QJniObject::getStaticField( + QtJniTypes::Traits::className(), + "PERMISSION_WRITE_ENCRYPTED"); + } + + if (descData.readConstraints() & QBluetooth::AttAccessConstraint::AttEncryptionRequired) { + permissions |= QJniObject::getStaticField( + QtJniTypes::Traits::className(), + "PERMISSION_WRITE_ENCRYPTED_MITM"); + } + } + + return permissions; +} + +void QLowEnergyControllerPrivateAndroid::addToGenericAttributeList(const QLowEnergyServiceData &serviceData, + QLowEnergyHandle startHandle) +{ + QSharedPointer service = serviceForHandle(startHandle); + if (service.isNull()) + return; + + // create BluetoothGattService object + jint sType = QJniObject::getStaticField( + QtJniTypes::Traits::className(), + "SERVICE_TYPE_PRIMARY"); + if (serviceData.type() == QLowEnergyServiceData::ServiceTypeSecondary) + sType = QJniObject::getStaticField( + QtJniTypes::Traits::className(), + "SERVICE_TYPE_SECONDARY"); + + service->androidService = QJniObject::construct( + javaUuidfromQtUuid(service->uuid).object(), sType); + + // add included services, which must have been added earlier already + const QList includedServices = serviceData.includedServices(); + for (const auto includedServiceEntry: includedServices) { + //TODO test this end-to-end + const jboolean result = service->androidService.callMethod("addService", + includedServiceEntry->d_ptr->androidService.object()); + if (!result) + qWarning(QT_BT_ANDROID) << "Cannot add included service " << includedServiceEntry->serviceUuid() + << "to current service" << service->uuid; + } + + // add characteristics + const QList serviceCharsData = serviceData.characteristics(); + for (const auto &charData: serviceCharsData) { + + // User may have set minimum and/or maximum characteristic value size. Enforce + // them here. If the user has not defined these limits, the default values 0..INT_MAX + // do not limit anything. If the sizes are violated here (ie. when adding the + // characteristics), regard it as a programming error. + if (charData.value().size() < charData.minimumValueLength() || + charData.value().size() > charData.maximumValueLength()) { + qWarning() << "Warning: Ignoring characteristic" << charData.uuid() + << "with invalid length:" << charData.value().size() + << "(minimum:" << charData.minimumValueLength() + << "maximum:" << charData.maximumValueLength() << ")."; + continue; + } + + // Issue a warning if the attribute length exceeds the bluetooth standard limit. + if (charData.value().size() > BTLE_MAX_ATTRIBUTE_VALUE_SIZE) { + qCWarning(QT_BT_ANDROID) << "Warning: characteristic" << charData.uuid() << "size" + << "exceeds the standard: " << BTLE_MAX_ATTRIBUTE_VALUE_SIZE + << ", value size:" << charData.value().size(); + } + + QJniObject javaChar = QJniObject::construct( + javaUuidfromQtUuid(charData.uuid()).object(), + int(charData.properties()), + setupCharPermissions(charData), + charData.minimumValueLength(), + charData.maximumValueLength()); + + QJniEnvironment env; + jbyteArray jb = env->NewByteArray(charData.value().size()); + env->SetByteArrayRegion(jb, 0, charData.value().size(), (jbyte*)charData.value().data()); + jboolean success = javaChar.callMethod("setLocalValue", jb); + if (!success) + qCWarning(QT_BT_ANDROID) << "Cannot setup initial characteristic value for " << charData.uuid(); + env->DeleteLocalRef(jb); + + const QList descriptorList = charData.descriptors(); + for (const auto &descData: descriptorList) { + QJniObject javaDesc = QJniObject::construct( + javaUuidfromQtUuid(descData.uuid()).object(), + setupDescPermissions(descData)); + + jb = env->NewByteArray(descData.value().size()); + env->SetByteArrayRegion(jb, 0, descData.value().size(), (jbyte*)descData.value().data()); + success = javaDesc.callMethod("setLocalValue", jb); + if (!success) { + qCWarning(QT_BT_ANDROID) << "Cannot setup initial descriptor value for " + << descData.uuid() << "(char" << charData.uuid() + << "on service " << service->uuid << ")"; + } + + env->DeleteLocalRef(jb); + + + success = javaChar.callMethod("addDescriptor", + javaDesc.object()); + if (!success) { + qCWarning(QT_BT_ANDROID) << "Cannot add descriptor" << descData.uuid() + << "to service" << service->uuid << "(char:" + << charData.uuid() << ")"; + } + } + + success = service->androidService.callMethod( + "addCharacteristic", + javaChar.object()); + if (!success) { + qCWarning(QT_BT_ANDROID) << "Cannot add characteristic" << charData.uuid() + << "to service" << service->uuid; + } + } + + hub->javaObject().callMethod("addService", + service->androidService.object()); +} + +int QLowEnergyControllerPrivateAndroid::mtu() const +{ + if (!hub) { + qCWarning(QT_BT_ANDROID) << "could not determine MTU, hub is does not exist"; + return -1; + } else { + int result = hub->javaObject().callMethod("mtu"); + qCDebug(QT_BT_ANDROID) << "MTU found to be" << result; + return result; + } +} + +void QLowEnergyControllerPrivateAndroid::readRssi() +{ + if (!hub || !hub->javaObject().callMethod("readRemoteRssi")) { + qCWarning(QT_BT_ANDROID) << "request to read RSSI failed"; + setError(QLowEnergyController::RssiReadError); + return; + } +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/qlowenergycontroller_android_p.h b/src/bluetooth/qlowenergycontroller_android_p.h new file mode 100644 index 0000000..6f1bbfa --- /dev/null +++ b/src/bluetooth/qlowenergycontroller_android_p.h @@ -0,0 +1,122 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QLOWENERGYCONTROLLERPRIVATEANDROID_P_H +#define QLOWENERGYCONTROLLERPRIVATEANDROID_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 "qlowenergycontroller.h" +#include "qlowenergycontrollerbase_p.h" + +#include +#include "android/lowenergynotificationhub_p.h" + +#include + +QT_BEGIN_NAMESPACE + +class QLowEnergyServiceData; +class QTimer; + +class LowEnergyNotificationHub; + +extern void registerQLowEnergyControllerMetaType(); + +class QLowEnergyControllerPrivateAndroid final : public QLowEnergyControllerPrivate +{ + Q_OBJECT +public: + QLowEnergyControllerPrivateAndroid(); + ~QLowEnergyControllerPrivateAndroid() override; + + void init() override; + + void connectToDevice() override; + void disconnectFromDevice() override; + + void discoverServices() override; + void discoverServiceDetails(const QBluetoothUuid &service, + QLowEnergyService::DiscoveryMode mode) override; + + void startAdvertising(const QLowEnergyAdvertisingParameters ¶ms, + const QLowEnergyAdvertisingData &advertisingData, + const QLowEnergyAdvertisingData &scanResponseData) override; + void stopAdvertising() override; + + void requestConnectionUpdate(const QLowEnergyConnectionParameters ¶ms) override; + + // read data + void readCharacteristic(const QSharedPointer service, + const QLowEnergyHandle charHandle) override; + void readDescriptor(const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle) override; + + // write data + void writeCharacteristic(const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QByteArray &newValue, QLowEnergyService::WriteMode mode) override; + void writeDescriptor(const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle, + const QByteArray &newValue) override; + + void addToGenericAttributeList(const QLowEnergyServiceData &service, + QLowEnergyHandle startHandle) override; + + int mtu() const override; + void readRssi() override; + +private: + + LowEnergyNotificationHub *hub; + +private slots: + void connectionUpdated(QLowEnergyController::ControllerState newState, + QLowEnergyController::Error errorCode); + void mtuChanged(int mtu); + void remoteRssiRead(int rssi, bool success); + void servicesDiscovered(QLowEnergyController::Error errorCode, + const QString &foundServices); + void serviceDetailsDiscoveryFinished(const QString& serviceUuid, + int startHandle, int endHandle); + void characteristicRead(const QBluetoothUuid &serviceUuid, int handle, + const QBluetoothUuid &charUuid, int properties, + const QByteArray& data); + void descriptorRead(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid, + int handle, const QBluetoothUuid &descUuid, const QByteArray &data); + void characteristicWritten(int charHandle, const QByteArray &data, + QLowEnergyService::ServiceError errorCode); + void descriptorWritten(int descHandle, const QByteArray &data, + QLowEnergyService::ServiceError errorCode); + void serverDescriptorWritten(const QJniObject &jniDesc, const QByteArray &newValue); + void characteristicChanged(int charHandle, const QByteArray &data); + void serverCharacteristicChanged(const QJniObject &jniChar, const QByteArray &newValue); + void serviceError(int attributeHandle, QLowEnergyService::ServiceError errorCode); + void advertisementError(int errorCode); + +private: + void peripheralConnectionUpdated(QLowEnergyController::ControllerState newState, + QLowEnergyController::Error errorCode); + void centralConnectionUpdated(QLowEnergyController::ControllerState newState, + QLowEnergyController::Error errorCode); +}; + +QT_END_NAMESPACE + +#endif // QLOWENERGYCONTROLLERPRIVATEANDROID_P_H diff --git a/src/bluetooth/qlowenergycontroller_bluez.cpp b/src/bluetooth/qlowenergycontroller_bluez.cpp new file mode 100644 index 0000000..6f0c985 --- /dev/null +++ b/src/bluetooth/qlowenergycontroller_bluez.cpp @@ -0,0 +1,3458 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// Copyright (C) 2016 Javier S. Pedro +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "lecmaccalculator_p.h" +#include "qlowenergycontroller_bluez_p.h" +#include "qbluetoothsocketbase_p.h" +#include "qbluetoothsocket_bluez_p.h" +#include "qleadvertiser_bluez_p.h" +#include "bluez/bluez_data_p.h" +#include "bluez/hcimanager_p.h" +#include "bluez/objectmanager_p.h" +#include "bluez/remotedevicemanager_p.h" +#include "bluez/bluez5_helper_p.h" +#include "bluez/bluetoothmanagement_p.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +constexpr quint16 ATT_DEFAULT_LE_MTU = 23; +constexpr quint16 ATT_MAX_LE_MTU = 0x200; + +#define GATT_PRIMARY_SERVICE quint16(0x2800) +#define GATT_SECONDARY_SERVICE quint16(0x2801) +#define GATT_INCLUDED_SERVICE quint16(0x2802) +#define GATT_CHARACTERISTIC quint16(0x2803) + +//GATT command sizes in bytes +#define ERROR_RESPONSE_HEADER_SIZE 5 +#define FIND_INFO_REQUEST_HEADER_SIZE 5 +#define GRP_TYPE_REQ_HEADER_SIZE 7 +#define READ_BY_TYPE_REQ_HEADER_SIZE 7 +#define READ_REQUEST_HEADER_SIZE 3 +#define READ_BLOB_REQUEST_HEADER_SIZE 5 +#define WRITE_REQUEST_HEADER_SIZE 3 // same size for WRITE_COMMAND header +#define PREPARE_WRITE_HEADER_SIZE 5 +#define EXECUTE_WRITE_HEADER_SIZE 2 +#define MTU_EXCHANGE_HEADER_SIZE 3 + +#define APPEND_VALUE true +#define NEW_VALUE false + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ) + +using namespace QBluetooth; + +const int maxPrepareQueueSize = 1024; + +static void dumpErrorInformation(const QByteArray &response) +{ + const char *data = response.constData(); + if (response.size() != 5 + || (static_cast(data[0]) + != QBluezConst::AttCommand::ATT_OP_ERROR_RESPONSE)) { + qCWarning(QT_BT_BLUEZ) << QLatin1String("Not a valid error response"); + return; + } + + QBluezConst::AttCommand lastCommand = static_cast(data[1]); + quint16 handle = bt_get_le16(&data[2]); + QBluezConst::AttError errorCode = static_cast(data[4]); + + QString errorString; + switch (errorCode) { + case QBluezConst::AttError::ATT_ERROR_INVALID_HANDLE: + errorString = QStringLiteral("invalid handle"); break; + case QBluezConst::AttError::ATT_ERROR_READ_NOT_PERM: + errorString = QStringLiteral("not readable attribute - permissions"); break; + case QBluezConst::AttError::ATT_ERROR_WRITE_NOT_PERM: + errorString = QStringLiteral("not writable attribute - permissions"); break; + case QBluezConst::AttError::ATT_ERROR_INVALID_PDU: + errorString = QStringLiteral("PDU invalid"); break; + case QBluezConst::AttError::ATT_ERROR_INSUF_AUTHENTICATION: + errorString = QStringLiteral("needs authentication - permissions"); break; + case QBluezConst::AttError::ATT_ERROR_REQUEST_NOT_SUPPORTED: + errorString = QStringLiteral("server does not support request"); break; + case QBluezConst::AttError::ATT_ERROR_INVALID_OFFSET: + errorString = QStringLiteral("offset past end of attribute"); break; + case QBluezConst::AttError::ATT_ERROR_INSUF_AUTHORIZATION: + errorString = QStringLiteral("need authorization - permissions"); break; + case QBluezConst::AttError::ATT_ERROR_PREPARE_QUEUE_FULL: + errorString = QStringLiteral("run out of prepare queue space"); break; + case QBluezConst::AttError::ATT_ERROR_ATTRIBUTE_NOT_FOUND: + errorString = QStringLiteral("no attribute in given range found"); break; + case QBluezConst::AttError::ATT_ERROR_ATTRIBUTE_NOT_LONG: + errorString = QStringLiteral("attribute not read/written using read blob"); break; + case QBluezConst::AttError::ATT_ERROR_INSUF_ENCR_KEY_SIZE: + errorString = QStringLiteral("need encryption key size - permissions"); break; + case QBluezConst::AttError::ATT_ERROR_INVAL_ATTR_VALUE_LEN: + errorString = QStringLiteral("written value is invalid size"); break; + case QBluezConst::AttError::ATT_ERROR_UNLIKELY: + errorString = QStringLiteral("unlikely error"); break; + case QBluezConst::AttError::ATT_ERROR_INSUF_ENCRYPTION: + errorString = QStringLiteral("needs encryption - permissions"); break; + case QBluezConst::AttError::ATT_ERROR_UNSUPPRTED_GROUP_TYPE: + errorString = QStringLiteral("unsupported group type"); break; + case QBluezConst::AttError::ATT_ERROR_INSUF_RESOURCES: + errorString = QStringLiteral("insufficient resources to complete request"); break; + default: + if (errorCode >= QBluezConst::AttError::ATT_ERROR_APPLICATION_START + && errorCode <= QBluezConst::AttError::ATT_ERROR_APPLICATION_END) + errorString = + QStringLiteral("application error: %1").arg(static_cast(errorCode)); + else + errorString = QStringLiteral("unknown error code"); + break; + } + + qCDebug(QT_BT_BLUEZ) << "Error:" << errorCode << "Error description:" << errorString + << "last command:" << lastCommand << "handle:" << handle; +} + +static int getUuidSize(const QBluetoothUuid &uuid) +{ + return uuid.minimumSize() == 2 ? 2 : 16; +} + +template static void putDataAndIncrement(const T &src, char *&dst) +{ + putBtData(src, dst); + dst += sizeof(T); +} +template<> void putDataAndIncrement(const QBluetoothUuid &uuid, char *&dst) +{ + bool ok; + quint16 uuid16 = uuid.toUInt16(&ok); + if (ok) { + putBtData(uuid16, dst); + dst += sizeof(uuid16); + } else { + QUuid::Id128Bytes btOrder = uuid.toBytes(QSysInfo::LittleEndian); + memcpy(dst, btOrder.data, sizeof(btOrder)); + dst += sizeof(btOrder); + } +} +template<> void putDataAndIncrement(const QByteArray &value, char *&dst) +{ + using namespace std; + memcpy(dst, value.constData(), value.size()); + dst += value.size(); +} + +QLowEnergyControllerPrivateBluez::QLowEnergyControllerPrivateBluez() + : QLowEnergyControllerPrivate(), + requestPending(false), + mtuSize(ATT_DEFAULT_LE_MTU), + securityLevelValue(-1), + encryptionChangePending(false) +{ + registerQLowEnergyControllerMetaType(); + qRegisterMetaType >(); +} + +void QLowEnergyControllerPrivateBluez::init() +{ + // The HCI manager is shared between this class and the advertiser + hciManager = std::make_shared(localAdapter); + + if (!hciManager->isValid()){ + setError(QLowEnergyController::InvalidBluetoothAdapterError); + return; + } + + hciManager->monitorEvent(HciManager::HciEvent::EVT_ENCRYPT_CHANGE); + connect(hciManager.get(), SIGNAL(encryptionChangedEvent(QBluetoothAddress,bool)), + this, SLOT(encryptionChangedEvent(QBluetoothAddress,bool))); + hciManager->monitorEvent(HciManager::HciEvent::EVT_LE_META_EVENT); + hciManager->monitorAclPackets(); + connect(hciManager.get(), &HciManager::connectionComplete, this, [this](quint16 handle) { + connectionHandle = handle; + qCDebug(QT_BT_BLUEZ) << "received connection complete event, handle:" << handle; + }); + connect(hciManager.get(), &HciManager::connectionUpdate, this, + [this](quint16 handle, const QLowEnergyConnectionParameters ¶ms) { + if (handle == connectionHandle) + emit q_ptr->connectionUpdated(params); + } + ); + connect(hciManager.get(), &HciManager::signatureResolvingKeyReceived, this, + [this](quint16 handle, bool remoteKey, const QUuid::Id128Bytes &csrk) { + if (handle != connectionHandle) + return; + if ((remoteKey && role == QLowEnergyController::CentralRole) + || (!remoteKey && role == QLowEnergyController::PeripheralRole)) { + return; + } + qCDebug(QT_BT_BLUEZ) << "received new signature resolving key" + << QByteArray(reinterpret_cast(csrk.data), + sizeof csrk).toHex(); + signingData.insert(remoteDevice.toUInt64(), SigningData(csrk)); + } + ); + + if (role == QLowEnergyController::CentralRole) { + if (Q_UNLIKELY(!qEnvironmentVariableIsEmpty("BLUETOOTH_GATT_TIMEOUT"))) { + bool ok = false; + int value = qEnvironmentVariableIntValue("BLUETOOTH_GATT_TIMEOUT", &ok); + if (ok) + gattRequestTimeout = value; + } + + // permit disabling of timeout behavior via environment variable + if (gattRequestTimeout > 0) { + qCWarning(QT_BT_BLUEZ) << "Enabling GATT request timeout behavior" << gattRequestTimeout; + requestTimer = new QTimer(this); + requestTimer->setSingleShot(true); + requestTimer->setInterval(gattRequestTimeout); + connect(requestTimer, &QTimer::timeout, + this, &QLowEnergyControllerPrivateBluez::handleGattRequestTimeout); + } + } +} + +void QLowEnergyControllerPrivateBluez::handleGattRequestTimeout() +{ + // antyhing open that might require cancellation or a warning? + if (encryptionChangePending) { + // We cannot really recover for now but the warning is essential for debugging + qCWarning(QT_BT_BLUEZ) << "****** Encryption change event blocking further GATT requests"; + return; + } + + if (!openRequests.isEmpty() && requestPending) { + const Request currentRequest = openRequests.dequeue(); + requestPending = false; // reset pending flag + + qCWarning(QT_BT_BLUEZ).nospace() << "****** Request type 0x" << currentRequest.command + << " to server/peripheral timed out"; + qCWarning(QT_BT_BLUEZ) << "****** Looks like the characteristic or descriptor does NOT act in" + << "accordance to Bluetooth 4.x spec."; + qCWarning(QT_BT_BLUEZ) << "****** Please check server implementation." + << "Continuing under reservation."; + + QBluezConst::AttCommand command = currentRequest.command; + const auto createRequestErrorMessage = [](QBluezConst::AttCommand opcodeWithError, + QLowEnergyHandle handle) { + QByteArray errorPackage(ERROR_RESPONSE_HEADER_SIZE, Qt::Uninitialized); + errorPackage[0] = static_cast(QBluezConst::AttCommand::ATT_OP_ERROR_RESPONSE); + errorPackage[1] = static_cast( + opcodeWithError); // e.g. QBluezConst::AttCommand::ATT_OP_READ_REQUEST + putBtData(handle, errorPackage.data() + 2); // + errorPackage[4] = static_cast(QBluezConst::AttError::ATT_ERROR_REQUEST_STALLED); + + return errorPackage; + }; + + switch (command) { + case QBluezConst::AttCommand::ATT_OP_EXCHANGE_MTU_REQUEST: // MTU change request + // never received reply to MTU request + // it is safe to skip and go to next request + break; + case QBluezConst::AttCommand::ATT_OP_READ_BY_GROUP_REQUEST: // primary or secondary service + // discovery + case QBluezConst::AttCommand::ATT_OP_READ_BY_TYPE_REQUEST: // characteristic or included + // service discovery + // jump back into usual response handling with custom error code + // 2nd param "0" as required by spec + processReply(currentRequest, createRequestErrorMessage(command, 0)); + break; + case QBluezConst::AttCommand::ATT_OP_READ_REQUEST: // read descriptor or characteristic + // value + case QBluezConst::AttCommand::ATT_OP_READ_BLOB_REQUEST: // read long descriptor or + // characteristic + case QBluezConst::AttCommand::ATT_OP_WRITE_REQUEST: // write descriptor or characteristic + { + uint handleData = currentRequest.reference.toUInt(); + const QLowEnergyHandle charHandle = (handleData & 0xffff); + const QLowEnergyHandle descriptorHandle = ((handleData >> 16) & 0xffff); + processReply(currentRequest, createRequestErrorMessage(command, + descriptorHandle ? descriptorHandle : charHandle)); + } break; + case QBluezConst::AttCommand::ATT_OP_FIND_INFORMATION_REQUEST: // get descriptor information + processReply(currentRequest, createRequestErrorMessage( + command, currentRequest.reference2.toUInt())); + break; + case QBluezConst::AttCommand::ATT_OP_PREPARE_WRITE_REQUEST: // prepare to write long desc or + // char + case QBluezConst::AttCommand::ATT_OP_EXECUTE_WRITE_REQUEST: // execute long write of desc or + // char + { + uint handleData = currentRequest.reference.toUInt(); + const QLowEnergyHandle attrHandle = (handleData & 0xffff); + processReply(currentRequest, + createRequestErrorMessage(command, attrHandle)); + } break; + default: + // not a command used by central role implementation + qCWarning(QT_BT_BLUEZ) << "Missing response for ATT peripheral command: " + << Qt::hex << command; + break; + } + + // spin openRequest queue further + sendNextPendingRequest(); + } +} + +QLowEnergyControllerPrivateBluez::~QLowEnergyControllerPrivateBluez() +{ + closeServerSocket(); + delete cmacCalculator; + cmacCalculator = nullptr; +} + +class ServerSocket +{ +public: + bool listen(const QBluetoothAddress &localAdapter) + { + m_socket = ::socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); + if (m_socket == -1) { + qCWarning(QT_BT_BLUEZ) << "socket creation failed:" << qt_error_string(errno); + return false; + } + sockaddr_l2 addr; + + // memset should be in std namespace for C++ compilers, but we also need to support + // broken ones that put it in the global one. + using namespace std; + memset(&addr, 0, sizeof addr); + + addr.l2_family = AF_BLUETOOTH; + addr.l2_cid = htobs(ATTRIBUTE_CHANNEL_ID); + addr.l2_bdaddr_type = BDADDR_LE_PUBLIC; + convertAddress(localAdapter.toUInt64(), addr.l2_bdaddr.b); + if (::bind(m_socket, reinterpret_cast(&addr), sizeof addr) == -1) { + qCWarning(QT_BT_BLUEZ) << "bind() failed:" << qt_error_string(errno); + return false; + } + if (::listen(m_socket, 1)) { + qCWarning(QT_BT_BLUEZ) << "listen() failed:" << qt_error_string(errno); + return false; + } + return true; + } + + ~ServerSocket() + { + if (m_socket != -1) + close(m_socket); + } + + int takeSocket() + { + const int socket = m_socket; + m_socket = -1; + return socket; + } + +private: + int m_socket = -1; +}; + + +void QLowEnergyControllerPrivateBluez::startAdvertising(const QLowEnergyAdvertisingParameters ¶ms, + const QLowEnergyAdvertisingData &advertisingData, + const QLowEnergyAdvertisingData &scanResponseData) +{ + qCDebug(QT_BT_BLUEZ) << "Starting to advertise"; + if (!advertiser) { + advertiser = new QLeAdvertiserBluez(params, advertisingData, scanResponseData, hciManager, + this); + connect(advertiser, &QLeAdvertiser::errorOccurred, this, + &QLowEnergyControllerPrivateBluez::handleAdvertisingError); + } + setState(QLowEnergyController::AdvertisingState); + advertiser->startAdvertising(); + if (params.mode() == QLowEnergyAdvertisingParameters::AdvNonConnInd + || params.mode() == QLowEnergyAdvertisingParameters::AdvScanInd) { + qCDebug(QT_BT_BLUEZ) << "Non-connectable advertising requested, " + "not listening for connections."; + return; + } + + ServerSocket serverSocket; + if (!serverSocket.listen(localAdapter)) { + setError(QLowEnergyController::AdvertisingError); + setState(QLowEnergyController::UnconnectedState); + return; + } + + const int socketFd = serverSocket.takeSocket(); + serverSocketNotifier = new QSocketNotifier(socketFd, QSocketNotifier::Read, this); + connect(serverSocketNotifier, &QSocketNotifier::activated, this, + &QLowEnergyControllerPrivateBluez::handleConnectionRequest); +} + +void QLowEnergyControllerPrivateBluez::stopAdvertising() +{ + setState(QLowEnergyController::UnconnectedState); + advertiser->stopAdvertising(); +} + +void QLowEnergyControllerPrivateBluez::requestConnectionUpdate(const QLowEnergyConnectionParameters ¶ms) +{ + // The spec says that the connection update command can be used by both slave and master + // devices, but BlueZ allows it only for master devices. So for slave devices, we have to use a + // connection parameter update request, which we need to wrap in an ACL command, as BlueZ + // does not allow user-space sockets for the signaling channel. + if (role == QLowEnergyController::CentralRole) + hciManager->sendConnectionUpdateCommand(connectionHandle, params); + else + hciManager->sendConnectionParameterUpdateRequest(connectionHandle, params); +} + +void QLowEnergyControllerPrivateBluez::connectToDevice() +{ + if (remoteDevice.isNull()) { + qCWarning(QT_BT_BLUEZ) << "Invalid/null remote device address"; + setError(QLowEnergyController::UnknownRemoteDeviceError); + return; + } + + setState(QLowEnergyController::ConnectingState); + if (l2cpSocket) { + delete l2cpSocket; + l2cpSocket = nullptr; + } + + createServicesForCentralIfRequired(); + + // check for active running connections + // BlueZ 5.37+ (maybe even earlier versions) can have pending BTLE connections + // Only one active L2CP socket to CID 0x4 possible at a time + + QList activeHandles = hciManager->activeLowEnergyConnections(); + if (!activeHandles.isEmpty()) { + qCWarning(QT_BT_BLUEZ) << "Cannot connect due to pending active LE connections"; + + if (!device1Manager) { + device1Manager = new RemoteDeviceManager(localAdapter, this); + connect(device1Manager, &RemoteDeviceManager::finished, + this, &QLowEnergyControllerPrivateBluez::activeConnectionTerminationDone); + } + + QList connectedAddresses; + for (const auto handle: activeHandles) { + const QBluetoothAddress addr = hciManager->addressForConnectionHandle(handle); + if (!addr.isNull()) + connectedAddresses.push_back(addr); + } + device1Manager->scheduleJob(RemoteDeviceManager::JobType::JobDisconnectDevice, connectedAddresses); + } else { + establishL2cpClientSocket(); + } +} + +/*! + * Handles outcome of attempts to close external connections. + */ +void QLowEnergyControllerPrivateBluez::activeConnectionTerminationDone() +{ + if (!device1Manager) + return; + + qCDebug(QT_BT_BLUEZ) << "RemoteDeviceManager finished attempting" + << "to close external connections"; + + QList activeHandles = hciManager->activeLowEnergyConnections(); + if (!activeHandles.isEmpty()) { + qCWarning(QT_BT_BLUEZ) << "Cannot close pending external BTLE connections. Aborting connect attempt"; + setError(QLowEnergyController::ConnectionError); + setState(QLowEnergyController::UnconnectedState); + l2cpDisconnected(); + return; + } else { + establishL2cpClientSocket(); + } +} + +/*! + * Establishes the L2CP client socket. + */ +void QLowEnergyControllerPrivateBluez::establishL2cpClientSocket() +{ + //we are already in Connecting state + + l2cpSocket = new QBluetoothSocket(QBluetoothServiceInfo::L2capProtocol, this); + connect(l2cpSocket, SIGNAL(connected()), this, SLOT(l2cpConnected())); + connect(l2cpSocket, SIGNAL(disconnected()), this, SLOT(l2cpDisconnected())); + connect(l2cpSocket, SIGNAL(errorOccurred(QBluetoothSocket::SocketError)), this, + SLOT(l2cpErrorChanged(QBluetoothSocket::SocketError))); + connect(l2cpSocket, SIGNAL(readyRead()), this, SLOT(l2cpReadyRead())); + + quint32 addressTypeToUse = (addressType == QLowEnergyController::PublicAddress) + ? BDADDR_LE_PUBLIC : BDADDR_LE_RANDOM; + if (BluetoothManagement::instance()->isMonitoringEnabled()) { + // if monitoring is possible and it's private then we force it to the relevant option + if (BluetoothManagement::instance()->isAddressRandom(remoteDevice)) { + addressTypeToUse = BDADDR_LE_RANDOM; + } + } + + qCDebug(QT_BT_BLUEZ) << "addresstypeToUse:" + << (addressTypeToUse == BDADDR_LE_RANDOM + ? QStringLiteral("Random") : QStringLiteral("Public")); + + l2cpSocket->d_ptr->lowEnergySocketType = addressTypeToUse; + + int sockfd = l2cpSocket->socketDescriptor(); + if (sockfd < 0) { + qCWarning(QT_BT_BLUEZ) << "l2cp socket not initialised"; + setError(QLowEnergyController::ConnectionError); + setState(QLowEnergyController::UnconnectedState); + return; + } + + struct sockaddr_l2 addr; + memset(&addr, 0, sizeof(addr)); + addr.l2_family = AF_BLUETOOTH; + addr.l2_cid = htobs(ATTRIBUTE_CHANNEL_ID); + addr.l2_bdaddr_type = BDADDR_LE_PUBLIC; + convertAddress(localAdapter.toUInt64(), addr.l2_bdaddr.b); + + // bind the socket to the local device + if (::bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + qCWarning(QT_BT_BLUEZ) << qt_error_string(errno); + setError(QLowEnergyController::ConnectionError); + setState(QLowEnergyController::UnconnectedState); + return; + } + + // connect + // Unbuffered mode required to separate each GATT packet + l2cpSocket->connectToService(remoteDevice, ATTRIBUTE_CHANNEL_ID, + QIODevice::ReadWrite | QIODevice::Unbuffered); + loadSigningDataIfNecessary(LocalSigningKey); +} + +void QLowEnergyControllerPrivateBluez::createServicesForCentralIfRequired() +{ + bool ok = false; + int value = qEnvironmentVariableIntValue("QT_DEFAULT_CENTRAL_SERVICES", &ok); + if (Q_UNLIKELY(ok && value == 0)) + return; //nothing to do + + //do not add the services each time we start a connection + if (localServices.contains(QBluetoothUuid(QBluetoothUuid::ServiceClassUuid::GenericAccess))) + return; + + qCDebug(QT_BT_BLUEZ) << "Creating default GAP/GATT services"; + + //populate Generic Access service + //for now the values are static + QLowEnergyServiceData gapServiceData; + gapServiceData.setType(QLowEnergyServiceData::ServiceTypePrimary); + gapServiceData.setUuid(QBluetoothUuid::ServiceClassUuid::GenericAccess); + + QLowEnergyCharacteristicData gapDeviceName; + gapDeviceName.setUuid(QBluetoothUuid::CharacteristicType::DeviceName); + gapDeviceName.setProperties(QLowEnergyCharacteristic::Read); + + QBluetoothLocalDevice mainAdapter; + gapDeviceName.setValue(mainAdapter.name().toLatin1()); //static name + + QLowEnergyCharacteristicData gapAppearance; + gapAppearance.setUuid(QBluetoothUuid::CharacteristicType::Appearance); + gapAppearance.setProperties(QLowEnergyCharacteristic::Read); + gapAppearance.setValue(QByteArray::fromHex("80")); // Generic Computer (0x80) + + QLowEnergyCharacteristicData gapPrivacyFlag; + gapPrivacyFlag.setUuid(QBluetoothUuid::CharacteristicType::PeripheralPrivacyFlag); + gapPrivacyFlag.setProperties(QLowEnergyCharacteristic::Read); + gapPrivacyFlag.setValue(QByteArray::fromHex("00")); // disable privacy + + gapServiceData.addCharacteristic(gapDeviceName); + gapServiceData.addCharacteristic(gapAppearance); + gapServiceData.addCharacteristic(gapPrivacyFlag); + + Q_Q(QLowEnergyController); + QLowEnergyService *service = addServiceHelper(gapServiceData); + if (service) + service->setParent(q); + + QLowEnergyServiceData gattServiceData; + gattServiceData.setType(QLowEnergyServiceData::ServiceTypePrimary); + gattServiceData.setUuid(QBluetoothUuid::ServiceClassUuid::GenericAttribute); + + QLowEnergyCharacteristicData serviceChangedChar; + serviceChangedChar.setUuid(QBluetoothUuid::CharacteristicType::ServiceChanged); + serviceChangedChar.setProperties(QLowEnergyCharacteristic::Indicate); + //arbitrary range of 2 bit handle range (1-4 + serviceChangedChar.setValue(QByteArray::fromHex("0104")); + + const QLowEnergyDescriptorData clientConfig( + QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration, + QByteArray(2, 0)); + serviceChangedChar.addDescriptor(clientConfig); + gattServiceData.addCharacteristic(serviceChangedChar); + + service = addServiceHelper(gattServiceData); + if (service) + service->setParent(q); +} + +void QLowEnergyControllerPrivateBluez::l2cpConnected() +{ + Q_Q(QLowEnergyController); + + securityLevelValue = securityLevel(); + exchangeMTU(); + + setState(QLowEnergyController::ConnectedState); + emit q->connected(); +} + +void QLowEnergyControllerPrivateBluez::disconnectFromDevice() +{ + setState(QLowEnergyController::ClosingState); + if (l2cpSocket) + l2cpSocket->close(); + resetController(); + + // this may happen when RemoteDeviceManager::JobType::JobDisconnectDevice + // is pending. + if (!l2cpSocket) { + qWarning(QT_BT_BLUEZ) << "Unexpected closure of device. Cleaning up internal states."; + l2cpDisconnected(); + } +} + +void QLowEnergyControllerPrivateBluez::l2cpDisconnected() +{ + Q_Q(QLowEnergyController); + + if (role == QLowEnergyController::PeripheralRole) { + storeClientConfigurations(); + remoteDevice.clear(); + remoteName.clear(); + } + invalidateServices(); + resetController(); + setState(QLowEnergyController::UnconnectedState); + emit q->disconnected(); +} + +void QLowEnergyControllerPrivateBluez::l2cpErrorChanged(QBluetoothSocket::SocketError e) +{ + switch (e) { + case QBluetoothSocket::SocketError::HostNotFoundError: + setError(QLowEnergyController::UnknownRemoteDeviceError); + qCDebug(QT_BT_BLUEZ) << "The passed remote device address cannot be found"; + break; + case QBluetoothSocket::SocketError::NetworkError: + setError(QLowEnergyController::NetworkError); + qCDebug(QT_BT_BLUEZ) << "Network IO error while talking to LE device"; + break; + case QBluetoothSocket::SocketError::RemoteHostClosedError: + setError(QLowEnergyController::RemoteHostClosedError); + qCDebug(QT_BT_BLUEZ) << "Remote host closed the connection"; + break; + case QBluetoothSocket::SocketError::UnknownSocketError: + case QBluetoothSocket::SocketError::UnsupportedProtocolError: + case QBluetoothSocket::SocketError::OperationError: + case QBluetoothSocket::SocketError::ServiceNotFoundError: + default: + // these errors shouldn't happen -> as it means + // the code in this file has bugs + qCDebug(QT_BT_BLUEZ) << "Unknown l2cp socket error: " << e << l2cpSocket->errorString(); + setError(QLowEnergyController::UnknownError); + break; + } + + invalidateServices(); + resetController(); + setState(QLowEnergyController::UnconnectedState); +} + + +void QLowEnergyControllerPrivateBluez::resetController() +{ + openRequests.clear(); + openPrepareWriteRequests.clear(); + scheduledIndications.clear(); + indicationInFlight = false; + requestPending = false; + encryptionChangePending = false; + receivedMtuExchangeRequest = false; + mtuSize = ATT_DEFAULT_LE_MTU; + securityLevelValue = -1; + connectionHandle = 0; + + if (role == QLowEnergyController::PeripheralRole) { + // public API behavior requires stop of advertisement + if (advertiser) { + advertiser->stopAdvertising(); + delete advertiser; + advertiser = nullptr; + } + localAttributes.clear(); + } +} + +void QLowEnergyControllerPrivateBluez::restartRequestTimer() +{ + if (!requestTimer) + return; + + if (gattRequestTimeout > 0) + requestTimer->start(gattRequestTimeout); +} + +void QLowEnergyControllerPrivateBluez::l2cpReadyRead() +{ + const QByteArray incomingPacket = l2cpSocket->readAll(); + qCDebug(QT_BT_BLUEZ) << "Received size:" << incomingPacket.size() << "data:" + << incomingPacket.toHex(); + if (incomingPacket.isEmpty()) + return; + + const QBluezConst::AttCommand command = + static_cast(incomingPacket.constData()[0]); + switch (command) { + case QBluezConst::AttCommand::ATT_OP_HANDLE_VAL_NOTIFICATION: { + processUnsolicitedReply(incomingPacket); + return; + } + case QBluezConst::AttCommand::ATT_OP_HANDLE_VAL_INDICATION: { + //send confirmation + QByteArray packet; + packet.append(static_cast(QBluezConst::AttCommand::ATT_OP_HANDLE_VAL_CONFIRMATION)); + sendPacket(packet); + + processUnsolicitedReply(incomingPacket); + return; + } + //-------------------------------------------------- + // Peripheral side packet handling + case QBluezConst::AttCommand::ATT_OP_EXCHANGE_MTU_REQUEST: + handleExchangeMtuRequest(incomingPacket); + return; + case QBluezConst::AttCommand::ATT_OP_FIND_INFORMATION_REQUEST: + handleFindInformationRequest(incomingPacket); + return; + case QBluezConst::AttCommand::ATT_OP_FIND_BY_TYPE_VALUE_REQUEST: + handleFindByTypeValueRequest(incomingPacket); + return; + case QBluezConst::AttCommand::ATT_OP_READ_BY_TYPE_REQUEST: + handleReadByTypeRequest(incomingPacket); + return; + case QBluezConst::AttCommand::ATT_OP_READ_REQUEST: + handleReadRequest(incomingPacket); + return; + case QBluezConst::AttCommand::ATT_OP_READ_BLOB_REQUEST: + handleReadBlobRequest(incomingPacket); + return; + case QBluezConst::AttCommand::ATT_OP_READ_MULTIPLE_REQUEST: + handleReadMultipleRequest(incomingPacket); + return; + case QBluezConst::AttCommand::ATT_OP_READ_BY_GROUP_REQUEST: + handleReadByGroupTypeRequest(incomingPacket); + return; + case QBluezConst::AttCommand::ATT_OP_WRITE_REQUEST: + case QBluezConst::AttCommand::ATT_OP_WRITE_COMMAND: + case QBluezConst::AttCommand::ATT_OP_SIGNED_WRITE_COMMAND: + handleWriteRequestOrCommand(incomingPacket); + return; + case QBluezConst::AttCommand::ATT_OP_PREPARE_WRITE_REQUEST: + handlePrepareWriteRequest(incomingPacket); + return; + case QBluezConst::AttCommand::ATT_OP_EXECUTE_WRITE_REQUEST: + handleExecuteWriteRequest(incomingPacket); + return; + case QBluezConst::AttCommand::ATT_OP_HANDLE_VAL_CONFIRMATION: + if (indicationInFlight) { + indicationInFlight = false; + sendNextIndication(); + } else { + qCWarning(QT_BT_BLUEZ) << "received unexpected handle value confirmation"; + } + return; + //-------------------------------------------------- + default: + //only solicited replies finish pending requests + requestPending = false; + break; + } + + if (openRequests.isEmpty()) { + qCWarning(QT_BT_BLUEZ) << "Received unexpected packet from peer, disconnecting."; + disconnectFromDevice(); + return; + } + + const Request request = openRequests.dequeue(); + processReply(request, incomingPacket); + + sendNextPendingRequest(); +} + +/*! + * Called when the request for socket encryption has been + * processed by the kernel. Such requests take time as the kernel + * has to renegotiate the link parameters with the remote device. + * + * Therefore any such request delays the pending ATT commands until this + * callback is called. The first pending request in the queue is the request + * that triggered the encryption request. + */ +void QLowEnergyControllerPrivateBluez::encryptionChangedEvent( + const QBluetoothAddress &address, bool wasSuccess) +{ + if (!encryptionChangePending) // somebody else caused change event + return; + + if (remoteDevice != address) + return; + + securityLevelValue = securityLevel(); + + // On success continue to process ATT command queue + if (!wasSuccess) { + // We could not increase the security of the link + // The next request was requeued due to security error + // skip it to avoid endless loop of security negotiations + Q_ASSERT(!openRequests.isEmpty()); + Request failedRequest = openRequests.takeFirst(); + + if (failedRequest.command == QBluezConst::AttCommand::ATT_OP_WRITE_REQUEST) { + // Failing write requests trigger some sort of response + uint ref = failedRequest.reference.toUInt(); + const QLowEnergyHandle charHandle = (ref & 0xffff); + const QLowEnergyHandle descriptorHandle = ((ref >> 16) & 0xffff); + + QSharedPointer service + = serviceForHandle(charHandle); + if (!service.isNull() && service->characteristicList.contains(charHandle)) { + if (!descriptorHandle) + service->setError(QLowEnergyService::CharacteristicWriteError); + else + service->setError(QLowEnergyService::DescriptorWriteError); + } + } else if (failedRequest.command == QBluezConst::AttCommand::ATT_OP_PREPARE_WRITE_REQUEST) { + uint handleData = failedRequest.reference.toUInt(); + const QLowEnergyHandle attrHandle = (handleData & 0xffff); + const QByteArray newValue = failedRequest.reference2.toByteArray(); + + // Prepare command failed, cancel pending prepare queue on + // the device. The appropriate (Descriptor|Characteristic)WriteError + // is emitted too once the execute write request comes through + sendExecuteWriteRequest(attrHandle, newValue, true); + } + } + + encryptionChangePending = false; + sendNextPendingRequest(); +} + +void QLowEnergyControllerPrivateBluez::sendPacket(const QByteArray &packet) +{ + qint64 result = l2cpSocket->write(packet.constData(), + packet.size()); + // We ignore result == 0 which is likely to be caused by EAGAIN. + // This packet is effectively discarded but the controller can still recover + + if (result == -1) { + qCDebug(QT_BT_BLUEZ) << "Cannot write L2CP packet:" << Qt::hex + << packet.toHex() + << l2cpSocket->errorString(); + setError(QLowEnergyController::NetworkError); + } else if (result < packet.size()) { + qCWarning(QT_BT_BLUEZ) << "L2CP write request incomplete:" + << result << "of" << packet.size(); + } + +} + +void QLowEnergyControllerPrivateBluez::sendNextPendingRequest() +{ + if (openRequests.isEmpty() || requestPending || encryptionChangePending) + return; + + const Request &request = openRequests.head(); +// qCDebug(QT_BT_BLUEZ) << "Sending request, type:" << Qt::hex << request.command +// << request.payload.toHex(); + + requestPending = true; + restartRequestTimer(); + sendPacket(request.payload); +} + +QLowEnergyHandle parseReadByTypeCharDiscovery( + QLowEnergyServicePrivate::CharData *charData, + const char *data, quint16 elementLength) +{ + Q_ASSERT(charData); + Q_ASSERT(data); + + QLowEnergyHandle attributeHandle = bt_get_le16(&data[0]); + charData->properties = + (QLowEnergyCharacteristic::PropertyTypes)(data[2] & 0xff); + charData->valueHandle = bt_get_le16(&data[3]); + + // Bluetooth LE data comes as little endian + if (elementLength == 7) // 16 bit uuid + charData->uuid = QBluetoothUuid(bt_get_le16(&data[5])); + else + charData->uuid = QUuid::fromBytes(&data[5], QSysInfo::LittleEndian); + + qCDebug(QT_BT_BLUEZ) << "Found handle:" << Qt::hex << attributeHandle + << "properties:" << charData->properties + << "value handle:" << charData->valueHandle + << "uuid:" << charData->uuid.toString(); + + return attributeHandle; +} + +QLowEnergyHandle parseReadByTypeIncludeDiscovery( + QList *foundServices, + const char *data, quint16 elementLength) +{ + Q_ASSERT(foundServices); + Q_ASSERT(data); + + QLowEnergyHandle attributeHandle = bt_get_le16(&data[0]); + + // the next 2 elements are not required as we have discovered + // all (primary/secondary) services already. Now we are only + // interested in their relationship to each other + // data[2] -> included service start handle + // data[4] -> included service end handle + + if (elementLength == 8) //16 bit uuid + foundServices->append(QBluetoothUuid(bt_get_le16(&data[6]))); + else + foundServices->append(QUuid::fromBytes(&data[6], QSysInfo::LittleEndian)); + + qCDebug(QT_BT_BLUEZ) << "Found included service: " << Qt::hex + << attributeHandle << "uuid:" << *foundServices; + + return attributeHandle; +} + +void QLowEnergyControllerPrivateBluez::processReply( + const Request &request, const QByteArray &response) +{ + Q_Q(QLowEnergyController); + + QBluezConst::AttCommand command = static_cast(response.constData()[0]); + + bool isErrorResponse = false; + // if error occurred 2. byte is previous request type + if (command == QBluezConst::AttCommand::ATT_OP_ERROR_RESPONSE) { + dumpErrorInformation(response); + command = static_cast(response.constData()[1]); + isErrorResponse = true; + } + + switch (command) { + case QBluezConst::AttCommand::ATT_OP_EXCHANGE_MTU_REQUEST: // in case of error + case QBluezConst::AttCommand::ATT_OP_EXCHANGE_MTU_RESPONSE: { + Q_ASSERT(request.command == QBluezConst::AttCommand::ATT_OP_EXCHANGE_MTU_REQUEST); + quint16 oldMtuSize = mtuSize; + if (isErrorResponse) { + mtuSize = ATT_DEFAULT_LE_MTU; + } else { + const char *data = response.constData(); + quint16 mtu = bt_get_le16(&data[1]); + mtuSize = mtu; + if (mtuSize < ATT_DEFAULT_LE_MTU) + mtuSize = ATT_DEFAULT_LE_MTU; + + qCDebug(QT_BT_BLUEZ) << "Server MTU:" << mtu << "resulting mtu:" << mtuSize; + } + if (oldMtuSize != mtuSize) + emit q->mtuChanged(mtuSize); + } break; + case QBluezConst::AttCommand::ATT_OP_READ_BY_GROUP_REQUEST: // in case of error + case QBluezConst::AttCommand::ATT_OP_READ_BY_GROUP_RESPONSE: { + // Discovering services + Q_ASSERT(request.command == QBluezConst::AttCommand::ATT_OP_READ_BY_GROUP_REQUEST); + + const quint16 type = request.reference.toUInt(); + + if (isErrorResponse) { + if (type == GATT_SECONDARY_SERVICE) { + setState(QLowEnergyController::DiscoveredState); + q->discoveryFinished(); + } else { // search for secondary services + sendReadByGroupRequest(0x0001, 0xFFFF, GATT_SECONDARY_SERVICE); + } + break; + } + + QLowEnergyHandle start = 0, end = 0; + const quint16 elementLength = response.constData()[1]; + const quint16 numElements = (response.size() - 2) / elementLength; + quint16 offset = 2; + const char *data = response.constData(); + for (int i = 0; i < numElements; i++) { + start = bt_get_le16(&data[offset]); + end = bt_get_le16(&data[offset+2]); + + QBluetoothUuid uuid; + if (elementLength == 6) //16 bit uuid + uuid = QBluetoothUuid(bt_get_le16(&data[offset+4])); + else if (elementLength == 20) //128 bit uuid + uuid = QUuid::fromBytes(&data[offset+4], QSysInfo::LittleEndian); + //else -> do nothing + + offset += elementLength; + + + qCDebug(QT_BT_BLUEZ) << "Found uuid:" << uuid << "start handle:" << Qt::hex + << start << "end handle:" << end; + + QLowEnergyServicePrivate *priv = new QLowEnergyServicePrivate(); + priv->uuid = uuid; + priv->startHandle = start; + priv->endHandle = end; + if (type != GATT_PRIMARY_SERVICE) //unset PrimaryService bit + priv->type &= ~QLowEnergyService::PrimaryService; + priv->setController(this); + + QSharedPointer pointer(priv); + + serviceList.insert(uuid, pointer); + emit q->serviceDiscovered(uuid); + } + + if (end != 0xFFFF) { + sendReadByGroupRequest(end+1, 0xFFFF, type); + } else { + if (type == GATT_SECONDARY_SERVICE) { + setState(QLowEnergyController::DiscoveredState); + emit q->discoveryFinished(); + } else { // search for secondary services + sendReadByGroupRequest(0x0001, 0xFFFF, GATT_SECONDARY_SERVICE); + } + } + } break; + case QBluezConst::AttCommand::ATT_OP_READ_BY_TYPE_REQUEST: // in case of error + case QBluezConst::AttCommand::ATT_OP_READ_BY_TYPE_RESPONSE: { + // Discovering characteristics + Q_ASSERT(request.command == QBluezConst::AttCommand::ATT_OP_READ_BY_TYPE_REQUEST); + + QSharedPointer p = + request.reference.value >(); + const quint16 attributeType = request.reference2.toUInt(); + + if (isErrorResponse) { + if (attributeType == GATT_CHARACTERISTIC) { + // we reached end of service handle + // just finished up characteristic discovery + // continue with values of characteristics + if (!p->characteristicList.isEmpty()) { + readServiceValues(p->uuid, true); + } else { + // discovery finished since the service doesn't have any + // characteristics + p->setState(QLowEnergyService::RemoteServiceDiscovered); + } + } else if (attributeType == GATT_INCLUDED_SERVICE) { + // finished up include discovery + // continue with characteristic discovery + sendReadByTypeRequest(p, p->startHandle, GATT_CHARACTERISTIC); + } + break; + } + + /* packet format: + * if GATT_CHARACTERISTIC discovery + * + * []+ + * + * if GATT_INCLUDE discovery + * + * []+ + * + * The uuid can be 16 or 128 bit. + */ + QLowEnergyHandle lastHandle; + const quint16 elementLength = response.constData()[1]; + const quint16 numElements = (response.size() - 2) / elementLength; + quint16 offset = 2; + const char *data = response.constData(); + for (int i = 0; i < numElements; i++) { + if (attributeType == GATT_CHARACTERISTIC) { + QLowEnergyServicePrivate::CharData characteristic; + lastHandle = parseReadByTypeCharDiscovery( + &characteristic, &data[offset], elementLength); + p->characteristicList[lastHandle] = characteristic; + offset += elementLength; + } else if (attributeType == GATT_INCLUDED_SERVICE) { + QList includedServices; + lastHandle = parseReadByTypeIncludeDiscovery( + &includedServices, &data[offset], elementLength); + p->includedServices = includedServices; + for (const QBluetoothUuid &uuid : std::as_const(includedServices)) { + if (serviceList.contains(uuid)) + serviceList[uuid]->type |= QLowEnergyService::IncludedService; + } + } + } + + if (lastHandle + 1 < p->endHandle) { // more chars to discover + sendReadByTypeRequest(p, lastHandle + 1, attributeType); + } else { + if (attributeType == GATT_INCLUDED_SERVICE) + sendReadByTypeRequest(p, p->startHandle, GATT_CHARACTERISTIC); + else + readServiceValues(p->uuid, true); + } + } break; + case QBluezConst::AttCommand::ATT_OP_READ_REQUEST: // error case + case QBluezConst::AttCommand::ATT_OP_READ_RESPONSE: { + //Reading characteristics and descriptors + Q_ASSERT(request.command == QBluezConst::AttCommand::ATT_OP_READ_REQUEST); + + uint handleData = request.reference.toUInt(); + const QLowEnergyHandle charHandle = (handleData & 0xffff); + const QLowEnergyHandle descriptorHandle = ((handleData >> 16) & 0xffff); + + QSharedPointer service = serviceForHandle(charHandle); + Q_ASSERT(!service.isNull()); + bool isServiceDiscoveryRun + = !(service->state == QLowEnergyService::RemoteServiceDiscovered); + + if (isErrorResponse) { + Q_ASSERT(!encryptionChangePending); + QBluezConst::AttError err = static_cast(response.constData()[4]); + encryptionChangePending = increaseEncryptLevelfRequired(err); + if (encryptionChangePending) { + // Just requested a security level change. + // Retry the same command again once the change has happened + openRequests.prepend(request); + break; + } else if (!isServiceDiscoveryRun) { + // not encryption problem -> abort readCharacteristic()/readDescriptor() run + if (!descriptorHandle) + service->setError(QLowEnergyService::CharacteristicReadError); + else + service->setError(QLowEnergyService::DescriptorReadError); + } + } else { + if (!descriptorHandle) + updateValueOfCharacteristic(charHandle, response.mid(1), NEW_VALUE); + else + updateValueOfDescriptor(charHandle, descriptorHandle, + response.mid(1), NEW_VALUE); + + if (response.size() == mtuSize) { + qCDebug(QT_BT_BLUEZ) << "Switching to blob reads for" + << charHandle << descriptorHandle + << service->characteristicList[charHandle].uuid.toString(); + // Potentially more data -> switch to blob reads + readServiceValuesByOffset(handleData, mtuSize-1, + request.reference2.toBool()); + break; + } else if (!isServiceDiscoveryRun) { + // readCharacteristic() or readDescriptor() ongoing + if (!descriptorHandle) { + QLowEnergyCharacteristic ch(service, charHandle); + emit service->characteristicRead(ch, response.mid(1)); + } else { + QLowEnergyDescriptor descriptor(service, charHandle, descriptorHandle); + emit service->descriptorRead(descriptor, response.mid(1)); + } + break; + } + } + + if (request.reference2.toBool() && isServiceDiscoveryRun) { + // we only run into this code path during the initial service discovery + // and not when processing readCharacteristics() after service discovery + + //last characteristic -> progress to descriptor discovery + //last descriptor -> service discovery is done + if (!descriptorHandle) + discoverServiceDescriptors(service->uuid); + else + service->setState(QLowEnergyService::RemoteServiceDiscovered); + } + } break; + case QBluezConst::AttCommand::ATT_OP_READ_BLOB_REQUEST: // error case + case QBluezConst::AttCommand::ATT_OP_READ_BLOB_RESPONSE: { + //Reading characteristic or descriptor with value longer value than MTU + Q_ASSERT(request.command == QBluezConst::AttCommand::ATT_OP_READ_BLOB_REQUEST); + + uint handleData = request.reference.toUInt(); + const QLowEnergyHandle charHandle = (handleData & 0xffff); + const QLowEnergyHandle descriptorHandle = ((handleData >> 16) & 0xffff); + + QSharedPointer service = serviceForHandle(charHandle); + Q_ASSERT(!service.isNull()); + + /* + * READ_BLOB does not require encryption setup code. BLOB commands + * are only issued after read request if the read request is too long + * for single MTU. The preceding read request would have triggered + * the setup of the encryption already. + */ + if (!isErrorResponse) { + quint16 length = 0; + if (!descriptorHandle) + length = updateValueOfCharacteristic(charHandle, response.mid(1), APPEND_VALUE); + else + length = updateValueOfDescriptor(charHandle, descriptorHandle, + response.mid(1), APPEND_VALUE); + + if (response.size() == mtuSize) { + readServiceValuesByOffset(handleData, length, + request.reference2.toBool()); + break; + } else if (service->state == QLowEnergyService::RemoteServiceDiscovered) { + // readCharacteristic() or readDescriptor() ongoing + if (!descriptorHandle) { + QLowEnergyCharacteristic ch(service, charHandle); + emit service->characteristicRead(ch, ch.value()); + } else { + QLowEnergyDescriptor descriptor(service, charHandle, descriptorHandle); + emit service->descriptorRead(descriptor, descriptor.value()); + } + break; + } + } else { + qWarning() << "READ BLOB for char:" << charHandle + << "descriptor:" << descriptorHandle << "on service" + << service->uuid.toString() << "failed (service discovery run:" + << (service->state == QLowEnergyService::RemoteServiceDiscovered) << ")"; + } + + if (request.reference2.toBool()) { + //last overlong characteristic -> progress to descriptor discovery + //last overlong descriptor -> service discovery is done + + if (!descriptorHandle) + discoverServiceDescriptors(service->uuid); + else + service->setState(QLowEnergyService::RemoteServiceDiscovered); + } + + } break; + case QBluezConst::AttCommand::ATT_OP_FIND_INFORMATION_REQUEST: // error case + case QBluezConst::AttCommand::ATT_OP_FIND_INFORMATION_RESPONSE: { + //Discovering descriptors + Q_ASSERT(request.command == QBluezConst::AttCommand::ATT_OP_FIND_INFORMATION_REQUEST); + + /* packet format: + * []+ + * + * The uuid can be 16 or 128 bit which is indicated by format. + */ + + QList keys = request.reference.value >(); + if (keys.isEmpty()) { + qCWarning(QT_BT_BLUEZ) << "Descriptor discovery for unknown characteristic received"; + break; + } + QLowEnergyHandle charHandle = keys.first(); + + QSharedPointer p = + serviceForHandle(charHandle); + Q_ASSERT(!p.isNull()); + + if (isErrorResponse) { + if (keys.size() == 1) { + // no more descriptors to discover + readServiceValues(p->uuid, false); //read descriptor values + } else { + // hop to the next descriptor + keys.removeFirst(); + discoverNextDescriptor(p, keys, keys.first()); + } + break; + } + + const quint8 format = response[1]; + quint16 elementLength; + switch (format) { + case 0x01: + elementLength = 2 + 2; //sizeof(QLowEnergyHandle) + 16bit uuid + break; + case 0x02: + elementLength = 2 + 16; //sizeof(QLowEnergyHandle) + 128bit uuid + break; + default: + qCWarning(QT_BT_BLUEZ) << "Unknown format in FIND_INFORMATION_RESPONSE"; + return; + } + + const quint16 numElements = (response.size() - 2) / elementLength; + + quint16 offset = 2; + QLowEnergyHandle descriptorHandle {}; + QBluetoothUuid uuid; + const char *data = response.constData(); + for (int i = 0; i < numElements; i++) { + descriptorHandle = bt_get_le16(&data[offset]); + + if (format == 0x01) + uuid = QBluetoothUuid(bt_get_le16(&data[offset+2])); + else if (format == 0x02) + uuid = QUuid::fromBytes(&data[offset+2], QSysInfo::LittleEndian); + + offset += elementLength; + + // ignore all attributes which are not of type descriptor + // examples are the characteristics value or + bool ok = false; + quint16 shortUuid = uuid.toUInt16(&ok); + if (ok && shortUuid >= QLowEnergyServicePrivate::PrimaryService + && shortUuid <= QLowEnergyServicePrivate::Characteristic){ + qCDebug(QT_BT_BLUEZ) << "Suppressing primary/characteristic" << Qt::hex << shortUuid; + continue; + } + + // ignore value handle + if (descriptorHandle == p->characteristicList[charHandle].valueHandle) { + qCDebug(QT_BT_BLUEZ) << "Suppressing char handle" << Qt::hex << descriptorHandle; + continue; + } + + QLowEnergyServicePrivate::DescData data; + data.uuid = uuid; + p->characteristicList[charHandle].descriptorList.insert( + descriptorHandle, data); + + qCDebug(QT_BT_BLUEZ) << "Descriptor found, uuid:" + << uuid.toString() + << "descriptor handle:" << Qt::hex << descriptorHandle; + } + + const QLowEnergyHandle nextPotentialHandle = descriptorHandle + 1; + if (keys.size() == 1) { + // Reached last characteristic of service + + // The endhandle of a service is always the last handle of + // the current service. We must either continue until we have reached + // the starting handle of the next service (endHandle+1) or + // the last physical handle address (0xffff). Note that + // the endHandle of the last service on the device is 0xffff. + + if ((p->endHandle != 0xffff && nextPotentialHandle >= p->endHandle + 1) + || (descriptorHandle == 0xffff)) { + keys.removeFirst(); + // last descriptor of last characteristic found + // continue with reading descriptor values + readServiceValues(p->uuid, false); + } else { + discoverNextDescriptor(p, keys, nextPotentialHandle); + } + } else { + if (nextPotentialHandle >= keys[1]) //reached next char + keys.removeFirst(); + discoverNextDescriptor(p, keys, nextPotentialHandle); + } + } break; + case QBluezConst::AttCommand::ATT_OP_WRITE_REQUEST: // error case + case QBluezConst::AttCommand::ATT_OP_WRITE_RESPONSE: { + //Write command response + Q_ASSERT(request.command == QBluezConst::AttCommand::ATT_OP_WRITE_REQUEST); + + uint ref = request.reference.toUInt(); + const QLowEnergyHandle charHandle = (ref & 0xffff); + const QLowEnergyHandle descriptorHandle = ((ref >> 16) & 0xffff); + + QSharedPointer service = serviceForHandle(charHandle); + if (service.isNull() || !service->characteristicList.contains(charHandle)) + break; + + if (isErrorResponse) { + Q_ASSERT(!encryptionChangePending); + QBluezConst::AttError err = static_cast(response.constData()[4]); + encryptionChangePending = increaseEncryptLevelfRequired(err); + if (encryptionChangePending) { + openRequests.prepend(request); + break; + } + + if (!descriptorHandle) + service->setError(QLowEnergyService::CharacteristicWriteError); + else + service->setError(QLowEnergyService::DescriptorWriteError); + break; + } + + const QByteArray newValue = request.reference2.toByteArray(); + if (!descriptorHandle) { + QLowEnergyCharacteristic ch(service, charHandle); + if (ch.properties() & QLowEnergyCharacteristic::Read) + updateValueOfCharacteristic(charHandle, newValue, NEW_VALUE); + emit service->characteristicWritten(ch, newValue); + } else { + updateValueOfDescriptor(charHandle, descriptorHandle, newValue, NEW_VALUE); + QLowEnergyDescriptor descriptor(service, charHandle, descriptorHandle); + emit service->descriptorWritten(descriptor, newValue); + } + } break; + case QBluezConst::AttCommand::ATT_OP_PREPARE_WRITE_REQUEST: // error case + case QBluezConst::AttCommand::ATT_OP_PREPARE_WRITE_RESPONSE: { + //Prepare write command response + Q_ASSERT(request.command == QBluezConst::AttCommand::ATT_OP_PREPARE_WRITE_REQUEST); + + uint handleData = request.reference.toUInt(); + const QLowEnergyHandle attrHandle = (handleData & 0xffff); + const QByteArray newValue = request.reference2.toByteArray(); + const int writtenPayload = ((handleData >> 16) & 0xffff); + + if (isErrorResponse) { + Q_ASSERT(!encryptionChangePending); + QBluezConst::AttError err = static_cast(response.constData()[4]); + encryptionChangePending = increaseEncryptLevelfRequired(err); + if (encryptionChangePending) { + openRequests.prepend(request); + break; + } + //emits error on cancellation and aborts existing prepare reuqests + sendExecuteWriteRequest(attrHandle, newValue, true); + } else { + if (writtenPayload < newValue.size()) { + sendNextPrepareWriteRequest(attrHandle, newValue, writtenPayload); + } else { + sendExecuteWriteRequest(attrHandle, newValue, false); + } + } + } break; + case QBluezConst::AttCommand::ATT_OP_EXECUTE_WRITE_REQUEST: // error case + case QBluezConst::AttCommand::ATT_OP_EXECUTE_WRITE_RESPONSE: { + // right now used in connection with long characteristic/descriptor value writes + // not catering for reliable writes + Q_ASSERT(request.command == QBluezConst::AttCommand::ATT_OP_EXECUTE_WRITE_REQUEST); + + uint handleData = request.reference.toUInt(); + const QLowEnergyHandle attrHandle = handleData & 0xffff; + bool wasCancellation = !((handleData >> 16) & 0xffff); + const QByteArray newValue = request.reference2.toByteArray(); + + // is it a descriptor or characteristic? + const QLowEnergyDescriptor descriptor = descriptorForHandle(attrHandle); + QSharedPointer service = serviceForHandle(attrHandle); + Q_ASSERT(!service.isNull()); + + if (isErrorResponse || wasCancellation) { + // charHandle == 0 -> cancellation + if (descriptor.isValid()) + service->setError(QLowEnergyService::DescriptorWriteError); + else + service->setError(QLowEnergyService::CharacteristicWriteError); + } else { + if (descriptor.isValid()) { + updateValueOfDescriptor(descriptor.characteristicHandle(), + attrHandle, newValue, NEW_VALUE); + emit service->descriptorWritten(descriptor, newValue); + } else { + QLowEnergyCharacteristic ch(service, attrHandle); + if (ch.properties() & QLowEnergyCharacteristic::Read) + updateValueOfCharacteristic(attrHandle, newValue, NEW_VALUE); + emit service->characteristicWritten(ch, newValue); + } + } + } break; + default: + qCDebug(QT_BT_BLUEZ) << "Unknown packet: " << response.toHex(); + break; + } +} + +void QLowEnergyControllerPrivateBluez::discoverServices() +{ + sendReadByGroupRequest(0x0001, 0xFFFF, GATT_PRIMARY_SERVICE); +} + +void QLowEnergyControllerPrivateBluez::sendReadByGroupRequest( + QLowEnergyHandle start, QLowEnergyHandle end, quint16 type) +{ + //call for primary and secondary services + quint8 packet[GRP_TYPE_REQ_HEADER_SIZE]; + + packet[0] = static_cast(QBluezConst::AttCommand::ATT_OP_READ_BY_GROUP_REQUEST); + putBtData(start, &packet[1]); + putBtData(end, &packet[3]); + putBtData(type, &packet[5]); + + QByteArray data(GRP_TYPE_REQ_HEADER_SIZE, Qt::Uninitialized); + memcpy(data.data(), packet, GRP_TYPE_REQ_HEADER_SIZE); + qCDebug(QT_BT_BLUEZ) << "Sending read_by_group_type request, startHandle:" << Qt::hex + << start << "endHandle:" << end << type; + + Request request; + request.payload = data; + request.command = QBluezConst::AttCommand::ATT_OP_READ_BY_GROUP_REQUEST; + request.reference = type; + openRequests.enqueue(request); + + sendNextPendingRequest(); +} + +void QLowEnergyControllerPrivateBluez::discoverServiceDetails(const QBluetoothUuid &service, + QLowEnergyService::DiscoveryMode mode) +{ + if (!serviceList.contains(service)) { + qCWarning(QT_BT_BLUEZ) << "Discovery of unknown service" << service.toString() + << "not possible"; + return; + } + + QSharedPointer serviceData = serviceList.value(service); + serviceData->mode = mode; + serviceData->characteristicList.clear(); + sendReadByTypeRequest(serviceData, serviceData->startHandle, GATT_INCLUDED_SERVICE); +} + +void QLowEnergyControllerPrivateBluez::sendReadByTypeRequest( + QSharedPointer serviceData, + QLowEnergyHandle nextHandle, quint16 attributeType) +{ + quint8 packet[READ_BY_TYPE_REQ_HEADER_SIZE]; + + packet[0] = static_cast(QBluezConst::AttCommand::ATT_OP_READ_BY_TYPE_REQUEST); + putBtData(nextHandle, &packet[1]); + putBtData(serviceData->endHandle, &packet[3]); + putBtData(attributeType, &packet[5]); + + QByteArray data(READ_BY_TYPE_REQ_HEADER_SIZE, Qt::Uninitialized); + memcpy(data.data(), packet, READ_BY_TYPE_REQ_HEADER_SIZE); + qCDebug(QT_BT_BLUEZ) << "Sending read_by_type request, startHandle:" << Qt::hex + << nextHandle << "endHandle:" << serviceData->endHandle + << "type:" << attributeType << "packet:" << data.toHex(); + + Request request; + request.payload = data; + request.command = QBluezConst::AttCommand::ATT_OP_READ_BY_TYPE_REQUEST; + request.reference = QVariant::fromValue(serviceData); + request.reference2 = attributeType; + openRequests.enqueue(request); + + sendNextPendingRequest(); +} + +/*! + \internal + + Reads all values of specific characteristic and descriptor. This function is + used during the initial service discovery process. + + \a readCharacteristics determines whether we intend to read a characteristic; + otherwise we read a descriptor. + */ +void QLowEnergyControllerPrivateBluez::readServiceValues( + const QBluetoothUuid &serviceUuid, bool readCharacteristics) +{ + quint8 packet[READ_REQUEST_HEADER_SIZE]; + if (QT_BT_BLUEZ().isDebugEnabled()) { + if (readCharacteristics) + qCDebug(QT_BT_BLUEZ) << "Reading all characteristic values for" + << serviceUuid.toString(); + else + qCDebug(QT_BT_BLUEZ) << "Reading all descriptor values for" + << serviceUuid.toString(); + } + + QSharedPointer service = serviceList.value(serviceUuid); + + if (service->mode == QLowEnergyService::SkipValueDiscovery) { + if (readCharacteristics) { + // -> continue with descriptor discovery + discoverServiceDescriptors(service->uuid); + } else { + service->setState(QLowEnergyService::RemoteServiceDiscovered); + } + return; + } + + // pair.first -> target attribute + // pair.second -> context information for read request + QPair pair; + + // Create list of attribute handles which need to be read + QList > targetHandles; + + CharacteristicDataMap::const_iterator charIt = service->characteristicList.constBegin(); + for ( ; charIt != service->characteristicList.constEnd(); ++charIt) { + const QLowEnergyHandle charHandle = charIt.key(); + const QLowEnergyServicePrivate::CharData &charDetails = charIt.value(); + + if (readCharacteristics) { + // Collect handles of all characteristic value attributes + + // Don't try to read writeOnly characteristic + if (!(charDetails.properties & QLowEnergyCharacteristic::Read)) + continue; + + pair.first = charDetails.valueHandle; + pair.second = charHandle; + targetHandles.append(pair); + + } else { + // Collect handles of all descriptor attributes + DescriptorDataMap::const_iterator descIt = charDetails.descriptorList.constBegin(); + for ( ; descIt != charDetails.descriptorList.constEnd(); ++descIt) { + const QLowEnergyHandle descriptorHandle = descIt.key(); + + pair.first = descriptorHandle; + pair.second = (charHandle | (descriptorHandle << 16)); + targetHandles.append(pair); + } + } + } + + + if (targetHandles.isEmpty()) { + if (readCharacteristics) { + // none of the characteristics is readable + // -> continue with descriptor discovery + discoverServiceDescriptors(service->uuid); + } else { + // characteristic w/o descriptors + service->setState(QLowEnergyService::RemoteServiceDiscovered); + } + return; + } + + for (qsizetype i = 0; i < targetHandles.size(); i++) { + pair = targetHandles.at(i); + packet[0] = static_cast(QBluezConst::AttCommand::ATT_OP_READ_REQUEST); + putBtData(pair.first, &packet[1]); + + QByteArray data(READ_REQUEST_HEADER_SIZE, Qt::Uninitialized); + memcpy(data.data(), packet, READ_REQUEST_HEADER_SIZE); + + Request request; + request.payload = data; + request.command = QBluezConst::AttCommand::ATT_OP_READ_REQUEST; + request.reference = pair.second; + // last entry? + request.reference2 = QVariant((bool)(i + 1 == targetHandles.size())); + openRequests.enqueue(request); + } + + sendNextPendingRequest(); +} + +/*! + \internal + + This function is used when reading a handle value that is + longer than the mtuSize. + + The BLOB read request is prepended to the list of + open requests to finish the current value read up before + starting the next read request. + */ +void QLowEnergyControllerPrivateBluez::readServiceValuesByOffset( + uint handleData, quint16 offset, bool isLastValue) +{ + const QLowEnergyHandle charHandle = (handleData & 0xffff); + const QLowEnergyHandle descriptorHandle = ((handleData >> 16) & 0xffff); + + QByteArray data(READ_BLOB_REQUEST_HEADER_SIZE, Qt::Uninitialized); + data[0] = static_cast(QBluezConst::AttCommand::ATT_OP_READ_BLOB_REQUEST); + + QLowEnergyHandle handleToRead = charHandle; + if (descriptorHandle) { + handleToRead = descriptorHandle; + qCDebug(QT_BT_BLUEZ) << "Reading descriptor via blob request" + << Qt::hex << descriptorHandle; + } else { + //charHandle is not the char's value handle + QSharedPointer service = + serviceForHandle(charHandle); + if (!service.isNull() + && service->characteristicList.contains(charHandle)) { + handleToRead = service->characteristicList[charHandle].valueHandle; + qCDebug(QT_BT_BLUEZ) << "Reading characteristic via blob request" + << Qt::hex << handleToRead; + } else { + Q_ASSERT(false); + } + } + + putBtData(handleToRead, data.data() + 1); + putBtData(offset, data.data() + 3); + + Request request; + request.payload = data; + request.command = QBluezConst::AttCommand::ATT_OP_READ_BLOB_REQUEST; + request.reference = handleData; + request.reference2 = isLastValue; + openRequests.prepend(request); +} + +void QLowEnergyControllerPrivateBluez::discoverServiceDescriptors( + const QBluetoothUuid &serviceUuid) +{ + qCDebug(QT_BT_BLUEZ) << "Discovering descriptor values for" + << serviceUuid.toString(); + QSharedPointer service = serviceList.value(serviceUuid); + + if (service->characteristicList.isEmpty()) { // service has no characteristics + // implies that characteristic & descriptor discovery can be skipped + service->setState(QLowEnergyService::RemoteServiceDiscovered); + return; + } + + // start handle of all known characteristics + QList keys = service->characteristicList.keys(); + std::sort(keys.begin(), keys.end()); + + discoverNextDescriptor(service, keys, keys[0]); +} + +void QLowEnergyControllerPrivateBluez::processUnsolicitedReply(const QByteArray &payload) +{ + const char *data = payload.constData(); + bool isNotification = (static_cast(data[0]) + == QBluezConst::AttCommand::ATT_OP_HANDLE_VAL_NOTIFICATION); + const QLowEnergyHandle changedHandle = bt_get_le16(&data[1]); + + if (QT_BT_BLUEZ().isDebugEnabled()) { + if (isNotification) + qCDebug(QT_BT_BLUEZ) << "Change notification for handle" << Qt::hex << changedHandle; + else + qCDebug(QT_BT_BLUEZ) << "Change indication for handle" << Qt::hex << changedHandle; + } + + const QLowEnergyCharacteristic ch = characteristicForHandle(changedHandle); + if (ch.isValid() && ch.handle() == changedHandle) { + if (ch.properties() & QLowEnergyCharacteristic::Read) + updateValueOfCharacteristic(ch.attributeHandle(), payload.mid(3), NEW_VALUE); + emit ch.d_ptr->characteristicChanged(ch, payload.mid(3)); + } else { + qCWarning(QT_BT_BLUEZ) << "Cannot find matching characteristic for " + "notification/indication"; + } +} + +void QLowEnergyControllerPrivateBluez::exchangeMTU() +{ + qCDebug(QT_BT_BLUEZ) << "Exchanging MTU"; + + quint8 packet[MTU_EXCHANGE_HEADER_SIZE]; + packet[0] = static_cast(QBluezConst::AttCommand::ATT_OP_EXCHANGE_MTU_REQUEST); + putBtData(ATT_MAX_LE_MTU, &packet[1]); + + QByteArray data(MTU_EXCHANGE_HEADER_SIZE, Qt::Uninitialized); + memcpy(data.data(), packet, MTU_EXCHANGE_HEADER_SIZE); + + Request request; + request.payload = data; + request.command = QBluezConst::AttCommand::ATT_OP_EXCHANGE_MTU_REQUEST; + openRequests.enqueue(request); + + sendNextPendingRequest(); +} + +int QLowEnergyControllerPrivateBluez::securityLevel() const +{ + int socket = l2cpSocket->socketDescriptor(); + if (socket < 0) { + qCWarning(QT_BT_BLUEZ) << "Invalid l2cp socket, aborting getting of sec level"; + return -1; + } + + struct bt_security secData; + socklen_t length = sizeof(secData); + memset(&secData, 0, length); + + if (getsockopt(socket, SOL_BLUETOOTH, BT_SECURITY, &secData, &length) == 0) { + qCDebug(QT_BT_BLUEZ) << "Current l2cp sec level:" << secData.level; + return secData.level; + } + + if (errno != ENOPROTOOPT) //older kernel, fall back to L2CAP_LM option + return -1; + + // cater for older kernels + int optval; + length = sizeof(optval); + if (getsockopt(socket, SOL_L2CAP, L2CAP_LM, &optval, &length) == 0) { + int level = BT_SECURITY_SDP; + if (optval & L2CAP_LM_AUTH) + level = BT_SECURITY_LOW; + if (optval & L2CAP_LM_ENCRYPT) + level = BT_SECURITY_MEDIUM; + if (optval & L2CAP_LM_SECURE) + level = BT_SECURITY_HIGH; + + qCDebug(QT_BT_BLUEZ) << "Current l2cp sec level (old):" << level; + return level; + } + + return -1; +} + +bool QLowEnergyControllerPrivateBluez::setSecurityLevel(int level) +{ + if (level > BT_SECURITY_HIGH || level < BT_SECURITY_LOW) + return false; + + int socket = l2cpSocket->socketDescriptor(); + if (socket < 0) { + qCWarning(QT_BT_BLUEZ) << "Invalid l2cp socket, aborting setting of sec level"; + return false; + } + + struct bt_security secData; + socklen_t length = sizeof(secData); + memset(&secData, 0, length); + secData.level = level; + + if (setsockopt(socket, SOL_BLUETOOTH, BT_SECURITY, &secData, length) == 0) { + qCDebug(QT_BT_BLUEZ) << "Setting new l2cp sec level:" << secData.level; + return true; + } + + if (errno != ENOPROTOOPT) //older kernel + return false; + + int optval = 0; + switch (level) { // fall through intendeds + case BT_SECURITY_HIGH: + optval |= L2CAP_LM_SECURE; + Q_FALLTHROUGH(); + case BT_SECURITY_MEDIUM: + optval |= L2CAP_LM_ENCRYPT; + Q_FALLTHROUGH(); + case BT_SECURITY_LOW: + optval |= L2CAP_LM_AUTH; + break; + default: + return false; + } + + if (setsockopt(socket, SOL_L2CAP, L2CAP_LM, &optval, sizeof(optval)) == 0) { + qCDebug(QT_BT_BLUEZ) << "Old l2cp sec level:" << optval; + return true; + } + + return false; +} + +void QLowEnergyControllerPrivateBluez::discoverNextDescriptor( + QSharedPointer serviceData, + const QList pendingCharHandles, + const QLowEnergyHandle startingHandle) +{ + Q_ASSERT(!pendingCharHandles.isEmpty()); + Q_ASSERT(!serviceData.isNull()); + + qCDebug(QT_BT_BLUEZ) << "Sending find_info request" << Qt::hex + << pendingCharHandles << startingHandle; + + quint8 packet[FIND_INFO_REQUEST_HEADER_SIZE]; + packet[0] = static_cast(QBluezConst::AttCommand::ATT_OP_FIND_INFORMATION_REQUEST); + + const QLowEnergyHandle charStartHandle = startingHandle; + QLowEnergyHandle charEndHandle = 0; + if (pendingCharHandles.size() == 1) //single characteristic + charEndHandle = serviceData->endHandle; + else + charEndHandle = pendingCharHandles[1] - 1; + + putBtData(charStartHandle, &packet[1]); + putBtData(charEndHandle, &packet[3]); + + QByteArray data(FIND_INFO_REQUEST_HEADER_SIZE, Qt::Uninitialized); + memcpy(data.data(), packet, FIND_INFO_REQUEST_HEADER_SIZE); + + Request request; + request.payload = data; + request.command = QBluezConst::AttCommand::ATT_OP_FIND_INFORMATION_REQUEST; + request.reference = QVariant::fromValue >(pendingCharHandles); + request.reference2 = startingHandle; + openRequests.enqueue(request); + + sendNextPendingRequest(); +} + +void QLowEnergyControllerPrivateBluez::sendNextPrepareWriteRequest( + const QLowEnergyHandle handle, const QByteArray &newValue, + quint16 offset) +{ + // is it a descriptor or characteristic? + QLowEnergyHandle targetHandle = 0; + const QLowEnergyDescriptor descriptor = descriptorForHandle(handle); + if (descriptor.isValid()) + targetHandle = descriptor.handle(); + else + targetHandle = characteristicForHandle(handle).handle(); + + if (!targetHandle) { + qCWarning(QT_BT_BLUEZ) << "sendNextPrepareWriteRequest cancelled due to invalid handle" + << handle; + return; + } + + quint8 packet[PREPARE_WRITE_HEADER_SIZE]; + packet[0] = static_cast(QBluezConst::AttCommand::ATT_OP_PREPARE_WRITE_REQUEST); + putBtData(targetHandle, &packet[1]); // attribute handle + putBtData(offset, &packet[3]); // offset into newValue + + qCDebug(QT_BT_BLUEZ) << "Writing long characteristic (prepare):" + << Qt::hex << handle; + + + const qsizetype maxAvailablePayload = qsizetype(mtuSize) - PREPARE_WRITE_HEADER_SIZE; + const qsizetype requiredPayload = (std::min)(newValue.size() - offset, maxAvailablePayload); + const qsizetype dataSize = PREPARE_WRITE_HEADER_SIZE + requiredPayload; + + Q_ASSERT((offset + requiredPayload) <= newValue.size()); + Q_ASSERT(dataSize <= mtuSize); + + QByteArray data(dataSize, Qt::Uninitialized); + memcpy(data.data(), packet, PREPARE_WRITE_HEADER_SIZE); + memcpy(&(data.data()[PREPARE_WRITE_HEADER_SIZE]), &(newValue.constData()[offset]), + requiredPayload); + + Request request; + request.payload = data; + request.command = QBluezConst::AttCommand::ATT_OP_PREPARE_WRITE_REQUEST; + request.reference = (handle | ((offset + requiredPayload) << 16)); + request.reference2 = newValue; + openRequests.enqueue(request); +} + +/*! + Sends an "Execute Write Request" for a long characteristic or descriptor write. + This cannot be used for executes in relation to reliable write requests. + + A cancellation removes all pending prepare write request on the GATT server. + Otherwise this function sends an execute request for all pending prepare + write requests. + */ +void QLowEnergyControllerPrivateBluez::sendExecuteWriteRequest( + const QLowEnergyHandle attrHandle, const QByteArray &newValue, + bool isCancelation) +{ + quint8 packet[EXECUTE_WRITE_HEADER_SIZE]; + packet[0] = static_cast(QBluezConst::AttCommand::ATT_OP_EXECUTE_WRITE_REQUEST); + if (isCancelation) + packet[1] = 0x00; // cancel pending write prepare requests + else + packet[1] = 0x01; // execute pending write prepare requests + + QByteArray data(EXECUTE_WRITE_HEADER_SIZE, Qt::Uninitialized); + memcpy(data.data(), packet, EXECUTE_WRITE_HEADER_SIZE); + + qCDebug(QT_BT_BLUEZ) << "Sending Execute Write Request for long characteristic value" + << Qt::hex << attrHandle; + + Request request; + request.payload = data; + request.command = QBluezConst::AttCommand::ATT_OP_EXECUTE_WRITE_REQUEST; + request.reference = (attrHandle | ((isCancelation ? 0x00 : 0x01) << 16)); + request.reference2 = newValue; + openRequests.prepend(request); +} + + +/*! + Writes long (prepare write request), short (write request) + and writeWithoutResponse characteristic values. + + TODO Reliable/prepare write across multiple characteristics is not supported + */ +void QLowEnergyControllerPrivateBluez::writeCharacteristic( + const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QByteArray &newValue, + QLowEnergyService::WriteMode mode) +{ + Q_ASSERT(!service.isNull()); + + if (!service->characteristicList.contains(charHandle)) + return; + + QLowEnergyServicePrivate::CharData &charData = service->characteristicList[charHandle]; + if (role == QLowEnergyController::PeripheralRole) + writeCharacteristicForPeripheral(charData, newValue); + else + writeCharacteristicForCentral(service, charHandle, charData.valueHandle, newValue, mode); +} + +void QLowEnergyControllerPrivateBluez::writeDescriptor( + const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle, + const QByteArray &newValue) +{ + Q_ASSERT(!service.isNull()); + + if (role == QLowEnergyController::PeripheralRole) + writeDescriptorForPeripheral(service, charHandle, descriptorHandle, newValue); + else + writeDescriptorForCentral(charHandle, descriptorHandle, newValue); +} + +/*! + \internal + + Reads the value of one specific characteristic. + */ +void QLowEnergyControllerPrivateBluez::readCharacteristic( + const QSharedPointer service, + const QLowEnergyHandle charHandle) +{ + Q_ASSERT(!service.isNull()); + if (!service->characteristicList.contains(charHandle)) + return; + + const QLowEnergyServicePrivate::CharData &charDetails + = service->characteristicList[charHandle]; + if (!(charDetails.properties & QLowEnergyCharacteristic::Read)) { + // if this succeeds the device has a bug, char is advertised as + // non-readable. We try to be permissive and let the remote + // device answer to the read attempt + qCWarning(QT_BT_BLUEZ) << "Reading non-readable char" << charHandle; + } + + quint8 packet[READ_REQUEST_HEADER_SIZE]; + packet[0] = static_cast(QBluezConst::AttCommand::ATT_OP_READ_REQUEST); + putBtData(charDetails.valueHandle, &packet[1]); + + QByteArray data(READ_REQUEST_HEADER_SIZE, Qt::Uninitialized); + memcpy(data.data(), packet, READ_REQUEST_HEADER_SIZE); + + qCDebug(QT_BT_BLUEZ) << "Targeted reading characteristic" << Qt::hex << charHandle; + + Request request; + request.payload = data; + request.command = QBluezConst::AttCommand::ATT_OP_READ_REQUEST; + request.reference = charHandle; + // reference2 not really required but false prevents service discovery + // code from running in QBluezConst::AttCommand::ATT_OP_READ_RESPONSE handler + request.reference2 = false; + openRequests.enqueue(request); + + sendNextPendingRequest(); +} + +void QLowEnergyControllerPrivateBluez::readDescriptor( + const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle) +{ + Q_ASSERT(!service.isNull()); + if (!service->characteristicList.contains(charHandle)) + return; + + const QLowEnergyServicePrivate::CharData &charDetails + = service->characteristicList[charHandle]; + if (!charDetails.descriptorList.contains(descriptorHandle)) + return; + + quint8 packet[READ_REQUEST_HEADER_SIZE]; + packet[0] = static_cast(QBluezConst::AttCommand::ATT_OP_READ_REQUEST); + putBtData(descriptorHandle, &packet[1]); + + QByteArray data(READ_REQUEST_HEADER_SIZE, Qt::Uninitialized); + memcpy(data.data(), packet, READ_REQUEST_HEADER_SIZE); + + qCDebug(QT_BT_BLUEZ) << "Targeted reading descriptor" << Qt::hex << descriptorHandle; + + Request request; + request.payload = data; + request.command = QBluezConst::AttCommand::ATT_OP_READ_REQUEST; + request.reference = (charHandle | (descriptorHandle << 16)); + // reference2 not really required but false prevents service discovery + // code from running in QBluezConst::AttCommand::ATT_OP_READ_RESPONSE handler + request.reference2 = false; + openRequests.enqueue(request); + + sendNextPendingRequest(); +} + +/*! + * Returns true if the encryption change was successfully requested. + * The request is triggered if we got a related ATT error. + */ +bool QLowEnergyControllerPrivateBluez::increaseEncryptLevelfRequired( + QBluezConst::AttError errorCode) +{ + if (securityLevelValue == BT_SECURITY_HIGH) + return false; + + switch (errorCode) { + case QBluezConst::AttError::ATT_ERROR_INSUF_ENCRYPTION: + case QBluezConst::AttError::ATT_ERROR_INSUF_AUTHENTICATION: + case QBluezConst::AttError::ATT_ERROR_INSUF_ENCR_KEY_SIZE: + if (!hciManager->isValid()) + return false; + if (!hciManager->monitorEvent(HciManager::HciEvent::EVT_ENCRYPT_CHANGE)) + return false; + if (securityLevelValue != BT_SECURITY_HIGH) { + qCDebug(QT_BT_BLUEZ) << "Requesting encrypted link"; + if (setSecurityLevel(BT_SECURITY_HIGH)) { + restartRequestTimer(); + return true; + } + } + break; + default: + break; + } + + return false; +} + +void QLowEnergyControllerPrivateBluez::handleAdvertisingError() +{ + qCWarning(QT_BT_BLUEZ) << "received advertising error"; + setError(QLowEnergyController::AdvertisingError); + setState(QLowEnergyController::UnconnectedState); +} + +bool QLowEnergyControllerPrivateBluez::checkPacketSize(const QByteArray &packet, int minSize, + int maxSize) +{ + if (maxSize == -1) + maxSize = minSize; + if (Q_LIKELY(packet.size() >= minSize && packet.size() <= maxSize)) + return true; + qCWarning(QT_BT_BLUEZ) << "client request of type" << packet.at(0) + << "has unexpected packet size" << packet.size(); + sendErrorResponse(static_cast(packet.at(0)), 0, + QBluezConst::AttError::ATT_ERROR_INVALID_PDU); + return false; +} + +bool QLowEnergyControllerPrivateBluez::checkHandle(const QByteArray &packet, QLowEnergyHandle handle) +{ + if (handle != 0 && handle <= lastLocalHandle) + return true; + sendErrorResponse(static_cast(packet.at(0)), handle, + QBluezConst::AttError::ATT_ERROR_INVALID_HANDLE); + return false; +} + +bool QLowEnergyControllerPrivateBluez::checkHandlePair(QBluezConst::AttCommand request, + QLowEnergyHandle startingHandle, + QLowEnergyHandle endingHandle) +{ + if (startingHandle == 0 || startingHandle > endingHandle) { + qCDebug(QT_BT_BLUEZ) << "handle range invalid"; + sendErrorResponse(request, startingHandle, QBluezConst::AttError::ATT_ERROR_INVALID_HANDLE); + return false; + } + return true; +} + +void QLowEnergyControllerPrivateBluez::handleExchangeMtuRequest(const QByteArray &packet) +{ + // Spec v4.2, Vol 3, Part F, 3.4.2 + + if (!checkPacketSize(packet, 3)) + return; + if (receivedMtuExchangeRequest) { // Client must only send this once per connection. + qCDebug(QT_BT_BLUEZ) << "Client sent extraneous MTU exchange packet"; + sendErrorResponse(static_cast(packet.at(0)), 0, + QBluezConst::AttError::ATT_ERROR_REQUEST_NOT_SUPPORTED); + return; + } + receivedMtuExchangeRequest = true; + + // Send reply. + QByteArray reply(MTU_EXCHANGE_HEADER_SIZE, Qt::Uninitialized); + reply[0] = static_cast(QBluezConst::AttCommand::ATT_OP_EXCHANGE_MTU_RESPONSE); + putBtData(ATT_MAX_LE_MTU, reply.data() + 1); + sendPacket(reply); + + // Apply requested MTU. + const quint16 clientRxMtu = bt_get_le16(packet.constData() + 1); + mtuSize = std::clamp(clientRxMtu, ATT_DEFAULT_LE_MTU, ATT_MAX_LE_MTU); + qCDebug(QT_BT_BLUEZ) << "MTU request from client:" << clientRxMtu + << "effective client RX MTU:" << mtuSize; + qCDebug(QT_BT_BLUEZ) << "Sending server RX MTU" << ATT_MAX_LE_MTU; +} + +void QLowEnergyControllerPrivateBluez::handleFindInformationRequest(const QByteArray &packet) +{ + // Spec v4.2, Vol 3, Part F, 3.4.3.1-2 + + if (!checkPacketSize(packet, 5)) + return; + const QLowEnergyHandle startingHandle = bt_get_le16(packet.constData() + 1); + const QLowEnergyHandle endingHandle = bt_get_le16(packet.constData() + 3); + qCDebug(QT_BT_BLUEZ) << "client sends find information request; start:" << startingHandle + << "end:" << endingHandle; + if (!checkHandlePair(static_cast(packet.at(0)), startingHandle, + endingHandle)) + return; + + QList results = getAttributes(startingHandle, endingHandle); + if (results.isEmpty()) { + sendErrorResponse(static_cast(packet.at(0)), startingHandle, + QBluezConst::AttError::ATT_ERROR_ATTRIBUTE_NOT_FOUND); + return; + } + ensureUniformUuidSizes(results); + + QByteArray responsePrefix(2, Qt::Uninitialized); + const int uuidSize = getUuidSize(results.first().type); + responsePrefix[0] = + static_cast(QBluezConst::AttCommand::ATT_OP_FIND_INFORMATION_RESPONSE); + responsePrefix[1] = uuidSize == 2 ? 0x1 : 0x2; + const int elementSize = sizeof(QLowEnergyHandle) + uuidSize; + const auto elemWriter = [](const Attribute &attr, char *&data) { + putDataAndIncrement(attr.handle, data); + putDataAndIncrement(attr.type, data); + }; + sendListResponse(responsePrefix, elementSize, results, elemWriter); + +} + +void QLowEnergyControllerPrivateBluez::handleFindByTypeValueRequest(const QByteArray &packet) +{ + // Spec v4.2, Vol 3, Part F, 3.4.3.3-4 + + if (!checkPacketSize(packet, 7, mtuSize)) + return; + const QLowEnergyHandle startingHandle = bt_get_le16(packet.constData() + 1); + const QLowEnergyHandle endingHandle = bt_get_le16(packet.constData() + 3); + const quint16 type = bt_get_le16(packet.constData() + 5); + const QByteArray value = QByteArray::fromRawData(packet.constData() + 7, packet.size() - 7); + qCDebug(QT_BT_BLUEZ) << "client sends find by type value request; start:" << startingHandle + << "end:" << endingHandle << "type:" << type + << "value:" << value.toHex(); + if (!checkHandlePair(static_cast(packet.at(0)), startingHandle, + endingHandle)) + return; + + const auto predicate = [value, this, type](const Attribute &attr) { + return attr.type == QBluetoothUuid(type) && attr.value == value + && checkReadPermissions(attr) == QBluezConst::AttError::ATT_ERROR_NO_ERROR; + }; + const QList results = getAttributes(startingHandle, endingHandle, predicate); + if (results.isEmpty()) { + sendErrorResponse(static_cast(packet.at(0)), startingHandle, + QBluezConst::AttError::ATT_ERROR_ATTRIBUTE_NOT_FOUND); + return; + } + + QByteArray responsePrefix( + 1, static_cast(QBluezConst::AttCommand::ATT_OP_FIND_BY_TYPE_VALUE_RESPONSE)); + const int elemSize = 2 * sizeof(QLowEnergyHandle); + const auto elemWriter = [](const Attribute &attr, char *&data) { + putDataAndIncrement(attr.handle, data); + putDataAndIncrement(attr.groupEndHandle, data); + }; + sendListResponse(responsePrefix, elemSize, results, elemWriter); +} + +void QLowEnergyControllerPrivateBluez::handleReadByTypeRequest(const QByteArray &packet) +{ + // Spec v4.2, Vol 3, Part F, 3.4.4.1-2 + + if (!checkPacketSize(packet, 7, 21)) + return; + const QLowEnergyHandle startingHandle = bt_get_le16(packet.constData() + 1); + const QLowEnergyHandle endingHandle = bt_get_le16(packet.constData() + 3); + const void * const typeStart = packet.constData() + 5; + const bool is16BitUuid = packet.size() == 7; + const bool is128BitUuid = packet.size() == 21; + QBluetoothUuid type; + if (is16BitUuid) { + type = QBluetoothUuid(bt_get_le16(typeStart)); + } else if (is128BitUuid) { + type = QUuid::fromBytes(typeStart, QSysInfo::LittleEndian); + } else { + qCWarning(QT_BT_BLUEZ) << "read by type request has invalid packet size" << packet.size(); + sendErrorResponse(static_cast(packet.at(0)), 0, + QBluezConst::AttError::ATT_ERROR_INVALID_PDU); + return; + } + qCDebug(QT_BT_BLUEZ) << "client sends read by type request, start:" << startingHandle + << "end:" << endingHandle << "type:" << type; + if (!checkHandlePair(static_cast(packet.at(0)), startingHandle, + endingHandle)) + return; + + // Get all attributes with matching type. + QList results = + getAttributes(startingHandle, endingHandle, + [type](const Attribute &attr) { return attr.type == type; }); + ensureUniformValueSizes(results); + + if (results.isEmpty()) { + sendErrorResponse(static_cast(packet.at(0)), startingHandle, + QBluezConst::AttError::ATT_ERROR_ATTRIBUTE_NOT_FOUND); + return; + } + + const QBluezConst::AttError error = checkReadPermissions(results); + if (error != QBluezConst::AttError::ATT_ERROR_NO_ERROR) { + sendErrorResponse(static_cast(packet.at(0)), + results.first().handle, error); + return; + } + + const qsizetype elementSize = sizeof(QLowEnergyHandle) + results.first().value.size(); + QByteArray responsePrefix(2, Qt::Uninitialized); + responsePrefix[0] = static_cast(QBluezConst::AttCommand::ATT_OP_READ_BY_TYPE_RESPONSE); + responsePrefix[1] = elementSize; + const auto elemWriter = [](const Attribute &attr, char *&data) { + putDataAndIncrement(attr.handle, data); + putDataAndIncrement(attr.value, data); + }; + sendListResponse(responsePrefix, elementSize, results, elemWriter); +} + +void QLowEnergyControllerPrivateBluez::handleReadRequest(const QByteArray &packet) +{ + // Spec v4.2, Vol 3, Part F, 3.4.4.3-4 + + if (!checkPacketSize(packet, 3)) + return; + const QLowEnergyHandle handle = bt_get_le16(packet.constData() + 1); + qCDebug(QT_BT_BLUEZ) << "client sends read request; handle:" << handle; + + if (!checkHandle(packet, handle)) + return; + const Attribute &attribute = localAttributes.at(handle); + const QBluezConst::AttError permissionsError = checkReadPermissions(attribute); + if (permissionsError != QBluezConst::AttError::ATT_ERROR_NO_ERROR) { + sendErrorResponse(static_cast(packet.at(0)), handle, + permissionsError); + return; + } + + const qsizetype sentValueLength = (std::min)(attribute.value.size(), qsizetype(mtuSize) - 1); + QByteArray response(1 + sentValueLength, Qt::Uninitialized); + response[0] = static_cast(QBluezConst::AttCommand::ATT_OP_READ_RESPONSE); + using namespace std; + memcpy(response.data() + 1, attribute.value.constData(), sentValueLength); + qCDebug(QT_BT_BLUEZ) << "sending response:" << response.toHex(); + sendPacket(response); +} + +void QLowEnergyControllerPrivateBluez::handleReadBlobRequest(const QByteArray &packet) +{ + // Spec v4.2, Vol 3, Part F, 3.4.4.5-6 + + if (!checkPacketSize(packet, 5)) + return; + const QLowEnergyHandle handle = bt_get_le16(packet.constData() + 1); + const quint16 valueOffset = bt_get_le16(packet.constData() + 3); + qCDebug(QT_BT_BLUEZ) << "client sends read blob request; handle:" << handle + << "offset:" << valueOffset; + + if (!checkHandle(packet, handle)) + return; + const Attribute &attribute = localAttributes.at(handle); + const QBluezConst::AttError permissionsError = checkReadPermissions(attribute); + if (permissionsError != QBluezConst::AttError::ATT_ERROR_NO_ERROR) { + sendErrorResponse(static_cast(packet.at(0)), handle, + permissionsError); + return; + } + if (valueOffset > attribute.value.size()) { + sendErrorResponse(static_cast(packet.at(0)), handle, + QBluezConst::AttError::ATT_ERROR_INVALID_OFFSET); + return; + } + if (attribute.value.size() <= mtuSize - 3) { + sendErrorResponse(static_cast(packet.at(0)), handle, + QBluezConst::AttError::ATT_ERROR_ATTRIBUTE_NOT_LONG); + return; + } + + // Yes, this value can be zero. + const qsizetype sentValueLength = (std::min)(attribute.value.size() - valueOffset, + qsizetype(mtuSize) - 1); + + QByteArray response(1 + sentValueLength, Qt::Uninitialized); + response[0] = static_cast(QBluezConst::AttCommand::ATT_OP_READ_BLOB_RESPONSE); + using namespace std; + memcpy(response.data() + 1, attribute.value.constData() + valueOffset, sentValueLength); + qCDebug(QT_BT_BLUEZ) << "sending response:" << response.toHex(); + sendPacket(response); +} + +void QLowEnergyControllerPrivateBluez::handleReadMultipleRequest(const QByteArray &packet) +{ + // Spec v4.2, Vol 3, Part F, 3.4.4.7-8 + + if (!checkPacketSize(packet, 5, mtuSize)) + return; + QList handles((packet.size() - 1) / sizeof(QLowEnergyHandle)); + auto *packetPtr = reinterpret_cast(packet.constData() + 1); + for (qsizetype i = 0; i < handles.size(); ++i, ++packetPtr) + handles[i] = bt_get_le16(packetPtr); + qCDebug(QT_BT_BLUEZ) << "client sends read multiple request for handles" << handles; + + const auto it = std::find_if(handles.constBegin(), handles.constEnd(), + [this](QLowEnergyHandle handle) { return handle >= lastLocalHandle; }); + if (it != handles.constEnd()) { + sendErrorResponse(static_cast(packet.at(0)), *it, + QBluezConst::AttError::ATT_ERROR_INVALID_HANDLE); + return; + } + const QList results = getAttributes(handles.first(), handles.last()); + QByteArray response( + 1, static_cast(QBluezConst::AttCommand::ATT_OP_READ_MULTIPLE_RESPONSE)); + for (const Attribute &attr : results) { + const QBluezConst::AttError error = checkReadPermissions(attr); + if (error != QBluezConst::AttError::ATT_ERROR_NO_ERROR) { + sendErrorResponse(static_cast(packet.at(0)), attr.handle, + error); + return; + } + + // Note: We do not abort if no more values fit into the packet, because we still have to + // report possible permission errors for the other handles. + response += attr.value.left(mtuSize - response.size()); + } + + qCDebug(QT_BT_BLUEZ) << "sending response:" << response.toHex(); + sendPacket(response); +} + +void QLowEnergyControllerPrivateBluez::handleReadByGroupTypeRequest(const QByteArray &packet) +{ + // Spec v4.2, Vol 3, Part F, 3.4.4.9-10 + + if (!checkPacketSize(packet, 7, 21)) + return; + const QLowEnergyHandle startingHandle = bt_get_le16(packet.constData() + 1); + const QLowEnergyHandle endingHandle = bt_get_le16(packet.constData() + 3); + const bool is16BitUuid = packet.size() == 7; + const bool is128BitUuid = packet.size() == 21; + const void * const typeStart = packet.constData() + 5; + QBluetoothUuid type; + if (is16BitUuid) { + type = QBluetoothUuid(bt_get_le16(typeStart)); + } else if (is128BitUuid) { + type = QUuid::fromBytes(typeStart, QSysInfo::LittleEndian); + } else { + qCWarning(QT_BT_BLUEZ) << "read by group type request has invalid packet size" + << packet.size(); + sendErrorResponse(static_cast(packet.at(0)), 0, + QBluezConst::AttError::ATT_ERROR_INVALID_PDU); + return; + } + qCDebug(QT_BT_BLUEZ) << "client sends read by group type request, start:" << startingHandle + << "end:" << endingHandle << "type:" << type; + + if (!checkHandlePair(static_cast(packet.at(0)), startingHandle, + endingHandle)) + return; + if (type != QBluetoothUuid(static_cast(GATT_PRIMARY_SERVICE)) + && type != QBluetoothUuid(static_cast(GATT_SECONDARY_SERVICE))) { + sendErrorResponse(static_cast(packet.at(0)), startingHandle, + QBluezConst::AttError::ATT_ERROR_UNSUPPRTED_GROUP_TYPE); + return; + } + + QList results = + getAttributes(startingHandle, endingHandle, + [type](const Attribute &attr) { return attr.type == type; }); + if (results.isEmpty()) { + sendErrorResponse(static_cast(packet.at(0)), startingHandle, + QBluezConst::AttError::ATT_ERROR_ATTRIBUTE_NOT_FOUND); + return; + } + const QBluezConst::AttError error = checkReadPermissions(results); + if (error != QBluezConst::AttError::ATT_ERROR_NO_ERROR) { + sendErrorResponse(static_cast(packet.at(0)), + results.first().handle, error); + return; + } + + ensureUniformValueSizes(results); + + const qsizetype elementSize = 2 * sizeof(QLowEnergyHandle) + results.first().value.size(); + QByteArray responsePrefix(2, Qt::Uninitialized); + responsePrefix[0] = static_cast(QBluezConst::AttCommand::ATT_OP_READ_BY_GROUP_RESPONSE); + responsePrefix[1] = elementSize; + const auto elemWriter = [](const Attribute &attr, char *&data) { + putDataAndIncrement(attr.handle, data); + putDataAndIncrement(attr.groupEndHandle, data); + putDataAndIncrement(attr.value, data); + }; + sendListResponse(responsePrefix, elementSize, results, elemWriter); +} + +void QLowEnergyControllerPrivateBluez::updateLocalAttributeValue( + QLowEnergyHandle handle, + const QByteArray &value, + QLowEnergyCharacteristic &characteristic, + QLowEnergyDescriptor &descriptor) +{ + localAttributes[handle].value = value; + for (const auto &service : std::as_const(localServices)) { + if (handle < service->startHandle || handle > service->endHandle) + continue; + for (auto charIt = service->characteristicList.begin(); + charIt != service->characteristicList.end(); ++charIt) { + QLowEnergyServicePrivate::CharData &charData = charIt.value(); + if (handle == charIt.key() + 1) { // Char value decl comes right after char decl. + charData.value = value; + characteristic = QLowEnergyCharacteristic(service, charIt.key()); + return; + } + for (auto descIt = charData.descriptorList.begin(); + descIt != charData.descriptorList.end(); ++descIt) { + if (handle == descIt.key()) { + descIt.value().value = value; + descriptor = QLowEnergyDescriptor(service, charIt.key(), handle); + return; + } + } + } + } + qFatal("local services map inconsistent with local attribute map"); +} + +static bool isNotificationEnabled(quint16 clientConfigValue) { return clientConfigValue & 0x1; } +static bool isIndicationEnabled(quint16 clientConfigValue) { return clientConfigValue & 0x2; } + +void QLowEnergyControllerPrivateBluez::writeCharacteristicForPeripheral( + QLowEnergyServicePrivate::CharData &charData, + const QByteArray &newValue) +{ + const QLowEnergyHandle valueHandle = charData.valueHandle; + Q_ASSERT(valueHandle <= lastLocalHandle); + Attribute &attribute = localAttributes[valueHandle]; + if (newValue.size() < attribute.minLength || newValue.size() > attribute.maxLength) { + qCWarning(QT_BT_BLUEZ) << "ignoring value of invalid length" << newValue.size() + << "for attribute" << valueHandle; + return; + } + attribute.value = newValue; + charData.value = newValue; + const bool hasNotifyProperty = attribute.properties & QLowEnergyCharacteristic::Notify; + const bool hasIndicateProperty + = attribute.properties & QLowEnergyCharacteristic::Indicate; + if (!hasNotifyProperty && !hasIndicateProperty) + return; + for (const QLowEnergyServicePrivate::DescData &desc : std::as_const(charData.descriptorList)) { + if (desc.uuid != QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration) + continue; + + // Notify/indicate currently connected client. + const bool isConnected = state == QLowEnergyController::ConnectedState; + if (isConnected) { + Q_ASSERT(desc.value.size() == 2); + quint16 configValue = bt_get_le16(desc.value.constData()); + if (isNotificationEnabled(configValue) && hasNotifyProperty) { + sendNotification(valueHandle); + } else if (isIndicationEnabled(configValue) && hasIndicateProperty) { + if (indicationInFlight) + scheduledIndications << valueHandle; + else + sendIndication(valueHandle); + } + } + + // Prepare notification/indication of unconnected, bonded clients. + for (auto it = clientConfigData.begin(); it != clientConfigData.end(); ++it) { + if (isConnected && it.key() == remoteDevice.toUInt64()) + continue; + QList &configDataList = it.value(); + for (ClientConfigurationData &configData : configDataList) { + if (configData.charValueHandle != valueHandle) + continue; + if ((isNotificationEnabled(configData.configValue) && hasNotifyProperty) + || (isIndicationEnabled(configData.configValue) && hasIndicateProperty)) { + configData.charValueWasUpdated = true; + break; + } + } + } + break; + } +} + +void QLowEnergyControllerPrivateBluez::writeCharacteristicForCentral(const QSharedPointer &service, + QLowEnergyHandle charHandle, + QLowEnergyHandle valueHandle, + const QByteArray &newValue, + QLowEnergyService::WriteMode mode) +{ + QByteArray packet(WRITE_REQUEST_HEADER_SIZE + newValue.size(), Qt::Uninitialized); + putBtData(valueHandle, packet.data() + 1); + memcpy(packet.data() + 3, newValue.constData(), newValue.size()); + bool writeWithResponse = false; + switch (mode) { + case QLowEnergyService::WriteWithResponse: + if (newValue.size() > (mtuSize - WRITE_REQUEST_HEADER_SIZE)) { + sendNextPrepareWriteRequest(charHandle, newValue, 0); + sendNextPendingRequest(); + return; + } + // write value fits into single package + packet[0] = static_cast(QBluezConst::AttCommand::ATT_OP_WRITE_REQUEST); + writeWithResponse = true; + break; + case QLowEnergyService::WriteWithoutResponse: + packet[0] = static_cast(QBluezConst::AttCommand::ATT_OP_WRITE_COMMAND); + break; + case QLowEnergyService::WriteSigned: + packet[0] = static_cast(QBluezConst::AttCommand::ATT_OP_SIGNED_WRITE_COMMAND); + if (!isBonded()) { + qCWarning(QT_BT_BLUEZ) << "signed write not possible: requires bond between devices"; + service->setError(QLowEnergyService::CharacteristicWriteError); + return; + } + if (securityLevel() >= BT_SECURITY_MEDIUM) { + qCWarning(QT_BT_BLUEZ) << "signed write not possible: not allowed on encrypted link"; + service->setError(QLowEnergyService::CharacteristicWriteError); + return; + } + const auto signingDataIt = signingData.find(remoteDevice.toUInt64()); + if (signingDataIt == signingData.end()) { + qCWarning(QT_BT_BLUEZ) << "signed write not possible: no signature key found"; + service->setError(QLowEnergyService::CharacteristicWriteError); + return; + } + ++signingDataIt.value().counter; + packet = LeCmacCalculator::createFullMessage(packet, signingDataIt.value().counter); + const quint64 mac = LeCmacCalculator().calculateMac(packet, signingDataIt.value().key); + packet.resize(packet.size() + sizeof mac); + putBtData(mac, packet.data() + packet.size() - sizeof mac); + storeSignCounter(LocalSigningKey); + break; + } + + qCDebug(QT_BT_BLUEZ) << "Writing characteristic" << Qt::hex << charHandle + << "(size:" << packet.size() << "with response:" + << (mode == QLowEnergyService::WriteWithResponse) + << "signed:" << (mode == QLowEnergyService::WriteSigned) << ")"; + + // Advantage of write without response is the quick turnaround. + // It can be sent at any time and does not produce responses. + // Therefore we will not put them into the openRequest queue at all. + if (!writeWithResponse) { + sendPacket(packet); + return; + } + + Request request; + request.payload = packet; + request.command = QBluezConst::AttCommand::ATT_OP_WRITE_REQUEST; + request.reference = charHandle; + request.reference2 = newValue; + openRequests.enqueue(request); + + sendNextPendingRequest(); +} + +void QLowEnergyControllerPrivateBluez::writeDescriptorForPeripheral( + const QSharedPointer &service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle, + const QByteArray &newValue) +{ + Q_ASSERT(descriptorHandle <= lastLocalHandle); + Attribute &attribute = localAttributes[descriptorHandle]; + if (newValue.size() < attribute.minLength || newValue.size() > attribute.maxLength) { + qCWarning(QT_BT_BLUEZ) << "invalid value of size" << newValue.size() + << "for attribute" << descriptorHandle; + return; + } + attribute.value = newValue; + service->characteristicList[charHandle].descriptorList[descriptorHandle].value = newValue; +} + +void QLowEnergyControllerPrivateBluez::writeDescriptorForCentral( + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle, + const QByteArray &newValue) +{ + if (newValue.size() > (mtuSize - WRITE_REQUEST_HEADER_SIZE)) { + sendNextPrepareWriteRequest(descriptorHandle, newValue, 0); + sendNextPendingRequest(); + return; + } + + quint8 packet[WRITE_REQUEST_HEADER_SIZE]; + packet[0] = static_cast(QBluezConst::AttCommand::ATT_OP_WRITE_REQUEST); + putBtData(descriptorHandle, &packet[1]); + + const qsizetype size = WRITE_REQUEST_HEADER_SIZE + newValue.size(); + QByteArray data(size, Qt::Uninitialized); + memcpy(data.data(), packet, WRITE_REQUEST_HEADER_SIZE); + memcpy(&(data.data()[WRITE_REQUEST_HEADER_SIZE]), newValue.constData(), newValue.size()); + + qCDebug(QT_BT_BLUEZ) << "Writing descriptor" << Qt::hex << descriptorHandle + << "(size:" << size << ")"; + + Request request; + request.payload = data; + request.command = QBluezConst::AttCommand::ATT_OP_WRITE_REQUEST; + request.reference = (charHandle | (descriptorHandle << 16)); + request.reference2 = newValue; + openRequests.enqueue(request); + + sendNextPendingRequest(); +} + +void QLowEnergyControllerPrivateBluez::handleWriteRequestOrCommand(const QByteArray &packet) +{ + // Spec v4.2, Vol 3, Part F, 3.4.5.1-3 + + const bool isRequest = static_cast(packet.at(0)) + == QBluezConst::AttCommand::ATT_OP_WRITE_REQUEST; + const bool isSigned = static_cast(packet.at(0)) + == QBluezConst::AttCommand::ATT_OP_SIGNED_WRITE_COMMAND; + if (!checkPacketSize(packet, isSigned ? 15 : 3, mtuSize)) + return; + const QLowEnergyHandle handle = bt_get_le16(packet.constData() + 1); + qCDebug(QT_BT_BLUEZ) << "client sends" << (isSigned ? "signed" : "") << "write" + << (isRequest ? "request" : "command") << "for handle" << handle; + + if (!checkHandle(packet, handle)) + return; + + Attribute &attribute = localAttributes[handle]; + const QLowEnergyCharacteristic::PropertyType type = isRequest + ? QLowEnergyCharacteristic::Write : isSigned + ? QLowEnergyCharacteristic::WriteSigned : QLowEnergyCharacteristic::WriteNoResponse; + const QBluezConst::AttError permissionsError = checkPermissions(attribute, type); + if (permissionsError != QBluezConst::AttError::ATT_ERROR_NO_ERROR) { + sendErrorResponse(static_cast(packet.at(0)), handle, + permissionsError); + return; + } + + int valueLength; + if (isSigned) { + if (!isBonded()) { + qCWarning(QT_BT_BLUEZ) << "Ignoring signed write from non-bonded device."; + return; + } + if (securityLevel() >= BT_SECURITY_MEDIUM) { + qCWarning(QT_BT_BLUEZ) << "Ignoring signed write on encrypted link."; + return; + } + const auto signingDataIt = signingData.find(remoteDevice.toUInt64()); + if (signingDataIt == signingData.constEnd()) { + qCWarning(QT_BT_BLUEZ) << "No CSRK found for peer device, ignoring signed write"; + return; + } + + const quint32 signCounter = getBtData(packet.data() + packet.size() - 12); + if (signCounter < signingDataIt.value().counter + 1) { + qCWarning(QT_BT_BLUEZ) << "Client's' sign counter" << signCounter + << "not greater than local sign counter" + << signingDataIt.value().counter + << "; ignoring signed write command."; + return; + } + + const quint64 macFromClient = getBtData(packet.data() + packet.size() - 8); + const bool signatureCorrect = verifyMac(packet.left(packet.size() - 12), + signingDataIt.value().key, signCounter, macFromClient); + if (!signatureCorrect) { + qCWarning(QT_BT_BLUEZ) << "Signed Write packet has wrong signature, disconnecting"; + disconnectFromDevice(); // Recommended by spec v4.2, Vol 3, part C, 10.4.2 + return; + } + + signingDataIt.value().counter = signCounter; + storeSignCounter(RemoteSigningKey); + valueLength = packet.size() - 15; + } else { + valueLength = packet.size() - 3; + } + + if (valueLength > attribute.maxLength) { + sendErrorResponse(static_cast(packet.at(0)), handle, + QBluezConst::AttError::ATT_ERROR_INVAL_ATTR_VALUE_LEN); + return; + } + + // If the attribute value has a fixed size and the value in the packet is shorter, + // then we overwrite only the start of the attribute value and keep the rest. + QByteArray value = packet.mid(3, valueLength); + if (attribute.minLength == attribute.maxLength && valueLength < attribute.minLength) + value += attribute.value.mid(valueLength, attribute.maxLength - valueLength); + + QLowEnergyCharacteristic characteristic; + QLowEnergyDescriptor descriptor; + updateLocalAttributeValue(handle, value, characteristic, descriptor); + + if (isRequest) { + const QByteArray response = + QByteArray(1, static_cast(QBluezConst::AttCommand::ATT_OP_WRITE_RESPONSE)); + sendPacket(response); + } + + if (characteristic.isValid()) { + emit characteristic.d_ptr->characteristicChanged(characteristic, value); + } else { + Q_ASSERT(descriptor.isValid()); + emit descriptor.d_ptr->descriptorWritten(descriptor, value); + } +} + +void QLowEnergyControllerPrivateBluez::handlePrepareWriteRequest(const QByteArray &packet) +{ + // Spec v4.2, Vol 3, Part F, 3.4.6.1 + + if (!checkPacketSize(packet, 5, mtuSize)) + return; + const quint16 handle = bt_get_le16(packet.constData() + 1); + qCDebug(QT_BT_BLUEZ) << "client sends prepare write request for handle" << handle; + + if (!checkHandle(packet, handle)) + return; + const Attribute &attribute = localAttributes.at(handle); + const QBluezConst::AttError permissionsError = + checkPermissions(attribute, QLowEnergyCharacteristic::Write); + if (permissionsError != QBluezConst::AttError::ATT_ERROR_NO_ERROR) { + sendErrorResponse(static_cast(packet.at(0)), handle, + permissionsError); + return; + } + if (openPrepareWriteRequests.size() >= maxPrepareQueueSize) { + sendErrorResponse(static_cast(packet.at(0)), handle, + QBluezConst::AttError::ATT_ERROR_PREPARE_QUEUE_FULL); + return; + } + + // The value is not checked here, but on the Execute request. + openPrepareWriteRequests << WriteRequest(handle, bt_get_le16(packet.constData() + 3), + packet.mid(5)); + + QByteArray response = packet; + response[0] = static_cast(QBluezConst::AttCommand::ATT_OP_PREPARE_WRITE_RESPONSE); + sendPacket(response); +} + +void QLowEnergyControllerPrivateBluez::handleExecuteWriteRequest(const QByteArray &packet) +{ + // Spec v4.2, Vol 3, Part F, 3.4.6.3 + + if (!checkPacketSize(packet, 2)) + return; + const bool cancel = packet.at(1) == 0; + qCDebug(QT_BT_BLUEZ) << "client sends execute write request; flag is" + << (cancel ? "cancel" : "flush"); + + QList requests = openPrepareWriteRequests; + openPrepareWriteRequests.clear(); + QList characteristics; + QList descriptors; + if (!cancel) { + for (const WriteRequest &request : std::as_const(requests)) { + Attribute &attribute = localAttributes[request.handle]; + if (request.valueOffset > attribute.value.size()) { + sendErrorResponse(static_cast(packet.at(0)), + request.handle, QBluezConst::AttError::ATT_ERROR_INVALID_OFFSET); + return; + } + const QByteArray newValue = attribute.value.left(request.valueOffset) + request.value; + if (newValue.size() > attribute.maxLength) { + sendErrorResponse(static_cast(packet.at(0)), + request.handle, + QBluezConst::AttError::ATT_ERROR_INVAL_ATTR_VALUE_LEN); + return; + } + QLowEnergyCharacteristic characteristic; + QLowEnergyDescriptor descriptor; + // TODO: Redundant attribute lookup for the case of the same handle appearing + // more than once. + updateLocalAttributeValue(request.handle, newValue, characteristic, descriptor); + if (characteristic.isValid()) { + characteristics << characteristic; + } else if (descriptor.isValid()) { + Q_ASSERT(descriptor.isValid()); + descriptors << descriptor; + } + } + } + + sendPacket(QByteArray( + 1, static_cast(QBluezConst::AttCommand::ATT_OP_EXECUTE_WRITE_RESPONSE))); + + for (const QLowEnergyCharacteristic &characteristic : std::as_const(characteristics)) + emit characteristic.d_ptr->characteristicChanged(characteristic, characteristic.value()); + for (const QLowEnergyDescriptor &descriptor : std::as_const(descriptors)) + emit descriptor.d_ptr->descriptorWritten(descriptor, descriptor.value()); +} + +void QLowEnergyControllerPrivateBluez::sendErrorResponse(QBluezConst::AttCommand request, + quint16 handle, QBluezConst::AttError code) +{ + // An ATT command never receives an error response. + if (request == QBluezConst::AttCommand::ATT_OP_WRITE_COMMAND + || request == QBluezConst::AttCommand::ATT_OP_SIGNED_WRITE_COMMAND) + return; + + QByteArray packet(ERROR_RESPONSE_HEADER_SIZE, Qt::Uninitialized); + packet[0] = static_cast(QBluezConst::AttCommand::ATT_OP_ERROR_RESPONSE); + packet[1] = static_cast(request); + putBtData(handle, packet.data() + 2); + packet[4] = static_cast(code); + qCWarning(QT_BT_BLUEZ) << "sending error response; request:" + << request << "handle:" << handle + << "code:" << code; + sendPacket(packet); +} + +void QLowEnergyControllerPrivateBluez::sendListResponse(const QByteArray &packetStart, + qsizetype elemSize, + const QList &attributes, + const ElemWriter &elemWriter) +{ + const qsizetype offset = packetStart.size(); + const qsizetype elemCount = (std::min)(attributes.size(), (mtuSize - offset) / elemSize); + const qsizetype totalPacketSize = offset + elemCount * elemSize; + QByteArray response(totalPacketSize, Qt::Uninitialized); + using namespace std; + memcpy(response.data(), packetStart.constData(), offset); + char *data = response.data() + offset; + for_each(attributes.constBegin(), attributes.constBegin() + elemCount, + [&data, elemWriter](const Attribute &attr) { elemWriter(attr, data); }); + qCDebug(QT_BT_BLUEZ) << "sending response:" << response.toHex(); + sendPacket(response); +} + +void QLowEnergyControllerPrivateBluez::sendNotification(QLowEnergyHandle handle) +{ + sendNotificationOrIndication(QBluezConst::AttCommand::ATT_OP_HANDLE_VAL_NOTIFICATION, handle); +} + +void QLowEnergyControllerPrivateBluez::sendIndication(QLowEnergyHandle handle) +{ + Q_ASSERT(!indicationInFlight); + indicationInFlight = true; + sendNotificationOrIndication(QBluezConst::AttCommand::ATT_OP_HANDLE_VAL_INDICATION, handle); +} + +void QLowEnergyControllerPrivateBluez::sendNotificationOrIndication(QBluezConst::AttCommand opCode, + QLowEnergyHandle handle) +{ + Q_ASSERT(handle <= lastLocalHandle); + const Attribute &attribute = localAttributes.at(handle); + const qsizetype maxValueLength = (std::min)(attribute.value.size(), qsizetype(mtuSize) - 3); + QByteArray packet(3 + maxValueLength, Qt::Uninitialized); + packet[0] = static_cast(opCode); + putBtData(handle, packet.data() + 1); + using namespace std; + memcpy(packet.data() + 3, attribute.value.constData(), maxValueLength); + qCDebug(QT_BT_BLUEZ) << "sending notification/indication:" << packet.toHex(); + sendPacket(packet); +} + +void QLowEnergyControllerPrivateBluez::sendNextIndication() +{ + if (!scheduledIndications.isEmpty()) + sendIndication(scheduledIndications.takeFirst()); +} + +static QString nameOfRemoteCentral(const QBluetoothAddress &peerAddress) +{ + const QString peerAddressString = peerAddress.toString(); + initializeBluez5(); + OrgFreedesktopDBusObjectManagerInterface manager(QStringLiteral("org.bluez"), + QStringLiteral("/"), + QDBusConnection::systemBus()); + QDBusPendingReply reply = manager.GetManagedObjects(); + reply.waitForFinished(); + if (reply.isError()) + return QString(); + + ManagedObjectList managedObjectList = reply.value(); + for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) { + const InterfaceList &ifaceList = it.value(); + + for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) { + const QString &iface = jt.key(); + const QVariantMap &ifaceValues = jt.value(); + + if (iface == QStringLiteral("org.bluez.Device1")) { + if (ifaceValues.value(QStringLiteral("Address")).toString() == peerAddressString) + return ifaceValues.value(QStringLiteral("Alias")).toString(); + } + } + } + return QString(); +} + +void QLowEnergyControllerPrivateBluez::handleConnectionRequest() +{ + if (state != QLowEnergyController::AdvertisingState) { + qCWarning(QT_BT_BLUEZ) << "Incoming connection request in unexpected state" << state; + return; + } + Q_ASSERT(serverSocketNotifier); + serverSocketNotifier->setEnabled(false); + sockaddr_l2 clientAddr; + socklen_t clientAddrSize = sizeof clientAddr; + const int clientSocket = accept(serverSocketNotifier->socket(), + reinterpret_cast(&clientAddr), &clientAddrSize); + if (clientSocket == -1) { + // Not fatal in itself. The next one might succeed. + qCWarning(QT_BT_BLUEZ) << "accept() failed:" << qt_error_string(errno); + serverSocketNotifier->setEnabled(true); + return; + } + + remoteDevice = QBluetoothAddress(convertAddress(clientAddr.l2_bdaddr.b)); + remoteName = nameOfRemoteCentral(remoteDevice); + qCDebug(QT_BT_BLUEZ) << "GATT connection from device" << remoteDevice << remoteName; + + if (connectionHandle == 0) + qCWarning(QT_BT_BLUEZ) << "Received client connection, but no connection complete event"; + + if (l2cpSocket) { + disconnect(l2cpSocket); + if (l2cpSocket->isOpen()) + l2cpSocket->close(); + + l2cpSocket->deleteLater(); + l2cpSocket = nullptr; + } + closeServerSocket(); + + QBluetoothSocketPrivateBluez *rawSocketPrivate = new QBluetoothSocketPrivateBluez(); + l2cpSocket = new QBluetoothSocket( + rawSocketPrivate, QBluetoothServiceInfo::L2capProtocol, this); + connect(l2cpSocket, &QBluetoothSocket::disconnected, + this, &QLowEnergyControllerPrivateBluez::l2cpDisconnected); + connect(l2cpSocket, &QBluetoothSocket::errorOccurred, this, + &QLowEnergyControllerPrivateBluez::l2cpErrorChanged); + connect(l2cpSocket, &QIODevice::readyRead, this, &QLowEnergyControllerPrivateBluez::l2cpReadyRead); + l2cpSocket->d_ptr->lowEnergySocketType = addressType == QLowEnergyController::PublicAddress + ? BDADDR_LE_PUBLIC : BDADDR_LE_RANDOM; + l2cpSocket->setSocketDescriptor(clientSocket, QBluetoothServiceInfo::L2capProtocol, + QBluetoothSocket::SocketState::ConnectedState, QIODevice::ReadWrite | QIODevice::Unbuffered); + restoreClientConfigurations(); + loadSigningDataIfNecessary(RemoteSigningKey); + + Q_Q(QLowEnergyController); + setState(QLowEnergyController::ConnectedState); + emit q->connected(); +} + +void QLowEnergyControllerPrivateBluez::closeServerSocket() +{ + if (!serverSocketNotifier) + return; + serverSocketNotifier->disconnect(); + close(serverSocketNotifier->socket()); + serverSocketNotifier->deleteLater(); + serverSocketNotifier = nullptr; +} + +bool QLowEnergyControllerPrivateBluez::isBonded() const +{ + // Pairing does not necessarily imply bonding, but we don't know whether the + // bonding flag was set in the original pairing request. + return QBluetoothLocalDevice(localAdapter).pairingStatus(remoteDevice) + != QBluetoothLocalDevice::Unpaired; +} + +QList +QLowEnergyControllerPrivateBluez::gatherClientConfigData() +{ + QList data; + for (const auto &service : std::as_const(localServices)) { + for (auto charIt = service->characteristicList.begin(); + charIt != service->characteristicList.end(); ++charIt) { + QLowEnergyServicePrivate::CharData &charData = charIt.value(); + for (auto descIt = charData.descriptorList.begin(); + descIt != charData.descriptorList.end(); ++descIt) { + QLowEnergyServicePrivate::DescData &descData = descIt.value(); + if (descData.uuid == QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration) { + data << TempClientConfigurationData(&descData, charData.valueHandle, + descIt.key()); + break; + } + } + } + } + return data; +} + +void QLowEnergyControllerPrivateBluez::storeClientConfigurations() +{ + if (!isBonded()) { + clientConfigData.remove(remoteDevice.toUInt64()); + return; + } + QList clientConfigs; + const QList &tempConfigList = gatherClientConfigData(); + for (const auto &tempConfigData : tempConfigList) { + Q_ASSERT(tempConfigData.descData->value.size() == 2); + const quint16 value = bt_get_le16(tempConfigData.descData->value.constData()); + if (value != 0) { + clientConfigs << ClientConfigurationData(tempConfigData.charValueHandle, + tempConfigData.configHandle, value); + } + } + clientConfigData.insert(remoteDevice.toUInt64(), clientConfigs); +} + +void QLowEnergyControllerPrivateBluez::restoreClientConfigurations() +{ + const QList &tempConfigList = gatherClientConfigData(); + const QList &restoredClientConfigs = isBonded() + ? clientConfigData.value(remoteDevice.toUInt64()) + : QList(); + QList notifications; + for (const auto &tempConfigData : tempConfigList) { + bool wasRestored = false; + for (const auto &restoredData : restoredClientConfigs) { + if (restoredData.charValueHandle == tempConfigData.charValueHandle) { + Q_ASSERT(tempConfigData.descData->value.size() == 2); + putBtData(restoredData.configValue, tempConfigData.descData->value.data()); + wasRestored = true; + if (restoredData.charValueWasUpdated) { + if (isNotificationEnabled(restoredData.configValue)) + notifications << restoredData.charValueHandle; + else if (isIndicationEnabled(restoredData.configValue)) + scheduledIndications << restoredData.charValueHandle; + } + break; + } + } + if (!wasRestored) + tempConfigData.descData->value = QByteArray(2, 0); // Default value. + Q_ASSERT(lastLocalHandle >= tempConfigData.configHandle); + Q_ASSERT(tempConfigData.configHandle > tempConfigData.charValueHandle); + localAttributes[tempConfigData.configHandle].value = tempConfigData.descData->value; + } + + for (const QLowEnergyHandle handle : std::as_const(notifications)) + sendNotification(handle); + sendNextIndication(); +} + +void QLowEnergyControllerPrivateBluez::loadSigningDataIfNecessary(SigningKeyType keyType) +{ + const auto signingDataIt = signingData.constFind(remoteDevice.toUInt64()); + if (signingDataIt != signingData.constEnd()) + return; // We are up to date for this device. + const QString settingsFilePath = keySettingsFilePath(); + if (!QFileInfo(settingsFilePath).exists()) { + qCDebug(QT_BT_BLUEZ) << "No settings found for peer device."; + return; + } + QSettings settings(settingsFilePath, QSettings::IniFormat); + const QString group = signingKeySettingsGroup(keyType); + settings.beginGroup(group); + const QByteArray keyString = settings.value(QLatin1String("Key")).toByteArray(); + if (keyString.isEmpty()) { + qCDebug(QT_BT_BLUEZ) << "Group" << group << "not found in settings file"; + return; + } + const QByteArray keyData = QByteArray::fromHex(keyString); + if (keyData.size() != qsizetype(sizeof(BluezUint128))) { + qCWarning(QT_BT_BLUEZ) << "Signing key in settings file has invalid size" + << keyString.size(); + return; + } + qCDebug(QT_BT_BLUEZ) << "CSRK of peer device is" << keyString; + const quint32 counter = settings.value(QLatin1String("Counter"), 0).toUInt(); + using namespace std; + BluezUint128 csrk; + memcpy(csrk.data, keyData.constData(), keyData.size()); + signingData.insert(remoteDevice.toUInt64(), SigningData(csrk, counter - 1)); +} + +void QLowEnergyControllerPrivateBluez::storeSignCounter(SigningKeyType keyType) const +{ + const auto signingDataIt = signingData.constFind(remoteDevice.toUInt64()); + if (signingDataIt == signingData.constEnd()) + return; + const QString settingsFilePath = keySettingsFilePath(); + if (!QFileInfo(settingsFilePath).exists()) + return; + QSettings settings(settingsFilePath, QSettings::IniFormat); + if (!settings.isWritable()) + return; + settings.beginGroup(signingKeySettingsGroup(keyType)); + const QString counterKey = QLatin1String("Counter"); + if (!settings.allKeys().contains(counterKey)) + return; + const quint32 counterValue = signingDataIt.value().counter + 1; + if (counterValue == settings.value(counterKey).toUInt()) + return; + settings.setValue(counterKey, counterValue); +} + +QString QLowEnergyControllerPrivateBluez::signingKeySettingsGroup(SigningKeyType keyType) const +{ + return QLatin1String(keyType == LocalSigningKey ? "LocalSignatureKey" : "RemoteSignatureKey"); +} + +QString QLowEnergyControllerPrivateBluez::keySettingsFilePath() const +{ + return QString::fromLatin1("/var/lib/bluetooth/%1/%2/info") + .arg(localAdapter.toString(), remoteDevice.toString()); +} + +static QByteArray uuidToByteArray(const QBluetoothUuid &uuid) +{ + QByteArray ba(sizeof(uuid), Qt::Uninitialized); + char *ptr = ba.data(); + putDataAndIncrement(uuid, ptr); + ba.resize(ptr - ba.constData()); + return ba; +} + +void QLowEnergyControllerPrivateBluez::addToGenericAttributeList(const QLowEnergyServiceData &service, + QLowEnergyHandle startHandle) +{ + // Construct generic attribute data for the service with handles as keys. + // Otherwise a number of request handling functions will be awkward to write + // as well as computationally inefficient. + + localAttributes.resize(lastLocalHandle + 1); + Attribute serviceAttribute; + serviceAttribute.handle = startHandle; + serviceAttribute.type = QBluetoothUuid(static_cast(service.type())); + serviceAttribute.properties = QLowEnergyCharacteristic::Read; + serviceAttribute.value = uuidToByteArray(service.uuid()); + QLowEnergyHandle currentHandle = startHandle; + const QList includedServices = service.includedServices(); + for (const QLowEnergyService * const service : includedServices) { + Attribute attribute; + attribute.handle = ++currentHandle; + attribute.type = QBluetoothUuid(GATT_INCLUDED_SERVICE); + attribute.properties = QLowEnergyCharacteristic::Read; + const bool includeUuidInValue = service->serviceUuid().minimumSize() == 2; + attribute.value.resize((2 + includeUuidInValue) * sizeof(QLowEnergyHandle)); + char *valueData = attribute.value.data(); + putDataAndIncrement(service->d_ptr->startHandle, valueData); + putDataAndIncrement(service->d_ptr->endHandle, valueData); + if (includeUuidInValue) + putDataAndIncrement(service->serviceUuid(), valueData); + localAttributes[attribute.handle] = attribute; + } + const QList characteristics = service.characteristics(); + for (const QLowEnergyCharacteristicData &cd : characteristics) { + Attribute attribute; + + // Characteristic declaration; + attribute.handle = ++currentHandle; + attribute.groupEndHandle = attribute.handle + 1 + cd.descriptors().size(); + attribute.type = QBluetoothUuid(GATT_CHARACTERISTIC); + attribute.properties = QLowEnergyCharacteristic::Read; + attribute.value.resize(1 + sizeof(QLowEnergyHandle) + cd.uuid().minimumSize()); + char *valueData = attribute.value.data(); + putDataAndIncrement(static_cast(cd.properties()), valueData); + putDataAndIncrement(QLowEnergyHandle(currentHandle + 1), valueData); + putDataAndIncrement(cd.uuid(), valueData); + localAttributes[attribute.handle] = attribute; + + // Characteristic value declaration. + attribute.handle = ++currentHandle; + attribute.groupEndHandle = attribute.handle; + attribute.type = cd.uuid(); + attribute.properties = cd.properties(); + attribute.readConstraints = cd.readConstraints(); + attribute.writeConstraints = cd.writeConstraints(); + attribute.value = cd.value(); + attribute.minLength = cd.minimumValueLength(); + attribute.maxLength = cd.maximumValueLength(); + localAttributes[attribute.handle] = attribute; + + const QList descriptors = cd.descriptors(); + for (const QLowEnergyDescriptorData &dd : descriptors) { + attribute.handle = ++currentHandle; + attribute.groupEndHandle = attribute.handle; + attribute.type = dd.uuid(); + attribute.properties = QLowEnergyCharacteristic::PropertyTypes(); + attribute.readConstraints = AttAccessConstraints(); + attribute.writeConstraints = AttAccessConstraints(); + attribute.minLength = 0; + attribute.maxLength = INT_MAX; + + // Spec v4.2, Vol. 3, Part G, 3.3.3.x + if (attribute.type == QBluetoothUuid::DescriptorType::CharacteristicExtendedProperties) { + attribute.properties = QLowEnergyCharacteristic::Read; + attribute.minLength = attribute.maxLength = 2; + } else if (attribute.type == QBluetoothUuid::DescriptorType::CharacteristicPresentationFormat) { + attribute.properties = QLowEnergyCharacteristic::Read; + attribute.minLength = attribute.maxLength = 7; + } else if (attribute.type == QBluetoothUuid::DescriptorType::CharacteristicAggregateFormat) { + attribute.properties = QLowEnergyCharacteristic::Read; + attribute.minLength = 4; + } else if (attribute.type == QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration + || attribute.type == QBluetoothUuid::DescriptorType::ServerCharacteristicConfiguration) { + attribute.properties = QLowEnergyCharacteristic::Read + | QLowEnergyCharacteristic::Write + | QLowEnergyCharacteristic::WriteNoResponse + | QLowEnergyCharacteristic::WriteSigned; + attribute.writeConstraints = dd.writeConstraints(); + attribute.minLength = attribute.maxLength = 2; + } else { + if (dd.isReadable()) + attribute.properties |= QLowEnergyCharacteristic::Read; + if (dd.isWritable()) { + attribute.properties |= QLowEnergyCharacteristic::Write; + attribute.properties |= QLowEnergyCharacteristic::WriteNoResponse; + attribute.properties |= QLowEnergyCharacteristic::WriteSigned; + } + attribute.readConstraints = dd.readConstraints(); + attribute.writeConstraints = dd.writeConstraints(); + } + + attribute.value = dd.value(); + if (attribute.value.size() < attribute.minLength + || attribute.value.size() > attribute.maxLength) { + qCWarning(QT_BT_BLUEZ) << "attribute of type" << attribute.type + << "has invalid length of" << attribute.value.size() + << "bytes"; + attribute.value = QByteArray(attribute.minLength, 0); + } + localAttributes[attribute.handle] = attribute; + } + } + serviceAttribute.groupEndHandle = currentHandle; + localAttributes[serviceAttribute.handle] = serviceAttribute; +} + +int QLowEnergyControllerPrivateBluez::mtu() const +{ + return mtuSize; +} + +void QLowEnergyControllerPrivateBluez::ensureUniformAttributes( + QList &attributes, const std::function &getSize) +{ + if (attributes.isEmpty()) + return; + const int firstSize = getSize(attributes.first()); + const auto it = std::find_if(attributes.begin() + 1, attributes.end(), + [firstSize, getSize](const Attribute &attr) { return getSize(attr) != firstSize; }); + if (it != attributes.end()) + attributes.erase(it, attributes.end()); + +} + +void QLowEnergyControllerPrivateBluez::ensureUniformUuidSizes(QList &attributes) +{ + ensureUniformAttributes(attributes, + [](const Attribute &attr) { return getUuidSize(attr.type); }); +} + +void QLowEnergyControllerPrivateBluez::ensureUniformValueSizes(QList &attributes) +{ + ensureUniformAttributes(attributes, + [](const Attribute &attr) { return attr.value.size(); }); +} + +QList +QLowEnergyControllerPrivateBluez::getAttributes(QLowEnergyHandle startHandle, + QLowEnergyHandle endHandle, + const AttributePredicate &attributePredicate) +{ + QList results; + if (startHandle > lastLocalHandle) + return results; + if (lastLocalHandle == 0) // We have no services at all. + return results; + Q_ASSERT(startHandle <= endHandle); // Must have been checked before. + const QLowEnergyHandle firstHandle = qMin(startHandle, lastLocalHandle); + const QLowEnergyHandle lastHandle = qMin(endHandle, lastLocalHandle); + for (QLowEnergyHandle i = firstHandle; i <= lastHandle; ++i) { + const Attribute &attr = localAttributes.at(i); + if (attributePredicate(attr)) + results << attr; + } + return results; +} + +QBluezConst::AttError +QLowEnergyControllerPrivateBluez::checkPermissions(const Attribute &attr, + QLowEnergyCharacteristic::PropertyType type) +{ + const bool isReadAccess = type == QLowEnergyCharacteristic::Read; + const bool isWriteCommand = type == QLowEnergyCharacteristic::WriteNoResponse; + const bool isWriteAccess = type == QLowEnergyCharacteristic::Write + || type == QLowEnergyCharacteristic::WriteSigned + || isWriteCommand; + Q_ASSERT(isReadAccess || isWriteAccess); + if (!(attr.properties & type)) { + if (isReadAccess) + return QBluezConst::AttError::ATT_ERROR_READ_NOT_PERM; + + // The spec says: If an attribute requires a signed write, then a non-signed write command + // can also be used if the link is encrypted. + const bool unsignedWriteOk = isWriteCommand + && (attr.properties & QLowEnergyCharacteristic::WriteSigned) + && securityLevel() >= BT_SECURITY_MEDIUM; + if (!unsignedWriteOk) + return QBluezConst::AttError::ATT_ERROR_WRITE_NOT_PERM; + } + const AttAccessConstraints constraints = isReadAccess + ? attr.readConstraints : attr.writeConstraints; + if (constraints.testFlag(AttAccessConstraint::AttAuthorizationRequired)) + return QBluezConst::AttError::ATT_ERROR_INSUF_AUTHORIZATION; // TODO: emit signal (and offer + // authorization function)? + if (constraints.testFlag(AttAccessConstraint::AttEncryptionRequired) + && securityLevel() < BT_SECURITY_MEDIUM) + return QBluezConst::AttError::ATT_ERROR_INSUF_ENCRYPTION; + if (constraints.testFlag(AttAccessConstraint::AttAuthenticationRequired) + && securityLevel() < BT_SECURITY_HIGH) + return QBluezConst::AttError::ATT_ERROR_INSUF_AUTHENTICATION; + if (false) + return QBluezConst::AttError::ATT_ERROR_INSUF_ENCR_KEY_SIZE; + return QBluezConst::AttError::ATT_ERROR_NO_ERROR; +} + +QBluezConst::AttError QLowEnergyControllerPrivateBluez::checkReadPermissions(const Attribute &attr) +{ + return checkPermissions(attr, QLowEnergyCharacteristic::Read); +} + +QBluezConst::AttError +QLowEnergyControllerPrivateBluez::checkReadPermissions(QList &attributes) +{ + if (attributes.isEmpty()) + return QBluezConst::AttError::ATT_ERROR_NO_ERROR; + + // The logic prescribed in the spec is as follows: + // 1) If the first in a list of matching attributes has a permissions error, + // then that error is returned via an error response. + // 2) If any other element of that list would cause a permissions error, then all + // attributes from this one on are not part of the result set, but no error is returned. + const QBluezConst::AttError error = checkReadPermissions(attributes.first()); + if (error != QBluezConst::AttError::ATT_ERROR_NO_ERROR) + return error; + const auto it = + std::find_if(attributes.begin() + 1, attributes.end(), [this](const Attribute &attr) { + return checkReadPermissions(attr) != QBluezConst::AttError::ATT_ERROR_NO_ERROR; + }); + if (it != attributes.end()) + attributes.erase(it, attributes.end()); + return QBluezConst::AttError::ATT_ERROR_NO_ERROR; +} + +bool QLowEnergyControllerPrivateBluez::verifyMac(const QByteArray &message, BluezUint128 csrk, + quint32 signCounter, quint64 expectedMac) +{ + if (!cmacCalculator) + cmacCalculator = new LeCmacCalculator; + return cmacCalculator->verify(LeCmacCalculator::createFullMessage(message, signCounter), csrk, + expectedMac); +} + +QT_END_NAMESPACE + +#include "moc_qlowenergycontroller_bluez_p.cpp" diff --git a/src/bluetooth/qlowenergycontroller_bluez_p.h b/src/bluetooth/qlowenergycontroller_bluez_p.h new file mode 100644 index 0000000..5c42ccd --- /dev/null +++ b/src/bluetooth/qlowenergycontroller_bluez_p.h @@ -0,0 +1,329 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QLOWENERGYCONTROLLERBLUEZ_P_H +#define QLOWENERGYCONTROLLERBLUEZ_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 "qlowenergycontroller.h" +#include "qlowenergycontrollerbase_p.h" +#include "bluez/bluez_data_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +class QLowEnergyServiceData; +class QTimer; + +class HciManager; +class LeCmacCalculator; +class QSocketNotifier; +class RemoteDeviceManager; + +extern void registerQLowEnergyControllerMetaType(); + +class QLeAdvertiser; + +class QLowEnergyControllerPrivateBluez final: public QLowEnergyControllerPrivate +{ + Q_OBJECT +public: + QLowEnergyControllerPrivateBluez(); + ~QLowEnergyControllerPrivateBluez() override; + + void init() override; + + void connectToDevice() override; + void disconnectFromDevice() override; + + void discoverServices() override; + void discoverServiceDetails(const QBluetoothUuid &service, + QLowEnergyService::DiscoveryMode mode) override; + + void startAdvertising(const QLowEnergyAdvertisingParameters ¶ms, + const QLowEnergyAdvertisingData &advertisingData, + const QLowEnergyAdvertisingData &scanResponseData) override; + void stopAdvertising() override; + + void requestConnectionUpdate(const QLowEnergyConnectionParameters ¶ms) override; + + // read data + void readCharacteristic(const QSharedPointer service, + const QLowEnergyHandle charHandle) override; + void readDescriptor(const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle) override; + + // write data + void writeCharacteristic(const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QByteArray &newValue, QLowEnergyService::WriteMode mode) override; + void writeDescriptor(const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle, + const QByteArray &newValue) override; + + void addToGenericAttributeList(const QLowEnergyServiceData &service, + QLowEnergyHandle startHandle) override; + + int mtu() const override; + + struct Attribute { + Attribute() : handle(0) {} + + QLowEnergyHandle handle; + QLowEnergyHandle groupEndHandle; + QLowEnergyCharacteristic::PropertyTypes properties; + QBluetooth::AttAccessConstraints readConstraints; + QBluetooth::AttAccessConstraints writeConstraints; + QBluetoothUuid type; + QByteArray value; + int minLength; + int maxLength; + }; + QList localAttributes; + +private: + quint16 connectionHandle = 0; + QBluetoothSocket *l2cpSocket = nullptr; + struct Request { + QBluezConst::AttCommand command; + QByteArray payload; + // TODO reference below is ugly but until we know all commands and their + // requirements this is WIP + QVariant reference; + QVariant reference2; + }; + QQueue openRequests; + + struct WriteRequest { + WriteRequest() {} + WriteRequest(quint16 h, quint16 o, const QByteArray &v) + : handle(h), valueOffset(o), value(v) {} + quint16 handle; + quint16 valueOffset; + QByteArray value; + }; + QList openPrepareWriteRequests; + + // Invariant: !scheduledIndications.isEmpty => indicationInFlight == true + QList scheduledIndications; + bool indicationInFlight = false; + + struct TempClientConfigurationData { + TempClientConfigurationData(QLowEnergyServicePrivate::DescData *dd = nullptr, + QLowEnergyHandle chHndl = 0, QLowEnergyHandle coHndl = 0) + : descData(dd), charValueHandle(chHndl), configHandle(coHndl) {} + + QLowEnergyServicePrivate::DescData *descData; + QLowEnergyHandle charValueHandle; + QLowEnergyHandle configHandle; + }; + + struct ClientConfigurationData { + ClientConfigurationData(QLowEnergyHandle chHndl = 0, QLowEnergyHandle coHndl = 0, + quint16 val = 0) + : charValueHandle(chHndl), configHandle(coHndl), configValue(val) {} + + QLowEnergyHandle charValueHandle; + QLowEnergyHandle configHandle; + quint16 configValue; + bool charValueWasUpdated = false; + }; + QHash> clientConfigData; + + struct SigningData { + SigningData() = default; + SigningData(BluezUint128 csrk, quint32 signCounter = quint32(-1)) + : key(csrk), counter(signCounter) {} + + BluezUint128 key; + quint32 counter = quint32(-1); + }; + QHash signingData; + LeCmacCalculator *cmacCalculator = nullptr; + + bool requestPending; + quint16 mtuSize; + int securityLevelValue; + bool encryptionChangePending; + bool receivedMtuExchangeRequest = false; + + std::shared_ptr hciManager; + QLeAdvertiser *advertiser = nullptr; + QSocketNotifier *serverSocketNotifier = nullptr; + QTimer *requestTimer = nullptr; + RemoteDeviceManager* device1Manager = nullptr; + + /* + Defines the maximum number of milliseconds the implementation will + wait for requests that require a response. + + This addresses the problem that some non-conformant BTLE devices + do not implement the request/response system properly. In such cases + the queue system would hang forever. + + Once timeout has been triggered we gracefully continue with the next request. + Depending on the type of the timed out ATT command we either ignore it + or artifically trigger an error response to ensure the API gives the + appropriate response. Potentially this can cause problems when the + response for the dropped requests arrives very late. That's why a big warning + is printed about the compromised state when a timeout is triggered. + */ + int gattRequestTimeout = 20000; + + void handleConnectionRequest(); + void closeServerSocket(); + + bool isBonded() const; + QList gatherClientConfigData(); + void storeClientConfigurations(); + void restoreClientConfigurations(); + + enum SigningKeyType { LocalSigningKey, RemoteSigningKey }; + void loadSigningDataIfNecessary(SigningKeyType keyType); + void storeSignCounter(SigningKeyType keyType) const; + QString signingKeySettingsGroup(SigningKeyType keyType) const; + QString keySettingsFilePath() const; + + void sendPacket(const QByteArray &packet); + void sendNextPendingRequest(); + void processReply(const Request &request, const QByteArray &reply); + + void sendReadByGroupRequest(QLowEnergyHandle start, QLowEnergyHandle end, + quint16 type); + void sendReadByTypeRequest(QSharedPointer serviceData, + QLowEnergyHandle nextHandle, quint16 attributeType); + void sendReadValueRequest(QLowEnergyHandle attributeHandle, bool isDescriptor); + void readServiceValues(const QBluetoothUuid &service, + bool readCharacteristics); + void readServiceValuesByOffset(uint handleData, quint16 offset, + bool isLastValue); + + void discoverServiceDescriptors(const QBluetoothUuid &serviceUuid); + void discoverNextDescriptor(QSharedPointer serviceData, + const QList pendingCharHandles, + QLowEnergyHandle startingHandle); + void processUnsolicitedReply(const QByteArray &msg); + void exchangeMTU(); + bool setSecurityLevel(int level); + int securityLevel() const; + void sendExecuteWriteRequest(const QLowEnergyHandle attrHandle, + const QByteArray &newValue, + bool isCancelation); + void sendNextPrepareWriteRequest(const QLowEnergyHandle handle, + const QByteArray &newValue, quint16 offset); + bool increaseEncryptLevelfRequired(QBluezConst::AttError errorCode); + + void resetController(); + + void handleAdvertisingError(); + + bool checkPacketSize(const QByteArray &packet, int minSize, int maxSize = -1); + bool checkHandle(const QByteArray &packet, QLowEnergyHandle handle); + bool checkHandlePair(QBluezConst::AttCommand request, QLowEnergyHandle startingHandle, + QLowEnergyHandle endingHandle); + + void handleExchangeMtuRequest(const QByteArray &packet); + void handleFindInformationRequest(const QByteArray &packet); + void handleFindByTypeValueRequest(const QByteArray &packet); + void handleReadByTypeRequest(const QByteArray &packet); + void handleReadRequest(const QByteArray &packet); + void handleReadBlobRequest(const QByteArray &packet); + void handleReadMultipleRequest(const QByteArray &packet); + void handleReadByGroupTypeRequest(const QByteArray &packet); + void handleWriteRequestOrCommand(const QByteArray &packet); + void handlePrepareWriteRequest(const QByteArray &packet); + void handleExecuteWriteRequest(const QByteArray &packet); + + void sendErrorResponse(QBluezConst::AttCommand request, quint16 handle, + QBluezConst::AttError code); + + using ElemWriter = std::function; + void sendListResponse(const QByteArray &packetStart, qsizetype elemSize, + const QList &attributes, const ElemWriter &elemWriter); + + void sendNotification(QLowEnergyHandle handle); + void sendIndication(QLowEnergyHandle handle); + void sendNotificationOrIndication(QBluezConst::AttCommand opCode, QLowEnergyHandle handle); + void sendNextIndication(); + + void ensureUniformAttributes(QList &attributes, + const std::function &getSize); + void ensureUniformUuidSizes(QList &attributes); + void ensureUniformValueSizes(QList &attributes); + + using AttributePredicate = std::function; + QList getAttributes( + QLowEnergyHandle startHandle, QLowEnergyHandle endHandle, + const AttributePredicate &attributePredicate = [](const Attribute &) { return true; }); + + QBluezConst::AttError checkPermissions(const Attribute &attr, + QLowEnergyCharacteristic::PropertyType type); + QBluezConst::AttError checkReadPermissions(const Attribute &attr); + QBluezConst::AttError checkReadPermissions(QList &attributes); + + bool verifyMac(const QByteArray &message, BluezUint128 csrk, quint32 signCounter, + quint64 expectedMac); + + void updateLocalAttributeValue( + QLowEnergyHandle handle, + const QByteArray &value, + QLowEnergyCharacteristic &characteristic, + QLowEnergyDescriptor &descriptor); + + void writeCharacteristicForPeripheral( + QLowEnergyServicePrivate::CharData &charData, + const QByteArray &newValue); + void writeCharacteristicForCentral(const QSharedPointer &service, + QLowEnergyHandle charHandle, + QLowEnergyHandle valueHandle, + const QByteArray &newValue, + QLowEnergyService::WriteMode mode); + + void writeDescriptorForPeripheral( + const QSharedPointer &service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle, + const QByteArray &newValue); + void writeDescriptorForCentral( + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle, + const QByteArray &newValue); + + void restartRequestTimer(); + void establishL2cpClientSocket(); + void createServicesForCentralIfRequired(); + +private slots: + void l2cpConnected(); + void l2cpDisconnected(); + void l2cpErrorChanged(QBluetoothSocket::SocketError); + void l2cpReadyRead(); + void encryptionChangedEvent(const QBluetoothAddress&, bool); + void handleGattRequestTimeout(); + void activeConnectionTerminationDone(); +}; + +Q_DECLARE_TYPEINFO(QLowEnergyControllerPrivateBluez::Attribute, Q_RELOCATABLE_TYPE); + +QT_END_NAMESPACE + +#endif //QLOWENERGYCONTROLLERBLUEZ_P_H diff --git a/src/bluetooth/qlowenergycontroller_bluezdbus.cpp b/src/bluetooth/qlowenergycontroller_bluezdbus.cpp new file mode 100644 index 0000000..a00e438 --- /dev/null +++ b/src/bluetooth/qlowenergycontroller_bluezdbus.cpp @@ -0,0 +1,1516 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qlowenergycontroller_bluezdbus_p.h" +#include "bluez/adapter1_bluez5_p.h" +#include "bluez/bluez5_helper_p.h" +#include "bluez/device1_bluez5_p.h" +#include "bluez/gattservice1_p.h" +#include "bluez/gattchar1_p.h" +#include "bluez/gattdesc1_p.h" +#include "bluez/battery1_p.h" +#include "bluez/objectmanager_p.h" +#include "bluez/properties_p.h" +#include "bluez/bluezperipheralapplication_p.h" +#include "bluez/bluezperipheralconnectionmanager_p.h" + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ) + +QLowEnergyControllerPrivateBluezDBus::QLowEnergyControllerPrivateBluezDBus( + const QString &adapterPathWithPeripheralSupport) + : QLowEnergyControllerPrivate(), + adapterPathWithPeripheralSupport(adapterPathWithPeripheralSupport) +{ +} + +QLowEnergyControllerPrivateBluezDBus::~QLowEnergyControllerPrivateBluezDBus() +{ + if (state != QLowEnergyController::UnconnectedState) { + qCWarning(QT_BT_BLUEZ) << "Low Energy Controller is not Unconnected when deleted." + << "Deleted in state:" << state; + } +} + +void QLowEnergyControllerPrivateBluezDBus::init() +{ + if (role == QLowEnergyController::PeripheralRole) { + Q_ASSERT(!adapterPathWithPeripheralSupport.isEmpty()); + + peripheralApplication = new QtBluezPeripheralApplication(adapterPathWithPeripheralSupport, + this); + + QObject::connect(peripheralApplication, &QtBluezPeripheralApplication::errorOccurred, this, + &QLowEnergyControllerPrivateBluezDBus::handlePeripheralApplicationError); + + QObject::connect(peripheralApplication, &QtBluezPeripheralApplication::registered, this, + &QLowEnergyControllerPrivateBluezDBus::handlePeripheralApplicationRegistered); + + QObject::connect(peripheralApplication, + &QtBluezPeripheralApplication::characteristicValueUpdatedByRemote, this, + &QLowEnergyControllerPrivateBluezDBus::handlePeripheralCharacteristicValueUpdate); + + QObject::connect(peripheralApplication, + &QtBluezPeripheralApplication::descriptorValueUpdatedByRemote, this, + &QLowEnergyControllerPrivateBluezDBus::handlePeripheralDescriptorValueUpdate); + + peripheralConnectionManager = + new QtBluezPeripheralConnectionManager(localAdapter, this); + + QObject::connect(peripheralApplication, + &QtBluezPeripheralApplication::remoteDeviceAccessEvent, + peripheralConnectionManager, + &QtBluezPeripheralConnectionManager::remoteDeviceAccessEvent); + + QObject::connect(peripheralConnectionManager, + &QtBluezPeripheralConnectionManager::connectivityStateChanged, this, + &QLowEnergyControllerPrivateBluezDBus::handlePeripheralConnectivityChanged); + + QObject::connect(peripheralConnectionManager, + &QtBluezPeripheralConnectionManager::remoteDeviceChanged, this, + &QLowEnergyControllerPrivateBluezDBus::handlePeripheralRemoteDeviceChanged); + } +} + +void QLowEnergyControllerPrivateBluezDBus::devicePropertiesChanged( + const QString &interface, const QVariantMap &changedProperties, + const QStringList &/*removedProperties*/) +{ + if (interface == QStringLiteral("org.bluez.Device1")) { + qCDebug(QT_BT_BLUEZ) << "######" << interface << changedProperties; + if (changedProperties.contains(QStringLiteral("ServicesResolved"))) { + //we could check for Connected property as well, but we choose to wait + //for ServicesResolved being true + + if (pendingConnect) { + bool isResolved = changedProperties.value(QStringLiteral("ServicesResolved")).toBool(); + if (isResolved) { + setState(QLowEnergyController::ConnectedState); + pendingConnect = false; + disconnectSignalRequired = true; + Q_Q(QLowEnergyController); + emit q->connected(); + } + } + } + + if (changedProperties.contains(QStringLiteral("Connected"))) { + bool isConnected = changedProperties.value(QStringLiteral("Connected")).toBool(); + if (!isConnected) { + switch (state) { + case QLowEnergyController::ConnectingState: + case QLowEnergyController::ConnectedState: + case QLowEnergyController::DiscoveringState: + case QLowEnergyController::DiscoveredState: + case QLowEnergyController::ClosingState: + { + QLowEnergyController::Error newError = QLowEnergyController::NoError; + if (pendingConnect) + newError = QLowEnergyController::ConnectionError; + + executeClose(newError); + } + break; + case QLowEnergyController::AdvertisingState: + case QLowEnergyController::UnconnectedState: + //ignore + break; + } + } + } + + if (changedProperties.contains(QStringLiteral("UUIDs"))) { + const QStringList newUuidStringList = changedProperties.value(QStringLiteral("UUIDs")).toStringList(); + QList newUuidList; + for (const QString &uuidString : newUuidStringList) + newUuidList.append(QBluetoothUuid(uuidString)); + + for (const QBluetoothUuid &uuid : serviceList.keys()) { + if (!newUuidList.contains(uuid)) { + qCDebug(QT_BT_BLUEZ) << __func__ << "Service" << uuid << "has been removed"; + QSharedPointer service = serviceList.take(uuid); + service->setController(nullptr); + dbusServices.remove(uuid); + } + } + } + + } else if (interface == QStringLiteral("org.bluez.Battery1")) { + qCDebug(QT_BT_BLUEZ) << "######" << interface << changedProperties; + if (changedProperties.contains(QStringLiteral("Percentage"))) { + // if battery service is discovered and ClientCharConfig is enabled + // emit characteristicChanged() signal + const QBluetoothUuid uuid(QBluetoothUuid::ServiceClassUuid::BatteryService); + if (!serviceList.contains(uuid) || !dbusServices.contains(uuid) + || !dbusServices[uuid].hasBatteryService + || dbusServices[uuid].batteryInterface.isNull()) + return; + + QSharedPointer serviceData = serviceList.value(uuid); + if (serviceData->state != QLowEnergyService::RemoteServiceDiscovered) + return; + + QHash::iterator iter; + iter = serviceData->characteristicList.begin(); + while (iter != serviceData->characteristicList.end()) { + auto &charData = iter.value(); + if (charData.uuid != QBluetoothUuid::CharacteristicType::BatteryLevel) + continue; + + // Client Characteristic Notification enabled? + bool cccActive = false; + for (const QLowEnergyServicePrivate::DescData &descData : std::as_const(charData.descriptorList)) { + if (descData.uuid != QBluetoothUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration)) + continue; + if (descData.value == QByteArray::fromHex("0100") + || descData.value == QByteArray::fromHex("0200")) { + cccActive = true; + break; + } + } + + const QByteArray newValue(1, char(dbusServices[uuid].batteryInterface->percentage())); + qCDebug(QT_BT_BLUEZ) << "Battery1 char update" << cccActive + << charData.value.toHex() << "->" << newValue.toHex(); + if (cccActive && newValue != charData.value) { + qCDebug(QT_BT_BLUEZ) << "Property update for Battery1"; + charData.value = newValue; + QLowEnergyCharacteristic ch(serviceData, iter.key()); + emit serviceData->characteristicChanged(ch, newValue); + } + + break; + } + } + } +} + +void QLowEnergyControllerPrivateBluezDBus::characteristicPropertiesChanged( + QLowEnergyHandle charHandle, const QString &interface, + const QVariantMap &changedProperties, + const QStringList &/*removedProperties*/) +{ + //qCDebug(QT_BT_BLUEZ) << "$$$$$$$$$$$$$$$$$$ char monitor" + // << interface << changedProperties << charHandle; + if (interface != QStringLiteral("org.bluez.GattCharacteristic1")) + return; + + if (!changedProperties.contains(QStringLiteral("Value"))) + return; + + const QLowEnergyCharacteristic changedChar = characteristicForHandle(charHandle); + const QLowEnergyDescriptor ccnDescriptor = changedChar.descriptor( + QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration); + if (!ccnDescriptor.isValid()) + return; + + const QByteArray newValue = changedProperties.value(QStringLiteral("Value")).toByteArray(); + if (changedChar.properties() & QLowEnergyCharacteristic::Read) + updateValueOfCharacteristic(charHandle, newValue, false); //TODO upgrade to NEW_VALUE/APPEND_VALUE + + auto service = serviceForHandle(charHandle); + + if (!service.isNull()) + emit service->characteristicChanged(changedChar, newValue); +} + +void QLowEnergyControllerPrivateBluezDBus::interfacesRemoved(const QDBusObjectPath &objectPath, + const QStringList &interfaces) +{ + if (objectPath.path() == device->path()) { + if (interfaces.contains(QStringLiteral("org.bluez.Device1"))) { + qCWarning(QT_BT_BLUEZ) << "DBus Device1 was removed"; + executeClose(QLowEnergyController::UnknownRemoteDeviceError); + } else { + qCDebug(QT_BT_BLUEZ) << "DBus interfaces" << interfaces << "were removed from" + << objectPath.path(); + } + } else if (objectPath.path() == adapter->path()) { + qCWarning(QT_BT_BLUEZ) << "DBus Adapter was removed"; + executeClose(QLowEnergyController::InvalidBluetoothAdapterError); + } +} + +void QLowEnergyControllerPrivateBluezDBus::resetController() +{ + if (managerBluez) { + delete managerBluez; + managerBluez = nullptr; + } + + if (adapter) { + delete adapter; + adapter = nullptr; + } + + if (device) { + delete device; + device = nullptr; + } + + if (deviceMonitor) { + delete deviceMonitor; + deviceMonitor = nullptr; + } + + if (advertiser) { + delete advertiser; + advertiser = nullptr; + } + + if (peripheralApplication) + peripheralApplication->reset(); + + if (peripheralConnectionManager) + peripheralConnectionManager->reset(); + + remoteName.clear(); + remoteMtu = -1; + + dbusServices.clear(); + jobs.clear(); + invalidateServices(); + + pendingConnect = disconnectSignalRequired = false; + jobPending = false; +} + +void QLowEnergyControllerPrivateBluezDBus::connectToDeviceHelper() +{ + resetController(); + + bool ok = false; + const QString hostAdapterPath = findAdapterForAddress(localAdapter, &ok); + if (!ok || hostAdapterPath.isEmpty()) { + qCWarning(QT_BT_BLUEZ) << "Cannot find suitable bluetooth adapter"; + setError(QLowEnergyController::InvalidBluetoothAdapterError); + return; + } + + auto manager = std::make_unique( + QStringLiteral("org.bluez"), QStringLiteral("/"), QDBusConnection::systemBus()); + + QDBusPendingReply reply = manager->GetManagedObjects(); + reply.waitForFinished(); + if (reply.isError()) { + qCWarning(QT_BT_BLUEZ) << "Cannot enumerate Bluetooth devices for GATT connect"; + setError(QLowEnergyController::ConnectionError); + return; + } + + QString devicePath; + ManagedObjectList managedObjectList = reply.value(); + for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) { + const InterfaceList &ifaceList = it.value(); + + for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) { + const QString &iface = jt.key(); + const QVariantMap &ifaceValues = jt.value(); + + if (iface == QStringLiteral("org.bluez.Device1")) { + if (remoteDevice.toString() == ifaceValues.value(QStringLiteral("Address")).toString()) + { + const QVariant adapterForCurrentDevice = ifaceValues.value(QStringLiteral("Adapter")); + if (qvariant_cast(adapterForCurrentDevice).path() == hostAdapterPath) { + devicePath = it.key().path(); + break; + } + } + } + } + + if (!devicePath.isEmpty()) + break; + } + + if (devicePath.isEmpty()) { + qCDebug(QT_BT_BLUEZ) << "Cannot find targeted remote device. " + "Re-running device discovery might help"; + setError(QLowEnergyController::UnknownRemoteDeviceError); + return; + } + + managerBluez = manager.release(); + connect(managerBluez, &OrgFreedesktopDBusObjectManagerInterface::InterfacesRemoved, + this, &QLowEnergyControllerPrivateBluezDBus::interfacesRemoved); + adapter = new OrgBluezAdapter1Interface( + QStringLiteral("org.bluez"), hostAdapterPath, + QDBusConnection::systemBus(), this); + device = new OrgBluezDevice1Interface( + QStringLiteral("org.bluez"), devicePath, + QDBusConnection::systemBus(), this); + deviceMonitor = new OrgFreedesktopDBusPropertiesInterface( + QStringLiteral("org.bluez"), devicePath, + QDBusConnection::systemBus(), this); + connect(deviceMonitor, &OrgFreedesktopDBusPropertiesInterface::PropertiesChanged, + this, &QLowEnergyControllerPrivateBluezDBus::devicePropertiesChanged); +} + +void QLowEnergyControllerPrivateBluezDBus::connectToDevice() +{ + qCDebug(QT_BT_BLUEZ) << "QLowEnergyControllerPrivateBluezDBus::connectToDevice()"; + + connectToDeviceHelper(); + + if (!adapter || !device) + return; + + if (!adapter->powered()) { + qCWarning(QT_BT_BLUEZ) << "Error: Local adapter is powered off"; + setError(QLowEnergyController::ConnectionError); + return; + } + + setState(QLowEnergyController::ConnectingState); + + //Bluez interface is shared among all platform processes + //and hence we might be connected already + if (device->connected() && device->servicesResolved()) { + //connectToDevice is noop + disconnectSignalRequired = true; + + setState(QLowEnergyController::ConnectedState); + Q_Q(QLowEnergyController); + emit q->connected(); + return; + } + + pendingConnect = true; + + QDBusPendingReply<> reply = device->Connect(); + QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, &QDBusPendingCallWatcher::finished, this, + [this](QDBusPendingCallWatcher* call) { + QDBusPendingReply<> reply = *call; + if (reply.isError()) { + qCDebug(QT_BT_BLUEZ) << "BTLE_DBUS::connect() failed" + << reply.reply().errorName() + << reply.reply().errorMessage(); + executeClose(QLowEnergyController::UnknownError); + } // else -> connected when Connected property is set to true (see devicePropertiesChanged()) + call->deleteLater(); + }); +} + +void QLowEnergyControllerPrivateBluezDBus::disconnectFromDevice() +{ + if (role == QLowEnergyController::CentralRole) { + if (!device) + return; + + setState(QLowEnergyController::ClosingState); + + QDBusPendingReply<> reply = device->Disconnect(); + QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, &QDBusPendingCallWatcher::finished, this, + [this](QDBusPendingCallWatcher* call) { + QDBusPendingReply<> reply = *call; + if (reply.isError()) { + qCDebug(QT_BT_BLUEZ) << "BTLE_DBUS::disconnect() failed" + << reply.reply().errorName() + << reply.reply().errorMessage(); + executeClose(QLowEnergyController::UnknownError); + } else { + executeClose(QLowEnergyController::NoError); + } + call->deleteLater(); + }); + } else { + Q_Q(QLowEnergyController); + peripheralConnectionManager->disconnectDevices(); + resetController(); + remoteDevice.clear(); + const auto emitDisconnected = (state == QLowEnergyController::ConnectedState); + setState(QLowEnergyController::UnconnectedState); + if (emitDisconnected) + emit q->disconnected(); + } +} + +void QLowEnergyControllerPrivateBluezDBus::discoverServices() +{ + QDBusPendingReply reply = managerBluez->GetManagedObjects(); + reply.waitForFinished(); + if (reply.isError()) { + qCWarning(QT_BT_BLUEZ) << "Cannot discover services"; + setError(QLowEnergyController::UnknownError); + setState(QLowEnergyController::DiscoveredState); + return; + } + + Q_Q(QLowEnergyController); + + auto setupServicePrivate = [&, q]( + QLowEnergyService::ServiceType type, const QBluetoothUuid &uuid, + const QString &path, const bool battery1Interface = false){ + QSharedPointer priv = QSharedPointer::create(); + priv->uuid = uuid; + priv->type = type; // we make a guess we cannot validate + priv->setController(this); + + GattService serviceContainer; + serviceContainer.servicePath = path; + + if (battery1Interface) { + qCDebug(QT_BT_BLUEZ) << "Using Battery1 interface to emulate generic interface"; + serviceContainer.hasBatteryService = true; + } + + serviceList.insert(priv->uuid, priv); + dbusServices.insert(priv->uuid, serviceContainer); + + emit q->serviceDiscovered(priv->uuid); + }; + + const ManagedObjectList managedObjectList = reply.value(); + const QString servicePathPrefix = device->path().append(QStringLiteral("/service")); + + // The Bluez battery service (0x180f) support has evolved over time and needs additional logic: + // + // * Until 5.47 Bluez exposes battery services via generic interface (GattService1) only + // * Between 5.48..5.54 Bluez exposes battery service as a dedicated 'Battery1' interface only + // * From 5.55 Bluez exposes both the generic service as well as the dedicated 'Battery1' + // + // To hide the difference from users the 'Battery1' interface will be used to emulate the + // generic interface. Importantly also the GattService1 interface, if available, is available + // early whereas the Battery1 interface may be available only later (generated too late for + // this service discovery's purposes) + // + // The precedence for battery service here is as follows: + // * If available via GattService1, use that and ignore possible Battery1 interface + // * If Battery1 interface is available or the 'org.bluez.Device1' lists battery service + // amongst list of available services, mark the service such that the code will later + // look up the Battery1 service details + bool gattBatteryService{false}; + QString batteryServicePath; + + for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) { + const InterfaceList &ifaceList = it.value(); + + if (!it.key().path().startsWith(device->path())) + continue; + + if (it.key().path() == device->path()) { + // See if the battery service is available or is assumed to be available later + for (InterfaceList::const_iterator battIter = ifaceList.constBegin(); battIter != ifaceList.constEnd(); ++battIter) { + const QString &iface = battIter.key(); + if (iface == QStringLiteral("org.bluez.Battery1")) { + qCDebug(QT_BT_BLUEZ) << "Dedicated Battery1 service available"; + batteryServicePath = it.key().path(); + break; + } else if (iface == QStringLiteral("org.bluez.Device1")) { + for (auto const& uuid : + battIter.value()[QStringLiteral("UUIDs")].toStringList()) { + if (QBluetoothUuid(uuid) == + QBluetoothUuid::ServiceClassUuid::BatteryService) { + qCDebug(QT_BT_BLUEZ) << "Battery service listed as available service"; + batteryServicePath = it.key().path(); + break; + } + } + } + } + continue; + } + + if (!it.key().path().startsWith(servicePathPrefix)) + continue; + + for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) { + const QString &iface = jt.key(); + + if (iface == QStringLiteral("org.bluez.GattService1")) { + QScopedPointer service(new OrgBluezGattService1Interface( + QStringLiteral("org.bluez"),it.key().path(), + QDBusConnection::systemBus(), this)); + if (QBluetoothUuid(service->uUID()) == + QBluetoothUuid::ServiceClassUuid::BatteryService) { + qCDebug(QT_BT_BLUEZ) << "Using battery service via GattService1 interface"; + gattBatteryService = true; + } + setupServicePrivate(service->primary() + ? QLowEnergyService::PrimaryService + : QLowEnergyService::IncludedService, + QBluetoothUuid(service->uUID()), it.key().path()); + } + } + } + + if (!gattBatteryService && !batteryServicePath.isEmpty()) { + setupServicePrivate(QLowEnergyService::PrimaryService, + QBluetoothUuid::ServiceClassUuid::BatteryService, + batteryServicePath, true); + } + + setState(QLowEnergyController::DiscoveredState); + emit q->discoveryFinished(); +} + +void QLowEnergyControllerPrivateBluezDBus::discoverBatteryServiceDetails( + GattService &dbusData, QSharedPointer serviceData) +{ + // This process exists to work around the fact that Battery services (0x180f) + // are not mapped as generic services but use the Battery1 interface. + // Artificial chararacteristics and descriptors are created to emulate the generic behavior. + + auto batteryService = QSharedPointer::create( + QStringLiteral("org.bluez"), dbusData.servicePath, + QDBusConnection::systemBus()); + dbusData.batteryInterface = batteryService; + + serviceData->startHandle = runningHandle++; //service start handle + + // Create BatteryLevel char + QLowEnergyHandle indexHandle = runningHandle++; // char handle index + QLowEnergyServicePrivate::CharData charData; + + charData.valueHandle = runningHandle++; + charData.properties.setFlag(QLowEnergyCharacteristic::Read); + charData.properties.setFlag(QLowEnergyCharacteristic::Notify); + charData.uuid = QBluetoothUuid::CharacteristicType::BatteryLevel; + charData.value = QByteArray(1, char(batteryService->percentage())); + + // Create the descriptors for the BatteryLevel + // They are hardcoded although CCC may change + QLowEnergyServicePrivate::DescData descData; + QLowEnergyHandle descriptorHandle = runningHandle++; + descData.uuid = QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration; + descData.value = QByteArray::fromHex("0000"); // all configs off + charData.descriptorList.insert(descriptorHandle, descData); + + descriptorHandle = runningHandle++; + descData.uuid = QBluetoothUuid::DescriptorType::CharacteristicPresentationFormat; + //for details see Characteristic Presentation Format Vol3, Part G 3.3.3.5 + // unsigend 8 bit, exp=1, org.bluetooth.unit.percentage, namespace & description + // bit order: little endian + descData.value = QByteArray::fromHex("0400ad27011131"); + charData.descriptorList.insert(descriptorHandle, descData); + + descriptorHandle = runningHandle++; + descData.uuid = QBluetoothUuid::DescriptorType::ReportReference; + descData.value = QByteArray::fromHex("0401"); + charData.descriptorList.insert(descriptorHandle, descData); + + serviceData->characteristicList[indexHandle] = charData; + serviceData->endHandle = runningHandle++; + + serviceData->setState(QLowEnergyService::RemoteServiceDiscovered); +} + +void QLowEnergyControllerPrivateBluezDBus::executeClose(QLowEnergyController::Error newError) +{ + const bool emitDisconnect = disconnectSignalRequired; + + resetController(); + if (newError != QLowEnergyController::NoError) + setError(newError); + + setState(QLowEnergyController::UnconnectedState); + if (emitDisconnect) { + Q_Q(QLowEnergyController); + emit q->disconnected(); + } +} + +void QLowEnergyControllerPrivateBluezDBus::discoverServiceDetails( + const QBluetoothUuid &service, QLowEnergyService::DiscoveryMode mode) +{ + if (!serviceList.contains(service) || !dbusServices.contains(service)) { + qCWarning(QT_BT_BLUEZ) << "Discovery of unknown service" << service.toString() + << "not possible"; + return; + } + + //clear existing service data and run new discovery + QSharedPointer serviceData = serviceList.value(service); + serviceData->characteristicList.clear(); + + GattService &dbusData = dbusServices[service]; + dbusData.characteristics.clear(); + + if (dbusData.hasBatteryService) { + qCDebug(QT_BT_BLUEZ) << "Triggering Battery1 service discovery on " << dbusData.servicePath; + discoverBatteryServiceDetails(dbusData, serviceData); + return; + } + + QDBusPendingReply reply = managerBluez->GetManagedObjects(); + reply.waitForFinished(); + if (reply.isError()) { + qCWarning(QT_BT_BLUEZ) << "Cannot discover services"; + setError(QLowEnergyController::UnknownError); + setState(QLowEnergyController::DiscoveredState); + return; + } + + QStringList descriptorPaths; + const ManagedObjectList managedObjectList = reply.value(); + for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) { + const InterfaceList &ifaceList = it.value(); + if (!it.key().path().startsWith(dbusData.servicePath)) + continue; + + for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) { + const QString &iface = jt.key(); + if (iface == QStringLiteral("org.bluez.GattCharacteristic1")) { + auto charInterface = QSharedPointer::create( + QStringLiteral("org.bluez"), it.key().path(), + QDBusConnection::systemBus()); + GattCharacteristic dbusCharData; + dbusCharData.characteristic = charInterface; + dbusData.characteristics.append(dbusCharData); + } else if (iface == QStringLiteral("org.bluez.GattDescriptor1")) { + auto descInterface = QSharedPointer::create( + QStringLiteral("org.bluez"), it.key().path(), + QDBusConnection::systemBus()); + bool found = false; + for (GattCharacteristic &dbusCharData : dbusData.characteristics) { + if (!descInterface->path().startsWith( + dbusCharData.characteristic->path())) + continue; + + found = true; + dbusCharData.descriptors.append(descInterface); + break; + } + + Q_ASSERT(found); + if (!found) + qCWarning(QT_BT_BLUEZ) << "Descriptor discovery error"; + } + } + } + + //populate servicePrivate based on dbus data + serviceData->startHandle = runningHandle++; + for (GattCharacteristic &dbusChar : dbusData.characteristics) { + const QLowEnergyHandle indexHandle = runningHandle++; + QLowEnergyServicePrivate::CharData charData; + + // characteristic data + charData.valueHandle = runningHandle++; + const QStringList properties = dbusChar.characteristic->flags(); + + for (const auto &entry : properties) { + if (entry == QStringLiteral("broadcast")) + charData.properties.setFlag(QLowEnergyCharacteristic::Broadcasting, true); + else if (entry == QStringLiteral("read")) + charData.properties.setFlag(QLowEnergyCharacteristic::Read, true); + else if (entry == QStringLiteral("write-without-response")) + charData.properties.setFlag(QLowEnergyCharacteristic::WriteNoResponse, true); + else if (entry == QStringLiteral("write")) + charData.properties.setFlag(QLowEnergyCharacteristic::Write, true); + else if (entry == QStringLiteral("notify")) + charData.properties.setFlag(QLowEnergyCharacteristic::Notify, true); + else if (entry == QStringLiteral("indicate")) + charData.properties.setFlag(QLowEnergyCharacteristic::Indicate, true); + else if (entry == QStringLiteral("authenticated-signed-writes")) + charData.properties.setFlag(QLowEnergyCharacteristic::WriteSigned, true); + else if (entry == QStringLiteral("reliable-write")) + charData.properties.setFlag(QLowEnergyCharacteristic::ExtendedProperty, true); + else if (entry == QStringLiteral("writable-auxiliaries")) + charData.properties.setFlag(QLowEnergyCharacteristic::ExtendedProperty, true); + //all others ignored - not relevant for this API + } + + charData.uuid = QBluetoothUuid(dbusChar.characteristic->uUID()); + + // schedule read for initial char value + if (mode == QLowEnergyService::FullDiscovery + && charData.properties.testFlag(QLowEnergyCharacteristic::Read)) { + GattJob job; + job.flags = GattJob::JobFlags({GattJob::CharRead, GattJob::ServiceDiscovery}); + job.service = serviceData; + job.handle = indexHandle; + jobs.append(job); + } + + // descriptor data + for (const auto &descEntry : std::as_const(dbusChar.descriptors)) { + const QLowEnergyHandle descriptorHandle = runningHandle++; + QLowEnergyServicePrivate::DescData descData; + descData.uuid = QBluetoothUuid(descEntry->uUID()); + charData.descriptorList.insert(descriptorHandle, descData); + + + // every ClientCharacteristicConfiguration needs to track property changes + if (descData.uuid + == QBluetoothUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration)) { + dbusChar.charMonitor = QSharedPointer::create( + QStringLiteral("org.bluez"), + dbusChar.characteristic->path(), + QDBusConnection::systemBus(), this); + connect(dbusChar.charMonitor.data(), &OrgFreedesktopDBusPropertiesInterface::PropertiesChanged, + this, [this, indexHandle](const QString &interface, const QVariantMap &changedProperties, + const QStringList &removedProperties) { + + characteristicPropertiesChanged(indexHandle, interface, + changedProperties, removedProperties); + }); + } + + if (mode == QLowEnergyService::FullDiscovery) { + // schedule read for initial descriptor value + GattJob job; + job.flags = GattJob::JobFlags({ GattJob::DescRead, GattJob::ServiceDiscovery }); + job.service = serviceData; + job.handle = descriptorHandle; + jobs.append(job); + } + } + + serviceData->characteristicList[indexHandle] = charData; + } + + serviceData->endHandle = runningHandle++; + + // last job is last step of service discovery + if (!jobs.isEmpty()) { + GattJob &lastJob = jobs.last(); + lastJob.flags.setFlag(GattJob::LastServiceDiscovery, true); + } else { + serviceData->setState(QLowEnergyService::RemoteServiceDiscovered); + } + + scheduleNextJob(); +} + +void QLowEnergyControllerPrivateBluezDBus::prepareNextJob() +{ + jobs.takeFirst(); // finish last job + jobPending = false; + + scheduleNextJob(); // continue with next job - if available +} + +void QLowEnergyControllerPrivateBluezDBus::onCharReadFinished(QDBusPendingCallWatcher *call) +{ + if (!jobPending || jobs.isEmpty()) { + // this may happen when service disconnects before dbus watcher returns later on + qCWarning(QT_BT_BLUEZ) << "Aborting onCharReadFinished due to disconnect"; + Q_ASSERT(state == QLowEnergyController::UnconnectedState); + return; + } + + const GattJob nextJob = jobs.constFirst(); + Q_ASSERT(nextJob.flags.testFlag(GattJob::CharRead)); + + QSharedPointer service = serviceForHandle(nextJob.handle); + if (service.isNull() || !dbusServices.contains(service->uuid)) { + qCWarning(QT_BT_BLUEZ) << "onCharReadFinished: Invalid GATT job. Skipping."; + call->deleteLater(); + prepareNextJob(); + return; + } + const QLowEnergyServicePrivate::CharData &charData = + service->characteristicList.value(nextJob.handle); + + bool isServiceDiscovery = nextJob.flags.testFlag(GattJob::ServiceDiscovery); + QDBusPendingReply reply = *call; + if (reply.isError()) { + qCWarning(QT_BT_BLUEZ) << "Cannot initiate reading of" << charData.uuid + << "of service" << service->uuid + << reply.error().name() << reply.error().message(); + if (!isServiceDiscovery) + service->setError(QLowEnergyService::CharacteristicReadError); + } else { + qCDebug(QT_BT_BLUEZ) << "Read Char:" << charData.uuid << reply.value().toHex(); + if (charData.properties.testFlag(QLowEnergyCharacteristic::Read)) + updateValueOfCharacteristic(nextJob.handle, reply.value(), false); + + if (isServiceDiscovery) { + if (nextJob.flags.testFlag(GattJob::LastServiceDiscovery)) + service->setState(QLowEnergyService::RemoteServiceDiscovered); + } else { + QLowEnergyCharacteristic ch(service, nextJob.handle); + emit service->characteristicRead(ch, reply.value()); + } + } + + call->deleteLater(); + prepareNextJob(); +} + +void QLowEnergyControllerPrivateBluezDBus::onDescReadFinished(QDBusPendingCallWatcher *call) +{ + if (!jobPending || jobs.isEmpty()) { + // this may happen when service disconnects before dbus watcher returns later on + qCWarning(QT_BT_BLUEZ) << "Aborting onDescReadFinished due to disconnect"; + Q_ASSERT(state == QLowEnergyController::UnconnectedState); + return; + } + + const GattJob nextJob = jobs.constFirst(); + Q_ASSERT(nextJob.flags.testFlag(GattJob::DescRead)); + + QSharedPointer service = serviceForHandle(nextJob.handle); + if (service.isNull() || !dbusServices.contains(service->uuid)) { + qCWarning(QT_BT_BLUEZ) << "onDescReadFinished: Invalid GATT job. Skipping."; + call->deleteLater(); + prepareNextJob(); + return; + } + + QLowEnergyCharacteristic ch = characteristicForHandle(nextJob.handle); + if (!ch.isValid()) { + qCWarning(QT_BT_BLUEZ) << "Cannot find char for desc read (onDescReadFinished 1)."; + call->deleteLater(); + prepareNextJob(); + return; + } + + const QLowEnergyServicePrivate::CharData &charData = + service->characteristicList.value(ch.attributeHandle()); + + if (!charData.descriptorList.contains(nextJob.handle)) { + qCWarning(QT_BT_BLUEZ) << "Cannot find descriptor (onDescReadFinished 2)."; + call->deleteLater(); + prepareNextJob(); + return; + } + + bool isServiceDiscovery = nextJob.flags.testFlag(GattJob::ServiceDiscovery); + + QDBusPendingReply reply = *call; + if (reply.isError()) { + qCWarning(QT_BT_BLUEZ) << "Cannot read descriptor (onDescReadFinished 3): " + << charData.descriptorList[nextJob.handle].uuid + << charData.uuid + << reply.error().name() << reply.error().message(); + if (!isServiceDiscovery) + service->setError(QLowEnergyService::DescriptorReadError); + } else { + qCDebug(QT_BT_BLUEZ) << "Read Desc:" << reply.value(); + updateValueOfDescriptor(ch.attributeHandle(), nextJob.handle, reply.value(), false); + + if (isServiceDiscovery) { + if (nextJob.flags.testFlag(GattJob::LastServiceDiscovery)) + service->setState(QLowEnergyService::RemoteServiceDiscovered); + } else { + QLowEnergyDescriptor desc(service, ch.attributeHandle(), nextJob.handle); + emit service->descriptorRead(desc, reply.value()); + } + } + + call->deleteLater(); + prepareNextJob(); +} + +void QLowEnergyControllerPrivateBluezDBus::onCharWriteFinished(QDBusPendingCallWatcher *call) +{ + if (!jobPending || jobs.isEmpty()) { + // this may happen when service disconnects before dbus watcher returns later on + qCWarning(QT_BT_BLUEZ) << "Aborting onCharWriteFinished due to disconnect"; + Q_ASSERT(state == QLowEnergyController::UnconnectedState); + return; + } + + const GattJob nextJob = jobs.constFirst(); + Q_ASSERT(nextJob.flags.testFlag(GattJob::CharWrite)); + + QSharedPointer service = nextJob.service; + if (!dbusServices.contains(service->uuid)) { + qCWarning(QT_BT_BLUEZ) << "onCharWriteFinished: Invalid GATT job. Skipping."; + call->deleteLater(); + prepareNextJob(); + return; + } + + const QLowEnergyServicePrivate::CharData &charData = + service->characteristicList.value(nextJob.handle); + + QDBusPendingReply<> reply = *call; + if (reply.isError()) { + qCWarning(QT_BT_BLUEZ) << "Cannot initiate writing of" << charData.uuid + << "of service" << service->uuid + << reply.error().name() << reply.error().message(); + service->setError(QLowEnergyService::CharacteristicWriteError); + } else { + if (charData.properties.testFlag(QLowEnergyCharacteristic::Read)) + updateValueOfCharacteristic(nextJob.handle, nextJob.value, false); + + QLowEnergyCharacteristic ch(service, nextJob.handle); + // write without response implies zero feedback + if (nextJob.writeMode == QLowEnergyService::WriteWithResponse) { + qCDebug(QT_BT_BLUEZ) << "Written Char:" << charData.uuid << nextJob.value.toHex(); + emit service->characteristicWritten(ch, nextJob.value); + } + } + + call->deleteLater(); + prepareNextJob(); +} + +void QLowEnergyControllerPrivateBluezDBus::onDescWriteFinished(QDBusPendingCallWatcher *call) +{ + if (!jobPending || jobs.isEmpty()) { + // this may happen when service disconnects before dbus watcher returns later on + qCWarning(QT_BT_BLUEZ) << "Aborting onDescWriteFinished due to disconnect"; + Q_ASSERT(state == QLowEnergyController::UnconnectedState); + return; + } + + const GattJob nextJob = jobs.constFirst(); + Q_ASSERT(nextJob.flags.testFlag(GattJob::DescWrite)); + + QSharedPointer service = nextJob.service; + if (!dbusServices.contains(service->uuid)) { + qCWarning(QT_BT_BLUEZ) << "onDescWriteFinished: Invalid GATT job. Skipping."; + call->deleteLater(); + prepareNextJob(); + return; + } + + const QLowEnergyCharacteristic associatedChar = characteristicForHandle(nextJob.handle); + const QLowEnergyDescriptor descriptor = descriptorForHandle(nextJob.handle); + if (!associatedChar.isValid() || !descriptor.isValid()) { + qCWarning(QT_BT_BLUEZ) << "onDescWriteFinished: Cannot find associated char/desc: " + << associatedChar.isValid(); + call->deleteLater(); + prepareNextJob(); + return; + } + + QDBusPendingReply<> reply = *call; + if (reply.isError()) { + qCWarning(QT_BT_BLUEZ) << "Cannot initiate writing of" << descriptor.uuid() + << "of char" << associatedChar.uuid() + << "of service" << service->uuid + << reply.error().name() << reply.error().message(); + service->setError(QLowEnergyService::DescriptorWriteError); + } else { + qCDebug(QT_BT_BLUEZ) << "Write Desc:" << descriptor.uuid() << nextJob.value.toHex(); + updateValueOfDescriptor(associatedChar.attributeHandle(), nextJob.handle, + nextJob.value, false); + emit service->descriptorWritten(descriptor, nextJob.value); + } + + call->deleteLater(); + prepareNextJob(); +} + +void QLowEnergyControllerPrivateBluezDBus::scheduleNextJob() +{ + if (jobPending || jobs.isEmpty()) + return; + + jobPending = true; + + const GattJob nextJob = jobs.constFirst(); + QSharedPointer service = serviceForHandle(nextJob.handle); + if (service.isNull() || !dbusServices.contains(service->uuid)) { + qCWarning(QT_BT_BLUEZ) << "Invalid GATT job (scheduleNextJob). Skipping."; + prepareNextJob(); + return; + } + + const GattService &dbusServiceData = dbusServices[service->uuid]; + + if (nextJob.flags.testFlag(GattJob::CharRead)) { + // characteristic reading *************************************** + if (!service->characteristicList.contains(nextJob.handle)) { + qCWarning(QT_BT_BLUEZ) << "Invalid Char handle when reading. Skipping."; + prepareNextJob(); + return; + } + + const QLowEnergyServicePrivate::CharData &charData = + service->characteristicList.value(nextJob.handle); + bool foundChar = false; + for (const auto &gattChar : std::as_const(dbusServiceData.characteristics)) { + if (charData.uuid != QBluetoothUuid(gattChar.characteristic->uUID())) + continue; + + QDBusPendingReply reply = gattChar.characteristic->ReadValue(QVariantMap()); + QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, &QDBusPendingCallWatcher::finished, + this, &QLowEnergyControllerPrivateBluezDBus::onCharReadFinished); + + foundChar = true; + break; + } + + if (!foundChar) { + qCWarning(QT_BT_BLUEZ) << "Cannot find char for reading. Skipping."; + prepareNextJob(); + return; + } + } else if (nextJob.flags.testFlag(GattJob::CharWrite)) { + // characteristic writing *************************************** + if (!service->characteristicList.contains(nextJob.handle)) { + qCWarning(QT_BT_BLUEZ) << "Invalid Char handle when writing. Skipping."; + prepareNextJob(); + return; + } + + const QLowEnergyServicePrivate::CharData &charData = + service->characteristicList.value(nextJob.handle); + bool foundChar = false; + for (const auto &gattChar : std::as_const(dbusServiceData.characteristics)) { + if (charData.uuid != QBluetoothUuid(gattChar.characteristic->uUID())) + continue; + + QVariantMap options; + // The "type" option only works with BlueZ >= 5.50, older versions always write with response + options[QStringLiteral("type")] = nextJob.writeMode == QLowEnergyService::WriteWithoutResponse ? + QStringLiteral("command") : QStringLiteral("request"); + QDBusPendingReply<> reply = gattChar.characteristic->WriteValue(nextJob.value, options); + + QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, &QDBusPendingCallWatcher::finished, + this, &QLowEnergyControllerPrivateBluezDBus::onCharWriteFinished); + + foundChar = true; + break; + } + + if (!foundChar) { + qCWarning(QT_BT_BLUEZ) << "Cannot find char for writing. Skipping."; + prepareNextJob(); + return; + } + } else if (nextJob.flags.testFlag(GattJob::DescRead)) { + // descriptor reading *************************************** + QLowEnergyCharacteristic ch = characteristicForHandle(nextJob.handle); + if (!ch.isValid()) { + qCWarning(QT_BT_BLUEZ) << "Invalid GATT job (scheduleReadDesc 1). Skipping."; + prepareNextJob(); + return; + } + + const QLowEnergyServicePrivate::CharData &charData = + service->characteristicList.value(ch.attributeHandle()); + if (!charData.descriptorList.contains(nextJob.handle)) { + qCWarning(QT_BT_BLUEZ) << "Invalid GATT job (scheduleReadDesc 2). Skipping."; + prepareNextJob(); + return; + } + + const QBluetoothUuid descUuid = charData.descriptorList[nextJob.handle].uuid; + bool foundDesc = false; + for (const auto &gattChar : std::as_const(dbusServiceData.characteristics)) { + if (charData.uuid != QBluetoothUuid(gattChar.characteristic->uUID())) + continue; + + for (const auto &gattDesc : std::as_const(gattChar.descriptors)) { + if (descUuid != QBluetoothUuid(gattDesc->uUID())) + continue; + + QDBusPendingReply reply = gattDesc->ReadValue(QVariantMap()); + QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, &QDBusPendingCallWatcher::finished, + this, &QLowEnergyControllerPrivateBluezDBus::onDescReadFinished); + foundDesc = true; + break; + } + + if (foundDesc) + break; + } + + if (!foundDesc) { + qCWarning(QT_BT_BLUEZ) << "Cannot find descriptor for reading. Skipping."; + prepareNextJob(); + return; + } + } else if (nextJob.flags.testFlag(GattJob::DescWrite)) { + // descriptor writing *************************************** + const QLowEnergyCharacteristic ch = characteristicForHandle(nextJob.handle); + if (!ch.isValid()) { + qCWarning(QT_BT_BLUEZ) << "Invalid GATT job (scheduleWriteDesc 1). Skipping."; + prepareNextJob(); + return; + } + + const QLowEnergyServicePrivate::CharData &charData = + service->characteristicList.value(ch.attributeHandle()); + if (!charData.descriptorList.contains(nextJob.handle)) { + qCWarning(QT_BT_BLUEZ) << "Invalid GATT job (scheduleWriteDesc 2). Skipping."; + prepareNextJob(); + return; + } + + const QBluetoothUuid descUuid = charData.descriptorList[nextJob.handle].uuid; + bool foundDesc = false; + for (const auto &gattChar : std::as_const(dbusServiceData.characteristics)) { + if (charData.uuid != QBluetoothUuid(gattChar.characteristic->uUID())) + continue; + + for (const auto &gattDesc : std::as_const(gattChar.descriptors)) { + if (descUuid != QBluetoothUuid(gattDesc->uUID())) + continue; + + //notifications enabled via characteristics Start/StopNotify() functions + //otherwise regular WriteValue() calls on descriptor interface + if (descUuid == QBluetoothUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration)) { + const QByteArray value = nextJob.value; + + QDBusPendingReply<> reply; + qCDebug(QT_BT_BLUEZ) << "Init CCC change to" << value.toHex() + << charData.uuid << service->uuid; + if (value == QByteArray::fromHex("0100") || value == QByteArray::fromHex("0200")) + reply = gattChar.characteristic->StartNotify(); + else + reply = gattChar.characteristic->StopNotify(); + QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, &QDBusPendingCallWatcher::finished, + this, &QLowEnergyControllerPrivateBluezDBus::onDescWriteFinished); + } else { + QDBusPendingReply<> reply = gattDesc->WriteValue(nextJob.value, QVariantMap()); + QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, &QDBusPendingCallWatcher::finished, + this, &QLowEnergyControllerPrivateBluezDBus::onDescWriteFinished); + + } + + foundDesc = true; + break; + } + + if (foundDesc) + break; + } + + if (!foundDesc) { + qCWarning(QT_BT_BLUEZ) << "Cannot find descriptor for writing. Skipping."; + prepareNextJob(); + return; + } + } else { + qCWarning(QT_BT_BLUEZ) << "Unknown gatt job type. Skipping."; + prepareNextJob(); + } +} + +void QLowEnergyControllerPrivateBluezDBus::readCharacteristic( + const QSharedPointer service, + const QLowEnergyHandle charHandle) +{ + Q_ASSERT(!service.isNull()); + if (!service->characteristicList.contains(charHandle)) { + qCWarning(QT_BT_BLUEZ) << "Read characteristic does not belong to service" + << service->uuid; + return; + } + + const QLowEnergyServicePrivate::CharData &charDetails + = service->characteristicList[charHandle]; + if (!(charDetails.properties & QLowEnergyCharacteristic::Read)) { + // if this succeeds the device has a bug, char is advertised as + // non-readable. We try to be permissive and let the remote + // device answer to the read attempt + qCWarning(QT_BT_BLUEZ) << "Reading non-readable char" << charHandle; + } + + const GattService &gattService = dbusServices[service->uuid]; + if (gattService.hasBatteryService && !gattService.batteryInterface.isNull()) { + // Reread from dbus interface and write to local cache + const QByteArray newValue(1, char(gattService.batteryInterface->percentage())); + quint16 result = updateValueOfCharacteristic(charHandle, newValue, false); + if (result > 0) { + QLowEnergyCharacteristic ch(service, charHandle); + emit service->characteristicRead(ch, newValue); + } else { + service->setError(QLowEnergyService::CharacteristicReadError); + } + return; + } + + GattJob job; + job.flags = GattJob::JobFlags({GattJob::CharRead}); + job.service = service; + job.handle = charHandle; + jobs.append(job); + + scheduleNextJob(); +} + +void QLowEnergyControllerPrivateBluezDBus::readDescriptor( + const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle) +{ + Q_ASSERT(!service.isNull()); + if (!service->characteristicList.contains(charHandle)) + return; + + const QLowEnergyServicePrivate::CharData &charDetails + = service->characteristicList[charHandle]; + if (!charDetails.descriptorList.contains(descriptorHandle)) + return; + + const GattService &gattService = dbusServices[service->uuid]; + if (gattService.hasBatteryService && !gattService.batteryInterface.isNull()) { + auto descriptor = descriptorForHandle(descriptorHandle); + if (descriptor.isValid()) + emit service->descriptorRead(descriptor, descriptor.value()); + else + service->setError(QLowEnergyService::DescriptorReadError); + + return; + } + + GattJob job; + job.flags = GattJob::JobFlags({GattJob::DescRead}); + job.service = service; + job.handle = descriptorHandle; + jobs.append(job); + + scheduleNextJob(); +} + +void QLowEnergyControllerPrivateBluezDBus::writeCharacteristic( + const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QByteArray &newValue, + QLowEnergyService::WriteMode writeMode) +{ + Q_ASSERT(!service.isNull()); + if (!service->characteristicList.contains(charHandle)) { + qCWarning(QT_BT_BLUEZ) << "Write characteristic does not belong to service" + << service->uuid; + return; + } + + if (role == QLowEnergyController::CentralRole) { + const GattService &gattService = dbusServices[service->uuid]; + if (gattService.hasBatteryService && !gattService.batteryInterface.isNull()) { + //Battery1 interface is readonly + service->setError(QLowEnergyService::CharacteristicWriteError); + return; + } + + + GattJob job; + job.flags = GattJob::JobFlags({GattJob::CharWrite}); + job.service = service; + job.handle = charHandle; + job.value = newValue; + job.writeMode = writeMode; + jobs.append(job); + + scheduleNextJob(); + } else { + // Peripheral role + Q_ASSERT(peripheralApplication); + if (!peripheralApplication->localCharacteristicWrite(charHandle, newValue)) { + qCWarning(QT_BT_BLUEZ) << "Characteristic write failed" + << characteristicForHandle(charHandle).uuid(); + service->setError(QLowEnergyService::CharacteristicWriteError); + return; + } + QLowEnergyServicePrivate::CharData &charData = service->characteristicList[charHandle]; + charData.value = newValue; + } +} + +void QLowEnergyControllerPrivateBluezDBus::writeDescriptor( + const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle, + const QByteArray &newValue) +{ + Q_ASSERT(!service.isNull()); + if (!service->characteristicList.contains(charHandle)) + return; + + if (role == QLowEnergyController::CentralRole) { + const GattService &gattService = dbusServices[service->uuid]; + if (gattService.hasBatteryService && !gattService.batteryInterface.isNull()) { + auto descriptor = descriptorForHandle(descriptorHandle); + if (!descriptor.isValid()) + return; + + if (descriptor.uuid() == QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration) { + if (newValue == QByteArray::fromHex("0000") + || newValue == QByteArray::fromHex("0100") + || newValue == QByteArray::fromHex("0200")) { + quint16 result = updateValueOfDescriptor(charHandle, descriptorHandle, newValue, false); + if (result > 0) + emit service->descriptorWritten(descriptor, newValue); + else + emit service->setError(QLowEnergyService::DescriptorWriteError); + + } + } else { + service->setError(QLowEnergyService::DescriptorWriteError); + } + + return; + } + + GattJob job; + job.flags = GattJob::JobFlags({GattJob::DescWrite}); + job.service = service; + job.handle = descriptorHandle; + job.value = newValue; + jobs.append(job); + + scheduleNextJob(); + } else { + // Peripheral role + Q_ASSERT(peripheralApplication); + + auto desc = descriptorForHandle(descriptorHandle); + if (desc.uuid() == QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration) { + qCWarning(QT_BT_BLUEZ) << "CCCD write not supported in peripheral role"; + service->setError(QLowEnergyService::DescriptorWriteError); + return; + } else if (!peripheralApplication->localDescriptorWrite(descriptorHandle, newValue)) { + qCWarning(QT_BT_BLUEZ) << "Descriptor write failed" << desc.uuid(); + service->setError(QLowEnergyService::DescriptorWriteError); + return; + } + service->characteristicList[charHandle].descriptorList[descriptorHandle].value = newValue; + } +} + +void QLowEnergyControllerPrivateBluezDBus::startAdvertising( + const QLowEnergyAdvertisingParameters ¶ms, + const QLowEnergyAdvertisingData &advertisingData, + const QLowEnergyAdvertisingData &scanResponseData) +{ + error = QLowEnergyController::NoError; + errorString.clear(); + + Q_ASSERT(peripheralApplication); + Q_ASSERT(!adapterPathWithPeripheralSupport.isEmpty()); + + if (advertiser) { + // Clear any previous advertiser in case advertising data has changed. + // For clarity: this function is called only in 'Unconnected' state + delete advertiser; + advertiser = nullptr; + } + advertiser = new QLeDBusAdvertiser(params, advertisingData, scanResponseData, + adapterPathWithPeripheralSupport, this); + connect(advertiser, &QLeDBusAdvertiser::errorOccurred, + this, &QLowEnergyControllerPrivateBluezDBus::handleAdvertisingError); + + setState(QLowEnergyController::AdvertisingState); + + // First register the application to bluez if needed, and then start the advertisement. + // The application registration may fail and is asynchronous => serialize the steps. + // For clarity: advertisements can be used without any services, but registering such + // application to Bluez would fail + if (peripheralApplication->registrationNeeded()) + peripheralApplication->registerApplication(); + else + advertiser->startAdvertising(); +} + +void QLowEnergyControllerPrivateBluezDBus::stopAdvertising() +{ + // This function is called only in Advertising state + setState(QLowEnergyController::UnconnectedState); + if (advertiser) { + advertiser->stopAdvertising(); + delete advertiser; + advertiser = nullptr; + } +} + +void QLowEnergyControllerPrivateBluezDBus::handlePeripheralApplicationRegistered() +{ + // Start the actual advertising now that the application is registered. + // Check the state first in case user has called stopAdvertising() during + // application registration + if (advertiser && state == QLowEnergyController::AdvertisingState) + advertiser->startAdvertising(); + else + peripheralApplication->unregisterApplication(); +} + +void QLowEnergyControllerPrivateBluezDBus::handlePeripheralCharacteristicValueUpdate( + QLowEnergyHandle handle, const QByteArray& value) +{ + const auto characteristic = characteristicForHandle(handle); + if (characteristic.d_ptr + && updateValueOfCharacteristic(handle, value, false) == value.size()) { + emit characteristic.d_ptr->characteristicChanged(characteristic, value); + } else { + qCWarning(QT_BT_BLUEZ) << "Remote characteristic write failed"; + } +} + +void QLowEnergyControllerPrivateBluezDBus::handlePeripheralDescriptorValueUpdate( + QLowEnergyHandle characteristicHandle, + QLowEnergyHandle descriptorHandle, + const QByteArray& value) +{ + const auto descriptor = descriptorForHandle(descriptorHandle); + if (descriptor.d_ptr && updateValueOfDescriptor( + characteristicHandle, descriptorHandle, value, false) == value.size()) { + emit descriptor.d_ptr->descriptorWritten(descriptor, value); + } else { + qCWarning(QT_BT_BLUEZ) << "Remote descriptor write failed"; + } +} + +void QLowEnergyControllerPrivateBluezDBus::handlePeripheralRemoteDeviceChanged( + const QBluetoothAddress& address, + const QString& name, + quint16 mtu) +{ + remoteDevice = address; + remoteName = name; + remoteMtu = mtu; +} + +void QLowEnergyControllerPrivateBluezDBus::handleAdvertisingError() +{ + Q_ASSERT(peripheralApplication); + qCWarning(QT_BT_BLUEZ) << "An advertising error occurred"; + setError(QLowEnergyController::AdvertisingError); + setState(QLowEnergyController::UnconnectedState); + peripheralApplication->unregisterApplication(); +} + +void QLowEnergyControllerPrivateBluezDBus::handlePeripheralApplicationError() +{ + qCWarning(QT_BT_BLUEZ) << "A Bluez peripheral application error occurred"; + setError(QLowEnergyController::UnknownError); + setState(QLowEnergyController::UnconnectedState); +} + +void QLowEnergyControllerPrivateBluezDBus::handlePeripheralConnectivityChanged(bool connected) +{ + Q_Q(QLowEnergyController); + qCDebug(QT_BT_BLUEZ) << "Peripheral application connected change to:" << connected; + if (connected) { + setState(QLowEnergyController::ConnectedState); + } else { + resetController(); + remoteDevice.clear(); + setState(QLowEnergyController::UnconnectedState); + emit q->disconnected(); + } +} + +void QLowEnergyControllerPrivateBluezDBus::requestConnectionUpdate( + const QLowEnergyConnectionParameters & /* params */) +{ + qCWarning(QT_BT_BLUEZ) << "Connection udpate requests not supported on Bluez DBus"; +} + +void QLowEnergyControllerPrivateBluezDBus::addToGenericAttributeList( + const QLowEnergyServiceData &serviceData, + QLowEnergyHandle startHandle) +{ + Q_ASSERT(peripheralApplication); + QSharedPointer servicePrivate = serviceForHandle(startHandle); + if (servicePrivate.isNull()) + return; + peripheralApplication->addService(serviceData, servicePrivate, startHandle); +} + +int QLowEnergyControllerPrivateBluezDBus::mtu() const +{ + // currently only supported on peripheral role + return remoteMtu; +} + +QT_END_NAMESPACE + +#include "moc_qlowenergycontroller_bluezdbus_p.cpp" diff --git a/src/bluetooth/qlowenergycontroller_bluezdbus_p.h b/src/bluetooth/qlowenergycontroller_bluezdbus_p.h new file mode 100644 index 0000000..afa2e8f --- /dev/null +++ b/src/bluetooth/qlowenergycontroller_bluezdbus_p.h @@ -0,0 +1,182 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QLOWENERGYCONTROLLERPRIVATEDBUS_P_H +#define QLOWENERGYCONTROLLERPRIVATEDBUS_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 "qlowenergycontroller.h" +#include "qlowenergycontrollerbase_p.h" +#include "qleadvertiser_bluezdbus_p.h" + +#include + +class OrgBluezAdapter1Interface; +class OrgBluezBattery1Interface; +class OrgBluezDevice1Interface; +class OrgBluezGattCharacteristic1Interface; +class OrgBluezGattDescriptor1Interface; +class OrgBluezGattService1Interface; +class OrgFreedesktopDBusObjectManagerInterface; +class OrgFreedesktopDBusPropertiesInterface; + +QT_BEGIN_NAMESPACE + +class QtBluezPeripheralApplication; +class QtBluezPeripheralConnectionManager; +class QDBusPendingCallWatcher; + +class QLowEnergyControllerPrivateBluezDBus final : public QLowEnergyControllerPrivate +{ + Q_OBJECT +public: + QLowEnergyControllerPrivateBluezDBus(const QString& adapterPathWithPeripheralSupport = {}); + ~QLowEnergyControllerPrivateBluezDBus() override; + + void init() override; + void connectToDevice() override; + void disconnectFromDevice() override; + + void discoverServices() override; + void discoverServiceDetails(const QBluetoothUuid &service, + QLowEnergyService::DiscoveryMode mode) override; + + void readCharacteristic( + const QSharedPointer service, + const QLowEnergyHandle charHandle) override; + void readDescriptor( + const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle) override; + + void writeCharacteristic( + const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QByteArray &newValue, + QLowEnergyService::WriteMode writeMode) override; + void writeDescriptor( + const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle, + const QByteArray &newValue) override; + + void startAdvertising( + const QLowEnergyAdvertisingParameters ¶ms, + const QLowEnergyAdvertisingData &advertisingData, + const QLowEnergyAdvertisingData &scanResponseData) override; + void stopAdvertising() override; + + void requestConnectionUpdate( + const QLowEnergyConnectionParameters & params) override; + void addToGenericAttributeList( + const QLowEnergyServiceData &service, + QLowEnergyHandle startHandle) override; + + int mtu() const override; + +private: + void connectToDeviceHelper(); + void resetController(); + + void scheduleNextJob(); + +private slots: + void devicePropertiesChanged(const QString &interface, const QVariantMap &changedProperties, + const QStringList &invalidatedProperties); + void characteristicPropertiesChanged(QLowEnergyHandle charHandle, const QString &interface, + const QVariantMap &changedProperties, + const QStringList &invalidatedProperties); + void interfacesRemoved(const QDBusObjectPath &objectPath, const QStringList &interfaces); + + void onCharReadFinished(QDBusPendingCallWatcher *call); + void onDescReadFinished(QDBusPendingCallWatcher *call); + void onCharWriteFinished(QDBusPendingCallWatcher *call); + void onDescWriteFinished(QDBusPendingCallWatcher *call); +private: + + OrgBluezAdapter1Interface* adapter{}; + OrgBluezDevice1Interface* device{}; + OrgFreedesktopDBusObjectManagerInterface* managerBluez{}; + OrgFreedesktopDBusPropertiesInterface* deviceMonitor{}; + QString adapterPathWithPeripheralSupport; + + int remoteMtu{-1}; + QtBluezPeripheralApplication* peripheralApplication{}; + QtBluezPeripheralConnectionManager* peripheralConnectionManager{}; + QLeDBusAdvertiser *advertiser{}; + void handleAdvertisingError(); + void handlePeripheralApplicationError(); + void handlePeripheralApplicationRegistered(); + void handlePeripheralConnectivityChanged(bool connected); + void handlePeripheralCharacteristicValueUpdate(QLowEnergyHandle handle, + const QByteArray& value); + void handlePeripheralDescriptorValueUpdate(QLowEnergyHandle characteristicHandle, + QLowEnergyHandle descriptorHandle, + const QByteArray& value); + void handlePeripheralRemoteDeviceChanged(const QBluetoothAddress& address, + const QString& name, + quint16 mtu); + bool pendingConnect = false; + bool disconnectSignalRequired = false; + + struct GattCharacteristic + { + QSharedPointer characteristic; + QSharedPointer charMonitor; + QList> descriptors; + }; + + struct GattService + { + QString servicePath; + QList characteristics; + + bool hasBatteryService = false; + QSharedPointer batteryInterface; + }; + + QHash dbusServices; + QLowEnergyHandle runningHandle = 1; + + struct GattJob { + enum JobFlag { + Unset = 0x00, + CharRead = 0x01, + CharWrite = 0x02, + DescRead = 0x04, + DescWrite = 0x08, + ServiceDiscovery = 0x10, + LastServiceDiscovery = 0x20 + }; + Q_DECLARE_FLAGS(JobFlags, JobFlag) + + JobFlags flags = GattJob::Unset; + QLowEnergyHandle handle; + QByteArray value; + QLowEnergyService::WriteMode writeMode = QLowEnergyService::WriteWithResponse; + QSharedPointer service; + }; + + QList jobs; + bool jobPending = false; + + void prepareNextJob(); + void discoverBatteryServiceDetails(GattService &dbusData, + QSharedPointer serviceData); + void executeClose(QLowEnergyController::Error newError); +}; + +QT_END_NAMESPACE + +#endif // QLOWENERGYCONTROLLERPRIVATEDBUS_P_H diff --git a/src/bluetooth/qlowenergycontroller_darwin.mm b/src/bluetooth/qlowenergycontroller_darwin.mm new file mode 100644 index 0000000..40c9518 --- /dev/null +++ b/src/bluetooth/qlowenergycontroller_darwin.mm @@ -0,0 +1,1024 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// Copyright (C) 2016 Javier S. Pedro +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qlowenergycontroller_darwin_p.h" +#include "darwin/btperipheralmanager_p.h" +#include "qlowenergyserviceprivate_p.h" +#include "darwin/btcentralmanager_p.h" +#include "darwin/btutility_p.h" +#include "darwin/uistrings_p.h" + +#include "qlowenergyservicedata.h" +#include "qbluetoothlocaldevice.h" +#include "qbluetoothdeviceinfo.h" +#include "qlowenergycontroller.h" +#include "qbluetoothuuid.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace { + +typedef QSharedPointer ServicePrivate; + +// Convenience function, can return a smart pointer that 'isNull'. +ServicePrivate qt_createLEService(QLowEnergyControllerPrivateDarwin *controller, CBService *cbService, bool included) +{ + Q_ASSERT_X(controller, Q_FUNC_INFO, "invalid controller (null)"); + Q_ASSERT_X(cbService, Q_FUNC_INFO, "invalid service (nil)"); + + CBUUID *const cbUuid = cbService.UUID; + if (!cbUuid) { + qCDebug(QT_BT_DARWIN) << "invalid service, UUID is nil"; + return ServicePrivate(); + } + + const QBluetoothUuid qtUuid(DarwinBluetooth::qt_uuid(cbUuid)); + if (qtUuid.isNull()) // Conversion error is reported by qt_uuid. + return ServicePrivate(); + + ServicePrivate newService(new QLowEnergyServicePrivate); + newService->uuid = qtUuid; + newService->setController(controller); + + if (included) + newService->type |= QLowEnergyService::IncludedService; + + // TODO: isPrimary is ... always 'NO' - to be investigated. + /* + if (!cbService.isPrimary) { + // Our guess included/not was probably wrong. + newService->type &= ~QLowEnergyService::PrimaryService; + newService->type |= QLowEnergyService::IncludedService; + } + */ + return newService; +} + +typedef QList UUIDList; + +UUIDList qt_servicesUuids(NSArray *services) +{ + QT_BT_MAC_AUTORELEASEPOOL; + + if (!services || !services.count) + return UUIDList(); + + UUIDList uuids; + + for (CBService *s in services) + uuids.append(DarwinBluetooth::qt_uuid(s.UUID)); + + return uuids; +} + +} // unnamed namespace + +QLowEnergyControllerPrivateDarwin::QLowEnergyControllerPrivateDarwin() +{ + void registerQLowEnergyControllerMetaType(); + registerQLowEnergyControllerMetaType(); + qRegisterMetaType("QLowEnergyHandle"); + qRegisterMetaType>(); +} + +QLowEnergyControllerPrivateDarwin::~QLowEnergyControllerPrivateDarwin() +{ + if (const auto leQueue = DarwinBluetooth::qt_LE_queue()) { + if (role == QLowEnergyController::CentralRole) { + const auto manager = centralManager.getAs(); + dispatch_sync(leQueue, ^{ + [manager detach]; + }); + } else { + const auto manager = peripheralManager.getAs(); + dispatch_sync(leQueue, ^{ + [manager detach]; + }); + } + } +} + +bool QLowEnergyControllerPrivateDarwin::isValid() const +{ + return centralManager || peripheralManager; +} + +void QLowEnergyControllerPrivateDarwin::init() +{ + // We have to override the 'init', it's pure virtual in the base. + // Just creating a central or peripheral should not trigger any + // error yet. +} + +bool QLowEnergyControllerPrivateDarwin::lazyInit() +{ + using namespace DarwinBluetooth; + + if (peripheralManager || centralManager) + return true; + + if (qApp->checkPermission(QBluetoothPermission{}) != Qt::PermissionStatus::Granted) { + qCWarning(QT_BT_DARWIN, + "Use of Bluetooth LE must be explicitly requested by the application."); + setError(QLowEnergyController::MissingPermissionsError); + return false; + } + + std::unique_ptr notifier = std::make_unique(); + if (role == QLowEnergyController::PeripheralRole) { + peripheralManager.reset([[DarwinBTPeripheralManager alloc] initWith:notifier.get()], + DarwinBluetooth::RetainPolicy::noInitialRetain); + Q_ASSERT(peripheralManager); + } else { + centralManager.reset([[DarwinBTCentralManager alloc] initWith:notifier.get()], + DarwinBluetooth::RetainPolicy::noInitialRetain); + Q_ASSERT(centralManager); + } + + // FIXME: Q_UNLIKELY + if (!connectSlots(notifier.get())) + qCWarning(QT_BT_DARWIN) << "failed to connect to notifier's signal(s)"; + + // Ownership was taken by central manager. + notifier.release(); + + return true; +} + +void QLowEnergyControllerPrivateDarwin::connectToDevice() +{ + Q_ASSERT_X(state == QLowEnergyController::UnconnectedState, + Q_FUNC_INFO, "invalid state"); + + if (deviceUuid.isNull()) { + // Wrong constructor was used or invalid UUID was provided. + return _q_CBManagerError(QLowEnergyController::UnknownRemoteDeviceError); + } + + if (!lazyInit()) // MissingPermissionsError was emit. + return; + + // The logic enforcing the role is in the public class. + Q_ASSERT_X(role != QLowEnergyController::PeripheralRole, + Q_FUNC_INFO, "invalid role (peripheral)"); + + dispatch_queue_t leQueue(DarwinBluetooth::qt_LE_queue()); + Q_ASSERT_X(leQueue, Q_FUNC_INFO, "invalid LE queue (nullptr)"); + + setError(QLowEnergyController::NoError); + setState(QLowEnergyController::ConnectingState); + + const QBluetoothUuid deviceUuidCopy(deviceUuid); + DarwinBTCentralManager *manager = centralManager.getAs(); + dispatch_async(leQueue, ^{ + [manager connectToDevice:deviceUuidCopy]; + }); +} + +void QLowEnergyControllerPrivateDarwin::disconnectFromDevice() +{ + Q_ASSERT(isValid()); // Check for proper state is in Qt's code. + + if (role == QLowEnergyController::PeripheralRole) { + // CoreBluetooth API intentionally does not provide any way of closing + // a connection. All we can do here is to stop the advertisement. + return stopAdvertising(); + } + + const auto oldState = state; + + if (dispatch_queue_t leQueue = DarwinBluetooth::qt_LE_queue()) { + setState(QLowEnergyController::ClosingState); + invalidateServices(); + + auto manager = centralManager.getAs(); + dispatch_async(leQueue, ^{ + [manager disconnectFromDevice]; + }); + + if (oldState == QLowEnergyController::ConnectingState) { + // With a pending connect attempt there is no + // guarantee we'll ever have didDisconnect callback, + // set the state here and now to make sure we still + // can connect. + setState(QLowEnergyController::UnconnectedState); + } + } else { + qCCritical(QT_BT_DARWIN) << "qt LE queue is nil, " + "can not dispatch 'disconnect'"; + } +} + +void QLowEnergyControllerPrivateDarwin::discoverServices() +{ + Q_ASSERT_X(state != QLowEnergyController::UnconnectedState, + Q_FUNC_INFO, "not connected to peripheral"); + Q_ASSERT_X(role != QLowEnergyController::PeripheralRole, + Q_FUNC_INFO, "invalid role (peripheral)"); + + Q_ASSERT(isValid()); // Check we're in a proper state is in q's code. + + dispatch_queue_t leQueue(DarwinBluetooth::qt_LE_queue()); + Q_ASSERT_X(leQueue, Q_FUNC_INFO, "LE queue not found"); + + setState(QLowEnergyController::DiscoveringState); + + DarwinBTCentralManager *manager = centralManager.getAs(); + dispatch_async(leQueue, ^{ + [manager discoverServices]; + }); +} + +void QLowEnergyControllerPrivateDarwin::discoverServiceDetails( + const QBluetoothUuid &serviceUuid, QLowEnergyService::DiscoveryMode mode) +{ + Q_UNUSED(mode); + if (state != QLowEnergyController::DiscoveredState) { + qCWarning(QT_BT_DARWIN) << "can not discover service details in the current state, " + "QLowEnergyController::DiscoveredState is expected"; + return; + } + + if (!serviceList.contains(serviceUuid)) { + qCWarning(QT_BT_DARWIN) << "unknown service: " << serviceUuid; + return; + } + + dispatch_queue_t leQueue(DarwinBluetooth::qt_LE_queue()); + Q_ASSERT(leQueue); + + ServicePrivate qtService(serviceList.value(serviceUuid)); + qtService->setState(QLowEnergyService::RemoteServiceDiscovering); + // Copy objects ... + DarwinBTCentralManager *manager = centralManager.getAs(); + const QBluetoothUuid serviceUuidCopy(serviceUuid); + dispatch_async(leQueue, ^{ + [manager discoverServiceDetails:serviceUuidCopy readValues:mode == QLowEnergyService::FullDiscovery]; + }); +} + +void QLowEnergyControllerPrivateDarwin::requestConnectionUpdate(const QLowEnergyConnectionParameters ¶ms) +{ + Q_UNUSED(params); + // TODO: implement this, if possible. + qCWarning(QT_BT_DARWIN) << "Connection update not implemented on your platform"; +} + +void QLowEnergyControllerPrivateDarwin::addToGenericAttributeList(const QLowEnergyServiceData &service, + QLowEnergyHandle startHandle) +{ + // Darwin LE controller implements the addServiceHelper() for adding services, and thus + // the base class' addServiceHelper(), which calls this function, is not used + Q_UNUSED(service); + Q_UNUSED(startHandle); +} + +int QLowEnergyControllerPrivateDarwin::mtu() const +{ + // FIXME: check the state - neither public class does, + // nor us - not fun! E.g. readRssi correctly checked/asserted. + + __block int mtu = DarwinBluetooth::defaultMtu; + if (!isValid()) // A minimal check. + return defaultMtu; + + if (const auto leQueue = DarwinBluetooth::qt_LE_queue()) { + const auto *manager = centralManager.getAs(); + dispatch_sync(leQueue, ^{ + mtu = [manager mtu]; + }); + } + + return mtu; +} + +void QLowEnergyControllerPrivateDarwin::readRssi() +{ + Q_ASSERT(role == QLowEnergyController::CentralRole); + Q_ASSERT(state == QLowEnergyController::ConnectedState || + state == QLowEnergyController::DiscoveringState || + state == QLowEnergyController::DiscoveredState); + + if (const auto leQueue = DarwinBluetooth::qt_LE_queue()) { + const auto *manager = centralManager.getAs(); + dispatch_async(leQueue, ^{ + [manager readRssi]; + }); + } +} + +QLowEnergyService * QLowEnergyControllerPrivateDarwin::addServiceHelper(const QLowEnergyServiceData &service) +{ + if (!lazyInit() || !isValid()) { + qCWarning(QT_BT_DARWIN) << "invalid peripheral"; + return nullptr; + } + + for (auto includedService : service.includedServices()) + includedService->d_ptr->type |= QLowEnergyService::IncludedService; + + const auto manager = peripheralManager.getAs(); + Q_ASSERT(manager); + if (const auto servicePrivate = [manager addService:service]) { + servicePrivate->setController(this); + servicePrivate->state = QLowEnergyService::LocalService; + localServices.insert(servicePrivate->uuid, servicePrivate); + return new QLowEnergyService(servicePrivate); + } + + return nullptr; +} + +void QLowEnergyControllerPrivateDarwin::_q_connected() +{ + setState(QLowEnergyController::ConnectedState); + emit q_ptr->connected(); +} + +void QLowEnergyControllerPrivateDarwin::_q_disconnected() +{ + if (role == QLowEnergyController::CentralRole) + invalidateServices(); + + setState(QLowEnergyController::UnconnectedState); + emit q_ptr->disconnected(); +} + +void QLowEnergyControllerPrivateDarwin::_q_mtuChanged(int newValue) +{ + emit q_ptr->mtuChanged(newValue); +} + +void QLowEnergyControllerPrivateDarwin::_q_serviceDiscoveryFinished() +{ + Q_ASSERT_X(state == QLowEnergyController::DiscoveringState, + Q_FUNC_INFO, "invalid state"); + + using namespace DarwinBluetooth; + + QT_BT_MAC_AUTORELEASEPOOL; + + NSArray *const services = [centralManager.getAs() peripheral].services; + // Now we have to traverse the discovered services tree. + // Essentially it's an iterative version of more complicated code from the + // DarwinBTCentralManager's code. + // All Obj-C entities either auto-release, or guarded by ObjCScopedReferences. + if (services && [services count]) { + QMap discoveredCBServices; + //1. The first pass - none of this services is 'included' yet (we'll discover 'included' + // during the pass 2); we also ignore duplicates (== services with the same UUID) + // - since we do not have a way to distinguish them later + // (our API is using uuids when creating QLowEnergyServices). + for (CBService *cbService in services) { + const ServicePrivate newService(qt_createLEService(this, cbService, false)); + if (!newService.data()) + continue; + if (serviceList.contains(newService->uuid)) { + // It's a bit stupid we first created it ... + qCDebug(QT_BT_DARWIN) << "discovered service with a duplicated UUID" + << newService->uuid; + continue; + } + serviceList.insert(newService->uuid, newService); + discoveredCBServices.insert(newService->uuid, cbService); + } + + ObjCStrongReference toVisit([[NSMutableArray alloc] initWithArray:services], RetainPolicy::noInitialRetain); + ObjCStrongReference toVisitNext([[NSMutableArray alloc] init], RetainPolicy::noInitialRetain); + ObjCStrongReference visited([[NSMutableSet alloc] init], RetainPolicy::noInitialRetain); + + while (true) { + for (NSUInteger i = 0, e = [toVisit count]; i < e; ++i) { + CBService *const s = [toVisit objectAtIndex:i]; + if (![visited containsObject:s]) { + [visited addObject:s]; + if (s.includedServices && s.includedServices.count) + [toVisitNext addObjectsFromArray:s.includedServices]; + } + + const QBluetoothUuid uuid(qt_uuid(s.UUID)); + if (serviceList.contains(uuid) && discoveredCBServices.value(uuid) == s) { + ServicePrivate qtService(serviceList.value(uuid)); + // Add included UUIDs: + qtService->includedServices.append(qt_servicesUuids(s.includedServices)); + }// Else - we ignored this CBService object. + } + + if (![toVisitNext count]) + break; + + for (NSUInteger i = 0, e = [toVisitNext count]; i < e; ++i) { + CBService *const s = [toVisitNext objectAtIndex:i]; + const QBluetoothUuid uuid(qt_uuid(s.UUID)); + if (serviceList.contains(uuid)) { + if (discoveredCBServices.value(uuid) == s) { + ServicePrivate qtService(serviceList.value(uuid)); + qtService->type |= QLowEnergyService::IncludedService; + } // Else this is the duplicate we ignored already. + } else { + // Oh, we do not even have it yet??? + ServicePrivate newService(qt_createLEService(this, s, true)); + serviceList.insert(newService->uuid, newService); + discoveredCBServices.insert(newService->uuid, s); + } + } + + toVisit.swap(toVisitNext); + toVisitNext.reset([[NSMutableArray alloc] init], RetainPolicy::noInitialRetain); + } + } else { + qCDebug(QT_BT_DARWIN) << "no services found"; + } + + + state = QLowEnergyController::DiscoveredState; + + for (auto it = serviceList.constBegin(); it != serviceList.constEnd(); ++it) { + QMetaObject::invokeMethod(q_ptr, "serviceDiscovered", Qt::QueuedConnection, + Q_ARG(QBluetoothUuid, it.key())); + } + + QMetaObject::invokeMethod(q_ptr, "stateChanged", Qt::QueuedConnection, Q_ARG(QLowEnergyController::ControllerState, state)); + QMetaObject::invokeMethod(q_ptr, "discoveryFinished", Qt::QueuedConnection); +} + +void QLowEnergyControllerPrivateDarwin::_q_serviceDetailsDiscoveryFinished(QSharedPointer service) +{ + QT_BT_MAC_AUTORELEASEPOOL; + + Q_ASSERT(service); + + if (!serviceList.contains(service->uuid)) { + qCDebug(QT_BT_DARWIN) << "unknown service uuid:" + << service->uuid; + return; + } + + ServicePrivate qtService(serviceList.value(service->uuid)); + // Assert on handles? + qtService->startHandle = service->startHandle; + qtService->endHandle = service->endHandle; + qtService->characteristicList = service->characteristicList; + + qtService->setState(QLowEnergyService::RemoteServiceDiscovered); +} + +void QLowEnergyControllerPrivateDarwin::_q_servicesWereModified() +{ + if (!(state == QLowEnergyController::DiscoveringState + || state == QLowEnergyController::DiscoveredState)) { + qCWarning(QT_BT_DARWIN) << "services were modified while controller is not in Discovered/Discovering state"; + return; + } + + if (state == QLowEnergyController::DiscoveredState) + invalidateServices(); + + setState(QLowEnergyController::ConnectedState); + q_ptr->discoverServices(); +} + +void QLowEnergyControllerPrivateDarwin::_q_characteristicRead(QLowEnergyHandle charHandle, + const QByteArray &value) +{ + Q_ASSERT_X(charHandle, Q_FUNC_INFO, "invalid characteristic handle(0)"); + + ServicePrivate service(serviceForHandle(charHandle)); + if (service.isNull()) + return; + + QLowEnergyCharacteristic characteristic(characteristicForHandle(charHandle)); + if (!characteristic.isValid()) { + qCWarning(QT_BT_DARWIN) << "unknown characteristic"; + return; + } + + if (characteristic.properties() & QLowEnergyCharacteristic::Read) + updateValueOfCharacteristic(charHandle, value, false); + + emit service->characteristicRead(characteristic, value); +} + +void QLowEnergyControllerPrivateDarwin::_q_characteristicWritten(QLowEnergyHandle charHandle, + const QByteArray &value) +{ + Q_ASSERT_X(charHandle, Q_FUNC_INFO, "invalid characteristic handle(0)"); + + ServicePrivate service(serviceForHandle(charHandle)); + if (service.isNull()) { + qCWarning(QT_BT_DARWIN) << "can not find service for characteristic handle" + << charHandle; + return; + } + + QLowEnergyCharacteristic characteristic(characteristicForHandle(charHandle)); + if (!characteristic.isValid()) { + qCWarning(QT_BT_DARWIN) << "unknown characteristic"; + return; + } + + if (characteristic.properties() & QLowEnergyCharacteristic::Read) + updateValueOfCharacteristic(charHandle, value, false); + + emit service->characteristicWritten(characteristic, value); +} + +void QLowEnergyControllerPrivateDarwin::_q_characteristicUpdated(QLowEnergyHandle charHandle, + const QByteArray &value) +{ + // TODO: write/update notifications are quite similar (except asserts/warnings messages + // and different signals emitted). Merge them into one function? + Q_ASSERT_X(charHandle, Q_FUNC_INFO, "invalid characteristic handle(0)"); + + ServicePrivate service(serviceForHandle(charHandle)); + if (service.isNull()) { + // This can be an error (no characteristic found for this handle), + // it can also be that we set notify value before the service + // was reported (serviceDetailsDiscoveryFinished) - this happens, + // if we read a descriptor (characteristic client configuration), + // and it's (pre)set. + return; + } + + QLowEnergyCharacteristic characteristic(characteristicForHandle(charHandle)); + if (!characteristic.isValid()) { + qCWarning(QT_BT_DARWIN) << "unknown characteristic"; + return; + } + + if (characteristic.properties() & QLowEnergyCharacteristic::Read) + updateValueOfCharacteristic(charHandle, value, false); + + emit service->characteristicChanged(characteristic, value); +} + +void QLowEnergyControllerPrivateDarwin::_q_descriptorRead(QLowEnergyHandle dHandle, + const QByteArray &value) +{ + Q_ASSERT_X(dHandle, Q_FUNC_INFO, "invalid descriptor handle (0)"); + + const QLowEnergyDescriptor qtDescriptor(descriptorForHandle(dHandle)); + if (!qtDescriptor.isValid()) { + qCWarning(QT_BT_DARWIN) << "unknown descriptor" << dHandle; + return; + } + + ServicePrivate service(serviceForHandle(qtDescriptor.characteristicHandle())); + updateValueOfDescriptor(qtDescriptor.characteristicHandle(), dHandle, value, false); + emit service->descriptorRead(qtDescriptor, value); +} + +void QLowEnergyControllerPrivateDarwin::_q_descriptorWritten(QLowEnergyHandle dHandle, + const QByteArray &value) +{ + Q_ASSERT_X(dHandle, Q_FUNC_INFO, "invalid descriptor handle (0)"); + + const QLowEnergyDescriptor qtDescriptor(descriptorForHandle(dHandle)); + if (!qtDescriptor.isValid()) { + qCWarning(QT_BT_DARWIN) << "unknown descriptor" << dHandle; + return; + } + + ServicePrivate service(serviceForHandle(qtDescriptor.characteristicHandle())); + // TODO: test if this data is what we expected. + updateValueOfDescriptor(qtDescriptor.characteristicHandle(), dHandle, value, false); + emit service->descriptorWritten(qtDescriptor, value); +} + +void QLowEnergyControllerPrivateDarwin::_q_notificationEnabled(QLowEnergyHandle charHandle, + bool enabled) +{ + // CoreBluetooth in peripheral role does not allow mutable descriptors, + // in central we can only call setNotification:enabled/disabled. + // But from Qt API's point of view, a central has to write into + // client characteristic configuration descriptor. So here we emulate + // such a write (we cannot say if it's a notification or indication and + // report as both). + + Q_ASSERT_X(role == QLowEnergyController::PeripheralRole, Q_FUNC_INFO, + "controller has an invalid role, 'peripheral' expected"); + Q_ASSERT_X(charHandle, Q_FUNC_INFO, "invalid characteristic handle (0)"); + + const QLowEnergyCharacteristic qtChar(characteristicForHandle(charHandle)); + if (!qtChar.isValid()) { + qCWarning(QT_BT_DARWIN) << "unknown characteristic" << charHandle; + return; + } + + const QLowEnergyDescriptor qtDescriptor = + qtChar.descriptor(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration); + if (!qtDescriptor.isValid()) { + qCWarning(QT_BT_DARWIN) << "characteristic" << charHandle + << "does not have a client characteristic " + "descriptor"; + return; + } + + ServicePrivate service(serviceForHandle(charHandle)); + if (service.data()) { + // It's a 16-bit value, the least significant bit is for notifications, + // the next one - for indications (thus 1 means notifications enabled, + // 2 - indications enabled). + // 3 is the maximum value and it means both enabled. + QByteArray value(2, 0); + if (enabled) + value[0] = 3; + updateValueOfDescriptor(charHandle, qtDescriptor.handle(), value, false); + emit service->descriptorWritten(qtDescriptor, value); + } +} + +void QLowEnergyControllerPrivateDarwin::_q_LEnotSupported() +{ + // Report as an error. But this should not be possible + // actually: before connecting to any device, we have + // to discover it, if it was discovered ... LE _must_ + // be supported. +} + +void QLowEnergyControllerPrivateDarwin::_q_CBManagerError(QLowEnergyController::Error errorCode) +{ + qCDebug(QT_BT_DARWIN) << "QLowEnergyController error:" << errorCode << "in state:" << state; + // This function handles errors reported while connecting to a remote device + // and also other errors in general. + setError(errorCode); + + if (state == QLowEnergyController::ConnectingState + || state == QLowEnergyController::AdvertisingState) { + setState(QLowEnergyController::UnconnectedState); + } else if (state == QLowEnergyController::DiscoveringState) { + // An error occurred during service discovery, finish the discovery. + setState(QLowEnergyController::ConnectedState); + emit q_ptr->discoveryFinished(); + } + + // In any other case we stay in Discovered, it's + // a service/characteristic - related error. +} + +void QLowEnergyControllerPrivateDarwin::_q_CBManagerError(const QBluetoothUuid &serviceUuid, + QLowEnergyController::Error errorCode) +{ + // Errors reported while discovering service details etc. + Q_UNUSED(errorCode); // TODO: setError? + + // We failed to discover any characteristics/descriptors. + if (serviceList.contains(serviceUuid)) { + ServicePrivate qtService(serviceList.value(serviceUuid)); + qtService->setState(QLowEnergyService::InvalidService); + } else { + qCDebug(QT_BT_DARWIN) << "error reported for unknown service" + << serviceUuid; + } +} + +void QLowEnergyControllerPrivateDarwin::_q_CBManagerError(const QBluetoothUuid &serviceUuid, + QLowEnergyService::ServiceError errorCode) +{ + if (!serviceList.contains(serviceUuid)) { + qCDebug(QT_BT_DARWIN) << "unknown service uuid:" + << serviceUuid; + return; + } + + ServicePrivate service(serviceList.value(serviceUuid)); + service->setError(errorCode); +} + +void QLowEnergyControllerPrivateDarwin::setNotifyValue(QSharedPointer service, + QLowEnergyHandle charHandle, + const QByteArray &newValue) +{ + Q_ASSERT_X(!service.isNull(), Q_FUNC_INFO, "invalid service (null)"); + + if (role == QLowEnergyController::PeripheralRole) { + qCWarning(QT_BT_DARWIN) << "invalid role (peripheral)"; + service->setError(QLowEnergyService::DescriptorWriteError); + return; + } + + if (newValue.size() > 2) { + // Qt's API requires an error on such write. + // With Core Bluetooth we do not write any descriptor, + // but instead call a special method. So it's better to + // intercept wrong data size here: + qCWarning(QT_BT_DARWIN) << "client characteristic configuration descriptor" + "is 2 bytes, but value size is: " << newValue.size(); + service->setError(QLowEnergyService::DescriptorWriteError); + return; + } + + if (!serviceList.contains(service->uuid)) { + qCWarning(QT_BT_DARWIN) << "no service with uuid:" << service->uuid << "found"; + return; + } + + if (!service->characteristicList.contains(charHandle)) { + qCDebug(QT_BT_DARWIN) << "no characteristic with handle:" + << charHandle << "found"; + return; + } + + dispatch_queue_t leQueue(DarwinBluetooth::qt_LE_queue()); + Q_ASSERT_X(leQueue, Q_FUNC_INFO, "no LE queue found"); + + DarwinBTCentralManager *manager = centralManager.getAs(); + const QBluetoothUuid serviceUuid(service->uuid); + const QByteArray newValueCopy(newValue); + dispatch_async(leQueue, ^{ + [manager setNotifyValue:newValueCopy + forCharacteristic:charHandle + onService:serviceUuid]; + }); +} + +void QLowEnergyControllerPrivateDarwin::readCharacteristic(const QSharedPointer service, + const QLowEnergyHandle charHandle) +{ + Q_ASSERT_X(!service.isNull(), Q_FUNC_INFO, "invalid service (null)"); + + if (role == QLowEnergyController::PeripheralRole) { + qCWarning(QT_BT_DARWIN) << "invalid role (peripheral)"; + return; + } + + if (!serviceList.contains(service->uuid)) { + qCWarning(QT_BT_DARWIN) << "no service with uuid:" + << service->uuid << "found"; + return; + } + + if (!service->characteristicList.contains(charHandle)) { + qCDebug(QT_BT_DARWIN) << "no characteristic with handle:" + << charHandle << "found"; + return; + } + + dispatch_queue_t leQueue(DarwinBluetooth::qt_LE_queue()); + Q_ASSERT_X(leQueue, Q_FUNC_INFO, "no LE queue found"); + + // Attention! We have to copy UUID. + DarwinBTCentralManager *manager = centralManager.getAs(); + const QBluetoothUuid serviceUuid(service->uuid); + dispatch_async(leQueue, ^{ + [manager readCharacteristic:charHandle onService:serviceUuid]; + }); +} + +void QLowEnergyControllerPrivateDarwin::writeCharacteristic(const QSharedPointer service, + const QLowEnergyHandle charHandle, const QByteArray &newValue, + QLowEnergyService::WriteMode mode) +{ + Q_ASSERT_X(!service.isNull(), Q_FUNC_INFO, "invalid service (null)"); + + // We can work only with services found on a given peripheral + // (== created by the given LE controller). + + if (!serviceList.contains(service->uuid) && !localServices.contains(service->uuid)) { + qCWarning(QT_BT_DARWIN) << "no service with uuid:" + << service->uuid << " found"; + return; + } + + if (!service->characteristicList.contains(charHandle)) { + qCDebug(QT_BT_DARWIN) << "no characteristic with handle:" + << charHandle << " found"; + return; + } + + dispatch_queue_t leQueue(DarwinBluetooth::qt_LE_queue()); + Q_ASSERT_X(leQueue, Q_FUNC_INFO, "no LE queue found"); + // Attention! We have to copy objects! + const QByteArray newValueCopy(newValue); + if (role == QLowEnergyController::CentralRole) { + const QBluetoothUuid serviceUuid(service->uuid); + const auto manager = centralManager.getAs(); + dispatch_async(leQueue, ^{ + [manager write:newValueCopy + charHandle:charHandle + onService:serviceUuid + withResponse:mode == QLowEnergyService::WriteWithResponse]; + }); + } else { + const auto manager = peripheralManager.getAs(); + dispatch_async(leQueue, ^{ + [manager write:newValueCopy charHandle:charHandle]; + }); + } +} + +quint16 QLowEnergyControllerPrivateDarwin::updateValueOfCharacteristic(QLowEnergyHandle charHandle, + const QByteArray &value, + bool appendValue) +{ + QSharedPointer service = serviceForHandle(charHandle); + if (!service.isNull()) { + CharacteristicDataMap::iterator charIt = service->characteristicList.find(charHandle); + if (charIt != service->characteristicList.end()) { + QLowEnergyServicePrivate::CharData &charData = charIt.value(); + if (appendValue) + charData.value += value; + else + charData.value = value; + + return charData.value.size(); + } + } + + return 0; +} + +void QLowEnergyControllerPrivateDarwin::readDescriptor(const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle) +{ + Q_UNUSED(charHandle); // Hehe, yes! + + Q_ASSERT_X(!service.isNull(), Q_FUNC_INFO, "invalid service (null)"); + + if (role == QLowEnergyController::PeripheralRole) { + qCWarning(QT_BT_DARWIN) << "invalid role (peripheral)"; + return; + } + + if (!serviceList.contains(service->uuid)) { + qCWarning(QT_BT_DARWIN) << "no service with uuid:" + << service->uuid << "found"; + return; + } + + dispatch_queue_t leQueue(DarwinBluetooth::qt_LE_queue()); + if (!leQueue) { + qCWarning(QT_BT_DARWIN) << "no LE queue found"; + return; + } + // Attention! Copy objects! + const QBluetoothUuid serviceUuid(service->uuid); + DarwinBTCentralManager * const manager = centralManager.getAs(); + dispatch_async(leQueue, ^{ + [manager readDescriptor:descriptorHandle + onService:serviceUuid]; + }); +} + +void QLowEnergyControllerPrivateDarwin::writeDescriptor(const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle, + const QByteArray &newValue) +{ + Q_UNUSED(charHandle); + + Q_ASSERT_X(!service.isNull(), Q_FUNC_INFO, "invalid service (null)"); + + if (role == QLowEnergyController::PeripheralRole) { + qCWarning(QT_BT_DARWIN) << "invalid role (peripheral)"; + return; + } + + // We can work only with services found on a given peripheral + // (== created by the given LE controller), + // otherwise we can not write anything at all. + if (!serviceList.contains(service->uuid)) { + qCWarning(QT_BT_DARWIN) << "no service with uuid:" + << service->uuid << " found"; + return; + } + + dispatch_queue_t leQueue(DarwinBluetooth::qt_LE_queue()); + Q_ASSERT_X(leQueue, Q_FUNC_INFO, "no LE queue found"); + // Attention! Copy objects! + const QBluetoothUuid serviceUuid(service->uuid); + DarwinBTCentralManager * const manager = centralManager.getAs(); + const QByteArray newValueCopy(newValue); + dispatch_async(leQueue, ^{ + [manager write:newValueCopy + descHandle:descriptorHandle + onService:serviceUuid]; + }); +} + +quint16 QLowEnergyControllerPrivateDarwin::updateValueOfDescriptor(QLowEnergyHandle charHandle, QLowEnergyHandle descHandle, + const QByteArray &value, bool appendValue) +{ + QSharedPointer service = serviceForHandle(charHandle); + if (!service.isNull()) { + CharacteristicDataMap::iterator charIt = service->characteristicList.find(charHandle); + if (charIt != service->characteristicList.end()) { + QLowEnergyServicePrivate::CharData &charData = charIt.value(); + + DescriptorDataMap::iterator descIt = charData.descriptorList.find(descHandle); + if (descIt != charData.descriptorList.end()) { + QLowEnergyServicePrivate::DescData &descDetails = descIt.value(); + + if (appendValue) + descDetails.value += value; + else + descDetails.value = value; + + return descDetails.value.size(); + } + } + } + + return 0; +} + +bool QLowEnergyControllerPrivateDarwin::connectSlots(DarwinBluetooth::LECBManagerNotifier *notifier) +{ + using DarwinBluetooth::LECBManagerNotifier; + + Q_ASSERT_X(notifier, Q_FUNC_INFO, "invalid notifier object (null)"); + + bool ok = connect(notifier, &LECBManagerNotifier::connected, + this, &QLowEnergyControllerPrivateDarwin::_q_connected); + ok = ok && connect(notifier, &LECBManagerNotifier::disconnected, + this, &QLowEnergyControllerPrivateDarwin::_q_disconnected); + ok = ok && connect(notifier, &LECBManagerNotifier::serviceDiscoveryFinished, + this, &QLowEnergyControllerPrivateDarwin::_q_serviceDiscoveryFinished); + ok = ok && connect(notifier, &LECBManagerNotifier::servicesWereModified, + this, &QLowEnergyControllerPrivateDarwin::_q_servicesWereModified); + ok = ok && connect(notifier, &LECBManagerNotifier::serviceDetailsDiscoveryFinished, + this, &QLowEnergyControllerPrivateDarwin::_q_serviceDetailsDiscoveryFinished); + ok = ok && connect(notifier, &LECBManagerNotifier::characteristicRead, + this, &QLowEnergyControllerPrivateDarwin::_q_characteristicRead); + ok = ok && connect(notifier, &LECBManagerNotifier::characteristicWritten, + this, &QLowEnergyControllerPrivateDarwin::_q_characteristicWritten); + ok = ok && connect(notifier, &LECBManagerNotifier::characteristicUpdated, + this, &QLowEnergyControllerPrivateDarwin::_q_characteristicUpdated); + ok = ok && connect(notifier, &LECBManagerNotifier::descriptorRead, + this, &QLowEnergyControllerPrivateDarwin::_q_descriptorRead); + ok = ok && connect(notifier, &LECBManagerNotifier::descriptorWritten, + this, &QLowEnergyControllerPrivateDarwin::_q_descriptorWritten); + ok = ok && connect(notifier, &LECBManagerNotifier::notificationEnabled, + this, &QLowEnergyControllerPrivateDarwin::_q_notificationEnabled); + ok = ok && connect(notifier, &LECBManagerNotifier::LEnotSupported, + this, &QLowEnergyControllerPrivateDarwin::_q_LEnotSupported); + ok = ok && connect(notifier, SIGNAL(CBManagerError(QLowEnergyController::Error)), + this, SLOT(_q_CBManagerError(QLowEnergyController::Error))); + ok = ok && connect(notifier, SIGNAL(CBManagerError(const QBluetoothUuid &, QLowEnergyController::Error)), + this, SLOT(_q_CBManagerError(const QBluetoothUuid &, QLowEnergyController::Error))); + ok = ok && connect(notifier, SIGNAL(CBManagerError(const QBluetoothUuid &, QLowEnergyService::ServiceError)), + this, SLOT(_q_CBManagerError(const QBluetoothUuid &, QLowEnergyService::ServiceError))); + ok = ok && connect(notifier, &LECBManagerNotifier::mtuChanged, this, + &QLowEnergyControllerPrivateDarwin::_q_mtuChanged); + ok = ok && connect(notifier, &LECBManagerNotifier::rssiUpdated, q_ptr, + &QLowEnergyController::rssiRead, Qt::QueuedConnection); + + if (!ok) + notifier->disconnect(); + + return ok; +} + +void QLowEnergyControllerPrivateDarwin::startAdvertising(const QLowEnergyAdvertisingParameters ¶ms, + const QLowEnergyAdvertisingData &advertisingData, + const QLowEnergyAdvertisingData &scanResponseData) +{ + if (!lazyInit()) // Error was emit already. + return; + + auto leQueue(DarwinBluetooth::qt_LE_queue()); + Q_ASSERT_X(leQueue, Q_FUNC_INFO, "invalid LE queue (nullptr)"); + + const auto manager = peripheralManager.getAs(); + [manager setParameters:params data:advertisingData scanResponse:scanResponseData]; + + setState(QLowEnergyController::AdvertisingState); + + dispatch_async(leQueue, ^{ + [manager startAdvertising]; + }); +} + +void QLowEnergyControllerPrivateDarwin::stopAdvertising() +{ + if (!isValid()) + return _q_CBManagerError(QLowEnergyController::UnknownError); + + if (state != QLowEnergyController::AdvertisingState) { + qCDebug(QT_BT_DARWIN) << "cannot stop advertising, called in state" << state; + return; + } + + const auto leQueue = DarwinBluetooth::qt_LE_queue(); + Q_ASSERT_X(leQueue, Q_FUNC_INFO, "invalid LE queue (nullptr)"); + const auto manager = peripheralManager.getAs(); + dispatch_sync(leQueue, ^{ + [manager stopAdvertising]; + }); + + setState(QLowEnergyController::UnconnectedState); +} + +QT_END_NAMESPACE + diff --git a/src/bluetooth/qlowenergycontroller_darwin_p.h b/src/bluetooth/qlowenergycontroller_darwin_p.h new file mode 100644 index 0000000..2782ff5 --- /dev/null +++ b/src/bluetooth/qlowenergycontroller_darwin_p.h @@ -0,0 +1,129 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// Copyright (C) 2016 Javier S. Pedro +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +#ifndef QLOWENERGYCONTROLLER_DARWIN_P_H +#define QLOWENERGYCONTROLLER_DARWIN_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 "qlowenergyserviceprivate_p.h" +#include "qlowenergycontrollerbase_p.h" +#include "qlowenergycontroller.h" +#include "darwin/btnotifier_p.h" +#include "qbluetoothaddress.h" +#include "darwin/btraii_p.h" +#include "qbluetoothuuid.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QByteArray; + +class QLowEnergyControllerPrivateDarwin : public QLowEnergyControllerPrivate +{ + friend class QLowEnergyController; + friend class QLowEnergyService; + + Q_OBJECT +public: + QLowEnergyControllerPrivateDarwin(); + ~QLowEnergyControllerPrivateDarwin(); + + void init() override; + bool lazyInit(); + void connectToDevice() override; + void disconnectFromDevice() override; + void discoverServices() override; + void discoverServiceDetails(const QBluetoothUuid &serviceUuid, + QLowEnergyService::DiscoveryMode mode) override; + + void readCharacteristic(const QSharedPointer service, + const QLowEnergyHandle charHandle) override; + void readDescriptor(const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle) override; + + void writeCharacteristic(const QSharedPointer service, + const QLowEnergyHandle charHandle, const QByteArray &newValue, + QLowEnergyService::WriteMode mode) override; + void writeDescriptor(const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle, + const QByteArray &newValue) override; + + + void requestConnectionUpdate(const QLowEnergyConnectionParameters ¶ms) override; + void addToGenericAttributeList(const QLowEnergyServiceData &service, + QLowEnergyHandle startHandle) override; + + int mtu() const override; + void readRssi() override; + + void startAdvertising(const QLowEnergyAdvertisingParameters ¶ms, + const QLowEnergyAdvertisingData &advertisingData, + const QLowEnergyAdvertisingData &scanResponseData) override; + void stopAdvertising()override; + QLowEnergyService *addServiceHelper(const QLowEnergyServiceData &service) override; + + // Valid - a central or peripheral instance was allocated, and this may also + // mean a proper usage description was provided/found: + bool isValid() const; + +private Q_SLOTS: + void _q_connected(); + void _q_disconnected(); + + void _q_mtuChanged(int newValue); + void _q_serviceDiscoveryFinished(); + void _q_serviceDetailsDiscoveryFinished(QSharedPointer service); + void _q_servicesWereModified(); + + void _q_characteristicRead(QLowEnergyHandle charHandle, const QByteArray &value); + void _q_characteristicWritten(QLowEnergyHandle charHandle, const QByteArray &value); + void _q_characteristicUpdated(QLowEnergyHandle charHandle, const QByteArray &value); + void _q_descriptorRead(QLowEnergyHandle descHandle, const QByteArray &value); + void _q_descriptorWritten(QLowEnergyHandle charHandle, const QByteArray &value); + void _q_notificationEnabled(QLowEnergyHandle charHandle, bool enabled); + + void _q_LEnotSupported(); + void _q_CBManagerError(QLowEnergyController::Error error); + void _q_CBManagerError(const QBluetoothUuid &serviceUuid, QLowEnergyController::Error error); + void _q_CBManagerError(const QBluetoothUuid &serviceUuid, QLowEnergyService::ServiceError error); + +private: + void setNotifyValue(QSharedPointer service, + QLowEnergyHandle charHandle, const QByteArray &newValue); + + quint16 updateValueOfCharacteristic(QLowEnergyHandle charHandle, + const QByteArray &value, + bool appendValue); + + quint16 updateValueOfDescriptor(QLowEnergyHandle charHandle, + QLowEnergyHandle descHandle, + const QByteArray &value, + bool appendValue); + + bool connectSlots(DarwinBluetooth::LECBManagerNotifier *notifier); + + DarwinBluetooth::ScopedPointer centralManager; + DarwinBluetooth::ScopedPointer peripheralManager; + + using ServiceMap = QMap>; +}; + +QT_END_NAMESPACE + +#endif // QLOWENERGYCONTROLLER_DARWIN_P_H diff --git a/src/bluetooth/qlowenergycontroller_dummy.cpp b/src/bluetooth/qlowenergycontroller_dummy.cpp new file mode 100644 index 0000000..e271a8a --- /dev/null +++ b/src/bluetooth/qlowenergycontroller_dummy.cpp @@ -0,0 +1,108 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qlowenergycontroller_dummy_p.h" +#include "dummy/dummy_helper_p.h" + +QT_BEGIN_NAMESPACE + +QLowEnergyControllerPrivateCommon::QLowEnergyControllerPrivateCommon() + : QLowEnergyControllerPrivate() +{ + printDummyWarning(); + registerQLowEnergyControllerMetaType(); +} + +QLowEnergyControllerPrivateCommon::~QLowEnergyControllerPrivateCommon() +{ +} + +void QLowEnergyControllerPrivateCommon::init() +{ +} + +void QLowEnergyControllerPrivateCommon::connectToDevice() +{ + // required to pass unit test on default backend + if (remoteDevice.isNull()) { + qWarning() << "Invalid/null remote device address"; + setError(QLowEnergyController::UnknownRemoteDeviceError); + return; + } + + qWarning() << "QLowEnergyControllerPrivateCommon::connectToDevice(): Not implemented"; + setError(QLowEnergyController::UnknownError); +} + +void QLowEnergyControllerPrivateCommon::disconnectFromDevice() +{ + +} + +void QLowEnergyControllerPrivateCommon::discoverServices() +{ + +} + +void QLowEnergyControllerPrivateCommon::discoverServiceDetails( + const QBluetoothUuid & /*service*/, QLowEnergyService::DiscoveryMode /*mode*/) +{ + +} + +void QLowEnergyControllerPrivateCommon::readCharacteristic(const QSharedPointer /*service*/, + const QLowEnergyHandle /*charHandle*/) +{ + +} + +void QLowEnergyControllerPrivateCommon::readDescriptor(const QSharedPointer /*service*/, + const QLowEnergyHandle /*charHandle*/, + const QLowEnergyHandle /*descriptorHandle*/) +{ + +} + +void QLowEnergyControllerPrivateCommon::writeCharacteristic(const QSharedPointer /*service*/, + const QLowEnergyHandle /*charHandle*/, + const QByteArray &/*newValue*/, + QLowEnergyService::WriteMode /*writeMode*/) +{ + +} + +void QLowEnergyControllerPrivateCommon::writeDescriptor( + const QSharedPointer /*service*/, + const QLowEnergyHandle /*charHandle*/, + const QLowEnergyHandle /*descriptorHandle*/, + const QByteArray &/*newValue*/) +{ + +} + +void QLowEnergyControllerPrivateCommon::startAdvertising(const QLowEnergyAdvertisingParameters &/* params */, + const QLowEnergyAdvertisingData &/* advertisingData */, + const QLowEnergyAdvertisingData &/* scanResponseData */) +{ +} + +void QLowEnergyControllerPrivateCommon::stopAdvertising() +{ +} + +void QLowEnergyControllerPrivateCommon::requestConnectionUpdate(const QLowEnergyConnectionParameters & /* params */) +{ +} + +void QLowEnergyControllerPrivateCommon::addToGenericAttributeList(const QLowEnergyServiceData &/* service */, + QLowEnergyHandle /* startHandle */) +{ +} + +int QLowEnergyControllerPrivateCommon::mtu() const +{ + // not supported + return -1; +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/qlowenergycontroller_dummy_p.h b/src/bluetooth/qlowenergycontroller_dummy_p.h new file mode 100644 index 0000000..16fbab3 --- /dev/null +++ b/src/bluetooth/qlowenergycontroller_dummy_p.h @@ -0,0 +1,78 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QLOWENERGYCONTROLLERPRIVATE_P_H +#define QLOWENERGYCONTROLLERPRIVATE_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 "qlowenergycontroller.h" +#include "qlowenergycontrollerbase_p.h" + +QT_BEGIN_NAMESPACE + +class QLowEnergyServiceData; + +extern void registerQLowEnergyControllerMetaType(); + +class QLowEnergyControllerPrivateCommon final : public QLowEnergyControllerPrivate +{ + Q_OBJECT +public: + QLowEnergyControllerPrivateCommon(); + ~QLowEnergyControllerPrivateCommon() override; + + void init() override; + + void connectToDevice() override; + void disconnectFromDevice() override; + + void discoverServices() override; + void discoverServiceDetails(const QBluetoothUuid &service, + QLowEnergyService::DiscoveryMode mode) override; + + void startAdvertising(const QLowEnergyAdvertisingParameters ¶ms, + const QLowEnergyAdvertisingData &advertisingData, + const QLowEnergyAdvertisingData &scanResponseData) override; + void stopAdvertising() override; + + void requestConnectionUpdate(const QLowEnergyConnectionParameters ¶ms) override; + + // read data + void readCharacteristic(const QSharedPointer service, + const QLowEnergyHandle charHandle) override; + void readDescriptor(const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle) override; + + // write data + void writeCharacteristic(const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QByteArray &newValue, QLowEnergyService::WriteMode mode) override; + void writeDescriptor(const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle, + const QByteArray &newValue) override; + + void addToGenericAttributeList(const QLowEnergyServiceData &service, + QLowEnergyHandle startHandle) override; + + int mtu() const override; +}; + +QT_END_NAMESPACE + +#endif // QLOWENERGYCONTROLLERPRIVATE_P_H diff --git a/src/bluetooth/qlowenergycontroller_winrt.cpp b/src/bluetooth/qlowenergycontroller_winrt.cpp new file mode 100644 index 0000000..6914ed4 --- /dev/null +++ b/src/bluetooth/qlowenergycontroller_winrt.cpp @@ -0,0 +1,2023 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qlowenergycontroller_winrt_p.h" +#include "qbluetoothutils_winrt_p.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::Foundation::Metadata; +using namespace ABI::Windows::Devices; +using namespace ABI::Windows::Devices::Bluetooth; +using namespace ABI::Windows::Devices::Bluetooth::GenericAttributeProfile; +using namespace ABI::Windows::Devices::Enumeration; +using namespace ABI::Windows::Storage::Streams; + +QT_BEGIN_NAMESPACE + +typedef ITypedEventHandler StatusHandler; +typedef ITypedEventHandler MtuHandler; +typedef ITypedEventHandler ValueChangedHandler; +typedef GattReadClientCharacteristicConfigurationDescriptorResult ClientCharConfigDescriptorResult; +typedef IGattReadClientCharacteristicConfigurationDescriptorResult IClientCharConfigDescriptorResult; + +#define EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED(hr) \ + if (FAILED(hr)) { \ + emitErrorAndQuitThread(hr); \ + return; \ + } + +#define EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED_2(hr, message) \ + if (FAILED(hr)) { \ + emitErrorAndQuitThread(message); \ + return; \ + } + +#define WARN_AND_CONTINUE_IF_FAILED(hr, msg) \ + if (FAILED(hr)) { \ + qCWarning(QT_BT_WINDOWS) << msg; \ + continue; \ + } + +#define DEC_CHAR_COUNT_AND_CONTINUE_IF_FAILED(hr, msg) \ + if (FAILED(hr)) { \ + qCWarning(QT_BT_WINDOWS) << msg; \ + --mCharacteristicsCountToBeDiscovered; \ + continue; \ + } + +#define CHECK_FOR_DEVICE_CONNECTION_ERROR_IMPL(this, hr, msg, ret) \ + if (FAILED(hr)) { \ + this->handleConnectionError(msg); \ + ret; \ + } + +#define CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, msg, ret) \ + CHECK_FOR_DEVICE_CONNECTION_ERROR_IMPL(this, hr, msg, ret) + +#define CHECK_HR_AND_SET_SERVICE_ERROR(hr, msg, service, error, ret) \ + if (FAILED(hr)) { \ + qCDebug(QT_BT_WINDOWS) << msg; \ + service->setError(error); \ + ret; \ + } + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINDOWS) +Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINDOWS_SERVICE_THREAD) + +static constexpr qint64 kMaxConnectTimeout = 20000; // 20 sec + +static QByteArray byteArrayFromGattResult(const ComPtr &gattResult, + bool isWCharString = false) +{ + ComPtr buffer; + HRESULT hr; + hr = gattResult->get_Value(&buffer); + if (FAILED(hr) || !buffer) { + qCWarning(QT_BT_WINDOWS) << "Could not obtain buffer from GattReadResult"; + return QByteArray(); + } + return byteArrayFromBuffer(buffer, isWCharString); +} + +template +static void closeDeviceService(ComPtr service) +{ + ComPtr closableService; + HRESULT hr = service.As(&closableService); + RETURN_IF_FAILED("Could not cast type to closable", return); + hr = closableService->Close(); + RETURN_IF_FAILED("Close() call failed", return); +} + +class QWinRTLowEnergyServiceHandler : public QObject +{ + Q_OBJECT +public: + QWinRTLowEnergyServiceHandler(const QBluetoothUuid &service, + const ComPtr &deviceService, + QLowEnergyService::DiscoveryMode mode) + : mService(service), mMode(mode), mDeviceService(deviceService) + { + qCDebug(QT_BT_WINDOWS) << __FUNCTION__; + } + + ~QWinRTLowEnergyServiceHandler() + { + if (mAbortRequested) + closeDeviceService(mDeviceService); + qCDebug(QT_BT_WINDOWS) << __FUNCTION__; + } + +public slots: + void obtainCharList() + { + auto exitCondition = [this]() { return mAbortRequested; }; + + mIndicateChars.clear(); + qCDebug(QT_BT_WINDOWS) << __FUNCTION__; + ComPtr> characteristicsOp; + ComPtr characteristicsResult; + HRESULT hr = mDeviceService->GetCharacteristicsAsync(&characteristicsOp); + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED(hr); + hr = QWinRTFunctions::await(characteristicsOp, characteristicsResult.GetAddressOf(), + QWinRTFunctions::ProcessMainThreadEvents, 5000, + exitCondition); + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED(hr); + GattCommunicationStatus status; + hr = characteristicsResult->get_Status(&status); + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED(hr); + if (status != GattCommunicationStatus_Success) { + emitErrorAndQuitThread(QLatin1String("Could not obtain char list")); + return; + } + ComPtr> characteristics; + hr = characteristicsResult->get_Characteristics(&characteristics); + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED(hr); + + uint characteristicsCount; + hr = characteristics->get_Size(&characteristicsCount); + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED(hr); + + mCharacteristicsCountToBeDiscovered = characteristicsCount; + for (uint i = 0; !mAbortRequested && (i < characteristicsCount); ++i) { + ComPtr characteristic; + hr = characteristics->GetAt(i, &characteristic); + if (FAILED(hr)) { + qCWarning(QT_BT_WINDOWS) << "Could not obtain characteristic at" << i; + --mCharacteristicsCountToBeDiscovered; + continue; + } + + ComPtr characteristic3; + hr = characteristic.As(&characteristic3); + if (FAILED(hr)) { + qCWarning(QT_BT_WINDOWS) << "Could not cast characteristic"; + --mCharacteristicsCountToBeDiscovered; + continue; + } + + // For some strange reason, Windows doesn't discover descriptors of characteristics (if not paired). + // Qt API assumes that all characteristics and their descriptors are discovered in one go. + // So we start 'GetDescriptorsAsync' for each discovered characteristic and finish only + // when GetDescriptorsAsync for all characteristics return. + ComPtr> descAsyncOp; + hr = characteristic3->GetDescriptorsAsync(&descAsyncOp); + DEC_CHAR_COUNT_AND_CONTINUE_IF_FAILED(hr, "Could not obtain list of descriptors") + + ComPtr descResult; + hr = QWinRTFunctions::await(descAsyncOp, descResult.GetAddressOf(), + QWinRTFunctions::ProcessMainThreadEvents, 5000, + exitCondition); + DEC_CHAR_COUNT_AND_CONTINUE_IF_FAILED(hr, "Could not obtain descriptor read result") + + quint16 handle; + hr = characteristic->get_AttributeHandle(&handle); + DEC_CHAR_COUNT_AND_CONTINUE_IF_FAILED( + hr, "Could not obtain characteristic's attribute handle") + QLowEnergyServicePrivate::CharData charData; + charData.valueHandle = handle + 1; + if (mStartHandle == 0 || mStartHandle > handle) + mStartHandle = handle; + if (mEndHandle == 0 || mEndHandle < handle) + mEndHandle = handle; + GUID guuid; + hr = characteristic->get_Uuid(&guuid); + DEC_CHAR_COUNT_AND_CONTINUE_IF_FAILED(hr, "Could not obtain characteristic's Uuid") + charData.uuid = QBluetoothUuid(guuid); + GattCharacteristicProperties properties; + hr = characteristic->get_CharacteristicProperties(&properties); + DEC_CHAR_COUNT_AND_CONTINUE_IF_FAILED(hr, + "Could not obtain characteristic's properties") + charData.properties = QLowEnergyCharacteristic::PropertyTypes(properties & 0xff); + if (charData.properties & QLowEnergyCharacteristic::Read + && mMode == QLowEnergyService::FullDiscovery) { + ComPtr> readOp; + hr = characteristic->ReadValueWithCacheModeAsync(BluetoothCacheMode_Uncached, + &readOp); + DEC_CHAR_COUNT_AND_CONTINUE_IF_FAILED(hr, "Could not read characteristic") + ComPtr readResult; + hr = QWinRTFunctions::await(readOp, readResult.GetAddressOf(), + QWinRTFunctions::ProcessMainThreadEvents, 5000, + exitCondition); + DEC_CHAR_COUNT_AND_CONTINUE_IF_FAILED(hr, + "Could not obtain characteristic read result") + if (!readResult) + qCWarning(QT_BT_WINDOWS) << "Characteristic read result is null"; + else + charData.value = byteArrayFromGattResult(readResult); + } + mCharacteristicList.insert(handle, charData); + + ComPtr> descriptors; + + GattCommunicationStatus commStatus; + hr = descResult->get_Status(&commStatus); + if (FAILED(hr) || commStatus != GattCommunicationStatus_Success) { + qCWarning(QT_BT_WINDOWS) << "Descriptor operation failed"; + --mCharacteristicsCountToBeDiscovered; + continue; + } + + hr = descResult->get_Descriptors(&descriptors); + DEC_CHAR_COUNT_AND_CONTINUE_IF_FAILED(hr, "Could not obtain list of descriptors") + + uint descriptorCount; + hr = descriptors->get_Size(&descriptorCount); + DEC_CHAR_COUNT_AND_CONTINUE_IF_FAILED(hr, "Could not obtain list of descriptors' size") + for (uint j = 0; !mAbortRequested && (j < descriptorCount); ++j) { + QLowEnergyServicePrivate::DescData descData; + ComPtr descriptor; + hr = descriptors->GetAt(j, &descriptor); + WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain descriptor") + quint16 descHandle; + hr = descriptor->get_AttributeHandle(&descHandle); + WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain descriptor's attribute handle") + GUID descriptorUuid; + hr = descriptor->get_Uuid(&descriptorUuid); + WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain descriptor's Uuid") + descData.uuid = QBluetoothUuid(descriptorUuid); + charData.descriptorList.insert(descHandle, descData); + if (descData.uuid == QBluetoothUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration)) { + if (mMode == QLowEnergyService::FullDiscovery) { + ComPtr> readOp; + hr = characteristic->ReadClientCharacteristicConfigurationDescriptorAsync( + &readOp); + WARN_AND_CONTINUE_IF_FAILED(hr, "Could not read descriptor value") + ComPtr readResult; + hr = QWinRTFunctions::await(readOp, readResult.GetAddressOf(), + QWinRTFunctions::ProcessMainThreadEvents, 5000, + exitCondition); + WARN_AND_CONTINUE_IF_FAILED(hr, "Could not await descriptor read result") + GattClientCharacteristicConfigurationDescriptorValue value; + hr = readResult->get_ClientCharacteristicConfigurationDescriptor(&value); + WARN_AND_CONTINUE_IF_FAILED(hr, + "Could not get descriptor value from result") + quint16 result = 0; + bool correct = false; + if (value & GattClientCharacteristicConfigurationDescriptorValue_Indicate) { + result |= GattClientCharacteristicConfigurationDescriptorValue_Indicate; + correct = true; + } + if (value & GattClientCharacteristicConfigurationDescriptorValue_Notify) { + result |= GattClientCharacteristicConfigurationDescriptorValue_Notify; + correct = true; + } + if (value == GattClientCharacteristicConfigurationDescriptorValue_None) + correct = true; + if (!correct) + continue; + + descData.value = QByteArray(2, Qt::Uninitialized); + qToLittleEndian(result, descData.value.data()); + } + mIndicateChars << charData.uuid; + } else { + if (mMode == QLowEnergyService::FullDiscovery) { + ComPtr> readOp; + hr = descriptor->ReadValueWithCacheModeAsync(BluetoothCacheMode_Uncached, + &readOp); + WARN_AND_CONTINUE_IF_FAILED(hr, "Could not read descriptor value") + ComPtr readResult; + hr = QWinRTFunctions::await(readOp, readResult.GetAddressOf(), + QWinRTFunctions::ProcessMainThreadEvents, 5000, + exitCondition); + WARN_AND_CONTINUE_IF_FAILED(hr, "Could not await descriptor read result") + if (descData.uuid == QBluetoothUuid::DescriptorType::CharacteristicUserDescription) + descData.value = byteArrayFromGattResult(readResult, true); + else + descData.value = byteArrayFromGattResult(readResult); + } + } + charData.descriptorList.insert(descHandle, descData); + } + + mCharacteristicList.insert(handle, charData); + --mCharacteristicsCountToBeDiscovered; + } + checkAllCharacteristicsDiscovered(); + } + + void setAbortRequested() + { + mAbortRequested = true; + } + +private: + void checkAllCharacteristicsDiscovered(); + void emitErrorAndQuitThread(HRESULT hr); + void emitErrorAndQuitThread(const QString &error); + +public: + QBluetoothUuid mService; + QLowEnergyService::DiscoveryMode mMode; + ComPtr mDeviceService; + QHash mCharacteristicList; + uint mCharacteristicsCountToBeDiscovered; + quint16 mStartHandle = 0; + quint16 mEndHandle = 0; + QList mIndicateChars; + bool mAbortRequested = false; + +signals: + void charListObtained(const QBluetoothUuid &service, + QHash charList, + QList indicateChars, QLowEnergyHandle startHandle, + QLowEnergyHandle endHandle); + void errorOccured(const QString &error); +}; + +void QWinRTLowEnergyServiceHandler::checkAllCharacteristicsDiscovered() +{ + if (!mAbortRequested && (mCharacteristicsCountToBeDiscovered == 0)) { + emit charListObtained(mService, mCharacteristicList, mIndicateChars, + mStartHandle, mEndHandle); + } + QThread::currentThread()->quit(); +} + +void QWinRTLowEnergyServiceHandler::emitErrorAndQuitThread(HRESULT hr) +{ + emitErrorAndQuitThread(qt_error_string(hr)); +} + +void QWinRTLowEnergyServiceHandler::emitErrorAndQuitThread(const QString &error) +{ + mAbortRequested = true; // so that the service is closed during cleanup + emit errorOccured(error); + QThread::currentThread()->quit(); +} + +class QWinRTLowEnergyConnectionHandler : public QObject +{ + Q_OBJECT +public: + explicit QWinRTLowEnergyConnectionHandler(const QBluetoothAddress &address) : mAddress(address) + { + qCDebug(QT_BT_WINDOWS) << __FUNCTION__; + // This should be checked before the handler is created + Q_ASSERT(!mAddress.isNull()); + } + ~QWinRTLowEnergyConnectionHandler() + { + qCDebug(QT_BT_WINDOWS) << __FUNCTION__; + mDevice.Reset(); + mGattSession.Reset(); + // To close the COM library gracefully, each successful call to + // CoInitialize, including those that return S_FALSE, must be balanced + // by a corresponding call to CoUninitialize. + if (mInitialized == S_OK || mInitialized == S_FALSE) + CoUninitialize(); + } + +public slots: + void connectToDevice(); + void handleDeviceDisconnectRequest(); + +signals: + void deviceConnected(ComPtr device, ComPtr session); + void errorOccurred(const QString &error); + +private: + void connectToPairedDevice(); + void connectToUnpairedDevice(); + void emitErrorAndQuitThread(const QString &error); + void emitErrorAndQuitThread(const char *error); + void emitConnectedAndQuitThread(); + + ComPtr mDevice = nullptr; + ComPtr mGattSession = nullptr; + const QBluetoothAddress mAddress; + bool mAbortConnection = false; + HRESULT mInitialized = E_UNEXPECTED; // some error code +}; + +void QWinRTLowEnergyConnectionHandler::connectToDevice() +{ + qCDebug(QT_BT_WINDOWS) << __FUNCTION__; + mInitialized = CoInitializeEx(NULL, COINIT_MULTITHREADED); + qCDebug(QT_BT_WINDOWS) << qt_error_string(mInitialized); + + auto earlyExit = [this]() { return mAbortConnection; }; + ComPtr deviceStatics; + HRESULT hr = GetActivationFactory( + HString::MakeReference(RuntimeClass_Windows_Devices_Bluetooth_BluetoothLEDevice).Get(), + &deviceStatics); + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED_2(hr, "Could not obtain device factory"); + ComPtr> deviceFromIdOperation; + hr = deviceStatics->FromBluetoothAddressAsync(mAddress.toUInt64(), &deviceFromIdOperation); + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED_2(hr, "Could not find LE device from address"); + hr = QWinRTFunctions::await(deviceFromIdOperation, mDevice.GetAddressOf(), + QWinRTFunctions::ProcessMainThreadEvents, 5000, earlyExit); + if (FAILED(hr) || !mDevice) { + emitErrorAndQuitThread("Could not find LE device"); + return; + } + + // get GattSession: 1. get device id + ComPtr device4; + hr = mDevice.As(&device4); + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED_2(hr, "Could not cast device"); + + ComPtr deviceId; + hr = device4->get_BluetoothDeviceId(&deviceId); + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED_2(hr, "Could not get bluetooth device id"); + + // get GattSession: 2. get session statics + ComPtr sessionStatics; + hr = GetActivationFactory( + HString::MakeReference( + RuntimeClass_Windows_Devices_Bluetooth_GenericAttributeProfile_GattSession) + .Get(), + &sessionStatics); + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED_2(hr, "Could not obtain GattSession statics"); + + // get GattSession: 3. get session + ComPtr> gattSessionFromIdOperation; + hr = sessionStatics->FromDeviceIdAsync(deviceId.Get(), &gattSessionFromIdOperation); + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED_2(hr, "Could not get GattSession from id"); + hr = QWinRTFunctions::await(gattSessionFromIdOperation, mGattSession.GetAddressOf(), + QWinRTFunctions::ProcessMainThreadEvents, 5000, earlyExit); + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED_2(hr, "Could not complete Gatt session acquire"); + + BluetoothConnectionStatus status; + hr = mDevice->get_ConnectionStatus(&status); + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED_2(hr, "Could not obtain device's connection status"); + if (status == BluetoothConnectionStatus::BluetoothConnectionStatus_Connected) { + emitConnectedAndQuitThread(); + return; + } + + QBluetoothLocalDevice localDevice; + QBluetoothLocalDevice::Pairing pairing = localDevice.pairingStatus(mAddress); + if (pairing == QBluetoothLocalDevice::Unpaired) + connectToUnpairedDevice(); + else + connectToPairedDevice(); +} + +void QWinRTLowEnergyConnectionHandler::handleDeviceDisconnectRequest() +{ + mAbortConnection = true; + // Disconnect from the QLowEnergyControllerPrivateWinRT, so that it does + // not get notifications. It's absolutely fine to keep doing smth in + // background, as multiple connections to the same device should be handled + // correctly by OS. + disconnect(this, &QWinRTLowEnergyConnectionHandler::deviceConnected, nullptr, nullptr); + disconnect(this, &QWinRTLowEnergyConnectionHandler::errorOccurred, nullptr, nullptr); +} + +void QWinRTLowEnergyConnectionHandler::connectToPairedDevice() +{ + qCDebug(QT_BT_WINDOWS) << __FUNCTION__; + ComPtr device3; + HRESULT hr = mDevice.As(&device3); + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED_2(hr, "Could not cast device"); + ComPtr> deviceServicesOp; + auto earlyExit = [this]() { return mAbortConnection; }; + QDeadlineTimer deadline(kMaxConnectTimeout); + while (!mAbortConnection && !deadline.hasExpired()) { + hr = device3->GetGattServicesAsync(&deviceServicesOp); + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED_2(hr, "Could not obtain services"); + ComPtr deviceServicesResult; + hr = QWinRTFunctions::await(deviceServicesOp, deviceServicesResult.GetAddressOf(), + QWinRTFunctions::ProcessThreadEvents, 5000, earlyExit); + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED_2(hr, "Could not await services operation"); + + GattCommunicationStatus commStatus; + hr = deviceServicesResult->get_Status(&commStatus); + if (FAILED(hr) || commStatus != GattCommunicationStatus_Success) { + emitErrorAndQuitThread("Service operation failed"); + return; + } + + ComPtr> deviceServices; + hr = deviceServicesResult->get_Services(&deviceServices); + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED_2(hr, "Could not obtain list of services"); + uint serviceCount; + hr = deviceServices->get_Size(&serviceCount); + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED_2(hr, "Could not obtain service count"); + + if (serviceCount == 0) { + emitErrorAndQuitThread("Found devices without services"); + return; + } + + // Windows automatically connects to the device as soon as a service value is read/written. + // Thus we read one value in order to establish the connection. + for (uint i = 0; i < serviceCount; ++i) { + ComPtr service; + hr = deviceServices->GetAt(i, &service); + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED_2(hr, "Could not obtain service"); + ComPtr service3; + hr = service.As(&service3); + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED_2(hr, "Could not cast service"); + ComPtr> characteristicsOp; + hr = service3->GetCharacteristicsAsync(&characteristicsOp); + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED_2(hr, "Could not obtain characteristic"); + ComPtr characteristicsResult; + hr = QWinRTFunctions::await(characteristicsOp, characteristicsResult.GetAddressOf(), + QWinRTFunctions::ProcessThreadEvents, 5000, earlyExit); + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED_2(hr, "Could not await characteristic operation"); + GattCommunicationStatus commStatus; + hr = characteristicsResult->get_Status(&commStatus); + if (FAILED(hr) || commStatus != GattCommunicationStatus_Success) { + qCWarning(QT_BT_WINDOWS) << "Characteristic operation failed"; + break; + } + ComPtr> characteristics; + hr = characteristicsResult->get_Characteristics(&characteristics); + if (hr == E_ACCESSDENIED) { + // Everything will work as expected up until this point if the + // manifest capabilties for bluetooth LE are not set. + emitErrorAndQuitThread("Could not obtain characteristic list. " + "Please check your manifest capabilities"); + return; + } + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED_2(hr, "Could not obtain characteristic list"); + uint characteristicsCount; + hr = characteristics->get_Size(&characteristicsCount); + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED_2(hr, + "Could not obtain characteristic list's size"); + for (uint j = 0; j < characteristicsCount; ++j) { + ComPtr characteristic; + hr = characteristics->GetAt(j, &characteristic); + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED_2(hr, "Could not obtain characteristic"); + ComPtr> op; + GattCharacteristicProperties props; + hr = characteristic->get_CharacteristicProperties(&props); + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED_2( + hr, "Could not obtain characteristic's properties"); + if (!(props & GattCharacteristicProperties_Read)) + continue; + hr = characteristic->ReadValueWithCacheModeAsync( + BluetoothCacheMode::BluetoothCacheMode_Uncached, &op); + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED_2(hr, "Could not read characteristic value"); + ComPtr result; + // Reading characteristics can take surprisingly long at the + // first time, so we need to have a large the timeout here. + hr = QWinRTFunctions::await(op, result.GetAddressOf(), + QWinRTFunctions::ProcessThreadEvents, 5000, earlyExit); + // E_ILLEGAL_METHOD_CALL will be the result for a device, that is not reachable at + // the moment. In this case we should jump back into the outer loop and keep trying. + if (hr == E_ILLEGAL_METHOD_CALL) + break; + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED_2(hr, "Could not await characteristic read"); + ComPtr buffer; + hr = result->get_Value(&buffer); + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED_2(hr, "Could not obtain characteristic value"); + if (!buffer) { + qCDebug(QT_BT_WINDOWS) << "Problem reading value"; + break; + } + + emitConnectedAndQuitThread(); + return; + } + } + } + // If we got here because of mAbortConnection == true, the error message + // will not be delivered, so it does not matter. But we need to terminate + // the thread anyway! + emitErrorAndQuitThread("Connect to device failed due to timeout!"); +} + +void QWinRTLowEnergyConnectionHandler::connectToUnpairedDevice() +{ + qCDebug(QT_BT_WINDOWS) << __FUNCTION__; + ComPtr device3; + HRESULT hr = mDevice.As(&device3); + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED_2(hr, "Could not cast device"); + ComPtr deviceServicesResult; + auto earlyExit = [this]() { return mAbortConnection; }; + QDeadlineTimer deadline(kMaxConnectTimeout); + while (!mAbortConnection && !deadline.hasExpired()) { + ComPtr> deviceServicesOp; + hr = device3->GetGattServicesAsync(&deviceServicesOp); + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED_2(hr, "Could not obtain services"); + hr = QWinRTFunctions::await(deviceServicesOp, deviceServicesResult.GetAddressOf(), + QWinRTFunctions::ProcessMainThreadEvents, 0, earlyExit); + EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED_2(hr, "Could not await services operation"); + + GattCommunicationStatus commStatus; + hr = deviceServicesResult->get_Status(&commStatus); + if (commStatus == GattCommunicationStatus_Unreachable) + continue; + + if (FAILED(hr) || commStatus != GattCommunicationStatus_Success) { + emitErrorAndQuitThread("Service operation failed"); + return; + } + + emitConnectedAndQuitThread(); + return; + } + // If we got here because of mAbortConnection == true, the error message + // will not be delivered, so it does not matter. But we need to terminate + // the thread anyway! + emitErrorAndQuitThread("Connect to device failed due to timeout!"); +} + +void QWinRTLowEnergyConnectionHandler::emitErrorAndQuitThread(const QString &error) +{ + emit errorOccurred(error); + QThread::currentThread()->quit(); +} + +void QWinRTLowEnergyConnectionHandler::emitErrorAndQuitThread(const char *error) +{ + emitErrorAndQuitThread(QString::fromUtf8(error)); +} + +void QWinRTLowEnergyConnectionHandler::emitConnectedAndQuitThread() +{ + emit deviceConnected(mDevice, mGattSession); + QThread::currentThread()->quit(); +} + +QLowEnergyControllerPrivateWinRT::QLowEnergyControllerPrivateWinRT() + : QLowEnergyControllerPrivate() +{ + registerQLowEnergyControllerMetaType(); + connect(this, &QLowEnergyControllerPrivateWinRT::characteristicChanged, + this, &QLowEnergyControllerPrivateWinRT::handleCharacteristicChanged, + Qt::QueuedConnection); +} + +QLowEnergyControllerPrivateWinRT::~QLowEnergyControllerPrivateWinRT() +{ + unregisterFromStatusChanges(); + unregisterFromValueChanges(); +} + +void QLowEnergyControllerPrivateWinRT::init() +{ +} + +void QLowEnergyControllerPrivateWinRT::connectToDevice() +{ + qCDebug(QT_BT_WINDOWS) << __FUNCTION__; + if (remoteDevice.isNull()) { + qCWarning(QT_BT_WINDOWS) << "Invalid/null remote device address"; + setError(QLowEnergyController::UnknownRemoteDeviceError); + return; + } + setState(QLowEnergyController::ConnectingState); + + QWinRTLowEnergyConnectionHandler *worker = new QWinRTLowEnergyConnectionHandler(remoteDevice); + QThread *thread = new QThread; + worker->moveToThread(thread); + connect(this, &QLowEnergyControllerPrivateWinRT::abortConnection, worker, + &QWinRTLowEnergyConnectionHandler::handleDeviceDisconnectRequest); + connect(thread, &QThread::started, worker, &QWinRTLowEnergyConnectionHandler::connectToDevice); + connect(thread, &QThread::finished, worker, &QObject::deleteLater); + connect(worker, &QObject::destroyed, thread, &QObject::deleteLater); + connect(worker, &QWinRTLowEnergyConnectionHandler::errorOccurred, this, + [this](const QString &msg) { handleConnectionError(msg.toUtf8().constData()); }); + connect(worker, &QWinRTLowEnergyConnectionHandler::deviceConnected, this, + [this](ComPtr device, ComPtr session) { + if (!device || !session) { + handleConnectionError("Failed to get device or gatt service"); + return; + } + mDevice = device; + mGattSession = session; + + if (!registerForStatusChanges() || !registerForMtuChanges()) { + handleConnectionError("Failed to register for changes"); + return; + } + + Q_Q(QLowEnergyController); + setState(QLowEnergyController::ConnectedState); + emit q->connected(); + }); + thread->start(); +} + +void QLowEnergyControllerPrivateWinRT::disconnectFromDevice() +{ + qCDebug(QT_BT_WINDOWS) << __FUNCTION__; + Q_Q(QLowEnergyController); + setState(QLowEnergyController::ClosingState); + emit abortConnection(); + unregisterFromValueChanges(); + unregisterFromStatusChanges(); + unregisterFromMtuChanges(); + clearAllServices(); + mGattSession = nullptr; + mDevice = nullptr; + setState(QLowEnergyController::UnconnectedState); + emit q->disconnected(); +} + +HRESULT QLowEnergyControllerPrivateWinRT::getNativeService(const QBluetoothUuid &serviceUuid, + NativeServiceCallback callback) +{ + if (m_openedServices.contains(serviceUuid)) { + callback(m_openedServices.value(serviceUuid)); + return S_OK; + } + + ComPtr device3; + HRESULT hr = mDevice.As(&device3); + RETURN_IF_FAILED("Could not convert to IBluetoothDevice3", return hr); + + ComPtr> servicesResultOperation; + hr = device3->GetGattServicesForUuidAsync(serviceUuid, &servicesResultOperation); + RETURN_IF_FAILED("Could not start async services request", return hr); + + QPointer thisPtr(this); + hr = servicesResultOperation->put_Completed( + Callback>( + [thisPtr, callback, &serviceUuid]( + IAsyncOperation *op, AsyncStatus status) + { + if (thisPtr) { + if (status != AsyncStatus::Completed) { + qCDebug(QT_BT_WINDOWS) << "Failed to get result of async service request"; + return S_OK; + } + ComPtr result; + ComPtr> deviceServices; + HRESULT hr = op->GetResults(&result); + RETURN_IF_FAILED("Failed to get result of async service request", return hr); + + ComPtr> services; + hr = result->get_Services(&services); + RETURN_IF_FAILED("Failed to extract services from the result", return hr); + + uint servicesCount = 0; + hr = services->get_Size(&servicesCount); + RETURN_IF_FAILED("Failed to extract services count", return hr); + + if (servicesCount > 0) { + if (servicesCount > 1) { + qWarning() << "getNativeService: more than one service detected for UUID" + << serviceUuid << "The first service will be used."; + } + ComPtr service; + hr = services->GetAt(0, &service); + if (FAILED(hr)) { + qCDebug(QT_BT_WINDOWS) << "Could not obtain native service for Uuid" + << serviceUuid; + } + if (service) { + thisPtr->m_openedServices[serviceUuid] = service; + callback(service); // Use the service in a custom callback + } + } else { + qCWarning(QT_BT_WINDOWS) << "No services found for Uuid" << serviceUuid; + } + } else { + qCWarning(QT_BT_WINDOWS) << "LE controller was removed while getting native service"; + } + return S_OK; + }).Get()); + + return hr; +} + +HRESULT QLowEnergyControllerPrivateWinRT::getNativeCharacteristic( + const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid, + NativeCharacteristicCallback callback) +{ + QPointer thisPtr(this); + auto serviceCallback = [thisPtr, callback, charUuid](ComPtr service) { + ComPtr service3; + HRESULT hr = service.As(&service3); + RETURN_IF_FAILED("Could not cast service to service3", return); + + ComPtr> characteristicRequestOp; + hr = service3->GetCharacteristicsForUuidAsync(charUuid, &characteristicRequestOp); + + hr = characteristicRequestOp->put_Completed( + Callback>( + [thisPtr, callback]( + IAsyncOperation *op, AsyncStatus status) + { + if (thisPtr) { + if (status != AsyncStatus::Completed) { + qCDebug(QT_BT_WINDOWS) << "Failed to get result of async characteristic " + "operation"; + return S_OK; + } + ComPtr result; + HRESULT hr = op->GetResults(&result); + RETURN_IF_FAILED("Failed to get result of async characteristic operation", + return hr); + GattCommunicationStatus status; + hr = result->get_Status(&status); + if (FAILED(hr) || status != GattCommunicationStatus_Success) { + qErrnoWarning(hr, "Native characteristic operation failed."); + return S_OK; + } + ComPtr> characteristics; + hr = result->get_Characteristics(&characteristics); + RETURN_IF_FAILED("Could not obtain characteristic list.", return S_OK); + uint size; + hr = characteristics->get_Size(&size); + RETURN_IF_FAILED("Could not obtain characteristic list's size.", return S_OK); + if (size != 1) + qErrnoWarning("More than 1 characteristic found."); + ComPtr characteristic; + hr = characteristics->GetAt(0, &characteristic); + RETURN_IF_FAILED("Could not obtain first characteristic for service", return S_OK); + if (characteristic) + callback(characteristic); // use the characteristic in a custom callback + } + return S_OK; + }).Get()); + }; + + HRESULT hr = getNativeService(serviceUuid, serviceCallback); + if (FAILED(hr)) + qCDebug(QT_BT_WINDOWS) << "Failed to get native service for" << serviceUuid; + + return hr; +} + +void QLowEnergyControllerPrivateWinRT::registerForValueChanges(const QBluetoothUuid &serviceUuid, + const QBluetoothUuid &charUuid) +{ + qCDebug(QT_BT_WINDOWS) << "Registering characteristic" << charUuid << "in service" + << serviceUuid << "for value changes"; + for (const ValueChangedEntry &entry : std::as_const(mValueChangedTokens)) { + GUID guuid; + HRESULT hr; + hr = entry.characteristic->get_Uuid(&guuid); + WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain characteristic's Uuid") + if (QBluetoothUuid(guuid) == charUuid) + return; + } + + auto callback = [this, charUuid, serviceUuid](ComPtr characteristic) { + EventRegistrationToken token; + HRESULT hr; + hr = characteristic->add_ValueChanged( + Callback( + this, &QLowEnergyControllerPrivateWinRT::onValueChange).Get(), + &token); + RETURN_IF_FAILED("Could not register characteristic for value changes", return) + mValueChangedTokens.append(ValueChangedEntry(characteristic, token)); + qCDebug(QT_BT_WINDOWS) << "Characteristic" << charUuid << "in service" + << serviceUuid << "registered for value changes"; + }; + + HRESULT hr = getNativeCharacteristic(serviceUuid, charUuid, callback); + if (FAILED(hr)) { + qCDebug(QT_BT_WINDOWS).nospace() << "Could not obtain native characteristic " + << charUuid << " from service " << serviceUuid + << ". Qt will not be able to signal" + << " changes for this characteristic."; + } +} + +void QLowEnergyControllerPrivateWinRT::unregisterFromValueChanges() +{ + qCDebug(QT_BT_WINDOWS) << "Unregistering " << mValueChangedTokens.size() << " value change tokens"; + HRESULT hr; + for (const ValueChangedEntry &entry : std::as_const(mValueChangedTokens)) { + if (!entry.characteristic) { + qCWarning(QT_BT_WINDOWS) << "Unregistering from value changes for characteristic failed." + << "Characteristic has been deleted"; + continue; + } + hr = entry.characteristic->remove_ValueChanged(entry.token); + if (FAILED(hr)) + qCWarning(QT_BT_WINDOWS) << "Unregistering from value changes for characteristic failed."; + } + mValueChangedTokens.clear(); +} + +HRESULT QLowEnergyControllerPrivateWinRT::onValueChange(IGattCharacteristic *characteristic, IGattValueChangedEventArgs *args) +{ + HRESULT hr; + quint16 handle; + hr = characteristic->get_AttributeHandle(&handle); + RETURN_IF_FAILED("Could not obtain characteristic's handle", return S_OK) + ComPtr buffer; + hr = args->get_CharacteristicValue(&buffer); + RETURN_IF_FAILED("Could not obtain characteristic's value", return S_OK) + emit characteristicChanged(handle, byteArrayFromBuffer(buffer)); + return S_OK; +} +HRESULT QLowEnergyControllerPrivateWinRT::onMtuChange(IGattSession *session, IInspectable *args) +{ + qCDebug(QT_BT_WINDOWS) << __FUNCTION__; + if (session != mGattSession.Get()) { + qCWarning(QT_BT_WINDOWS) << "Got MTU changed event for wrong or outdated GattSession."; + return S_OK; + } + + Q_Q(QLowEnergyController); + emit q->mtuChanged(mtu()); + return S_OK; +} + +bool QLowEnergyControllerPrivateWinRT::registerForStatusChanges() +{ + if (!mDevice) + return false; + + qCDebug(QT_BT_WINDOWS) << __FUNCTION__; + + HRESULT hr; + hr = mDevice->add_ConnectionStatusChanged( + Callback(this, &QLowEnergyControllerPrivateWinRT::onStatusChange).Get(), + &mStatusChangedToken); + RETURN_IF_FAILED("Could not add status callback", return false) + return true; +} + +void QLowEnergyControllerPrivateWinRT::unregisterFromStatusChanges() +{ + qCDebug(QT_BT_WINDOWS) << __FUNCTION__; + if (mDevice && mStatusChangedToken.value) { + mDevice->remove_ConnectionStatusChanged(mStatusChangedToken); + mStatusChangedToken.value = 0; + } +} + +bool QLowEnergyControllerPrivateWinRT::registerForMtuChanges() +{ + if (!mDevice || !mGattSession) + return false; + + qCDebug(QT_BT_WINDOWS) << __FUNCTION__; + + HRESULT hr; + hr = mGattSession->add_MaxPduSizeChanged( + Callback(this, &QLowEnergyControllerPrivateWinRT::onMtuChange).Get(), + &mMtuChangedToken); + RETURN_IF_FAILED("Could not add MTU callback", return false) + return true; +} + +void QLowEnergyControllerPrivateWinRT::unregisterFromMtuChanges() +{ + qCDebug(QT_BT_WINDOWS) << __FUNCTION__; + if (mDevice && mGattSession && mMtuChangedToken.value) { + mGattSession->remove_MaxPduSizeChanged(mMtuChangedToken); + mMtuChangedToken.value = 0; + } +} + +HRESULT QLowEnergyControllerPrivateWinRT::onStatusChange(IBluetoothLEDevice *dev, IInspectable *) +{ + Q_Q(QLowEnergyController); + BluetoothConnectionStatus status; + HRESULT hr; + hr = dev->get_ConnectionStatus(&status); + RETURN_IF_FAILED("Could not obtain connection status", return S_OK) + if (state == QLowEnergyController::ConnectingState + && status == BluetoothConnectionStatus::BluetoothConnectionStatus_Connected) { + setState(QLowEnergyController::ConnectedState); + emit q->connected(); + } else if (state != QLowEnergyController::UnconnectedState + && status == BluetoothConnectionStatus::BluetoothConnectionStatus_Disconnected) { + invalidateServices(); + unregisterFromValueChanges(); + unregisterFromStatusChanges(); + unregisterFromMtuChanges(); + mGattSession = nullptr; + mDevice = nullptr; + setError(QLowEnergyController::RemoteHostClosedError); + setState(QLowEnergyController::UnconnectedState); + emit q->disconnected(); + } + return S_OK; +} + +void QLowEnergyControllerPrivateWinRT::obtainIncludedServices( + QSharedPointer servicePointer, + ComPtr service) +{ + Q_Q(QLowEnergyController); + ComPtr service3; + HRESULT hr = service.As(&service3); + RETURN_IF_FAILED("Could not cast service", return); + ComPtr> op; + hr = service3->GetIncludedServicesAsync(&op); + // Some devices return ERROR_ACCESS_DISABLED_BY_POLICY + RETURN_IF_FAILED("Could not obtain included services", return); + ComPtr result; + hr = QWinRTFunctions::await(op, result.GetAddressOf(), QWinRTFunctions::ProcessMainThreadEvents, 5000); + RETURN_IF_FAILED("Could not await service operation", return); + // The device can be disconnected by the time we return from await() + if (state != QLowEnergyController::DiscoveringState) + return; + GattCommunicationStatus status; + hr = result->get_Status(&status); + if (FAILED(hr) || status != GattCommunicationStatus_Success) { + qErrnoWarning("Could not obtain list of included services"); + return; + } + ComPtr> includedServices; + hr = result->get_Services(&includedServices); + RETURN_IF_FAILED("Could not obtain service list", return); + + uint count; + hr = includedServices->get_Size(&count); + RETURN_IF_FAILED("Could not obtain service list's size", return); + for (uint i = 0; i < count; ++i) { + ComPtr includedService; + hr = includedServices->GetAt(i, &includedService); + WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain service from list"); + GUID guuid; + hr = includedService->get_Uuid(&guuid); + WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain included service's Uuid"); + const QBluetoothUuid includedUuid(guuid); + QSharedPointer includedPointer; + qCDebug(QT_BT_WINDOWS_SERVICE_THREAD) << __FUNCTION__ + << "Changing service pointer from thread" + << QThread::currentThread(); + if (serviceList.contains(includedUuid)) { + includedPointer = serviceList.value(includedUuid); + } else { + QLowEnergyServicePrivate *priv = new QLowEnergyServicePrivate(); + priv->uuid = includedUuid; + priv->setController(this); + + includedPointer = QSharedPointer(priv); + serviceList.insert(includedUuid, includedPointer); + } + includedPointer->type |= QLowEnergyService::IncludedService; + servicePointer->includedServices.append(includedUuid); + + obtainIncludedServices(includedPointer, includedService); + + emit q->serviceDiscovered(includedUuid); + } +} + +HRESULT QLowEnergyControllerPrivateWinRT::onServiceDiscoveryFinished(ABI::Windows::Foundation::IAsyncOperation *op, AsyncStatus status) +{ + // Check if the device is in the proper state, because it can already be + // disconnected when the callback arrives. + // Also the callback can theoretically come when the connection is + // reestablisheed again (for example, if the user quickly clicks + // "Disconnect" and then "Connect" again in some UI). But we can probably + // omit such details, as we are connecting to the same device anyway. + if (state != QLowEnergyController::DiscoveringState) + return S_OK; + + Q_Q(QLowEnergyController); + if (status != AsyncStatus::Completed) { + qCDebug(QT_BT_WINDOWS) << "Could not obtain services"; + return S_OK; + } + ComPtr result; + ComPtr> deviceServices; + HRESULT hr = op->GetResults(&result); + CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain service discovery result", + return S_OK); + GattCommunicationStatus commStatus; + hr = result->get_Status(&commStatus); + CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain service discovery status", + return S_OK); + if (commStatus != GattCommunicationStatus_Success) + return S_OK; + + hr = result->get_Services(&deviceServices); + CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain service list", + return S_OK); + + uint serviceCount; + hr = deviceServices->get_Size(&serviceCount); + CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain service list size", + return S_OK); + for (uint i = 0; i < serviceCount; ++i) { + ComPtr deviceService; + hr = deviceServices->GetAt(i, &deviceService); + WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain service"); + GUID guuid; + hr = deviceService->get_Uuid(&guuid); + WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain service's Uuid"); + const QBluetoothUuid service(guuid); + m_openedServices[service] = deviceService; + + qCDebug(QT_BT_WINDOWS_SERVICE_THREAD) << __FUNCTION__ + << "Changing service pointer from thread" + << QThread::currentThread(); + QSharedPointer pointer; + if (serviceList.contains(service)) { + pointer = serviceList.value(service); + } else { + QLowEnergyServicePrivate *priv = new QLowEnergyServicePrivate(); + priv->uuid = service; + priv->setController(this); + + pointer = QSharedPointer(priv); + serviceList.insert(service, pointer); + } + pointer->type |= QLowEnergyService::PrimaryService; + + obtainIncludedServices(pointer, deviceService); + // The obtainIncludedServices method calls await(), so the device can be + // disconnected by the time we return from it. TODO - rewrite in an + // async way! + if (state != QLowEnergyController::DiscoveringState) { + emit q->discoveryFinished(); // Probably not needed when the device + // is already disconnected? + return S_OK; + } + + emit q->serviceDiscovered(service); + } + + setState(QLowEnergyController::DiscoveredState); + emit q->discoveryFinished(); + + return S_OK; +} + +void QLowEnergyControllerPrivateWinRT::clearAllServices() +{ + // These services will be closed in the respective + // QWinRTLowEnergyServiceHandler workers (in background threads). + for (auto &uuid : m_requestDetailsServiceUuids) + m_openedServices.remove(uuid); + m_requestDetailsServiceUuids.clear(); + + for (auto service : m_openedServices) { + closeDeviceService(service); + } + m_openedServices.clear(); +} + +void QLowEnergyControllerPrivateWinRT::closeAndRemoveService(const QBluetoothUuid &uuid) +{ + auto service = m_openedServices.take(uuid); + if (service) + closeDeviceService(service); +} + +void QLowEnergyControllerPrivateWinRT::discoverServices() +{ + qCDebug(QT_BT_WINDOWS) << "Service discovery initiated"; + // clear the previous services cache, as we request the services again + clearAllServices(); + ComPtr device3; + HRESULT hr = mDevice.As(&device3); + CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not cast device", return); + ComPtr> asyncResult; + hr = device3->GetGattServicesAsync(&asyncResult); + CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain services", return); + hr = asyncResult->put_Completed( + Callback>( + this, &QLowEnergyControllerPrivateWinRT::onServiceDiscoveryFinished).Get()); + CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not register services discovery callback", + return); +} + +void QLowEnergyControllerPrivateWinRT::discoverServiceDetails( + const QBluetoothUuid &service, QLowEnergyService::DiscoveryMode mode) +{ + qCDebug(QT_BT_WINDOWS) << __FUNCTION__ << service; + if (!serviceList.contains(service)) { + qCWarning(QT_BT_WINDOWS) << "Discovery done of unknown service:" + << service.toString(); + return; + } + + // clear the cache to rediscover service details + closeAndRemoveService(service); + + auto serviceCallback = [service, mode, this](ComPtr deviceService) { + discoverServiceDetailsHelper(service, mode, deviceService); + }; + + HRESULT hr = getNativeService(service, serviceCallback); + if (FAILED(hr)) + qCDebug(QT_BT_WINDOWS) << "Could not obtain native service for uuid " << service; +} + +void QLowEnergyControllerPrivateWinRT::discoverServiceDetailsHelper( + const QBluetoothUuid &service, QLowEnergyService::DiscoveryMode mode, + GattDeviceServiceComPtr deviceService) +{ + auto reactOnDiscoveryError = [](QSharedPointer service, + const QString &msg) + { + qCDebug(QT_BT_WINDOWS) << msg; + service->setError(QLowEnergyService::UnknownError); + service->setState(QLowEnergyService::RemoteService); + }; + //update service data + QSharedPointer pointer = serviceList.value(service); + if (!pointer) { + qCDebug(QT_BT_WINDOWS) << "Device was disconnected while doing service discovery"; + return; + } + qCDebug(QT_BT_WINDOWS_SERVICE_THREAD) << __FUNCTION__ << "Changing service pointer from thread" + << QThread::currentThread(); + pointer->setState(QLowEnergyService::RemoteServiceDiscovering); + ComPtr deviceService3; + HRESULT hr = deviceService.As(&deviceService3); + if (FAILED(hr)) { + reactOnDiscoveryError(pointer, QStringLiteral("Could not cast service: %1").arg(hr)); + return; + } + ComPtr> op; + hr = deviceService3->GetIncludedServicesAsync(&op); + if (FAILED(hr)) { + reactOnDiscoveryError(pointer, + QStringLiteral("Could not obtain included service list: %1").arg(hr)); + return; + } + ComPtr result; + hr = QWinRTFunctions::await(op, result.GetAddressOf()); + if (FAILED(hr)) { + reactOnDiscoveryError(pointer, + QStringLiteral("Could not await service operation: %1").arg(hr)); + return; + } + GattCommunicationStatus status; + hr = result->get_Status(&status); + if (FAILED(hr) || status != GattCommunicationStatus_Success) { + reactOnDiscoveryError(pointer, + QStringLiteral("Obtaining list of included services failed: %1"). + arg(hr)); + return; + } + ComPtr> deviceServices; + hr = result->get_Services(&deviceServices); + if (FAILED(hr)) { + reactOnDiscoveryError(pointer, + QStringLiteral("Could not obtain service list from result: %1"). + arg(hr)); + return; + } + uint serviceCount; + hr = deviceServices->get_Size(&serviceCount); + if (FAILED(hr)) { + reactOnDiscoveryError(pointer, + QStringLiteral("Could not obtain included service list's size: %1"). + arg(hr)); + return; + } + for (uint i = 0; i < serviceCount; ++i) { + ComPtr includedService; + hr = deviceServices->GetAt(i, &includedService); + WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain service from list") + GUID guuid; + hr = includedService->get_Uuid(&guuid); + WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain service Uuid") + + const QBluetoothUuid service(guuid); + if (service.isNull()) { + qCDebug(QT_BT_WINDOWS) << "Could not find service"; + continue; + } + + pointer->includedServices.append(service); + + // update the type of the included service + QSharedPointer otherService = serviceList.value(service); + if (!otherService.isNull()) + otherService->type |= QLowEnergyService::IncludedService; + } + + QWinRTLowEnergyServiceHandler *worker = + new QWinRTLowEnergyServiceHandler(service, deviceService3, mode); + m_requestDetailsServiceUuids.insert(service); + QThread *thread = new QThread; + worker->moveToThread(thread); + connect(thread, &QThread::started, worker, &QWinRTLowEnergyServiceHandler::obtainCharList); + connect(thread, &QThread::finished, worker, &QObject::deleteLater); + connect(worker, &QObject::destroyed, thread, &QObject::deleteLater); + connect(this, &QLowEnergyControllerPrivateWinRT::abortConnection, + worker, &QWinRTLowEnergyServiceHandler::setAbortRequested); + connect(worker, &QWinRTLowEnergyServiceHandler::errorOccured, + this, &QLowEnergyControllerPrivateWinRT::handleServiceHandlerError); + connect(worker, &QWinRTLowEnergyServiceHandler::charListObtained, this, + [this](const QBluetoothUuid &service, QHash charList, QList indicateChars, + QLowEnergyHandle startHandle, QLowEnergyHandle endHandle) { + if (!serviceList.contains(service)) { + qCWarning(QT_BT_WINDOWS) + << "Discovery complete for unknown service:" << service.toString(); + return; + } + m_requestDetailsServiceUuids.remove(service); + + QSharedPointer pointer = serviceList.value(service); + pointer->startHandle = startHandle; + pointer->endHandle = endHandle; + pointer->characteristicList = charList; + + for (const QBluetoothUuid &indicateChar : std::as_const(indicateChars)) + registerForValueChanges(service, indicateChar); + + pointer->setState(QLowEnergyService::RemoteServiceDiscovered); + }); + thread->start(); +} + +void QLowEnergyControllerPrivateWinRT::startAdvertising( + const QLowEnergyAdvertisingParameters &, + const QLowEnergyAdvertisingData &, + const QLowEnergyAdvertisingData &) +{ + setError(QLowEnergyController::AdvertisingError); + Q_UNIMPLEMENTED(); +} + +void QLowEnergyControllerPrivateWinRT::stopAdvertising() +{ + Q_UNIMPLEMENTED(); +} + +void QLowEnergyControllerPrivateWinRT::requestConnectionUpdate(const QLowEnergyConnectionParameters &) +{ + Q_UNIMPLEMENTED(); +} + +void QLowEnergyControllerPrivateWinRT::readCharacteristic( + const QSharedPointer service, + const QLowEnergyHandle charHandle) +{ + qCDebug(QT_BT_WINDOWS) << __FUNCTION__ << service << charHandle; + qCDebug(QT_BT_WINDOWS_SERVICE_THREAD) << __FUNCTION__ << "Changing service pointer from thread" + << QThread::currentThread(); + Q_ASSERT(!service.isNull()); + if (role == QLowEnergyController::PeripheralRole) { + service->setError(QLowEnergyService::CharacteristicReadError); + Q_UNIMPLEMENTED(); + return; + } + + if (!service->characteristicList.contains(charHandle)) { + qCDebug(QT_BT_WINDOWS) << charHandle << "could not be found in service" << service->uuid; + service->setError(QLowEnergyService::CharacteristicReadError); + return; + } + + const auto charData = service->characteristicList.value(charHandle); + if (!(charData.properties & QLowEnergyCharacteristic::Read)) + qCDebug(QT_BT_WINDOWS) << "Read flag is not set for characteristic" << charData.uuid; + + auto characteristicCallback = [charHandle, service, this]( + ComPtr characteristic) { + readCharacteristicHelper(service, charHandle, characteristic); + }; + + HRESULT hr = getNativeCharacteristic(service->uuid, charData.uuid, characteristicCallback); + if (FAILED(hr)) { + qCDebug(QT_BT_WINDOWS) << "Could not obtain native characteristic" << charData.uuid + << "from service" << service->uuid; + service->setError(QLowEnergyService::CharacteristicReadError); + } +} + +void QLowEnergyControllerPrivateWinRT::readCharacteristicHelper( + const QSharedPointer service, + const QLowEnergyHandle charHandle, + GattCharacteristicComPtr characteristic) +{ + ComPtr> readOp; + HRESULT hr = characteristic->ReadValueWithCacheModeAsync(BluetoothCacheMode_Uncached, &readOp); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not read characteristic", + service, QLowEnergyService::CharacteristicReadError, return) + auto readCompletedLambda = [charHandle, service] + (IAsyncOperation *op, AsyncStatus status) + { + if (status == AsyncStatus::Canceled || status == AsyncStatus::Error) { + qCDebug(QT_BT_WINDOWS) << "Characteristic" << charHandle << "read operation failed."; + service->setError(QLowEnergyService::CharacteristicReadError); + return S_OK; + } + ComPtr characteristicValue; + HRESULT hr; + hr = op->GetResults(&characteristicValue); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain result for characteristic", service, + QLowEnergyService::CharacteristicReadError, return S_OK) + + const QByteArray value = byteArrayFromGattResult(characteristicValue); + auto charData = service->characteristicList.value(charHandle); + charData.value = value; + service->characteristicList.insert(charHandle, charData); + emit service->characteristicRead(QLowEnergyCharacteristic(service, charHandle), value); + return S_OK; + }; + hr = readOp->put_Completed(Callback>( + readCompletedLambda).Get()); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not register characteristic read callback", + service, QLowEnergyService::CharacteristicReadError, return) +} + +void QLowEnergyControllerPrivateWinRT::readDescriptor( + const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descHandle) +{ + qCDebug(QT_BT_WINDOWS) << __FUNCTION__ << service << charHandle << descHandle; + qCDebug(QT_BT_WINDOWS_SERVICE_THREAD) << __FUNCTION__ << "Changing service pointer from thread" + << QThread::currentThread(); + Q_ASSERT(!service.isNull()); + if (role == QLowEnergyController::PeripheralRole) { + service->setError(QLowEnergyService::DescriptorReadError); + Q_UNIMPLEMENTED(); + return; + } + + if (!service->characteristicList.contains(charHandle)) { + qCDebug(QT_BT_WINDOWS) << "Descriptor" << descHandle << "in characteristic" << charHandle + << "cannot be found in service" << service->uuid; + service->setError(QLowEnergyService::DescriptorReadError); + return; + } + + const auto charData = service->characteristicList.value(charHandle); + + auto characteristicCallback = [charHandle, descHandle, service, this]( + ComPtr characteristic) { + readDescriptorHelper(service, charHandle, descHandle, characteristic); + }; + + HRESULT hr = getNativeCharacteristic(service->uuid, charData.uuid, characteristicCallback); + if (FAILED(hr)) { + qCDebug(QT_BT_WINDOWS) << "Could not obtain native characteristic" << charData.uuid + << "from service" << service->uuid; + service->setError(QLowEnergyService::DescriptorReadError); + } +} + +void QLowEnergyControllerPrivateWinRT::readDescriptorHelper( + const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descHandle, + GattCharacteristicComPtr characteristic) +{ + // Get native descriptor + const auto charData = service->characteristicList.value(charHandle); + if (!charData.descriptorList.contains(descHandle)) { + qCDebug(QT_BT_WINDOWS) << "Descriptor" << descHandle << "cannot be found in characteristic" + << charHandle; + } + const auto descData = charData.descriptorList.value(descHandle); + const QBluetoothUuid descUuid = descData.uuid; + if (descUuid == + QBluetoothUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration)) { + ComPtr> readOp; + HRESULT hr = characteristic->ReadClientCharacteristicConfigurationDescriptorAsync(&readOp); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not read client characteristic configuration", + service, QLowEnergyService::DescriptorReadError, return) + auto readCompletedLambda = [charHandle, descHandle, service] + (IAsyncOperation *op, AsyncStatus status) + { + if (status == AsyncStatus::Canceled || status == AsyncStatus::Error) { + qCDebug(QT_BT_WINDOWS) << "Descriptor" << descHandle << "read operation failed"; + service->setError(QLowEnergyService::DescriptorReadError); + return S_OK; + } + ComPtr iValue; + HRESULT hr; + hr = op->GetResults(&iValue); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain result for descriptor", service, + QLowEnergyService::DescriptorReadError, return S_OK) + GattClientCharacteristicConfigurationDescriptorValue value; + hr = iValue->get_ClientCharacteristicConfigurationDescriptor(&value); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain value for descriptor", service, + QLowEnergyService::DescriptorReadError, return S_OK) + quint16 result = 0; + bool correct = false; + if (value & GattClientCharacteristicConfigurationDescriptorValue_Indicate) { + result |= QLowEnergyCharacteristic::Indicate; + correct = true; + } + if (value & GattClientCharacteristicConfigurationDescriptorValue_Notify) { + result |= QLowEnergyCharacteristic::Notify; + correct = true; + } + if (value == GattClientCharacteristicConfigurationDescriptorValue_None) + correct = true; + if (!correct) { + qCDebug(QT_BT_WINDOWS) << "Descriptor" << descHandle + << "read operation failed. Obtained unexpected value."; + service->setError(QLowEnergyService::DescriptorReadError); + return S_OK; + } + QLowEnergyServicePrivate::DescData descData; + descData.uuid = QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration; + descData.value = QByteArray(2, Qt::Uninitialized); + qToLittleEndian(result, descData.value.data()); + service->characteristicList[charHandle].descriptorList[descHandle] = descData; + emit service->descriptorRead(QLowEnergyDescriptor(service, charHandle, descHandle), + descData.value); + return S_OK; + }; + hr = readOp->put_Completed( + Callback>( + readCompletedLambda).Get()); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not register descriptor read callback", + service, QLowEnergyService::DescriptorReadError, return) + return; + } + + ComPtr characteristic3; + HRESULT hr = characteristic.As(&characteristic3); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not cast characteristic", + service, QLowEnergyService::DescriptorReadError, return) + ComPtr> op; + hr = characteristic3->GetDescriptorsForUuidAsync(descData.uuid, &op); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain descriptor for uuid", + service, QLowEnergyService::DescriptorReadError, return) + ComPtr result; + hr = QWinRTFunctions::await(op, result.GetAddressOf(), + QWinRTFunctions::ProcessMainThreadEvents, 5000); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not await descritpor read result", + service, QLowEnergyService::DescriptorReadError, return) + + GattCommunicationStatus commStatus; + hr = result->get_Status(&commStatus); + if (FAILED(hr) || commStatus != GattCommunicationStatus_Success) { + qErrnoWarning("Could not obtain list of descriptors"); + service->setError(QLowEnergyService::DescriptorReadError); + return; + } + + ComPtr> descriptors; + hr = result->get_Descriptors(&descriptors); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain descriptor list", + service, QLowEnergyService::DescriptorReadError, return) + uint size; + hr = descriptors->get_Size(&size); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not await descritpor list's size", + service, QLowEnergyService::DescriptorReadError, return) + if (size == 0) { + qCWarning(QT_BT_WINDOWS) << "No descriptor with uuid" << descData.uuid << "was found."; + service->setError(QLowEnergyService::DescriptorReadError); + return; + } else if (size > 1) { + qCWarning(QT_BT_WINDOWS) << "There is more than 1 descriptor with uuid" << descData.uuid; + } + + ComPtr descriptor; + hr = descriptors->GetAt(0, &descriptor); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain descritpor from list", + service, QLowEnergyService::DescriptorReadError, return) + ComPtr> readOp; + hr = descriptor->ReadValueWithCacheModeAsync(BluetoothCacheMode_Uncached, &readOp); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not read descriptor value", + service, QLowEnergyService::DescriptorReadError, return) + auto readCompletedLambda = [charHandle, descHandle, descUuid, service] + (IAsyncOperation *op, AsyncStatus status) + { + if (status == AsyncStatus::Canceled || status == AsyncStatus::Error) { + qCDebug(QT_BT_WINDOWS) << "Descriptor" << descHandle << "read operation failed"; + service->setError(QLowEnergyService::DescriptorReadError); + return S_OK; + } + ComPtr descriptorValue; + HRESULT hr; + hr = op->GetResults(&descriptorValue); + if (FAILED(hr)) { + qCDebug(QT_BT_WINDOWS) << "Could not obtain result for descriptor" << descHandle; + service->setError(QLowEnergyService::DescriptorReadError); + return S_OK; + } + QLowEnergyServicePrivate::DescData descData; + descData.uuid = descUuid; + if (descData.uuid == QBluetoothUuid::DescriptorType::CharacteristicUserDescription) + descData.value = byteArrayFromGattResult(descriptorValue, true); + else + descData.value = byteArrayFromGattResult(descriptorValue); + service->characteristicList[charHandle].descriptorList[descHandle] = descData; + emit service->descriptorRead(QLowEnergyDescriptor(service, charHandle, descHandle), + descData.value); + return S_OK; + }; + hr = readOp->put_Completed(Callback>( + readCompletedLambda).Get()); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not register descriptor read callback", + service, QLowEnergyService::DescriptorReadError, return) +} + +void QLowEnergyControllerPrivateWinRT::writeCharacteristic( + const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QByteArray &newValue, + QLowEnergyService::WriteMode mode) +{ + qCDebug(QT_BT_WINDOWS) << __FUNCTION__ << service << charHandle << newValue << mode; + qCDebug(QT_BT_WINDOWS_SERVICE_THREAD) << __FUNCTION__ << "Changing service pointer from thread" + << QThread::currentThread(); + Q_ASSERT(!service.isNull()); + if (role == QLowEnergyController::PeripheralRole) { + service->setError(QLowEnergyService::CharacteristicWriteError); + Q_UNIMPLEMENTED(); + return; + } + if (!service->characteristicList.contains(charHandle)) { + qCDebug(QT_BT_WINDOWS) << "Characteristic" << charHandle << "cannot be found in service" + << service->uuid; + service->setError(QLowEnergyService::CharacteristicWriteError); + return; + } + + QLowEnergyServicePrivate::CharData charData = service->characteristicList.value(charHandle); + const bool writeWithResponse = mode == QLowEnergyService::WriteWithResponse; + if (!(charData.properties & (writeWithResponse ? QLowEnergyCharacteristic::Write + : QLowEnergyCharacteristic::WriteNoResponse))) + qCDebug(QT_BT_WINDOWS) << "Write flag is not set for characteristic" << charHandle; + + auto characteristicCallback = [charHandle, service, newValue, writeWithResponse, this]( + ComPtr characteristic) { + writeCharacteristicHelper(service, charHandle, newValue, writeWithResponse, + characteristic); + }; + + HRESULT hr = getNativeCharacteristic(service->uuid, charData.uuid, characteristicCallback); + if (FAILED(hr)) { + qCDebug(QT_BT_WINDOWS) << "Could not obtain native characteristic" << charData.uuid + << "from service" << service->uuid; + service->setError(QLowEnergyService::CharacteristicWriteError); + } +} + +void QLowEnergyControllerPrivateWinRT::writeCharacteristicHelper( + const QSharedPointer service, + const QLowEnergyHandle charHandle, const QByteArray &newValue, + bool writeWithResponse, GattCharacteristicComPtr characteristic) +{ + ComPtr bufferFactory; + HRESULT hr = GetActivationFactory( + HStringReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(), + &bufferFactory); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain buffer factory", + service, QLowEnergyService::CharacteristicWriteError, return) + ComPtr buffer; + const quint32 length = quint32(newValue.length()); + hr = bufferFactory->Create(length, &buffer); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not create buffer", + service, QLowEnergyService::CharacteristicWriteError, return) + hr = buffer->put_Length(length); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not set buffer length", + service, QLowEnergyService::CharacteristicWriteError, return) + ComPtr byteAccess; + hr = buffer.As(&byteAccess); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not cast buffer", + service, QLowEnergyService::CharacteristicWriteError, return) + byte *bytes; + hr = byteAccess->Buffer(&bytes); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not set buffer", + service, QLowEnergyService::CharacteristicWriteError, return) + memcpy(bytes, newValue, length); + ComPtr> writeOp; + GattWriteOption option = writeWithResponse ? GattWriteOption_WriteWithResponse + : GattWriteOption_WriteWithoutResponse; + hr = characteristic->WriteValueWithOptionAsync(buffer.Get(), option, &writeOp); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could write characteristic", + service, QLowEnergyService::CharacteristicWriteError, return) + const auto charData = service->characteristicList.value(charHandle); + QPointer thisPtr(this); + auto writeCompletedLambda = + [charData, charHandle, newValue, service, writeWithResponse, thisPtr] + (IAsyncOperation *op, AsyncStatus status) + { + if (status == AsyncStatus::Canceled || status == AsyncStatus::Error) { + qCDebug(QT_BT_WINDOWS) << "Characteristic" << charHandle << "write operation failed"; + service->setError(QLowEnergyService::CharacteristicWriteError); + return S_OK; + } + GattCommunicationStatus result; + HRESULT hr; + hr = op->GetResults(&result); + if (hr == E_BLUETOOTH_ATT_INVALID_ATTRIBUTE_VALUE_LENGTH) { + qCDebug(QT_BT_WINDOWS) << "Characteristic" << charHandle + << "write operation was tried with invalid value length"; + service->setError(QLowEnergyService::CharacteristicWriteError); + return S_OK; + } + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain characteristic write result", service, + QLowEnergyService::CharacteristicWriteError, return S_OK) + if (result != GattCommunicationStatus_Success) { + qCDebug(QT_BT_WINDOWS) << "Characteristic" << charHandle << "write operation failed"; + service->setError(QLowEnergyService::CharacteristicWriteError); + return S_OK; + } + // only update cache when property is readable. Otherwise it remains + // empty. + if (thisPtr && charData.properties & QLowEnergyCharacteristic::Read) + thisPtr->updateValueOfCharacteristic(charHandle, newValue, false); + if (writeWithResponse) { + emit service->characteristicWritten(QLowEnergyCharacteristic(service, charHandle), + newValue); + } + return S_OK; + }; + hr = writeOp->put_Completed( + Callback>( + writeCompletedLambda).Get()); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not register characteristic write callback", + service, QLowEnergyService::CharacteristicWriteError, return) +} + +void QLowEnergyControllerPrivateWinRT::writeDescriptor( + const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descHandle, + const QByteArray &newValue) +{ + qCDebug(QT_BT_WINDOWS) << __FUNCTION__ << service << charHandle << descHandle << newValue; + qCDebug(QT_BT_WINDOWS_SERVICE_THREAD) << __FUNCTION__ << "Changing service pointer from thread" + << QThread::currentThread(); + Q_ASSERT(!service.isNull()); + if (role == QLowEnergyController::PeripheralRole) { + service->setError(QLowEnergyService::DescriptorWriteError); + Q_UNIMPLEMENTED(); + return; + } + + if (!service->characteristicList.contains(charHandle)) { + qCDebug(QT_BT_WINDOWS) << "Descriptor" << descHandle << "in characteristic" << charHandle + << "could not be found in service" << service->uuid; + service->setError(QLowEnergyService::DescriptorWriteError); + return; + } + + const auto charData = service->characteristicList.value(charHandle); + + auto characteristicCallback = [descHandle, charHandle, service, newValue, this]( + ComPtr characteristic) { + writeDescriptorHelper(service, charHandle, descHandle, newValue, characteristic); + }; + + HRESULT hr = getNativeCharacteristic(service->uuid, charData.uuid, characteristicCallback); + if (FAILED(hr)) { + qCDebug(QT_BT_WINDOWS) << "Could not obtain native characteristic" << charData.uuid + << "from service" << service->uuid; + service->setError(QLowEnergyService::DescriptorWriteError); + } +} + +void QLowEnergyControllerPrivateWinRT::writeDescriptorHelper( + const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descHandle, + const QByteArray &newValue, + GattCharacteristicComPtr characteristic) +{ + // Get native descriptor + const auto charData = service->characteristicList.value(charHandle); + if (!charData.descriptorList.contains(descHandle)) { + qCDebug(QT_BT_WINDOWS) << "Descriptor" << descHandle + << "could not be found in Characteristic" << charHandle; + } + + QLowEnergyServicePrivate::DescData descData = charData.descriptorList.value(descHandle); + if (descData.uuid == + QBluetoothUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration)) { + GattClientCharacteristicConfigurationDescriptorValue value; + quint16 intValue = qFromLittleEndian(newValue); + if (intValue & GattClientCharacteristicConfigurationDescriptorValue_Indicate + && intValue & GattClientCharacteristicConfigurationDescriptorValue_Notify) { + qCWarning(QT_BT_WINDOWS) << "Setting both Indicate and Notify " + "is not supported on WinRT"; + value = GattClientCharacteristicConfigurationDescriptorValue( + (GattClientCharacteristicConfigurationDescriptorValue_Indicate + | GattClientCharacteristicConfigurationDescriptorValue_Notify)); + } else if (intValue & GattClientCharacteristicConfigurationDescriptorValue_Indicate) { + value = GattClientCharacteristicConfigurationDescriptorValue_Indicate; + } else if (intValue & GattClientCharacteristicConfigurationDescriptorValue_Notify) { + value = GattClientCharacteristicConfigurationDescriptorValue_Notify; + } else if (intValue == 0) { + value = GattClientCharacteristicConfigurationDescriptorValue_None; + } else { + qCDebug(QT_BT_WINDOWS) << "Descriptor" << descHandle + << "write operation failed: Invalid value"; + service->setError(QLowEnergyService::DescriptorWriteError); + return; + } + ComPtr> writeOp; + HRESULT hr = + characteristic->WriteClientCharacteristicConfigurationDescriptorAsync(value, &writeOp); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not write client characteristic configuration", + service, QLowEnergyService::DescriptorWriteError, return) + QPointer thisPtr(this); + auto writeCompletedLambda = [charHandle, descHandle, newValue, service, thisPtr] + (IAsyncOperation *op, AsyncStatus status) + { + if (status == AsyncStatus::Canceled || status == AsyncStatus::Error) { + qCDebug(QT_BT_WINDOWS) << "Descriptor" << descHandle << "write operation failed"; + service->setError(QLowEnergyService::DescriptorWriteError); + return S_OK; + } + GattCommunicationStatus result; + HRESULT hr; + hr = op->GetResults(&result); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain result for descriptor", service, + QLowEnergyService::DescriptorWriteError, return S_OK) + if (result != GattCommunicationStatus_Success) { + qCWarning(QT_BT_WINDOWS) << "Descriptor" << descHandle << "write operation failed"; + service->setError(QLowEnergyService::DescriptorWriteError); + return S_OK; + } + if (thisPtr) + thisPtr->updateValueOfDescriptor(charHandle, descHandle, newValue, false); + emit service->descriptorWritten(QLowEnergyDescriptor(service, charHandle, descHandle), + newValue); + return S_OK; + }; + hr = writeOp->put_Completed( + Callback>( + writeCompletedLambda).Get()); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not register descriptor write callback", + service, QLowEnergyService::DescriptorWriteError, return) + return; + } + + ComPtr characteristic3; + HRESULT hr = characteristic.As(&characteristic3); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not cast characteristic", + service, QLowEnergyService::DescriptorWriteError, return) + ComPtr> op; + hr = characteristic3->GetDescriptorsForUuidAsync(descData.uuid, &op); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain descriptor from Uuid", + service, QLowEnergyService::DescriptorWriteError, return) + ComPtr result; + hr = QWinRTFunctions::await(op, result.GetAddressOf(), + QWinRTFunctions::ProcessMainThreadEvents, 5000); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not await descriptor operation", + service, QLowEnergyService::DescriptorWriteError, return) + GattCommunicationStatus commStatus; + hr = result->get_Status(&commStatus); + if (FAILED(hr) || commStatus != GattCommunicationStatus_Success) { + qCWarning(QT_BT_WINDOWS) << "Descriptor operation failed"; + service->setError(QLowEnergyService::DescriptorWriteError); + return; + } + ComPtr> descriptors; + hr = result->get_Descriptors(&descriptors); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain list of descriptors", + service, QLowEnergyService::DescriptorWriteError, return) + uint size; + hr = descriptors->get_Size(&size); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain list of descriptors' size", + service, QLowEnergyService::DescriptorWriteError, return) + if (size == 0) { + qCWarning(QT_BT_WINDOWS) << "No descriptor with uuid" << descData.uuid << "was found."; + return; + } else if (size > 1) { + qCWarning(QT_BT_WINDOWS) << "There is more than 1 descriptor with uuid" << descData.uuid; + } + ComPtr descriptor; + hr = descriptors->GetAt(0, &descriptor); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain descriptor", + service, QLowEnergyService::DescriptorWriteError, return) + ComPtr bufferFactory; + hr = GetActivationFactory( + HStringReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(), + &bufferFactory); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain buffer factory", + service, QLowEnergyService::DescriptorWriteError, return) + ComPtr buffer; + const quint32 length = quint32(newValue.length()); + hr = bufferFactory->Create(length, &buffer); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not create buffer", + service, QLowEnergyService::DescriptorWriteError, return) + hr = buffer->put_Length(length); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not set buffer length", + service, QLowEnergyService::DescriptorWriteError, return) + ComPtr byteAccess; + hr = buffer.As(&byteAccess); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not cast buffer", + service, QLowEnergyService::DescriptorWriteError, return) + byte *bytes; + hr = byteAccess->Buffer(&bytes); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not set buffer", + service, QLowEnergyService::DescriptorWriteError, return) + memcpy(bytes, newValue, length); + ComPtr> writeOp; + hr = descriptor->WriteValueAsync(buffer.Get(), &writeOp); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not write descriptor value", + service, QLowEnergyService::DescriptorWriteError, return) + QPointer thisPtr(this); + auto writeCompletedLambda = [charHandle, descHandle, newValue, service, thisPtr] + (IAsyncOperation *op, AsyncStatus status) + { + if (status == AsyncStatus::Canceled || status == AsyncStatus::Error) { + qCDebug(QT_BT_WINDOWS) << "Descriptor" << descHandle << "write operation failed"; + service->setError(QLowEnergyService::DescriptorWriteError); + return S_OK; + } + GattCommunicationStatus result; + HRESULT hr; + hr = op->GetResults(&result); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain result for descriptor", service, + QLowEnergyService::DescriptorWriteError, return S_OK) + if (result != GattCommunicationStatus_Success) { + qCDebug(QT_BT_WINDOWS) << "Descriptor" << descHandle << "write operation failed"; + service->setError(QLowEnergyService::DescriptorWriteError); + return S_OK; + } + if (thisPtr) + thisPtr->updateValueOfDescriptor(charHandle, descHandle, newValue, false); + emit service->descriptorWritten(QLowEnergyDescriptor(service, charHandle, descHandle), + newValue); + return S_OK; + }; + hr = writeOp->put_Completed( + Callback>( + writeCompletedLambda).Get()); + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not register descriptor write callback", + service, QLowEnergyService::DescriptorWriteError, return) +} + +void QLowEnergyControllerPrivateWinRT::addToGenericAttributeList(const QLowEnergyServiceData &, + QLowEnergyHandle) +{ + Q_UNIMPLEMENTED(); +} + +int QLowEnergyControllerPrivateWinRT::mtu() const +{ + uint16_t mtu = 23; + if (!mGattSession) { + qCDebug(QT_BT_WINDOWS) << "mtu queried before GattSession available. Using default mtu."; + return mtu; + } + + HRESULT hr = mGattSession->get_MaxPduSize(&mtu); + RETURN_IF_FAILED("could not obtain MTU size", return mtu); + qCDebug(QT_BT_WINDOWS) << "mtu determined to be" << mtu; + return mtu; +} + +void QLowEnergyControllerPrivateWinRT::handleCharacteristicChanged( + quint16 charHandle, const QByteArray &data) +{ + qCDebug(QT_BT_WINDOWS) << __FUNCTION__ << charHandle << data; + qCDebug(QT_BT_WINDOWS_SERVICE_THREAD) << __FUNCTION__ << "Changing service pointer from thread" + << QThread::currentThread(); + QSharedPointer service = + serviceForHandle(charHandle); + if (service.isNull()) + return; + + qCDebug(QT_BT_WINDOWS) << "Characteristic change notification" << service->uuid + << charHandle << data.toHex(); + + QLowEnergyCharacteristic characteristic = characteristicForHandle(charHandle); + if (!characteristic.isValid()) { + qCWarning(QT_BT_WINDOWS) << "characteristicChanged: Cannot find characteristic"; + return; + } + + // only update cache when property is readable. Otherwise it remains + // empty. + if (characteristic.properties() & QLowEnergyCharacteristic::Read) + updateValueOfCharacteristic(characteristic.attributeHandle(), + data, false); + emit service->characteristicChanged(characteristic, data); +} + +void QLowEnergyControllerPrivateWinRT::handleServiceHandlerError(const QString &error) +{ + if (state != QLowEnergyController::DiscoveringState) + return; + + qCWarning(QT_BT_WINDOWS) << "Error while discovering services:" << error; + setState(QLowEnergyController::UnconnectedState); + setError(QLowEnergyController::ConnectionError); +} + +void QLowEnergyControllerPrivateWinRT::handleConnectionError(const char *logMessage) +{ + qCWarning(QT_BT_WINDOWS) << logMessage; + setError(QLowEnergyController::ConnectionError); + setState(QLowEnergyController::UnconnectedState); + unregisterFromStatusChanges(); + unregisterFromMtuChanges(); +} + +QT_END_NAMESPACE + +#include "qlowenergycontroller_winrt.moc" diff --git a/src/bluetooth/qlowenergycontroller_winrt_p.h b/src/bluetooth/qlowenergycontroller_winrt_p.h new file mode 100644 index 0000000..dc9c323 --- /dev/null +++ b/src/bluetooth/qlowenergycontroller_winrt_p.h @@ -0,0 +1,184 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QLOWENERGYCONTROLLERPRIVATEWINRT_P_H +#define QLOWENERGYCONTROLLERPRIVATEWINRT_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 "qlowenergycontroller.h" +#include "qlowenergycontrollerbase_p.h" + +namespace ABI { + namespace Windows { + namespace Devices { + namespace Bluetooth { + struct IBluetoothLEDevice; + } + } + namespace Foundation { + template struct IAsyncOperation; + enum class AsyncStatus; + } + } +} + +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +class QLowEnergyServiceData; +class QTimer; + +extern void registerQLowEnergyControllerMetaType(); + +class QLowEnergyControllerPrivateWinRT final : public QLowEnergyControllerPrivate +{ + Q_OBJECT +public: + QLowEnergyControllerPrivateWinRT(); + ~QLowEnergyControllerPrivateWinRT() override; + + void init() override; + + void connectToDevice() override; + void disconnectFromDevice() override; + + void discoverServices() override; + void discoverServiceDetails(const QBluetoothUuid &service, + QLowEnergyService::DiscoveryMode mode) override; + + void startAdvertising(const QLowEnergyAdvertisingParameters ¶ms, + const QLowEnergyAdvertisingData &advertisingData, + const QLowEnergyAdvertisingData &scanResponseData) override; + void stopAdvertising() override; + + void requestConnectionUpdate(const QLowEnergyConnectionParameters ¶ms) override; + + // read data + void readCharacteristic(const QSharedPointer service, + const QLowEnergyHandle charHandle) override; + void readDescriptor(const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle) override; + + // write data + void writeCharacteristic(const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QByteArray &newValue, QLowEnergyService::WriteMode mode) override; + void writeDescriptor(const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle, + const QByteArray &newValue) override; + + void addToGenericAttributeList(const QLowEnergyServiceData &service, + QLowEnergyHandle startHandle) override; + + int mtu() const override; + +signals: + void characteristicChanged(quint16 charHandle, const QByteArray &data); + void abortConnection(); + +private slots: + void handleCharacteristicChanged(quint16 charHandle, const QByteArray &data); + void handleServiceHandlerError(const QString &error); + +private: + void handleConnectionError(const char *logMessage); + + Microsoft::WRL::ComPtr mDevice; + Microsoft::WRL::ComPtr + mGattSession; + EventRegistrationToken mStatusChangedToken; + EventRegistrationToken mMtuChangedToken; + struct ValueChangedEntry { + ValueChangedEntry() {} + ValueChangedEntry(Microsoft::WRL::ComPtr c, + EventRegistrationToken t) + : characteristic(c) + , token(t) + { + } + + Microsoft::WRL::ComPtr characteristic; + EventRegistrationToken token; + }; + QList mValueChangedTokens; + + using GattDeviceServiceComPtr = Microsoft::WRL::ComPtr; + QMap m_openedServices; + QSet m_requestDetailsServiceUuids; + + using NativeServiceCallback = std::function; + HRESULT getNativeService(const QBluetoothUuid &serviceUuid, NativeServiceCallback callback); + + using GattCharacteristicComPtr = Microsoft::WRL::ComPtr; + using NativeCharacteristicCallback = std::function; + HRESULT getNativeCharacteristic(const QBluetoothUuid &serviceUuid, + const QBluetoothUuid &charUuid, + NativeCharacteristicCallback callback); + + void registerForValueChanges(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid); + void unregisterFromValueChanges(); + HRESULT onValueChange(ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattCharacteristic *characteristic, + ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattValueChangedEventArgs *args); + HRESULT onMtuChange(ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattSession *session, + IInspectable *args); + bool registerForMtuChanges(); + void unregisterFromMtuChanges(); + + bool registerForStatusChanges(); + void unregisterFromStatusChanges(); + HRESULT onStatusChange(ABI::Windows::Devices::Bluetooth::IBluetoothLEDevice *dev, IInspectable *); + + void obtainIncludedServices(QSharedPointer servicePointer, + Microsoft::WRL::ComPtr nativeService); + HRESULT onServiceDiscoveryFinished(ABI::Windows::Foundation::IAsyncOperation *op, + ABI::Windows::Foundation::AsyncStatus status); + + void readCharacteristicHelper(const QSharedPointer service, + const QLowEnergyHandle charHandle, + GattCharacteristicComPtr characteristic); + void readDescriptorHelper(const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle, + GattCharacteristicComPtr characteristic); + void writeCharacteristicHelper(const QSharedPointer service, + const QLowEnergyHandle charHandle, const QByteArray &newValue, + bool writeWithResponse, + GattCharacteristicComPtr characteristic); + void writeDescriptorHelper(const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle, + const QByteArray &newValue, + GattCharacteristicComPtr characteristic); + void discoverServiceDetailsHelper(const QBluetoothUuid &service, + QLowEnergyService::DiscoveryMode mode, + GattDeviceServiceComPtr deviceService); + + void clearAllServices(); + void closeAndRemoveService(const QBluetoothUuid &uuid); +}; + +QT_END_NAMESPACE + +#endif // QLOWENERGYCONTROLLERPRIVATEWINRT_P_H diff --git a/src/bluetooth/qlowenergycontrollerbase.cpp b/src/bluetooth/qlowenergycontrollerbase.cpp new file mode 100644 index 0000000..6907403 --- /dev/null +++ b/src/bluetooth/qlowenergycontrollerbase.cpp @@ -0,0 +1,309 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qlowenergycontrollerbase_p.h" + +#include + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT) + +QLowEnergyControllerPrivate::QLowEnergyControllerPrivate() + : QObject() +{ +} + +QLowEnergyControllerPrivate::~QLowEnergyControllerPrivate() +{ +} + +bool QLowEnergyControllerPrivate::isValidLocalAdapter() +{ +#if defined(QT_WINRT_BLUETOOTH) || defined(Q_OS_DARWIN) + return true; +#endif + if (localAdapter.isNull()) + return false; + + const QList foundAdapters = QBluetoothLocalDevice::allDevices(); + bool adapterFound = false; + + for (const QBluetoothHostInfo &info : foundAdapters) { + if (info.address() == localAdapter) { + adapterFound = true; + break; + } + } + + return adapterFound; +} + + +void QLowEnergyControllerPrivate::setError( + QLowEnergyController::Error newError) +{ + Q_Q(QLowEnergyController); + error = newError; + + switch (newError) { + case QLowEnergyController::UnknownRemoteDeviceError: + errorString = QLowEnergyController::tr("Remote device cannot be found"); + break; + case QLowEnergyController::InvalidBluetoothAdapterError: + errorString = QLowEnergyController::tr("Cannot find local adapter"); + break; + case QLowEnergyController::NetworkError: + errorString = QLowEnergyController::tr("Error occurred during connection I/O"); + break; + case QLowEnergyController::ConnectionError: + errorString = QLowEnergyController::tr("Error occurred trying to connect to remote device."); + break; + case QLowEnergyController::AdvertisingError: + errorString = QLowEnergyController::tr("Error occurred trying to start advertising"); + break; + case QLowEnergyController::RemoteHostClosedError: + errorString = QLowEnergyController::tr("Remote device closed the connection"); + break; + case QLowEnergyController::AuthorizationError: + errorString = QLowEnergyController::tr("Failed to authorize on the remote device"); + break; + case QLowEnergyController::MissingPermissionsError: + errorString = QLowEnergyController::tr("Missing permissions error"); + break; + case QLowEnergyController::RssiReadError: + errorString = QLowEnergyController::tr("Error reading RSSI value"); + break; + case QLowEnergyController::NoError: + return; + default: + case QLowEnergyController::UnknownError: + errorString = QLowEnergyController::tr("Unknown Error"); + break; + } + + emit q->errorOccurred(newError); +} + +void QLowEnergyControllerPrivate::setState( + QLowEnergyController::ControllerState newState) +{ + qCDebug(QT_BT) << "QLowEnergyControllerPrivate setting state to" << newState; + Q_Q(QLowEnergyController); + if (state == newState) + return; + + state = newState; + if (state == QLowEnergyController::UnconnectedState + && role == QLowEnergyController::PeripheralRole) { + remoteDevice.clear(); + } + emit q->stateChanged(state); +} + +QSharedPointer QLowEnergyControllerPrivate::serviceForHandle( + QLowEnergyHandle handle) +{ + ServiceDataMap ¤tList = serviceList; + if (role == QLowEnergyController::PeripheralRole) + currentList = localServices; + + const QList> values = currentList.values(); + for (auto service: values) + if (service->startHandle <= handle && handle <= service->endHandle) + return service; + + return QSharedPointer(); +} + +/*! + Returns a valid characteristic if the given handle is the + handle of the characteristic itself or one of its descriptors + */ +QLowEnergyCharacteristic QLowEnergyControllerPrivate::characteristicForHandle( + QLowEnergyHandle handle) +{ + QSharedPointer service = serviceForHandle(handle); + if (service.isNull()) + return QLowEnergyCharacteristic(); + + if (service->characteristicList.isEmpty()) + return QLowEnergyCharacteristic(); + + // check whether it is the handle of a characteristic header + if (service->characteristicList.contains(handle)) + return QLowEnergyCharacteristic(service, handle); + + // check whether it is the handle of the characteristic value or its descriptors + QList charHandles = service->characteristicList.keys(); + std::sort(charHandles.begin(), charHandles.end()); + for (qsizetype i = charHandles.size() - 1; i >= 0; --i) { + if (charHandles.at(i) > handle) + continue; + + return QLowEnergyCharacteristic(service, charHandles.at(i)); + } + + return QLowEnergyCharacteristic(); +} + +/*! + Returns a valid descriptor if \a handle belongs to a descriptor; + otherwise an invalid one. + */ +QLowEnergyDescriptor QLowEnergyControllerPrivate::descriptorForHandle( + QLowEnergyHandle handle) +{ + const QLowEnergyCharacteristic matchingChar = characteristicForHandle(handle); + if (!matchingChar.isValid()) + return QLowEnergyDescriptor(); + + const QLowEnergyServicePrivate::CharData charData = matchingChar. + d_ptr->characteristicList[matchingChar.attributeHandle()]; + + if (charData.descriptorList.contains(handle)) + return QLowEnergyDescriptor(matchingChar.d_ptr, matchingChar.attributeHandle(), + handle); + + return QLowEnergyDescriptor(); +} + +/*! + Returns the length of the updated characteristic value. + */ +quint16 QLowEnergyControllerPrivate::updateValueOfCharacteristic( + QLowEnergyHandle charHandle,const QByteArray &value, bool appendValue) +{ + QSharedPointer service = serviceForHandle(charHandle); + if (!service.isNull()) { + CharacteristicDataMap::iterator charIt = service->characteristicList.find(charHandle); + if (charIt != service->characteristicList.end()) { + QLowEnergyServicePrivate::CharData &charDetails = charIt.value(); + + if (appendValue) + charDetails.value += value; + else + charDetails.value = value; + + return charDetails.value.size(); + } + } + + return 0; +} + +/*! + Returns the length of the updated descriptor value. + */ +quint16 QLowEnergyControllerPrivate::updateValueOfDescriptor( + QLowEnergyHandle charHandle, QLowEnergyHandle descriptorHandle, + const QByteArray &value, bool appendValue) +{ + QSharedPointer service = serviceForHandle(charHandle); + if (!service.isNull()) { + CharacteristicDataMap::iterator charIt = service->characteristicList.find(charHandle); + if (charIt != service->characteristicList.end()) { + QLowEnergyServicePrivate::CharData &charDetails = charIt.value(); + + DescriptorDataMap::iterator descIt = charDetails.descriptorList.find(descriptorHandle); + if (descIt != charDetails.descriptorList.end()) { + QLowEnergyServicePrivate::DescData &descDetails = descIt.value(); + + if (appendValue) + descDetails.value += value; + else + descDetails.value = value; + + return descDetails.value.size(); + } + } + } + + return 0; +} + +void QLowEnergyControllerPrivate::invalidateServices() +{ + for (QSharedPointer service : serviceList.values()) + service->setController(nullptr); + + for (QSharedPointer service : localServices.values()) + service->setController(nullptr); + + serviceList.clear(); + localServices.clear(); + lastLocalHandle = {}; +} + +QLowEnergyService *QLowEnergyControllerPrivate::addServiceHelper( + const QLowEnergyServiceData &service) +{ + // Spec says services "should" be grouped by uuid length (16-bit first, then 128-bit). + // Since this is not mandatory, we ignore it here and let the caller take responsibility + // for it. + + const auto servicePrivate = QSharedPointer::create(); + servicePrivate->setController(this); + servicePrivate->state = QLowEnergyService::LocalService; + servicePrivate->uuid = service.uuid(); + servicePrivate->type = service.type() == QLowEnergyServiceData::ServiceTypePrimary + ? QLowEnergyService::PrimaryService : QLowEnergyService::IncludedService; + const QList includedServices = service.includedServices(); + for (QLowEnergyService * const includedService : includedServices) { + servicePrivate->includedServices << includedService->serviceUuid(); + includedService->d_ptr->type |= QLowEnergyService::IncludedService; + } + + // Spec v4.2, Vol 3, Part G, Section 3. + const QLowEnergyHandle oldLastHandle = this->lastLocalHandle; + servicePrivate->startHandle = ++this->lastLocalHandle; // Service declaration. + this->lastLocalHandle += servicePrivate->includedServices.size(); // Include declarations. + const QList characteristics = service.characteristics(); + for (const QLowEnergyCharacteristicData &cd : characteristics) { + const QLowEnergyHandle declHandle = ++this->lastLocalHandle; + QLowEnergyServicePrivate::CharData charData; + charData.valueHandle = ++this->lastLocalHandle; + charData.uuid = cd.uuid(); + charData.properties = cd.properties(); + charData.value = cd.value(); + const QList descriptors = cd.descriptors(); + for (const QLowEnergyDescriptorData &dd : descriptors) { + QLowEnergyServicePrivate::DescData descData; + descData.uuid = dd.uuid(); + descData.value = dd.value(); + charData.descriptorList.insert(++this->lastLocalHandle, descData); + } + servicePrivate->characteristicList.insert(declHandle, charData); + } + servicePrivate->endHandle = this->lastLocalHandle; + const bool handleOverflow = this->lastLocalHandle <= oldLastHandle; + if (handleOverflow) { + qCWarning(QT_BT) << "Not enough attribute handles left to create this service"; + this->lastLocalHandle = oldLastHandle; + return nullptr; + } + + if (localServices.contains(servicePrivate->uuid)) { + qCWarning(QT_BT) << "Overriding existing local service with uuid" + << servicePrivate->uuid; + } + this->localServices.insert(servicePrivate->uuid, servicePrivate); + + this->addToGenericAttributeList(service, servicePrivate->startHandle); + return new QLowEnergyService(servicePrivate); +} + +void QLowEnergyControllerPrivate::readRssi() +{ + qCWarning(QT_BT, "This platform does not support reading RSSI"); + setError(QLowEnergyController::RssiReadError); +} + +QT_END_NAMESPACE + +#include "moc_qlowenergycontrollerbase_p.cpp" diff --git a/src/bluetooth/qlowenergycontrollerbase_p.h b/src/bluetooth/qlowenergycontrollerbase_p.h new file mode 100644 index 0000000..0b18e6e --- /dev/null +++ b/src/bluetooth/qlowenergycontrollerbase_p.h @@ -0,0 +1,133 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QLOWENERGYCONTROLLERPRIVATEBASE_P_H +#define QLOWENERGYCONTROLLERPRIVATEBASE_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 "qlowenergyserviceprivate_p.h" + +QT_BEGIN_NAMESPACE + +typedef QMap > ServiceDataMap; + +class QLowEnergyControllerPrivate : public QObject +{ + Q_OBJECT +public: + // This class is required to enable selection of multiple + // alternative QLowEnergyControllerPrivate implementations on BlueZ. + // Bluez has a low level ATT protocol stack implementation and a DBus + // implementation. + + QLowEnergyControllerPrivate(); + virtual ~QLowEnergyControllerPrivate(); + + // interface definition + virtual void init() = 0; + virtual void connectToDevice() = 0; + virtual void disconnectFromDevice() = 0; + + virtual void discoverServices() = 0; + virtual void discoverServiceDetails(const QBluetoothUuid &service, + QLowEnergyService::DiscoveryMode mode) = 0; + + virtual void readCharacteristic( + const QSharedPointer service, + const QLowEnergyHandle charHandle) = 0; + virtual void readDescriptor( + const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle) = 0; + + virtual void writeCharacteristic( + const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QByteArray &newValue, + QLowEnergyService::WriteMode writeMode) = 0; + virtual void writeDescriptor( + const QSharedPointer service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle, + const QByteArray &newValue) = 0; + + virtual void startAdvertising( + const QLowEnergyAdvertisingParameters ¶ms, + const QLowEnergyAdvertisingData &advertisingData, + const QLowEnergyAdvertisingData &scanResponseData) = 0; + virtual void stopAdvertising() = 0; + + virtual void requestConnectionUpdate( + const QLowEnergyConnectionParameters & params) = 0; + virtual void addToGenericAttributeList( + const QLowEnergyServiceData &service, + QLowEnergyHandle startHandle) = 0; + + virtual int mtu() const = 0; + virtual void readRssi(); + + virtual QLowEnergyService *addServiceHelper( + const QLowEnergyServiceData &service); + + // common backend methods + bool isValidLocalAdapter(); + void setError(QLowEnergyController::Error newError); + void setState(QLowEnergyController::ControllerState newState); + + // public variables + QLowEnergyController::Role role; + QLowEnergyController::RemoteAddressType addressType; + + // list of all found service uuids on remote device + ServiceDataMap serviceList; + // list of all found service uuids on local peripheral device + ServiceDataMap localServices; + + //common helper functions + QSharedPointer serviceForHandle(QLowEnergyHandle handle); + QLowEnergyCharacteristic characteristicForHandle(QLowEnergyHandle handle); + QLowEnergyDescriptor descriptorForHandle(QLowEnergyHandle handle); + quint16 updateValueOfCharacteristic(QLowEnergyHandle charHandle, + const QByteArray &value, + bool appendValue); + quint16 updateValueOfDescriptor(QLowEnergyHandle charHandle, + QLowEnergyHandle descriptorHandle, + const QByteArray &value, + bool appendValue); + void invalidateServices(); + +protected: + QLowEnergyController::ControllerState state = QLowEnergyController::UnconnectedState; + QLowEnergyController::Error error = QLowEnergyController::NoError; + QString errorString; + + QBluetoothAddress remoteDevice; + QBluetoothAddress localAdapter; + + QLowEnergyHandle lastLocalHandle{}; + + QString remoteName; // device name of the remote + QBluetoothUuid deviceUuid; // quite useless anywhere but Darwin (CoreBluetooth). + + Q_DECLARE_PUBLIC(QLowEnergyController) + QLowEnergyController *q_ptr; +}; + +QT_END_NAMESPACE + +#endif // QLOWENERGYCONTROLLERPRIVATEBASE_P_H diff --git a/src/bluetooth/qlowenergydescriptor.cpp b/src/bluetooth/qlowenergydescriptor.cpp new file mode 100644 index 0000000..04f5117 --- /dev/null +++ b/src/bluetooth/qlowenergydescriptor.cpp @@ -0,0 +1,297 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2016 BlackBerry Limited. All rights reserved. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include +#include "qlowenergyserviceprivate_p.h" +#include "qlowenergydescriptor.h" + +QT_BEGIN_NAMESPACE + +QT_IMPL_METATYPE_EXTERN(QLowEnergyDescriptor) + +/*! + \class QLowEnergyDescriptor + \inmodule QtBluetooth + \brief The QLowEnergyDescriptor class stores information about the Bluetooth + Low Energy descriptor. + \since 5.4 + + QLowEnergyDescriptor provides information about a Bluetooth Low Energy + descriptor's name(), uuid(), and value(). Descriptors are + encapsulated by Bluetooth Low Energy characteristics and provide additional + contextual information about the characteristic (data format, notification activation + and so on). + + The descriptor value may be written via the QLowEnergyService instance + that manages the service to which this descriptor belongs. The + \l {QLowEnergyService::writeDescriptor()} function writes the new value. + The \l {QLowEnergyService::descriptorWritten()} signal + is emitted upon success. The cached value() of this object is updated accordingly. + + \sa QLowEnergyService, QLowEnergyCharacteristic +*/ + +struct QLowEnergyDescriptorPrivate +{ + QLowEnergyHandle charHandle; + QLowEnergyHandle descHandle; +}; + +/*! + Construct a new QLowEnergyDescriptor. A default-constructed instance + of this class is always invalid. +*/ +QLowEnergyDescriptor::QLowEnergyDescriptor(): + d_ptr(nullptr) +{ +} + +/*! + Construct a new QLowEnergyDescriptor that is a copy of \a other. + + The two copies continue to share the same underlying data which does not detach + upon write. +*/ +QLowEnergyDescriptor::QLowEnergyDescriptor(const QLowEnergyDescriptor &other): + d_ptr(other.d_ptr) +{ + if (other.data) { + data = new QLowEnergyDescriptorPrivate(); + data->charHandle = other.data->charHandle; + data->descHandle = other.data->descHandle; + } +} + +/*! + \internal + +*/ +QLowEnergyDescriptor::QLowEnergyDescriptor(QSharedPointer p, + QLowEnergyHandle charHandle, + QLowEnergyHandle descHandle): + d_ptr(p) +{ + data = new QLowEnergyDescriptorPrivate(); + data->charHandle = charHandle; + data->descHandle = descHandle; + +} + +/*! + Destroys the QLowEnergyDescriptor object. +*/ +QLowEnergyDescriptor::~QLowEnergyDescriptor() +{ + delete data; +} + +/*! + Makes a copy of \a other and assigns it to this QLowEnergyDescriptor object. + The two copies continue to share the same service and controller details. +*/ +QLowEnergyDescriptor &QLowEnergyDescriptor::operator=(const QLowEnergyDescriptor &other) +{ + d_ptr = other.d_ptr; + + if (!other.data) { + if (data) { + delete data; + data = nullptr; + } + } else { + if (!data) + data = new QLowEnergyDescriptorPrivate(); + + data->charHandle = other.data->charHandle; + data->descHandle = other.data->descHandle; + } + + return *this; +} + +/*! + \fn bool QLowEnergyDescriptor::operator==(const QLowEnergyDescriptor &a, + const QLowEnergyDescriptor &b) + \brief Returns \c true if \a a is equal to \a b; otherwise \c false. + + Two QLowEnergyDescriptor instances are considered to be equal if they refer to + the same descriptor on the same remote Bluetooth Low Energy device or both + instances have been default-constructed. + */ + +/*! + \fn bool QLowEnergyDescriptor::operator!=(const QLowEnergyDescriptor &a, + const QLowEnergyDescriptor &b) + \brief Returns \c true if \a a is not equal to \a b; otherwise \c false. + + Two QLowEnergyDescriptor instances are considered to be equal if they refer to + the same descriptor on the same remote Bluetooth Low Energy device or both + instances have been default-constructed. + */ + +/*! + \brief Returns \c true if \a other is equal to this QLowEnergyCharacteristic, + otherwise \c false. + \internal + + Two QLowEnergyDescriptor instances are considered to be equal if they refer to + the same descriptor on the same remote Bluetooth Low Energy device or both + instances have been default-constructed. + */ +bool QLowEnergyDescriptor::equals(const QLowEnergyDescriptor &a, const QLowEnergyDescriptor &b) +{ + if (a.d_ptr != b.d_ptr) + return false; + + if ((a.data && !b.data) || (!a.data && b.data)) + return false; + + if (!a.data) + return true; + + if (a.data->charHandle != b.data->charHandle || a.data->descHandle != b.data->descHandle) { + return false; + } + + return true; +} + +/*! + Returns \c true if the QLowEnergyDescriptor object is valid, otherwise returns \c false. + + An invalid descriptor instance is not associated with any service (default-constructed) + or the associated service is no longer valid due to a disconnect from + the underlying Bluetooth Low Energy device, for example. Once the object is invalid + it cannot become valid anymore. + + \note If a QLowEnergyDescriptor instance turns invalid due to a disconnect + from the underlying device, the information encapsulated by the current + instance remains as it was at the time of the disconnect. Therefore it can be + retrieved after the disconnect event. +*/ +bool QLowEnergyDescriptor::isValid() const +{ + if (d_ptr.isNull() || !data) + return false; + + if (d_ptr->state == QLowEnergyService::InvalidService) + return false; + + return true; +} + +/*! + Returns the UUID of this descriptor if \l isValid() returns \c true; otherwise a + \l {QUuid::isNull()}{null} UUID. +*/ +QBluetoothUuid QLowEnergyDescriptor::uuid() const +{ + if (d_ptr.isNull() || !data + || !d_ptr->characteristicList.contains(data->charHandle) + || !d_ptr->characteristicList[data->charHandle]. + descriptorList.contains(data->descHandle)) { + return QBluetoothUuid(); + } + + return d_ptr->characteristicList[data->charHandle].descriptorList[data->descHandle].uuid; +} + +/*! + \internal + + Returns the handle of the descriptor or \c 0 if the handle + cannot be accessed on the platform or the descriptor is invalid. + + \note On \macos and iOS handles can differ from 0, but these + values have no special meaning outside of internal/private API. +*/ +QLowEnergyHandle QLowEnergyDescriptor::handle() const +{ + if (!data) + return 0; + + return data->descHandle; +} + +/*! + Returns the cached value of the descriptor. + + The cached descriptor value may be updated using + \l QLowEnergyService::writeDescriptor() or \l QLowEnergyService::readDescriptor(). +*/ +QByteArray QLowEnergyDescriptor::value() const +{ + if (d_ptr.isNull() || !data + || !d_ptr->characteristicList.contains(data->charHandle) + || !d_ptr->characteristicList[data->charHandle]. + descriptorList.contains(data->descHandle)) { + return QByteArray(); + } + + return d_ptr->characteristicList[data->charHandle].descriptorList[data->descHandle].value; +} + +/*! + Returns the human-readable name of the descriptor. + + The name is based on the descriptor's \l type(). The complete list + of descriptor types can be found under + \l {https://developer.bluetooth.org/gatt/descriptors/Pages/DescriptorsHomePage.aspx}{Bluetooth.org Descriptors}. + + The returned string is empty if the \l type() is unknown. + + \sa type(), QBluetoothUuid::descriptorToString() +*/ + +QString QLowEnergyDescriptor::name() const +{ + return QBluetoothUuid::descriptorToString(type()); +} + +/*! + Returns the type of the descriptor. + + \sa name() + */ +QBluetoothUuid::DescriptorType QLowEnergyDescriptor::type() const +{ + const QBluetoothUuid u = uuid(); + bool ok = false; + QBluetoothUuid::DescriptorType shortUuid = static_cast(u.toUInt16(&ok)); + + if (!ok) + return QBluetoothUuid::DescriptorType::UnknownDescriptorType; + + switch (shortUuid) { + case QBluetoothUuid::DescriptorType::CharacteristicExtendedProperties: + case QBluetoothUuid::DescriptorType::CharacteristicUserDescription: + case QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration: + case QBluetoothUuid::DescriptorType::ServerCharacteristicConfiguration: + case QBluetoothUuid::DescriptorType::CharacteristicPresentationFormat: + case QBluetoothUuid::DescriptorType::CharacteristicAggregateFormat: + case QBluetoothUuid::DescriptorType::ValidRange: + case QBluetoothUuid::DescriptorType::ExternalReportReference: + case QBluetoothUuid::DescriptorType::ReportReference: + return (QBluetoothUuid::DescriptorType) shortUuid; + default: + break; + } + + return QBluetoothUuid::DescriptorType::UnknownDescriptorType; +} + +/*! + \internal + + Returns the handle of the characteristic to which this descriptor belongs + */ +QLowEnergyHandle QLowEnergyDescriptor::characteristicHandle() const +{ + if (d_ptr.isNull() || !data) + return 0; + + return data->charHandle; +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/qlowenergydescriptor.h b/src/bluetooth/qlowenergydescriptor.h new file mode 100644 index 0000000..37f2216 --- /dev/null +++ b/src/bluetooth/qlowenergydescriptor.h @@ -0,0 +1,71 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2016 BlackBerry Limited. All rights reserved. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QLOWENERGYDESCRIPTOR_H +#define QLOWENERGYDESCRIPTOR_H + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +struct QLowEnergyDescriptorPrivate; +class QLowEnergyServicePrivate; + +class Q_BLUETOOTH_EXPORT QLowEnergyDescriptor +{ +public: + QLowEnergyDescriptor(); + QLowEnergyDescriptor(const QLowEnergyDescriptor &other); + ~QLowEnergyDescriptor(); + + QLowEnergyDescriptor &operator=(const QLowEnergyDescriptor &other); + friend bool operator==(const QLowEnergyDescriptor &a, const QLowEnergyDescriptor &b) + { + return equals(a, b); + } + friend bool operator!=(const QLowEnergyDescriptor &a, const QLowEnergyDescriptor &b) + { + return !equals(a, b); + } + + bool isValid() const; + + QByteArray value() const; + + QBluetoothUuid uuid() const; + QString name() const; + + QBluetoothUuid::DescriptorType type() const; + +private: + QLowEnergyHandle handle() const; + QLowEnergyHandle characteristicHandle() const; + QSharedPointer d_ptr; + + friend class QLowEnergyCharacteristic; + friend class QLowEnergyService; + friend class QLowEnergyControllerPrivate; + friend class QLowEnergyControllerPrivateAndroid; + friend class QLowEnergyControllerPrivateBluez; + friend class QLowEnergyControllerPrivateBluezDBus; + friend class QLowEnergyControllerPrivateCommon; + friend class QLowEnergyControllerPrivateDarwin; + friend class QLowEnergyControllerPrivateWinRT; + QLowEnergyDescriptorPrivate *data = nullptr; + + QLowEnergyDescriptor(QSharedPointer p, + QLowEnergyHandle charHandle, + QLowEnergyHandle descHandle); + + static bool equals(const QLowEnergyDescriptor &a, const QLowEnergyDescriptor &b); +}; + +QT_END_NAMESPACE + +QT_DECL_METATYPE_EXTERN(QLowEnergyDescriptor, Q_BLUETOOTH_EXPORT) + +#endif // QLOWENERGYDESCRIPTOR_H diff --git a/src/bluetooth/qlowenergydescriptordata.cpp b/src/bluetooth/qlowenergydescriptordata.cpp new file mode 100644 index 0000000..34e8c85 --- /dev/null +++ b/src/bluetooth/qlowenergydescriptordata.cpp @@ -0,0 +1,201 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qlowenergydescriptordata.h" + +#include + +QT_BEGIN_NAMESPACE + +struct QLowEnergyDescriptorDataPrivate : public QSharedData +{ + QLowEnergyDescriptorDataPrivate() : readable(true), writable(true) {} + + QBluetoothUuid uuid; + QByteArray value; + QBluetooth::AttAccessConstraints readConstraints; + QBluetooth::AttAccessConstraints writeConstraints; + bool readable; + bool writable; +}; + +/*! + \since 5.7 + \class QLowEnergyDescriptorData + \brief The QLowEnergyDescriptorData class is used to create GATT service data. + \inmodule QtBluetooth + \ingroup shared + + An object of this class provides a descriptor to be added to a + \l QLowEnergyCharacteristicData object via \l QLowEnergyCharacteristicData::addDescriptor(). + + \note The member functions related to access permissions are only applicable to those + types of descriptors for which the Bluetooth specification does not prescribe if + and how their values can be accessed. + + \sa QLowEnergyCharacteristicData + \sa QLowEnergyServiceData + \sa QLowEnergyController::addService +*/ + +/*! Creates a new invalid object of this class. */ +QLowEnergyDescriptorData::QLowEnergyDescriptorData() : d(new QLowEnergyDescriptorDataPrivate) +{ +} + +/*! + Creates a new object of this class with UUID and value being provided by \a uuid and \a value, + respectively. + */ +QLowEnergyDescriptorData::QLowEnergyDescriptorData(const QBluetoothUuid &uuid, + const QByteArray &value) + : d(new QLowEnergyDescriptorDataPrivate) +{ + setUuid(uuid); + setValue(value); +} + +/*! Constructs a new object of this class that is a copy of \a other. */ +QLowEnergyDescriptorData::QLowEnergyDescriptorData(const QLowEnergyDescriptorData &other) + : d(other.d) +{ +} + +/*! Destroys this object. */ +QLowEnergyDescriptorData::~QLowEnergyDescriptorData() +{ +} + +/*! Makes this object a copy of \a other and returns the new value of this object. */ +QLowEnergyDescriptorData &QLowEnergyDescriptorData::operator=(const QLowEnergyDescriptorData &other) +{ + d = other.d; + return *this; +} + +/*! Returns the value of this descriptor. */ +QByteArray QLowEnergyDescriptorData::value() const +{ + return d->value; +} + +/*! + Sets the value of this descriptor to \a value. It will be sent to a peer device + exactly the way it is provided here, so callers need to take care of things such as endianness. + */ +void QLowEnergyDescriptorData::setValue(const QByteArray &value) +{ + d->value = value; +} + +/*! Returns the UUID of this descriptor. */ +QBluetoothUuid QLowEnergyDescriptorData::uuid() const +{ + return d->uuid; +} + +/*! Sets the UUID of this descriptor to \a uuid. */ +void QLowEnergyDescriptorData::setUuid(const QBluetoothUuid &uuid) +{ + d->uuid = uuid; +} + +/*! Returns true if and only if this object has a non-null UUID. */ +bool QLowEnergyDescriptorData::isValid() const +{ + return !uuid().isNull(); +} + +/*! + Specifies whether the value of this descriptor is \a readable and if so, under which + \a constraints. + \sa setWritePermissions() + */ +void QLowEnergyDescriptorData::setReadPermissions(bool readable, + QBluetooth::AttAccessConstraints constraints) +{ + d->readable = readable; + d->readConstraints = constraints; +} + +/*! Returns \c true if the value of this descriptor is readable and \c false otherwise. */ +bool QLowEnergyDescriptorData::isReadable() const +{ + return d->readable; +} + +/*! + Returns the constraints under which the value of this descriptor can be read. This value + is only relevant if \l isReadable() returns \c true. + */ +QBluetooth::AttAccessConstraints QLowEnergyDescriptorData::readConstraints() const +{ + return d->readConstraints; +} + +/*! + Specifies whether the value of this descriptor is \a writable and if so, under which + \a constraints. + \sa setReadPermissions() + */ +void QLowEnergyDescriptorData::setWritePermissions(bool writable, + QBluetooth::AttAccessConstraints constraints) +{ + d->writable = writable; + d->writeConstraints = constraints; +} + +/*! Returns \c true if the value of this descriptor is writable and \c false otherwise. */ +bool QLowEnergyDescriptorData::isWritable() const +{ + return d->writable; +} + +/*! + Returns the constraints under which the value of this descriptor can be written. This value + is only relevant if \l isWritable() returns \c true. + */ +QBluetooth::AttAccessConstraints QLowEnergyDescriptorData::writeConstraints() const +{ + return d->writeConstraints; +} + +/*! + \fn void QLowEnergyDescriptorData::swap(QLowEnergyDescriptorData &other) + Swaps this object with \a other. + */ + +/*! + \fn bool QLowEnergyDescriptorData::operator==(const QLowEnergyDescriptorData &a, + const QLowEnergyDescriptorData &b) + + \brief Returns \c true if \a a and \a b are equal with respect to their public state, + otherwise returns \c false. + */ + +/*! + \fn bool QLowEnergyDescriptorData::operator!=(const QLowEnergyDescriptorData &a, + const QLowEnergyDescriptorData &b) + + \brief Returns \c true if \a a and \a b are unequal with respect to their public state, + otherwise returns \c false. + */ + +/*! + \brief Returns \c true if \a a and \a b are equal with respect to their public state, + otherwise returns \c false. + \internal + */ +bool QLowEnergyDescriptorData::equals(const QLowEnergyDescriptorData &a, + const QLowEnergyDescriptorData &b) +{ + return a.d == b.d || ( + a.uuid() == b.uuid() + && a.value() == b.value() + && a.isReadable() == b.isReadable() + && a.isWritable() == b.isWritable() + && a.readConstraints() == b.readConstraints() + && a.writeConstraints() == b.writeConstraints()); +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/qlowenergydescriptordata.h b/src/bluetooth/qlowenergydescriptordata.h new file mode 100644 index 0000000..7abd01e --- /dev/null +++ b/src/bluetooth/qlowenergydescriptordata.h @@ -0,0 +1,65 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QLOWENERGYDESCRIPTORDATA_H +#define QLOWENERGYDESCRIPTORDATA_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QByteArray; +struct QLowEnergyDescriptorDataPrivate; + +class Q_BLUETOOTH_EXPORT QLowEnergyDescriptorData +{ +public: + QLowEnergyDescriptorData(); + QLowEnergyDescriptorData(const QBluetoothUuid &uuid, + const QByteArray &value); + QLowEnergyDescriptorData(const QLowEnergyDescriptorData &other); + ~QLowEnergyDescriptorData(); + + QLowEnergyDescriptorData &operator=(const QLowEnergyDescriptorData &other); + friend bool operator==(const QLowEnergyDescriptorData &a, const QLowEnergyDescriptorData &b) + { + return equals(a, b); + } + + friend bool operator!=(const QLowEnergyDescriptorData &a, const QLowEnergyDescriptorData &b) + { + return !equals(a, b); + } + + QByteArray value() const; + void setValue(const QByteArray &value); + + QBluetoothUuid uuid() const; + void setUuid(const QBluetoothUuid &uuid); + + bool isValid() const; + + void setReadPermissions(bool readable, + QBluetooth::AttAccessConstraints constraints = QBluetooth::AttAccessConstraints()); + bool isReadable() const; + QBluetooth::AttAccessConstraints readConstraints() const; + + void setWritePermissions(bool writable, + QBluetooth::AttAccessConstraints constraints = QBluetooth::AttAccessConstraints()); + bool isWritable() const; + QBluetooth::AttAccessConstraints writeConstraints() const; + + void swap(QLowEnergyDescriptorData &other) noexcept { d.swap(other.d); } + +private: + static bool equals(const QLowEnergyDescriptorData &a, const QLowEnergyDescriptorData &b); + QSharedDataPointer d; +}; + +Q_DECLARE_SHARED(QLowEnergyDescriptorData) + +QT_END_NAMESPACE + +#endif // Include guard. diff --git a/src/bluetooth/qlowenergyservice.cpp b/src/bluetooth/qlowenergyservice.cpp new file mode 100644 index 0000000..eee75bd --- /dev/null +++ b/src/bluetooth/qlowenergyservice.cpp @@ -0,0 +1,852 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2016 Javier S. Pedro +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include +#include +#include + +#include + +#include "qlowenergycontrollerbase_p.h" +#include "qlowenergyserviceprivate_p.h" + +#ifdef Q_OS_DARWIN +#include "qlowenergycontroller_darwin_p.h" +#endif // Q_OS_DARWIN + +QT_BEGIN_NAMESPACE + +QT_IMPL_METATYPE_EXTERN_TAGGED(QLowEnergyService::ServiceError, QLowEnergyService__ServiceError) +QT_IMPL_METATYPE_EXTERN_TAGGED(QLowEnergyService::ServiceState, QLowEnergyService__ServiceState) +QT_IMPL_METATYPE_EXTERN_TAGGED(QLowEnergyService::ServiceType, QLowEnergyService__ServiceType) +QT_IMPL_METATYPE_EXTERN_TAGGED(QLowEnergyService::WriteMode, QLowEnergyService__WriteMode) + +/*! + \class QLowEnergyService + \inmodule QtBluetooth + \brief The QLowEnergyService class represents an individual service + on a Bluetooth Low Energy Device. + + \since 5.4 + + QLowEnergyService provides access to the details of Bluetooth Low Energy + services. The class facilitates the discovery and publification of + service details, permits reading and writing of the contained data + and notifies about data changes. + + \section1 Service Structure + + A Bluetooth Low Energy peripheral device can contain multiple services. + In turn each service may include further services. This class represents a + single service of the peripheral device and is created via + \l QLowEnergyController::createServiceObject(). The \l type() indicates + whether this service is a primary (top-level) service or whether the + service is part of another service. Each service may contain one or more + characteristics and each characteristic may contain descriptors. The + resulting structure may look like the following diagram: + + \image peripheral-structure.png Structure of a generic peripheral + + A characteristic is the principal information carrier. It has a + \l {QLowEnergyCharacteristic::value()}{value()} and + \l {QLowEnergyCharacteristic::value()}{properties()} + describing the access permissions for the value. The general purpose + of the contained descriptor is to further define the nature of the + characteristic. For example, it might specify how the value is meant to be + interpreted or whether it can notify the value consumer about value + changes. + + \section1 Service Interaction + + Once a service object was created for the first time, its details are yet to + be discovered. This is indicated by its current \l state() being \l DiscoveryRequired. + It is only possible to retrieve the \l serviceUuid() and \l serviceName(). + + The discovery of its included services, characteristics and descriptors + is triggered when calling \l discoverDetails(). During the discovery the + \l state() transitions from \l DiscoveryRequired via \l DiscoveringService + to its final \l ServiceDiscovered state. This transition is advertised via + the \l stateChanged() signal. Once the details are known, all of the contained + characteristics, descriptors and included services are known and can be read + or written. + + The values of characteristics and descriptors can be retrieved via + \l QLowEnergyCharacteristic and \l QLowEnergyDescriptor, respectively. + However, direct reading or writing of these attributes requires the service object. + The \l readCharacteristic() function attempts to re-read the value of a characteristic. + Although the initial service discovery may have obtained a value already this call may + be required in cases where the characteristic value constantly changes without + any notifications being provided. An example might be a time characteristic + that provides a continuous value. If the read attempt is successful, the + \l characteristicRead() signal is emitted. A failure to read the value triggers + the \l CharacteristicReadError. + The \l writeCharacteristic() function attempts to write a new value to the given + characteristic. If the write attempt is successful, the \l characteristicWritten() + signal is emitted. A failure to write triggers the \l CharacteristicWriteError. + Reading and writing of descriptors follows the same pattern. + + Every attempt is made to read or write the value of a descriptor + or characteristic on the hardware. This means that meta information such as + \l QLowEnergyCharacteristic::properties() is generally ignored when reading and writing. + As an example, it is possible to call \l writeCharacteristic() despite the characteristic + being read-only based on its meta data description. The resulting write request is + forwarded to the connected device and it is up to the device to respond to the + potentially invalid request. In this case the result is the emission of the + \l CharacteristicWriteError in response to the returned device error. This behavior + simplifies interaction with devices which report wrong meta information. + If it was not possible to forward the request to the remote device the + \l OperationError is set. A potential reason could be that the to-be-written + characteristic object does not even belong the current service. In + summary, the two types of errors permit a quick distinction of local + and remote error cases. + + All requests are serialised based on First-In First-Out principle. + For example, issuing a second write request, before the previous + write request has finished, is delayed until the first write request has finished. + + \note Currently, it is not possible to send signed write or reliable write requests. + + \target notifications + + In some cases the peripheral generates value updates which + the central is interested in receiving. In order for a characteristic to support + such notifications it must have the \l QLowEnergyCharacteristic::Notify or + \l QLowEnergyCharacteristic::Indicate property and a descriptor of type + \l QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration. Provided those conditions + are fulfilled notifications can be enabled as shown in the following code segment: + + \snippet doc_src_qtbluetooth.cpp enable_btle_notifications + + The example shows a battery level characteristic which updates the central + on every value change. The notifications are provided via + the \l characteristicChanged() signal. More details about this mechanism + are provided by the + \l {https://developer.bluetooth.org/gatt/descriptors/Pages/DescriptorViewer.aspx?u=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml}{Bluetooth Specification}. + + \section1 Service Data Sharing + + Each QLowEnergyService instance shares its internal states and information + with other QLowEnergyService instance of the same service. If one instance + initiates the discovery of the service details, all remaining instances + automatically follow. Therefore the following snippet always works: + + \snippet doc_src_qtbluetooth.cpp data_share_qlowenergyservice + + Other operations such as calls to \l readCharacteristic(), \l readDescriptor(), \l writeCharacteristic(), + \l writeDescriptor() or the invalidation of the service due to the + related \l QLowEnergyController disconnecting from the device are shared + the same way. + + \sa QLowEnergyController, QLowEnergyCharacteristic, QLowEnergyDescriptor + */ + +/*! + \enum QLowEnergyService::ServiceType + + This enum describes the type of the service. + + \value PrimaryService The service is a top-level/primary service. + If this type flag is not set, the service is considered + to be a secondary service. Each service may be included + by another service which is indicated by IncludedService. + \value IncludedService The service is included by another service. + On some platforms, this flag cannot be determined until + the service that includes the current service was + discovered. +*/ + +/*! + \enum QLowEnergyService::ServiceError + + This enum describes all possible error conditions during the service's + existence. The \l error() function returns the last occurred error. + + \value NoError No error has occurred. + \value OperationError An operation was attempted while the service was not ready. + An example might be the attempt to write to + the service while it was not yet in the + \l ServiceDiscovered \l state() or the service is invalid + due to a loss of connection to the peripheral device. + \value [since 5.5] CharacteristicReadError An attempt to read a characteristic value failed. + For example, it might be triggered in response + to a call to \l readCharacteristic(). + \value CharacteristicWriteError An attempt to write a new value to a characteristic + failed. For example, it might be triggered when attempting + to write to a read-only characteristic. + \value [since 5.5] DescriptorReadError An attempt to read a descriptor value failed. + For example, it might be triggered in response + to a call to \l readDescriptor(). + \value DescriptorWriteError An attempt to write a new value to a descriptor + failed. For example, it might be triggered when attempting + to write to a read-only descriptor. + \value [since 5.5] UnknownError An unknown error occurred when interacting with the service. + */ + +/*! + \enum QLowEnergyService::ServiceState + + This enum describes the \l state() of the service object. + + \value InvalidService A service can become invalid when it looses + the connection to the underlying device. Even though + the connection may be lost it retains its last information. + An invalid service cannot become valid anymore even if + the connection to the device is re-established. + \value RemoteService The service details are yet to be discovered + by calling \l discoverDetails(). + The only reliable pieces of information are its + \l serviceUuid() and \l serviceName(). + \value RemoteServiceDiscovering The service details are being discovered. + \value RemoteServiceDiscovered The service details have been discovered. + \value [since 5.7] LocalService The service is associated with a controller object in the + \l{QLowEnergyController::PeripheralRole}{peripheral role}. + Such service objects do not change their state. + \value DiscoveryRequired Deprecated. Was renamed to RemoteService. + \value DiscoveringService Deprecated. Was renamed to RemoteServiceDiscovering. + \value ServiceDiscovered Deprecated. Was renamed to RemoteServiceDiscovered. + */ + +/*! + \enum QLowEnergyService::DiscoveryMode + + This enum lists service discovery modes. + All modes discover the characteristics of the service and the descriptors + of the characteristics. The modes differ in whether characteristic values + and descriptors are read. + + \value FullDiscovery During a full discovery, all characteristics + are discovered. All characteristic values and + descriptors are read. + \value SkipValueDiscovery During a minimal discovery, all characteristics + are discovered. Characteristic values and + descriptors are not read. + + \sa discoverDetails() + \since 6.2 +*/ + +/*! + \enum QLowEnergyService::WriteMode + + This enum describes the mode to be used when writing a characteristic value. + The characteristic advertises its supported write modes via its + \l {QLowEnergyCharacteristic::properties()}{properties}. + + \value WriteWithResponse If a characteristic is written using this mode, the peripheral + shall send a write confirmation. If the operation is + successful, the confirmation is emitted via the + \l characteristicWritten() signal. Otherwise the + \l CharacteristicWriteError is emitted. + A characteristic must have set the + \l QLowEnergyCharacteristic::Write property to support this + write mode. + + \value WriteWithoutResponse If a characteristic is written using this mode, the remote peripheral + shall not send a write confirmation. The operation's success + cannot be determined and the payload must not be longer than 20 bytes. + A characteristic must have set the + \l QLowEnergyCharacteristic::WriteNoResponse property to support this + write mode. Its adavantage is a quicker + write operation as it may happen in between other + device interactions. + + \value [since 5.7] WriteSigned If a characteristic is written using this mode, the remote + peripheral shall not send a write confirmation. The operation's + success cannot be determined and the payload must not be longer + than 8 bytes. A bond must exist between the two devices and the + link must not be encrypted. + A characteristic must have set the + \l QLowEnergyCharacteristic::WriteSigned property to support + this write mode. + This value is currently only supported on Android and on Linux + with BlueZ 5 and a kernel version 3.7 or newer. + */ + +/*! + \fn void QLowEnergyService::stateChanged(QLowEnergyService::ServiceState newState) + + This signal is emitted when the service's state changes. The \a newState can also be + retrieved via \l state(). + + \sa state() + */ + +/*! + \fn void QLowEnergyService::errorOccurred(QLowEnergyService::ServiceError newError) + + This signal is emitted when an error occurrs. The \a newError parameter + describes the error that occurred. + + \since 6.2 + */ + +/*! + \fn void QLowEnergyService::characteristicRead(const QLowEnergyCharacteristic &characteristic, const QByteArray &value) + + This signal is emitted when the read request for \a characteristic successfully returned + its \a value. The signal might be triggered by calling \l characteristicRead(). If + the read operation is not successful, the \l errorOccurred() signal is emitted using the + \l CharacteristicReadError flag. + + \note This signal is only emitted for Central Role related use cases. + + \sa readCharacteristic() + \since 5.5 + */ + +/*! + \fn void QLowEnergyService::characteristicWritten(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) + + This signal is emitted when the value of \a characteristic + is successfully changed to \a newValue. The change must have been triggered + by calling \l writeCharacteristic(). If the write operation is not successful, + the \l errorOccurred() signal is emitted using the \l CharacteristicWriteError flag. + + The reception of the written signal can be considered as a sign that the target device + received the to-be-written value and reports back the status of write request. + + \note If \l writeCharacteristic() is called using the \l WriteWithoutResponse mode, + this signal and the \l errorOccurred() are never emitted. + + \note This signal is only emitted for Central Role related use cases. + + \sa writeCharacteristic() + */ + +/*! + \fn void QLowEnergyService::characteristicChanged(const QLowEnergyCharacteristic + &characteristic, const QByteArray &newValue) + + If the associated controller object is in the \l {QLowEnergyController::CentralRole}{central} + role, this signal is emitted when the value of \a characteristic is changed by an event on the + peripheral/device side. In that case, the signal emission implies that change notifications must + have been activated via the characteristic's + \l {QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration}{ClientCharacteristicConfiguration} + descriptor prior to the change event on the peripheral. More details on how this might be + done can be found further \l{notifications}{above}. + + If the controller is in the \l {QLowEnergyController::PeripheralRole}{peripheral} role, that is, + the service object was created via \l QLowEnergyController::addService, the signal is emitted + when a GATT client has written the value of the characteristic using a write request or command. + + The \a newValue parameter contains the updated value of the \a characteristic. + + */ + +/*! + \fn void QLowEnergyService::descriptorRead(const QLowEnergyDescriptor &descriptor, const QByteArray &value) + + This signal is emitted when the read request for \a descriptor successfully returned + its \a value. The signal might be triggered by calling \l descriptorRead(). If + the read operation is not successful, the \l errorOccurred() signal is emitted using the + \l DescriptorReadError flag. + + \note This signal is only emitted for Central Role related use cases. + + \sa readDescriptor() + \since 5.5 + */ + +/*! + \fn void QLowEnergyService::descriptorWritten(const QLowEnergyDescriptor &descriptor, const QByteArray &newValue) + + This signal is emitted when the value of \a descriptor + is successfully changed to \a newValue. If the associated controller object is in the + \l {QLowEnergyController::CentralRole}{central} role, the change must have been caused + by calling \l writeDescriptor(). Otherwise, the signal is the result of a write request or + command from a GATT client to the respective descriptor. + + \sa writeDescriptor() + */ + +/*! + \internal + + QLowEnergyControllerPrivate creates instances of this class. + The user gets access to class instances via + \l QLowEnergyController::services(). + */ +QLowEnergyService::QLowEnergyService(QSharedPointer p, + QObject *parent) + : QObject(parent), + d_ptr(p) +{ + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + + connect(p.data(), &QLowEnergyServicePrivate::errorOccurred, this, + &QLowEnergyService::errorOccurred); + connect(p.data(), &QLowEnergyServicePrivate::stateChanged, + this, &QLowEnergyService::stateChanged); + connect(p.data(), &QLowEnergyServicePrivate::characteristicChanged, + this, &QLowEnergyService::characteristicChanged); + connect(p.data(), &QLowEnergyServicePrivate::characteristicWritten, + this, &QLowEnergyService::characteristicWritten); + connect(p.data(), &QLowEnergyServicePrivate::descriptorWritten, + this, &QLowEnergyService::descriptorWritten); + connect(p.data(), &QLowEnergyServicePrivate::characteristicRead, + this, &QLowEnergyService::characteristicRead); + connect(p.data(), &QLowEnergyServicePrivate::descriptorRead, + this, &QLowEnergyService::descriptorRead); +} + +/*! + Destroys the \l QLowEnergyService instance. + */ +QLowEnergyService::~QLowEnergyService() +{ +} + +/*! + Returns the UUIDs of all services which are included by the + current service. + + The returned list is empty if this service instance's \l discoverDetails() + was not yet called or there are no known characteristics. + + It is possible that an included service contains yet another service. Such + second level includes have to be obtained via their relevant first level + QLowEnergyService instance. Technically, this could create + a circular dependency. + + \l {QLowEnergyController::createServiceObject()} should be used to obtain + service instances for each of the UUIDs. + + \sa {QLowEnergyController::}{createServiceObject()} + */ +QList QLowEnergyService::includedServices() const +{ + return d_ptr->includedServices; +} + +/*! + Returns the current state of the service. + + If the device's service was instantiated for the first time, the object's + state is \l DiscoveryRequired. The state of all service objects which + point to the same service on the peripheral device are always equal. + This is caused by the shared nature of the internal object data. + Therefore any service object instance created after + the first one has a state equal to already existing instances. + + A service becomes invalid if the \l QLowEnergyController disconnects + from the remote device. An invalid service retains its internal state + at the time of the disconnect event. This implies that once the service + details are discovered they can even be retrieved from an invalid + service. This permits scenarios where the device connection is established, + the service details are retrieved and the device immediately disconnected + to permit the next device to connect to the peripheral device. + + However, under normal circumstances the connection should remain to avoid + repeated discovery of services and their details. The discovery may take + a while and the client can subscribe to ongoing change notifications. + + \sa stateChanged() + */ +QLowEnergyService::ServiceState QLowEnergyService::state() const +{ + return d_ptr->state; +} + +/*! + Returns the type of the service. + + \note The type attribute cannot be relied upon until the service has + reached the \l ServiceDiscovered state. This field is initialised + with \l PrimaryService. + + \note On Android, it is not possible to determine whether a service + is a primary or secondary service. Therefore all services + have the \l PrimaryService flag set. + + */ +QLowEnergyService::ServiceTypes QLowEnergyService::type() const +{ + return d_ptr->type; +} + +/*! + Returns the matching characteristic for \a uuid; otherwise an invalid + characteristic. + + The returned characteristic is invalid if this service instance's \l discoverDetails() + was not yet called or there are no characteristics with a matching \a uuid. + + \sa characteristics() +*/ +QLowEnergyCharacteristic QLowEnergyService::characteristic(const QBluetoothUuid &uuid) const +{ + CharacteristicDataMap::const_iterator charIt = d_ptr->characteristicList.constBegin(); + for ( ; charIt != d_ptr->characteristicList.constEnd(); ++charIt) { + const QLowEnergyHandle charHandle = charIt.key(); + const QLowEnergyServicePrivate::CharData &charDetails = charIt.value(); + + if (charDetails.uuid == uuid) + return QLowEnergyCharacteristic(d_ptr, charHandle); + } + + return QLowEnergyCharacteristic(); +} + +/*! + Returns all characteristics associated with this \c QLowEnergyService instance. + + The returned list is empty if this service instance's \l discoverDetails() + was not yet called or there are no known characteristics. + + \sa characteristic(), state(), discoverDetails() +*/ + +QList QLowEnergyService::characteristics() const +{ + QList results; + QList handles = d_ptr->characteristicList.keys(); + std::sort(handles.begin(), handles.end()); + + for (const QLowEnergyHandle &handle : std::as_const(handles)) { + QLowEnergyCharacteristic characteristic(d_ptr, handle); + results.append(characteristic); + } + return results; +} + + +/*! + Returns the UUID of the service; otherwise a null UUID. + */ +QBluetoothUuid QLowEnergyService::serviceUuid() const +{ + return d_ptr->uuid; +} + + +/*! + Returns the name of the service; otherwise an empty string. + + The returned name can only be retrieved if \l serviceUuid() + is a \l {https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx}{well-known UUID}. +*/ +QString QLowEnergyService::serviceName() const +{ + bool ok = false; + quint16 clsId = d_ptr->uuid.toUInt16(&ok); + if (ok) { + QBluetoothUuid::ServiceClassUuid id + = static_cast(clsId); + const QString name = QBluetoothUuid::serviceClassToString(id); + if (!name.isEmpty()) + return name; + } + return qApp ? + qApp->translate("QBluetoothServiceDiscoveryAgent", "Unknown Service") : + QStringLiteral("Unknown Service"); +} + +/*! + Initiates discovery of the service's included services, characteristics, + and their associated descriptors. + + The discovery process is indicated via the \l stateChanged() signal. + After creation, the service is in \l DiscoveryRequired state. + When calling discoverDetails() it transitions to \l DiscoveringService. + After completion of detail discovery, it transitions to + \l ServiceDiscovered state. On each transition, the \l stateChanged() + signal is emitted. + Depending on the argument \a mode, a \l FullDiscovery or a + \l SkipValueDiscovery is performed. In + any case, all services and characteristics are discovered. A + \l FullDiscovery proceeds and reads all characteristic values and + descriptors. A \l SkipValueDiscovery does not read characteristic values + and descriptors. A \l SkipValueDiscovery has two advantages. First, it is + faster. Second, it circumvents bugs in some devices which wrongly advertise + characteristics or descriptors as readable but nevertheless do not permit + reads on them. This can trigger unpredictable behavior. + After a \l SkipValueDiscovery, it is necessary to call + \l readCharacteristic() / \l readDescriptor() and wait for them to + finish successfully before accessing the value of a characteristic or + descriptor. + + The argument \a mode was introduced in Qt 6.2. + + \sa state() + */ +void QLowEnergyService::discoverDetails(DiscoveryMode mode) +{ + Q_D(QLowEnergyService); + + if (!d->controller || d->state == QLowEnergyService::InvalidService) { + d->setError(QLowEnergyService::OperationError); + return; + } + + if (d->state != QLowEnergyService::RemoteService) + return; + + d->setState(QLowEnergyService::RemoteServiceDiscovering); + + d->controller->discoverServiceDetails(d->uuid, mode); +} + +/*! + Returns the last occurred error or \l NoError. + */ +QLowEnergyService::ServiceError QLowEnergyService::error() const +{ + return d_ptr->lastError; +} + +/*! + Returns \c true if \a characteristic belongs to this service; + otherwise \c false. + + A characteristic belongs to a service if \l characteristics() + contains the \a characteristic. + */ +bool QLowEnergyService::contains(const QLowEnergyCharacteristic &characteristic) const +{ + if (characteristic.d_ptr.isNull() || !characteristic.data) + return false; + + if (d_ptr == characteristic.d_ptr + && d_ptr->characteristicList.contains(characteristic.attributeHandle())) { + return true; + } + + return false; +} + + +/*! + Reads the value of \a characteristic. If the operation is successful, the + \l characteristicRead() signal is emitted; otherwise the \l CharacteristicReadError + is set. In general, a \a characteristic is readable, if its + \l QLowEnergyCharacteristic::Read property is set. + + All descriptor and characteristic requests towards the same remote device are + serialised. A queue is employed when issuing multiple requests at the same time. + The queue does not eliminate duplicated read requests for the same characteristic. + + A characteristic can only be read if the service is in the \l ServiceDiscovered state + and belongs to the service. If one of these conditions is + not true the \l QLowEnergyService::OperationError is set. + + \note Calling this function despite \l QLowEnergyCharacteristic::properties() reporting a non-readable property + always attempts to read the characteristic's value on the hardware. If the hardware + returns with an error the \l CharacteristicReadError is set. + + \sa characteristicRead(), writeCharacteristic() + + \since 5.5 + */ +void QLowEnergyService::readCharacteristic( + const QLowEnergyCharacteristic &characteristic) +{ + Q_D(QLowEnergyService); + + if (d->controller == nullptr || state() != RemoteServiceDiscovered || !contains(characteristic)) { + d->setError(QLowEnergyService::OperationError); + return; + } + + d->controller->readCharacteristic(characteristic.d_ptr, + characteristic.attributeHandle()); +} + +/*! + Writes \a newValue as value for the \a characteristic. The exact semantics depend on + the role that the associated controller object is in. + + \b {Central role} + + The call results in a write request or command to a remote peripheral. + If the operation is successful, + the \l characteristicWritten() signal is emitted; otherwise the \l CharacteristicWriteError + is set. Calling this function does not trigger the a \l characteristicChanged() + signal unless the peripheral itself changes the value again after the current write request. + + The \a mode parameter determines whether the remote device should send a write + confirmation. The to-be-written \a characteristic must support the relevant + write mode. The characteristic's supported write modes are indicated by its + \l QLowEnergyCharacteristic::Write and \l QLowEnergyCharacteristic::WriteNoResponse + properties. + + All descriptor and characteristic write requests towards the same remote device are + serialised. A queue is employed when issuing multiple write requests at the same time. + The queue does not eliminate duplicated write requests for the same characteristic. + For example, if the same descriptor is set to the value A and immediately afterwards + to B, the two write request are executed in the given order. + + \note Currently, it is not possible to use signed or reliable writes as defined by the + Bluetooth specification. + + A characteristic can only be written if this service is in the \l ServiceDiscovered state + and belongs to the service. If one of these conditions is + not true the \l QLowEnergyService::OperationError is set. + + \note Calling this function despite \l QLowEnergyCharacteristic::properties() reporting + a non-writable property always attempts to write to the hardware. + Similarly, a \l WriteWithoutResponse is sent to the hardware too although the + characteristic may only support \l WriteWithResponse. If the hardware returns + with an error the \l CharacteristicWriteError is set. + + \b {Peripheral role} + + The call results in the value of the characteristic getting updated in the local database. + + If a client is currently connected and it has enabled notifications or indications for + the characteristic, the respective information will be sent. + If a device has enabled notifications or indications for the characteristic and that device + is currently not connected, but a bond exists between it and the local device, then + the notification or indication will be sent on the next reconnection. + + If there is a constraint on the length of the characteristic value and \a newValue + does not adhere to that constraint, the behavior is unspecified. + + \note The \a mode argument is ignored in peripheral mode. + + \sa QLowEnergyService::characteristicWritten(), QLowEnergyService::readCharacteristic() + + */ +void QLowEnergyService::writeCharacteristic( + const QLowEnergyCharacteristic &characteristic, + const QByteArray &newValue, QLowEnergyService::WriteMode mode) +{ + //TODO check behavior when writing to WriteSigned characteristic + Q_D(QLowEnergyService); + + if (d->controller == nullptr + || (d->controller->role == QLowEnergyController::CentralRole + && state() != RemoteServiceDiscovered) + || !contains(characteristic)) { + d->setError(QLowEnergyService::OperationError); + return; + } + + // don't write if properties don't permit it + d->controller->writeCharacteristic(characteristic.d_ptr, + characteristic.attributeHandle(), + newValue, + mode); +} + +/*! + Returns \c true if \a descriptor belongs to this service; otherwise \c false. + */ +bool QLowEnergyService::contains(const QLowEnergyDescriptor &descriptor) const +{ + if (descriptor.d_ptr.isNull() || !descriptor.data) + return false; + + const QLowEnergyHandle charHandle = descriptor.characteristicHandle(); + if (!charHandle) + return false; + + if (d_ptr == descriptor.d_ptr + && d_ptr->characteristicList.contains(charHandle) + && d_ptr->characteristicList[charHandle].descriptorList.contains(descriptor.handle())) + { + return true; + } + + return false; +} + +/*! + Reads the value of \a descriptor. If the operation is successful, the + \l descriptorRead() signal is emitted; otherwise the \l DescriptorReadError + is set. + + All descriptor and characteristic requests towards the same remote device are + serialised. A queue is employed when issuing multiple requests at the same time. + The queue does not eliminate duplicated read requests for the same descriptor. + + A descriptor can only be read if the service is in the \l ServiceDiscovered state + and the descriptor belongs to the service. If one of these conditions is + not true the \l QLowEnergyService::OperationError is set. + + \sa descriptorRead(), writeDescriptor() + + \since 5.5 + */ +void QLowEnergyService::readDescriptor( + const QLowEnergyDescriptor &descriptor) +{ + Q_D(QLowEnergyService); + + if (d->controller == nullptr || state() != RemoteServiceDiscovered || !contains(descriptor)) { + d->setError(QLowEnergyService::OperationError); + return; + } + + d->controller->readDescriptor(descriptor.d_ptr, + descriptor.characteristicHandle(), + descriptor.handle()); +} + +/*! + Writes \a newValue as value for \a descriptor. The exact semantics depend on + the role that the associated controller object is in. + + \b {Central role} + + A call to this function results in a write request to the remote device. + If the operation is successful, the \l descriptorWritten() signal is emitted; otherwise + the \l DescriptorWriteError is emitted. + + All descriptor and characteristic requests towards the same remote device are + serialised. A queue is employed when issuing multiple write requests at the same time. + The queue does not eliminate duplicated write requests for the same descriptor. + For example, if the same descriptor is set to the value A and immediately afterwards + to B, the two write request are executed in the given order. + + A descriptor can only be written if this service is in the \l ServiceDiscovered state, + belongs to the service. If one of these conditions is + not true the \l QLowEnergyService::OperationError is set. + + \b {Peripheral Role} + + The value is written to the local service database. If the contents of \a newValue are not + valid for \a descriptor, the behavior is unspecified. + + \sa descriptorWritten(), readDescriptor() + */ +void QLowEnergyService::writeDescriptor(const QLowEnergyDescriptor &descriptor, + const QByteArray &newValue) +{ + Q_D(QLowEnergyService); + + if (d->controller == nullptr + || (d->controller->role == QLowEnergyController::CentralRole + && state() != RemoteServiceDiscovered) + || !contains(descriptor)) { + d->setError(QLowEnergyService::OperationError); + return; + } +#ifdef Q_OS_DARWIN + if (descriptor.uuid() == QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration) { + // We have to identify a special case - ClientCharacteristicConfiguration + // since with CoreBluetooth: + // + // "You cannot use this method to write the value of a client configuration descriptor + // (represented by the CBUUIDClientCharacteristicConfigurationString constant), + // which describes how notification or indications are configured for a + // characteristic’s value with respect to a client. If you want to manage + // notifications or indications for a characteristic’s value, you must + // use the setNotifyValue:forCharacteristic: method instead." + auto controller = static_cast(d->controller.data()); + return controller->setNotifyValue(descriptor.d_ptr, descriptor.characteristicHandle(), newValue); + } +#endif // Q_OS_DARWIN + + d->controller->writeDescriptor(descriptor.d_ptr, + descriptor.characteristicHandle(), + descriptor.handle(), + newValue); +} + +QT_END_NAMESPACE + +#include "moc_qlowenergyservice.cpp" diff --git a/src/bluetooth/qlowenergyservice.h b/src/bluetooth/qlowenergyservice.h new file mode 100644 index 0000000..2fc9400 --- /dev/null +++ b/src/bluetooth/qlowenergyservice.h @@ -0,0 +1,142 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2016 Javier S. Pedro +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +#ifndef QLOWENERGYSERVICE_H +#define QLOWENERGYSERVICE_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QLowEnergyServicePrivate; +class Q_BLUETOOTH_EXPORT QLowEnergyService : public QObject +{ + Q_OBJECT +public: + enum ServiceType { + PrimaryService = 0x0001, + IncludedService = 0x0002 + }; + Q_ENUM(ServiceType) + Q_DECLARE_FLAGS(ServiceTypes, ServiceType) + + enum ServiceError { + NoError = 0, + OperationError, + CharacteristicWriteError, + DescriptorWriteError, + UnknownError, + CharacteristicReadError, + DescriptorReadError + }; + Q_ENUM(ServiceError) + + enum ServiceState { + InvalidService = 0, + RemoteService, + RemoteServiceDiscovering, // discoverDetails() called and running + RemoteServiceDiscovered, // all details have been synchronized + LocalService, + +#if QT_DEPRECATED_SINCE(6, 2) +// for source compatibility: + DiscoveryRequired + Q_DECL_ENUMERATOR_DEPRECATED_X( + "DiscoveryRequired was renamed to RemoteService.") + = RemoteService, + DiscoveringService + Q_DECL_ENUMERATOR_DEPRECATED_X( + "DiscoveringService was renamed to RemoteServiceDiscovering.") + = RemoteServiceDiscovering, + ServiceDiscovered + Q_DECL_ENUMERATOR_DEPRECATED_X( + "ServiceDiscovered was renamed to RemoteServiceDiscovered.") + = RemoteServiceDiscovered, +#endif + }; + Q_ENUM(ServiceState) + + enum DiscoveryMode { + FullDiscovery, // standard, reads all attributes + SkipValueDiscovery // does not read characteristic values and descriptors + }; + Q_ENUM(DiscoveryMode) + + enum WriteMode { + WriteWithResponse = 0, + WriteWithoutResponse, + WriteSigned + }; + Q_ENUM(WriteMode) + + ~QLowEnergyService(); + + QList includedServices() const; + + QLowEnergyService::ServiceTypes type() const; + QLowEnergyService::ServiceState state() const; + + QLowEnergyCharacteristic characteristic(const QBluetoothUuid &uuid) const; + QList characteristics() const; + QBluetoothUuid serviceUuid() const; + QString serviceName() const; + + void discoverDetails(DiscoveryMode mode = FullDiscovery); + + ServiceError error() const; + + bool contains(const QLowEnergyCharacteristic &characteristic) const; + void readCharacteristic(const QLowEnergyCharacteristic &characteristic); + void writeCharacteristic(const QLowEnergyCharacteristic &characteristic, + const QByteArray &newValue, + WriteMode mode = WriteWithResponse); + + bool contains(const QLowEnergyDescriptor &descriptor) const; + void readDescriptor(const QLowEnergyDescriptor &descriptor); + void writeDescriptor(const QLowEnergyDescriptor &descriptor, + const QByteArray &newValue); + +Q_SIGNALS: + void stateChanged(QLowEnergyService::ServiceState newState); + void characteristicChanged(const QLowEnergyCharacteristic &info, + const QByteArray &value); + void characteristicRead(const QLowEnergyCharacteristic &info, + const QByteArray &value); + void characteristicWritten(const QLowEnergyCharacteristic &info, + const QByteArray &value); + void descriptorRead(const QLowEnergyDescriptor &info, + const QByteArray &value); + void descriptorWritten(const QLowEnergyDescriptor &info, + const QByteArray &value); + void errorOccurred(QLowEnergyService::ServiceError error); + +private: + Q_DECLARE_PRIVATE(QLowEnergyService) + QSharedPointer d_ptr; + + // QLowEnergyController is the factory for this class + friend class QLowEnergyController; + friend class QLowEnergyControllerPrivate; + friend class QLowEnergyControllerPrivateBluez; + friend class QLowEnergyControllerPrivateAndroid; + friend class QLowEnergyControllerPrivateDarwin; + QLowEnergyService(QSharedPointer p, + QObject *parent = nullptr); +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QLowEnergyService::ServiceTypes) + +QT_END_NAMESPACE + +QT_DECL_METATYPE_EXTERN_TAGGED(QLowEnergyService::ServiceError, QLowEnergyService__ServiceError, + Q_BLUETOOTH_EXPORT) +QT_DECL_METATYPE_EXTERN_TAGGED(QLowEnergyService::ServiceState, QLowEnergyService__ServiceState, + Q_BLUETOOTH_EXPORT) +QT_DECL_METATYPE_EXTERN_TAGGED(QLowEnergyService::ServiceType, QLowEnergyService__ServiceType, + Q_BLUETOOTH_EXPORT) +QT_DECL_METATYPE_EXTERN_TAGGED(QLowEnergyService::WriteMode, QLowEnergyService__WriteMode, + Q_BLUETOOTH_EXPORT) + +#endif // QLOWENERGYSERVICE_H diff --git a/src/bluetooth/qlowenergyservicedata.cpp b/src/bluetooth/qlowenergyservicedata.cpp new file mode 100644 index 0000000..76d6b9f --- /dev/null +++ b/src/bluetooth/qlowenergyservicedata.cpp @@ -0,0 +1,194 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qlowenergyservicedata.h" + +#include "qlowenergycharacteristicdata.h" + +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT) + +struct QLowEnergyServiceDataPrivate : public QSharedData +{ + QLowEnergyServiceDataPrivate() : type(QLowEnergyServiceData::ServiceTypePrimary) {} + + QLowEnergyServiceData::ServiceType type; + QBluetoothUuid uuid; + QList includedServices; + QList characteristics; +}; + + +/*! + \since 5.7 + \class QLowEnergyServiceData + \brief The QLowEnergyServiceData class is used to set up GATT service data. + \inmodule QtBluetooth + \ingroup shared + + An Object of this class provides a service to be added to a GATT server via + \l QLowEnergyController::addService(). +*/ + +/*! + \enum QLowEnergyServiceData::ServiceType + The type of GATT service. + + \value ServiceTypePrimary + The service is a primary service. + \value ServiceTypeSecondary + The service is a secondary service. Secondary services are included by other services + to implement some higher-level functionality. + */ + +/*! Creates a new invalid object of this class. */ +QLowEnergyServiceData::QLowEnergyServiceData() : d(new QLowEnergyServiceDataPrivate) +{ +} + +/*! Constructs a new object of this class that is a copy of \a other. */ +QLowEnergyServiceData::QLowEnergyServiceData(const QLowEnergyServiceData &other) : d(other.d) +{ +} + +/*! Destroys this object. */ +QLowEnergyServiceData::~QLowEnergyServiceData() +{ +} + +/*! Makes this object a copy of \a other and returns the new value of this object. */ +QLowEnergyServiceData &QLowEnergyServiceData::operator=(const QLowEnergyServiceData &other) +{ + d = other.d; + return *this; +} + +/*! Returns the type of this service. */ +QLowEnergyServiceData::ServiceType QLowEnergyServiceData::type() const +{ + return d->type; +} + +/*! Sets the type of this service to \a type. */ +void QLowEnergyServiceData::setType(ServiceType type) +{ + d->type = type; +} + +/*! Returns the UUID of this service. */ +QBluetoothUuid QLowEnergyServiceData::uuid() const +{ + return d->uuid; +} + +/*! Sets the UUID of this service to \a uuid. */ +void QLowEnergyServiceData::setUuid(const QBluetoothUuid &uuid) +{ + d->uuid = uuid; +} + +/*! Returns the list of included services. */ +QList QLowEnergyServiceData::includedServices() const +{ + return d->includedServices; +} + +/*! + Sets the list of included services to \a services. + All objects in this list must have been returned from a call to + \l QLowEnergyController::addService. + \sa addIncludedService() +*/ +void QLowEnergyServiceData::setIncludedServices(const QList &services) +{ + d->includedServices = services; +} + +/*! + Adds \a service to the list of included services. + The \a service object must have been returned from a call to + \l QLowEnergyController::addService. This requirement prevents circular includes + (which are forbidden by the Bluetooth specification), and also helps to support the use case of + including more than one service of the same type. + \sa setIncludedServices() +*/ +void QLowEnergyServiceData::addIncludedService(QLowEnergyService *service) +{ + d->includedServices << service; +} + +/*! Returns the list of characteristics. */ +QList QLowEnergyServiceData::characteristics() const +{ + return d->characteristics; +} + +/*! + Sets the list of characteristics to \a characteristics. + Only valid characteristics are considered. + \sa addCharacteristic() + */ +void QLowEnergyServiceData::setCharacteristics(const QList &characteristics) +{ + d->characteristics.clear(); + for (const QLowEnergyCharacteristicData &cd : characteristics) + addCharacteristic(cd); +} + +/*! + Adds \a characteristic to the list of characteristics, if it is valid. + \sa setCharacteristics() + */ +void QLowEnergyServiceData::addCharacteristic(const QLowEnergyCharacteristicData &characteristic) +{ + if (characteristic.isValid()) + d->characteristics << characteristic; + else + qCWarning(QT_BT) << "not adding invalid characteristic to service"; +} + +/*! Returns \c true if this service is has a non-null UUID. */ +bool QLowEnergyServiceData::isValid() const +{ + return !uuid().isNull(); +} + +/*! + \fn void QLowEnergyServiceData::swap(QLowEnergyServiceData &other) + Swaps this object with \a other. + */ + +/*! + \fn bool QLowEnergyServiceData::operator==(const QLowEnergyServiceData &a, + const QLowEnergyServiceData &b) + + \brief Returns \c true if \a a and \a b are equal with respect to their public state, + otherwise returns \c false. + */ + +/*! + \fn bool QLowEnergyServiceData::operator!=(const QLowEnergyServiceData &a, + const QLowEnergyServiceData &b) + + \brief Returns \c true if \a a and \a b are unequal with respect to their public state, + otherwise returns \c false. + */ + +/*! + \brief Returns \c true if \a a and \a b are equal with respect to their public state, + otherwise returns \c false. + \internal + */ +bool QLowEnergyServiceData::equals(const QLowEnergyServiceData &a, const QLowEnergyServiceData &b) +{ + return a.d == b.d || ( + a.type() == b.type() + && a.uuid() == b.uuid() + && a.includedServices() == b.includedServices() + && a.characteristics() == b.characteristics()); +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/qlowenergyservicedata.h b/src/bluetooth/qlowenergyservicedata.h new file mode 100644 index 0000000..108b7d8 --- /dev/null +++ b/src/bluetooth/qlowenergyservicedata.h @@ -0,0 +1,62 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QLOWENERGYSERVICEDATA_H +#define QLOWENERGYSERVICEDATA_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QBluetoothUuid; +class QLowEnergyCharacteristicData; +class QLowEnergyService; +struct QLowEnergyServiceDataPrivate; + +class Q_BLUETOOTH_EXPORT QLowEnergyServiceData +{ +public: + QLowEnergyServiceData(); + QLowEnergyServiceData(const QLowEnergyServiceData &other); + ~QLowEnergyServiceData(); + + QLowEnergyServiceData &operator=(const QLowEnergyServiceData &other); + friend bool operator==(const QLowEnergyServiceData &a, const QLowEnergyServiceData &b) + { + return equals(a, b); + } + friend bool operator!=(const QLowEnergyServiceData &a, const QLowEnergyServiceData &b) + { + return !equals(a, b); + } + + enum ServiceType { ServiceTypePrimary = 0x2800, ServiceTypeSecondary = 0x2801 }; + ServiceType type() const; + void setType(ServiceType type); + + QBluetoothUuid uuid() const; + void setUuid(const QBluetoothUuid &uuid); + + QList includedServices() const; + void setIncludedServices(const QList &services); + void addIncludedService(QLowEnergyService *service); + + QList characteristics() const; + void setCharacteristics(const QList &characteristics); + void addCharacteristic(const QLowEnergyCharacteristicData &characteristic); + + bool isValid() const; + + void swap(QLowEnergyServiceData &other) noexcept { d.swap(other.d); } + +private: + static bool equals(const QLowEnergyServiceData &a, const QLowEnergyServiceData &b); + QSharedDataPointer d; +}; + +Q_DECLARE_SHARED(QLowEnergyServiceData) + +QT_END_NAMESPACE + +#endif // Include guard. diff --git a/src/bluetooth/qlowenergyserviceprivate.cpp b/src/bluetooth/qlowenergyserviceprivate.cpp new file mode 100644 index 0000000..c82897c --- /dev/null +++ b/src/bluetooth/qlowenergyserviceprivate.cpp @@ -0,0 +1,46 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qlowenergyserviceprivate_p.h" + +#include "qlowenergycontrollerbase_p.h" + +QT_BEGIN_NAMESPACE + +QT_IMPL_METATYPE_EXTERN_TAGGED(QSharedPointer, + QSharedPointer_QLowEnergyServicePrivate) + +QLowEnergyServicePrivate::QLowEnergyServicePrivate(QObject *parent) : QObject(parent) { } + +QLowEnergyServicePrivate::~QLowEnergyServicePrivate() +{ +} + +void QLowEnergyServicePrivate::setController(QLowEnergyControllerPrivate *control) +{ + controller = control; + + if (control) + setState(QLowEnergyService::RemoteService); + else + setState(QLowEnergyService::InvalidService); +} + +void QLowEnergyServicePrivate::setError(QLowEnergyService::ServiceError newError) +{ + lastError = newError; + emit errorOccurred(newError); +} + +void QLowEnergyServicePrivate::setState(QLowEnergyService::ServiceState newState) +{ + if (state == newState) + return; + + state = newState; + emit stateChanged(newState); +} + +QT_END_NAMESPACE + +#include "moc_qlowenergyserviceprivate_p.cpp" diff --git a/src/bluetooth/qlowenergyserviceprivate_p.h b/src/bluetooth/qlowenergyserviceprivate_p.h new file mode 100644 index 0000000..68d65da --- /dev/null +++ b/src/bluetooth/qlowenergyserviceprivate_p.h @@ -0,0 +1,109 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QLOWENERGYSERVICEPRIVATE_P_H +#define QLOWENERGYSERVICEPRIVATE_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 + +#if defined(QT_ANDROID_BLUETOOTH) +#include +#endif + +QT_BEGIN_NAMESPACE + +class QLowEnergyControllerPrivate; + +class QLowEnergyServicePrivate : public QObject +{ + Q_OBJECT +public: + explicit QLowEnergyServicePrivate(QObject *parent = nullptr); + ~QLowEnergyServicePrivate(); + + struct DescData { + QByteArray value; + QBluetoothUuid uuid; + }; + + struct CharData { + QLowEnergyHandle valueHandle; + QBluetoothUuid uuid; + QLowEnergyCharacteristic::PropertyTypes properties; + QByteArray value; + QHash descriptorList; + }; + + enum GattAttributeTypes { + PrimaryService = 0x2800, + SecondaryService = 0x2801, + IncludeAttribute = 0x2802, + Characteristic = 0x2803 + }; + + void setController(QLowEnergyControllerPrivate* control); + void setError(QLowEnergyService::ServiceError newError); + void setState(QLowEnergyService::ServiceState newState); + +signals: + void stateChanged(QLowEnergyService::ServiceState newState); + void errorOccurred(QLowEnergyService::ServiceError error); + void characteristicChanged(const QLowEnergyCharacteristic &characteristic, + const QByteArray &newValue); + void characteristicRead(const QLowEnergyCharacteristic &info, + const QByteArray &value); + void characteristicWritten(const QLowEnergyCharacteristic &characteristic, + const QByteArray &newValue); + void descriptorRead(const QLowEnergyDescriptor &info, + const QByteArray &value); + void descriptorWritten(const QLowEnergyDescriptor &descriptor, + const QByteArray &newValue); + +public: + QLowEnergyHandle startHandle = 0; + QLowEnergyHandle endHandle = 0; + + QBluetoothUuid uuid; + QList includedServices; + QLowEnergyService::ServiceTypes type = QLowEnergyService::PrimaryService; + QLowEnergyService::ServiceState state = QLowEnergyService::InvalidService; + QLowEnergyService::ServiceError lastError = QLowEnergyService::NoError; + QLowEnergyService::DiscoveryMode mode = QLowEnergyService::FullDiscovery; + + QHash characteristicList; + + QPointer controller; + +#if defined(QT_ANDROID_BLUETOOTH) + // reference to the BluetoothGattService object + QJniObject androidService; +#endif + +}; + +typedef QHash CharacteristicDataMap; +typedef QHash DescriptorDataMap; + +QT_END_NAMESPACE + +QT_DECL_METATYPE_EXTERN_TAGGED(QSharedPointer, + QSharedPointer_QLowEnergyServicePrivate, + /* not exported */) + +#endif // QLOWENERGYSERVICEPRIVATE_P_H diff --git a/src/bluetooth/qprivatelinearbuffer_p.h b/src/bluetooth/qprivatelinearbuffer_p.h new file mode 100644 index 0000000..e4072c5 --- /dev/null +++ b/src/bluetooth/qprivatelinearbuffer_p.h @@ -0,0 +1,150 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QPRIVATELINEARBUFFER_P_H +#define QPRIVATELINEARBUFFER_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. +// + +// This is QIODevice's read buffer, optimised for read(), isEmpty() and getChar() +class QPrivateLinearBuffer +{ +public: + QPrivateLinearBuffer() : len(0), first(0), buf(0), capacity(0) { + } + ~QPrivateLinearBuffer() { + delete [] buf; + } + void clear() { + first = buf; + len = 0; + } + qsizetype size() const + { + return len; + } + bool isEmpty() const { + return len == 0; + } + void skip(qsizetype n) + { + if (n >= len) { + clear(); + } else { + len -= n; + first += n; + } + } + int getChar() { + if (len == 0) + return -1; + int ch = uchar(*first); + len--; + first++; + return ch; + } + qsizetype read(char* target, qsizetype size) + { + qsizetype r = (std::min)(size, len); + memcpy(target, first, r); + len -= r; + first += r; + return r; + } + char* reserve(qsizetype size) + { + makeSpace(size + len, freeSpaceAtEnd); + char* writePtr = first + len; + len += size; + return writePtr; + } + void chop(qsizetype size) + { + if (size >= len) { + clear(); + } else { + len -= size; + } + } + QByteArray readAll() { + char* f = first; + qsizetype l = len; + clear(); + return QByteArray(f, l); + } + qsizetype readLine(char* target, qsizetype size) + { + qsizetype r = (std::min)(size, len); + char* eol = static_cast(memchr(first, '\n', r)); + if (eol) + r = 1+(eol-first); + memcpy(target, first, r); + len -= r; + first += r; + return r; + } + bool canReadLine() const { + return memchr(first, '\n', len); + } + void ungetChar(char c) { + if (first == buf) { + // underflow, the existing valid data needs to move to the end of the (potentially bigger) buffer + makeSpace(len+1, freeSpaceAtStart); + } + first--; + len++; + *first = c; + } + void ungetBlock(const char* block, qsizetype size) + { + if ((first - buf) < size) { + // underflow, the existing valid data needs to move to the end of the (potentially bigger) buffer + makeSpace(len + size, freeSpaceAtStart); + } + first -= size; + len += size; + memcpy(first, block, size); + } + +private: + enum FreeSpacePos {freeSpaceAtStart, freeSpaceAtEnd}; + void makeSpace(size_t required, FreeSpacePos where) { + size_t newCapacity = (std::max)(capacity, size_t(QPRIVATELINEARBUFFER_BUFFERSIZE)); + while (newCapacity < required) + newCapacity *= 2; + const qsizetype moveOffset = (where == freeSpaceAtEnd) ? 0 : qsizetype(newCapacity) - len; + if (newCapacity > capacity) { + // allocate more space + char* newBuf = new char[newCapacity]; + memmove(newBuf + moveOffset, first, len); + delete [] buf; + buf = newBuf; + capacity = newCapacity; + } else { + // shift any existing data to make space + memmove(buf + moveOffset, first, len); + } + first = buf + moveOffset; + } + +private: + // length of the unread data + qsizetype len; + // start of the unread data + char* first; + // the allocated buffer + char* buf; + // allocated buffer size + size_t capacity; +}; + +#endif // QPRIVATELINEARBUFFER_P_H diff --git a/src/bluetooth/qtbluetoothglobal.h b/src/bluetooth/qtbluetoothglobal.h new file mode 100644 index 0000000..62d41a4 --- /dev/null +++ b/src/bluetooth/qtbluetoothglobal.h @@ -0,0 +1,10 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +#ifndef QTBLUETOOTH_H +#define QTBLUETOOTH_H + +#include +#include // for feature detection +#include + +#endif // QTBLUETOOTH_H diff --git a/src/bluetooth/qtbluetoothglobal_p.h b/src/bluetooth/qtbluetoothglobal_p.h new file mode 100644 index 0000000..c2e400f --- /dev/null +++ b/src/bluetooth/qtbluetoothglobal_p.h @@ -0,0 +1,24 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QTBLUETOOTHGLOBAL_P_H +#define QTBLUETOOTHGLOBAL_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 + +#endif // QTBLUETOOTHGLOBAL_P_H diff --git a/src/bluetooth/removed_api.cpp b/src/bluetooth/removed_api.cpp new file mode 100644 index 0000000..c4f37b6 --- /dev/null +++ b/src/bluetooth/removed_api.cpp @@ -0,0 +1,57 @@ +// Copyright (C) 2022 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#define QT_BLUETOOTH_BUILD_REMOVED_API + +// Undefine Qt 128-bit int types +#define QT_NO_INT128 + +#include "qtbluetoothglobal.h" + +QT_USE_NAMESPACE + +#if QT_BLUETOOTH_REMOVED_SINCE(6, 6) + +#include "qbluetoothaddress.h" // inlined API + +#include "qbluetoothuuid.h" + +static_assert(std::is_aggregate_v); +static_assert(std::is_trivial_v); + +// These legacy functions can't just call the new (quint128, Endian) overloads, +// as the latter may see either QtCore's quint128 (__int128 built-in) _or_ our +// fake version from qbluetoothuuid.h. This TU must _always_ see the fake ones +// (as that is what we had in 6.5): +#ifdef QT_SUPPORTS_INT128 +# error This TU requires QT_NO_INT128 to be defined. +#endif + +QBluetoothUuid::QBluetoothUuid(quint128 uuid) + : QUuid(fromBytes(uuid.data)) +{} + +quint128 QBluetoothUuid::toUInt128() const +{ + quint128 uuid; + const auto bytes = toBytes(); + memcpy(uuid.data, bytes.data, sizeof(uuid.data)); + return uuid; +} + +// END quint128 functions + +QBluetoothUuid::QBluetoothUuid(const QString &uuid) + : QUuid(qToAnyStringViewIgnoringNull(uuid)) +{ +} + +#ifndef QT_NO_DEBUG_STREAM +QDebug QBluetoothUuid::streamingOperator(QDebug debug, const QBluetoothUuid &uuid) +{ + debug << uuid.toString(); + return debug; +} +#endif // QT_NO_DEBUG_STREAM + +#endif // QT_BLUETOOTH_REMOVED_SINCE(6, 6) diff --git a/src/nfc/ApiChangesQt6.txt b/src/nfc/ApiChangesQt6.txt new file mode 100644 index 0000000..10a5001 --- /dev/null +++ b/src/nfc/ApiChangesQt6.txt @@ -0,0 +1,18 @@ +This document lists the API changed done to QtNFC between Qt 5.15 and Qt 6. + +- Removed function QNearFieldTarget::url(). No replacement available as the function was never implemented. +- Removed function QNearFieldTarget::sendCommands(...). No replacement available as the function needs to be implemented by the API user. +- Renamed function QNearFieldManager::isAvailable() to QNearFieldManager::isEnabled(). +- Removed functions QNearFieldTarget::keepConnection() and QNearFieldTarget::setKeepConnection(...). Keeping the connection is the default behavior now. +- Removed QML API. No replacement available because the support has been discontinued. +- Removed functions QNearFieldTarget::(un)registerNdefMessageHandler(...). No replacement available. +- Removed QNearFieldShareManager/QNearFieldShareTarget. No replacement available. +- Removed function QNearFieldTarget::isProcessingCommand(). No replacement available as the function is not implemented. +- Removed functions setResponseForRequest, handleResponse and reportError from QNearFieldTarget. No replacement available as this is for internal use only. +- Added NfcTagType4A and NfcTagType4B to QNearFieldTarget::Type. +- Changed the type of typeInfo in QNdefNfcSmartPosterRecord from QByteArray to QString. +- Removed TargetAccessModes, setTargetAccessModes and targetAccessModes from QNearFieldManager. No replacement available. +- Removed ndefMessagesWritten signal. A requestCompleted signal is used instead. +- Added QNdefRecord::clear() method. +- QNdefFilter::appendRecord now returns bool to indicate if the record is added or not. +- Added QNdefFilter::match() to check if a message matches the filter. diff --git a/src/nfc/CMakeLists.txt b/src/nfc/CMakeLists.txt new file mode 100644 index 0000000..f23984d --- /dev/null +++ b/src/nfc/CMakeLists.txt @@ -0,0 +1,109 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## Nfc Module: +##################################################################### + +qt_internal_add_module(Nfc + SOURCES + qndeffilter.cpp qndeffilter.h + qndefmessage.cpp qndefmessage.h + qndefnfcsmartposterrecord.cpp qndefnfcsmartposterrecord.h qndefnfcsmartposterrecord_p.h + qndefnfctextrecord.cpp qndefnfctextrecord.h + qndefnfcurirecord.cpp qndefnfcurirecord.h + qndefrecord.cpp qndefrecord.h qndefrecord_p.h + qnearfieldmanager.cpp qnearfieldmanager.h qnearfieldmanager_p.h + qnearfieldtarget.cpp qnearfieldtarget.h qnearfieldtarget_p.cpp qnearfieldtarget_p.h + qtnfcglobal.h qtnfcglobal_p.h + DEFINES + QT_NO_CONTEXTLESS_CONNECT + PUBLIC_LIBRARIES + Qt::Core + GENERATE_CPP_EXPORTS +) + +#### Keys ignored in scope 1:.:.:nfc.pro:: +# OTHER_FILES = "doc/src/*.qdoc" + +## Scopes: +##################################################################### + +if(ANDROID AND (ANDROID AND NOT ANDROID_EMBEDDED)) + set_property(TARGET Nfc APPEND PROPERTY QT_ANDROID_BUNDLED_JAR_DEPENDENCIES + jar/Qt${QtConnectivity_VERSION_MAJOR}AndroidNfc.jar:org.qtproject.qt.android.nfc.QtNfc + ) + set_property(TARGET Nfc APPEND PROPERTY QT_ANDROID_PERMISSIONS + android.permission.NFC + ) + set(NFC_BACKEND_AVAILABLE ON) +endif() + +qt_internal_extend_target(Nfc CONDITION ANDROID AND NOT ANDROID_EMBEDDED + SOURCES + android/androidjninfc.cpp android/androidjninfc_p.h + android/androidmainnewintentlistener.cpp android/androidmainnewintentlistener_p.h + qnearfieldmanager_android.cpp qnearfieldmanager_android_p.h + qnearfieldtarget_android.cpp qnearfieldtarget_android_p.h + DEFINES + ANDROID_NFC + QT_ANDROID_NFC + LIBRARIES + Qt::CorePrivate + Qt::Gui +) + +if(IOS) + # special case begin + set(NFC_BACKEND_AVAILABLE ON) + qt_disable_apple_app_extension_api_only(Nfc) + qt_internal_find_apple_system_framework(FWCoreNFC CoreNFC) + # special case end +endif() + +qt_internal_extend_target(Nfc CONDITION IOS + SOURCES + ios/qiostagreaderdelegate.mm ios/qiostagreaderdelegate_p.h + ios/qiosnfcndefsessiondelegate.mm ios/qiosnfcndefsessiondelegate_p.h + ios/qiosndefnotifier.cpp ios/qiosndefnotifier_p.h + qnearfieldmanager_ios.mm qnearfieldmanager_ios_p.h + qnearfieldtarget_ios.mm qnearfieldtarget_ios_p.h + DEFINES + IOS_NFC + LIBRARIES + ${FWCoreNFC} + Qt::CorePrivate +) + +if(QT_FEATURE_pcsclite) + set(NFC_BACKEND_AVAILABLE ON) +endif() + +qt_internal_extend_target(Nfc CONDITION QT_FEATURE_pcsclite + SOURCES + qnearfieldmanager_pcsc.cpp qnearfieldmanager_pcsc_p.h + qnearfieldtarget_pcsc.cpp qnearfieldtarget_pcsc_p.h + qapduutils.cpp qapduutils_p.h + pcsc/qpcsc.cpp pcsc/qpcsc_p.h + pcsc/qpcscmanager.cpp pcsc/qpcscmanager_p.h + pcsc/qpcscslot.cpp pcsc/qpcscslot_p.h + pcsc/qpcsccard.cpp pcsc/qpcsccard_p.h + ndef/qndefaccessfsm_p.h + ndef/qnfctagtype4ndeffsm.cpp ndef/qnfctagtype4ndeffsm_p.h + DEFINES + PCSC_NFC + LIBRARIES + PkgConfig::PCSCLITE +) + +#### Keys ignored in scope 2:.:.:nfc.pro:ANDROID AND NOT ANDROID_EMBEDDED: +# NFC_BACKEND_AVAILABLE = "yes" + +qt_internal_extend_target(Nfc CONDITION NOT NFC_BACKEND_AVAILABLE + SOURCES + qnearfieldmanager_generic.cpp qnearfieldmanager_generic_p.h +) +qt_internal_add_docs(Nfc + doc/qtnfc.qdocconf +) + diff --git a/src/nfc/android/androidjninfc.cpp b/src/nfc/android/androidjninfc.cpp new file mode 100644 index 0000000..3f22698 --- /dev/null +++ b/src/nfc/android/androidjninfc.cpp @@ -0,0 +1,64 @@ +// Copyright (C) 2016 Centria research and development +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "androidjninfc_p.h" + +QT_BEGIN_NAMESPACE + +namespace QtNfc { + +bool startDiscovery() +{ + return QJniObject::callStaticMethod( + QtJniTypes::Traits::className(), "startDiscovery"); +} + +bool isEnabled() +{ + return QJniObject::callStaticMethod( + QtJniTypes::Traits::className(), "isEnabled"); +} + +bool isSupported() +{ + return QJniObject::callStaticMethod( + QtJniTypes::Traits::className(), "isSupported"); +} + +bool stopDiscovery() +{ + return QJniObject::callStaticMethod( + QtJniTypes::Traits::className(), "stopDiscovery"); +} + +QJniObject getStartIntent() +{ + return QJniObject::callStaticMethod( + QtJniTypes::Traits::className(), "getStartIntent"); +} + +QJniObject getTag(const QJniObject &intent) +{ + return QJniObject::callStaticMethod( + QtJniTypes::Traits::className(), "getTag", + intent.object()); +} + +} // namespace QtNfc + +QT_END_NAMESPACE + +Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void * /*reserved*/) +{ + static bool initialized = false; + if (initialized) + return JNI_VERSION_1_6; + initialized = true; + + JNIEnv* env; + if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK) { + return -1; + } + + return JNI_VERSION_1_6; +} diff --git a/src/nfc/android/androidjninfc_p.h b/src/nfc/android/androidjninfc_p.h new file mode 100644 index 0000000..476e051 --- /dev/null +++ b/src/nfc/android/androidjninfc_p.h @@ -0,0 +1,44 @@ +// Copyright (C) 2016 Centria research and development +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +#ifndef ANDROIDJNINFC_H +#define ANDROIDJNINFC_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 "qglobal.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_JNI_CLASS(QtNfc, "org/qtproject/qt/android/nfc/QtNfc") +Q_DECLARE_JNI_CLASS(QtNfcBroadcastReceiver, "org/qtproject/qt/android/nfc/QtNfcBroadcastReceiver") + +Q_DECLARE_JNI_TYPE(StringArray, "[Ljava/lang/String;") +Q_DECLARE_JNI_CLASS(Intent, "android/content/Intent") +Q_DECLARE_JNI_CLASS(Parcellable, "android/os/Parcelable") + +Q_DECLARE_JNI_CLASS(NdefMessage, "android/nfc/NdefMessage") + +namespace QtNfc { +bool startDiscovery(); +bool stopDiscovery(); +QJniObject getStartIntent(); +bool isEnabled(); +bool isSupported(); +QJniObject getTag(const QJniObject &intent); +} // namespace QtNfc + +QT_END_NAMESPACE + +#endif diff --git a/src/nfc/android/androidmainnewintentlistener.cpp b/src/nfc/android/androidmainnewintentlistener.cpp new file mode 100644 index 0000000..cebf92d --- /dev/null +++ b/src/nfc/android/androidmainnewintentlistener.cpp @@ -0,0 +1,103 @@ +// Copyright (C) 2016 BasysKom GmbH +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + + +#include "androidmainnewintentlistener_p.h" +#include "android/androidjninfc_p.h" +#include +#include + +QT_BEGIN_NAMESPACE + +QMainNfcNewIntentListener::QMainNfcNewIntentListener() : paused(true), receiving(false) +{ + QtAndroidPrivate::registerNewIntentListener(this); + QtAndroidPrivate::registerResumePauseListener(this); +} + +QMainNfcNewIntentListener::~QMainNfcNewIntentListener() +{ + QtAndroidPrivate::unregisterNewIntentListener(this); + QtAndroidPrivate::unregisterResumePauseListener(this); +} + +bool QMainNfcNewIntentListener::handleNewIntent(JNIEnv * /*env*/, jobject intent) +{ + // Only intents with a tag are relevant + if (!QtNfc::getTag(intent).isValid()) + return false; + + listenersLock.lockForRead(); + for (auto listener : std::as_const(listeners)) { + listener->newIntent(QJniObject(intent)); + } + listenersLock.unlock(); + return true; +} + +bool QMainNfcNewIntentListener::registerListener(QAndroidNfcListenerInterface *listener) +{ + static bool firstListener = true; + if (firstListener) { + QJniObject intent = QtNfc::getStartIntent(); + if (intent.isValid()) { + listener->newIntent(intent); + } + paused = static_cast(QGuiApplication::instance())->applicationState() != Qt::ApplicationActive; + } + firstListener = false; + listenersLock.lockForWrite(); + if (!listeners.contains(listener)) + listeners.push_back(listener); + listenersLock.unlock(); + updateReceiveState(); + return true; +} + +bool QMainNfcNewIntentListener::unregisterListener(QAndroidNfcListenerInterface *listener) +{ + listenersLock.lockForWrite(); + listeners.removeOne(listener); + listenersLock.unlock(); + updateReceiveState(); + return true; +} + +void QMainNfcNewIntentListener::handleResume() +{ + paused = false; + updateReceiveState(); +} + +void QMainNfcNewIntentListener::handlePause() +{ + paused = true; + updateReceiveState(); +} + +void QMainNfcNewIntentListener::updateReceiveState() +{ + if (paused) { + // We were paused while receiving, so we stop receiving. + if (receiving) { + QtNfc::stopDiscovery(); + receiving = false; + } + return; + } + + // We reach here, so we are not paused. + listenersLock.lockForRead(); + // We have nfc listeners and do not receive. Switch on. + if (!listeners.isEmpty() && !receiving) + receiving = QtNfc::startDiscovery(); + + // we have no nfc listeners and do receive. Switch off. + if (listeners.isEmpty() && receiving) { + QtNfc::stopDiscovery(); + receiving = false; + } + listenersLock.unlock(); +} + +QT_END_NAMESPACE diff --git a/src/nfc/android/androidmainnewintentlistener_p.h b/src/nfc/android/androidmainnewintentlistener_p.h new file mode 100644 index 0000000..eb3c521 --- /dev/null +++ b/src/nfc/android/androidmainnewintentlistener_p.h @@ -0,0 +1,62 @@ +// Copyright (C) 2016 BasysKom GmbH +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef ANDROIDMAINNEWINTENTLISTENER_P_H_ +#define ANDROIDMAINNEWINTENTLISTENER_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 "qlist.h" +#include "qreadwritelock.h" + +QT_BEGIN_NAMESPACE + +class QJniObject; + +class QAndroidNfcListenerInterface +{ +public: + virtual ~QAndroidNfcListenerInterface() = default; + virtual void newIntent(QJniObject intent) = 0; +}; + +class QMainNfcNewIntentListener : public QtAndroidPrivate::NewIntentListener, + QtAndroidPrivate::ResumePauseListener +{ +public: + QMainNfcNewIntentListener(); + ~QMainNfcNewIntentListener(); + + //QtAndroidPrivate::NewIntentListener + bool handleNewIntent(JNIEnv *env, jobject intent); + + bool registerListener(QAndroidNfcListenerInterface *listener); + bool unregisterListener(QAndroidNfcListenerInterface *listener); + + //QtAndroidPrivate::ResumePauseListener + void handleResume(); + void handlePause(); + +private: + void updateReceiveState(); + + QList listeners; + QReadWriteLock listenersLock; + bool paused; + bool receiving; +}; + +QT_END_NAMESPACE + +#endif /* ANDROIDMAINNEWINTENTLISTENER_P_H_ */ diff --git a/src/nfc/configure.cmake b/src/nfc/configure.cmake new file mode 100644 index 0000000..10d66c8 --- /dev/null +++ b/src/nfc/configure.cmake @@ -0,0 +1,8 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +qt_find_package(PCSCLITE PROVIDED_TARGETS PkgConfig::PCSCLITE) + +qt_feature("pcsclite" PUBLIC + LABEL "PCSCLite" + CONDITION PCSCLITE_FOUND) diff --git a/src/nfc/doc/qtnfc.qdocconf b/src/nfc/doc/qtnfc.qdocconf new file mode 100644 index 0000000..10aede7 --- /dev/null +++ b/src/nfc/doc/qtnfc.qdocconf @@ -0,0 +1,50 @@ +include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf) +include($QT_INSTALL_DOCS/config/exampleurl-qtconnectivity.qdocconf) + +project = QtNfc +description = Qt NFC Reference Documentation +version = $QT_VERSION + +examplesinstallpath = nfc + +qhp.projects = QtNfc + +qhp.QtNfc.file = qtnfc.qhp +qhp.QtNfc.namespace = org.qt-project.qtnfc.$QT_VERSION_TAG +qhp.QtNfc.virtualFolder = qtnfc +qhp.QtNfc.indexTitle = Qt NFC +qhp.QtNfc.indexRoot = + +qhp.QtNfc.subprojects = overviews classes examples +qhp.QtNfc.subprojects.classes.title = C++ Classes +qhp.QtNfc.subprojects.classes.indexTitle = Qt NFC C++ Classes +qhp.QtNfc.subprojects.classes.selectors = class fake:headerfile +qhp.QtNfc.subprojects.classes.sortPages = true +qhp.QtNfc.subprojects.overviews.title = Overviews +qhp.QtNfc.subprojects.overviews.indexTitle = Qt NFC Overview +qhp.QtNfc.subprojects.overviews.selectors = fake:page,group,module +qhp.QtNfc.subprojects.examples.title = Qt NFC Examples +qhp.QtNfc.subprojects.examples.indexTitle = Qt NFC Examples +qhp.QtNfc.subprojects.examples.selectors = fake:example + +tagfile = ../../../doc/qtnfc/qtnfc.tags + +depends += qtcore qtwidgets qtdoc qmake qtcmake + +headerdirs += .. + +sourcedirs += .. + +exampledirs += ../../../examples/nfc \ + snippets/ + +imagedirs += images + +manifestmeta.highlighted.names = \ + "QtNfc/Annotated URL" + +navigation.landingpage = "Qt NFC" +navigation.cppclassespage = "Qt NFC C++ Classes" + +# Enforce zero documentation warnings +warninglimit = 0 diff --git a/src/nfc/doc/snippets/main.cpp b/src/nfc/doc/snippets/main.cpp new file mode 100644 index 0000000..fb6724d --- /dev/null +++ b/src/nfc/doc/snippets/main.cpp @@ -0,0 +1,8 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +int main(int /*argc*/, char ** /*argv*/) +{ + return 0; +} + diff --git a/src/nfc/doc/snippets/nfc.cpp b/src/nfc/doc/snippets/nfc.cpp new file mode 100644 index 0000000..a1192be --- /dev/null +++ b/src/nfc/doc/snippets/nfc.cpp @@ -0,0 +1,36 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include +#include + +#include + +QT_USE_NAMESPACE + +void snippet_recordConversion() +{ + QNdefRecord record; + + //! [Record conversion] + if (record.isRecordType()) { + QNdefNfcTextRecord textRecord(record); + + qDebug() << textRecord.text(); + } + //! [Record conversion] +} + +//! [Specialized class definition] +class ExampleComF : public QNdefRecord +{ +public: + Q_DECLARE_NDEF_RECORD(ExampleComF, QNdefRecord::ExternalRtd, "example.com:f", + QByteArray(sizeof(int), char(0))) + + int foo() const; + void setFoo(int v); +}; + +Q_DECLARE_ISRECORDTYPE_FOR_NDEF_RECORD(ExampleComF, QNdefRecord::ExternalRtd, "example.com:f") +//! [Specialized class definition] diff --git a/src/nfc/doc/src/examples.qdoc b/src/nfc/doc/src/examples.qdoc new file mode 100644 index 0000000..a126763 --- /dev/null +++ b/src/nfc/doc/src/examples.qdoc @@ -0,0 +1,25 @@ +// Copyright (C) 2013 Aaron McCarthy +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! +\page nfc-examples.html +\title Qt NFC Examples +\brief Examples for the Qt NFC module. + +This is a variety of examples that cover the entire range of the Qt NFC API. You will find them +in their own documentation, but they are also accessible from here. + +\section2 C++ Examples +\table 80% + \header + \li Example + \li Description + \row + \li \l{annotatedurl}{Annotated URL} + \li Displays URLs stored on NFC Forum Tags. + \row + \li \l{ndefeditor}{NDEF Editor} + \li Create new or modify existing NDEF messages on NFC Forum Tags. +\endtable +*/ + diff --git a/src/nfc/doc/src/nfc-android.qdoc b/src/nfc/doc/src/nfc-android.qdoc new file mode 100644 index 0000000..e2ca540 --- /dev/null +++ b/src/nfc/doc/src/nfc-android.qdoc @@ -0,0 +1,64 @@ +// Copyright (C) 2015 BasysKom GmbH +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! +\ingroup connectivity-nfc +\inmodule QtNfc +\since 5.6 +\page nfc-android.html +\title Qt NFC on Android +\brief Notes on Nfc for Android. + +\section1 Automatically Launching NDEF Message Handlers on Android + +Android provides the possibility to automatically launch the application when +touching the NDEF tag. + +This can be achieved by providing an +\l {https://developer.android.com/guide/topics/manifest/manifest-intro.html} +{Android manifest file} (AndroidManifest.xml) with proper +\l{https://developer.android.com/guide/topics/connectivity/nfc/nfc.html#manifest} +{NFC intent-filter}. + +\badcode + + + + + +\endcode + +With this intent-filter enabled, the application will be automatically started +once the NDEF NFC tag is touched. + +\note It's important to design your application in such a way that all the GUI +is connected to the NFC classes before the target detection is actually started. +Otherwise it will be impossible to show the information from the tag that caused +application startup. + +\note It's important to touch the tag long enough for the application to start +and read the information. If the tag is lost during application startup, no data +will be available, and the tag needs to be touched again. + +See \l {annotatedurl}{Annotated URL} application as an example. + +\section2 Supported Tag Types + +Supported tag types in Android are +\l {https://developer.android.com/reference/android/nfc/NfcAdapter.html#ACTION_NDEF_DISCOVERED} +{ACTION_NDEF_DISCOVERED}, +\l {https://developer.android.com/reference/android/nfc/NfcAdapter.html#ACTION_TAG_DISCOVERED} +{ACTION_TAG_DISCOVERED} and +\l {https://developer.android.com/reference/android/nfc/NfcAdapter.html#ACTION_TECH_DISCOVERED} +{ACTION_TECH_DISCOVERED} with +\l {https://developer.android.com/reference/android/nfc/tech/TagTechnology.html} +{TagTechnology} \e NdefFormatable or \e Ndef. + +If the application registers other types in the +\l {https://developer.android.com/guide/topics/manifest/manifest-intro.html} +{Android manifest file}, the application will be started, but the tag will never +be processed. + +*/ + diff --git a/src/nfc/doc/src/nfc-cpp.qdoc b/src/nfc/doc/src/nfc-cpp.qdoc new file mode 100644 index 0000000..0fef1d6 --- /dev/null +++ b/src/nfc/doc/src/nfc-cpp.qdoc @@ -0,0 +1,30 @@ +// Copyright (C) 2013 Aaron McCarthy +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only +/*! + +\module QtNfc +\ingroup modules +\qtcmakepackage Nfc +\qtvariable nfc + +\title Qt NFC C++ Classes +\brief An API for accessing NFC Forum Tags. + +The \l{Qt NFC} C++ API enables an application to access NFC Forum Tags. + +\include module-use.qdocinc using qt module + +\badcode +find_package(Qt6 REQUIRED COMPONENTS Nfc) +target_link_libraries(mytarget PRIVATE Qt::Nfc) +\endcode + +\include module-use.qdocinc building with qmake + +\badcode +QT += nfc +\endcode + +*/ + diff --git a/src/nfc/doc/src/nfc-features.qdoc b/src/nfc/doc/src/nfc-features.qdoc new file mode 100644 index 0000000..65c31f0 --- /dev/null +++ b/src/nfc/doc/src/nfc-features.qdoc @@ -0,0 +1,64 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! +\page qtnfc-features.html +\title Supported NFC Features +\ingroup connectivity-nfc +\inmodule QtNfc +\brief Summary of supported NFC features on different platforms. + +Qt NFC provides two options for reading and writing the data. These options are +reflected in the \l {QNearFieldTarget::}{AccessMethod} enum. + +\list + \li \l {QNearFieldTarget::}{NdefAccess} - using NDEF messages via + \l {QNearFieldTarget::}{readNdefMessages()} and + \l {QNearFieldTarget::}{writeNdefMessages()}. + \li \l {QNearFieldTarget::}{TagTypeSpecificAccess} - sending custom commands + using \l {QNearFieldTarget::}{sendCommand()} and getting the results via + \l {QNearFieldTarget::}{requestResponse()}. +\endlist + +\l {QNearFieldTarget::}{TagTypeSpecificAccess} implies that the +user might need to send different data based on the NFC Tag Type. Tag types +recognized by Qt NFC are defined in the \l {QNearFieldTarget::}{Type} enum. + +Qt NFC support for different access methods and tag types varies depending on +the platform. The table below shows currently supported subsets of features +for every platform. + +\table + \header + \li Platform + \li Recognized Tag Types + \li NDEF Support + \li Tag Specific Access + \row + \li \l {Qt NFC on Android}{Android} + \li All from the \l {QNearFieldTarget::}{Type} enum + \li Yes + \li Yes + \row + \li iOS + \li \list + \li \l {QNearFieldTarget::}{NfcTagType4} + \li \l {QNearFieldTarget::}{NfcTagType4A} + \li \l {QNearFieldTarget::}{NfcTagType4B} + \li \l {QNearFieldTarget::}{ProprietaryTag} + \endlist + \li No + \li Yes - for supported tag types + \row + \li Linux, Windows, macOS + + (implemented using \l {PC/SC in Qt NFC}{PC/SC}) + \li \list + \li \l {QNearFieldTarget::}{NfcTagType4} + \li \l {QNearFieldTarget::}{ProprietaryTag} + \endlist + \li Yes - for \l {QNearFieldTarget::}{NfcTagType4} + \li Yes - for \l {QNearFieldTarget::}{ProprietaryTag} +\endtable + +*/ diff --git a/src/nfc/doc/src/nfc-index.qdoc b/src/nfc/doc/src/nfc-index.qdoc new file mode 100644 index 0000000..986c761 --- /dev/null +++ b/src/nfc/doc/src/nfc-index.qdoc @@ -0,0 +1,72 @@ +// Copyright (C) 2013 Aaron McCarthy +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! +\page qtnfc-index.html +\title Qt NFC +\brief Enables connectivity between NFC enabled devices. +\ingroup technology-apis + +The NFC API provides connectivity between NFC enabled devices. + +Currently, the API is supported on \l{Qt for Android}{Android} and \l{Qt for +iOS}{iOS}. This module also provides limited access to readers supporting +\l{PC/SC in Qt NFC}{PC/SC} specification on Linux, macOS, and Windows. + +NFC is a short-range (less than 20 centimeters) wireless technology +with a maximum transfer rate of 424 Kbps. NFC is ideal for transferring +small packets of data when two devices are placed together. + +The NFC module provides APIs for interacting with NFC Forum Tags and NFC Forum +Devices. It can detect targets and losses, register NDEF message handlers, read +and write NDEF messages on NFC Forum Tags, and send tag-specific commands. + +\section1 Using the Module + +\include {module-use.qdocinc} {using the c++ api} {NFC} + +\section2 Building with CMake + +\include {module-use.qdocinc} {building with cmake} {Nfc} + +\section2 Building with qmake + +\include {module-use.qdocinc} {building_with_qmake} {nfc} + +\section1 Articles and Guides + +\list + \li \l {Qt NFC Overview} + \li \l {Supported NFC Features} + \li \l {Qt NFC on Android} + \li \l {PC/SC in Qt NFC} +\endlist + +\section1 Examples + +\list + \li \l {annotatedurl}{Annotated URL} + \li \l {ndefeditor}{NDEF Editor} +\endlist + +\section1 Reference + +\list + \li \l {Qt NFC C++ Classes}{C++ Classes} +\endlist + +\section1 Module Evolution + +\l {Changes to Qt NFC} lists important changes in the module API and +functionality that were done for the Qt 6 series of Qt. + +\section1 Licenses + +Qt NFC is available under commercial licenses from \l{The Qt Company}. +In addition, it is available under free software licenses. Since Qt 5.4, +these free software licenses are +\l{GNU Lesser General Public License, version 3}, or +the \l{GNU General Public License, version 2}. +See \l{Qt Licensing} for further details. +*/ diff --git a/src/nfc/doc/src/nfc-overview.qdoc b/src/nfc/doc/src/nfc-overview.qdoc new file mode 100644 index 0000000..81e7212 --- /dev/null +++ b/src/nfc/doc/src/nfc-overview.qdoc @@ -0,0 +1,135 @@ +// Copyright (C) 2013 Aaron McCarthy +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! +\ingroup technology-apis +\title Qt NFC Overview +\page qtnfc-overview.html +\brief Provides access to NFC enabled devices. +\ingroup explanations-networkingandconnectivity + +\tableofcontents + +With the Qt NFC API typical use cases are: + +\list + \li Detecting NFC tags. + \li Reading and writing NDEF messages. + \li Registering NDEF message handlers. + \li Sharing files and messages. +\endlist + +The following sections describe how to use Qt NFC C++ classes and QML types for the above use cases. + +\note On Android, the detection of new NFC tags only works in foreground applications. Android +services do not support this because of API limitations on the Android side. The only way to use a +\l{https://developer.android.com/reference/android/nfc/Tag}{Tag} in a service is to provide an +\l{https://developer.android.com/guide/components/aidl}{AIDL} interface accepting the Tag and forward +it to Qt as shown in the following example. + +\code + public void setTag(Tag pTag) { + Intent newIntent = new Intent(); + newIntent.putExtra(NfcAdapter.EXTRA_TAG, pTag); + QtNative.onNewIntent(newIntent); + } +\endcode + +\section1 C++ Overview + +The C++ API provides access to the full feature set of the Qt NFC API. This section introduces the +major features available to developers. + +\section2 Detecting NFC Tags + +The \l QNearFieldManager class is responsible for the detection of new NFC tags coming +into range of the device. The \l QNearFieldManager::targetDetected() and +\l QNearFieldManager::targetLost() signals are emitted when +a tag comes into or leaves the range. The passed \l QNearFieldTarget parameter acts +as primary interaction point for each detected tag. The detection does not actually start though until +\l QNearFieldManager::startTargetDetection() has been called. + +\code +m_manager = new QNearFieldManager(this); +connect(m_manager, &QNearFieldManager::targetDetected, + this, &MainWindow::targetDetected); +connect(m_manager, &QNearFieldManager::targetLost, + this, &MainWindow::targetLost); +m_manager->startTargetDetection(QNearFieldTarget::NdefAccess); +\endcode + +Finally the detection can be stopped: + +\code +m_manager->stopTargetDetection(); +\endcode + +Although each \l QNearFieldTarget instance is owned by its related \l QNearFieldManager +instance it can be beneficial to manually delete each instance. Otherwise they would continue to +exist until the \l QNearFieldManager instance is deleted. The best way to do that would be in response +to the \l QNearFieldManager::targetLost() signal: + +\code +void MainWindow::targetLost(QNearFieldTarget *target) +{ + target->deleteLater(); +} +\endcode + +\note The target object should only be deleted via deleteLater() if it is deleted inside the slot. + +\section2 Connecting NFC Tags + +All functions of \l QNearFieldTarget that require a connection will create one by its own. +An active connection will prevent other instances to create a connection because only one +connection at the time is allowed. + +Qt 5 disconnected the tag at the end of the functions to allow other instances to connect. +QNearFieldManager::setKeepConnection() allowed to change this behavior. + +Since Qt 6, \l QNearFieldTarget keeps the connection by default. The connection is only closed +when the \l QNearFieldTarget is destroyed or \l QNearFieldManager::disconnect() is called. + +\section2 Reading and Writing NDEF Messages + +The \l QNearFieldTarget instance returned by \l QNearFieldManager::targetDetected() signal +is used to interact with the tag. Reading and writing a message is an asynchronous operation. +The \l QNearFieldTarget::RequestId class associates individual operations and their results. + +\code +void MainWindow::targetDetected(QNearFieldTarget *target) +{ + switch (m_touchAction) { + case NoAction: + break; + case ReadNdef: + connect(target, &QNearFieldTarget::ndefMessageRead, this, &MainWindow::ndefMessageRead); + connect(target, &QNearFieldTarget::error, this, &MainWindow::targetError); + + m_request = target->readNdefMessages(); + if (!m_request.isValid()) // cannot read messages + targetError(QNearFieldTarget::NdefReadError, m_request); + break; + case WriteNdef: + connect(target, &QNearFieldTarget::requestCompleted, this, &MainWindow::ndefMessageWritten); + connect(target, &QNearFieldTarget::error, this, &MainWindow::targetError); + + m_request = target->writeNdefMessages(QList() << ndefMessage()); + if (!m_request.isValid()) // cannot write messages + targetError(QNearFieldTarget::NdefWriteError, m_request); + break; + } +} +\endcode + +Once the \l QNearFieldTarget::readNdefMessages() request was successfully processed, the +\l QNearFieldTarget::ndefMessageRead() signal is emitted. Each returned \l QNdefMessage +may consist of zero or more \l QNdefRecord entries, which can be identified by their type. +For more information about processing of records, see the \l QNdefRecord class documentation. +As the above code demonstrates, writing of NDEF messages is triggered via +\l QNearFieldTarget::writeNdefMessages(). The successful completion of the write operation +is indicated by the emission of the \l QNearFieldTarget::requestCompleted() signal with the +corresponding request id. Any type of error during read or write is indicated via +\l QNearFieldTarget::error(). +*/ diff --git a/src/nfc/doc/src/nfc-pcsc.qdoc b/src/nfc/doc/src/nfc-pcsc.qdoc new file mode 100644 index 0000000..532f031 --- /dev/null +++ b/src/nfc/doc/src/nfc-pcsc.qdoc @@ -0,0 +1,34 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! +\page qtnfc-pcsc.html +\title PC/SC in Qt NFC +\ingroup connectivity-nfc +\inmodule QtNfc +\since 6.4 +\brief Notes on PC/SC support in Qt Nfc. + +PC/SC support is provided using native APIs on macOS and Windows, and using +\l{https://pcsclite.apdu.fr/}{PCSCLite} library on other platforms. The API +can be used for accessing both wired and wireless smartcards and storage cards. + +\section1 Limitations + +\list + \li The current API does not provide means to distinguish between separate + readers/slots. + \li NDEF access is only provided for NFC Type 4 tags. + \li Other applications starting transactions on cards may block Qt applications + from using Qt Nfc API. + \li QNearFieldTarget::sendCommand() used with a PC/SC target starts + a transaction that remains active until QNearFieldTarget::disconnect() + is called. This transaction prevents other applications from accessing + this target. + \li The backend is polling for new tags, that means that there + may be a delay up to the full polling interval before new tags are reported. + The default polling interval is 100 milliseconds. It can be adjusted + by setting environment valiable \c{QT_NFC_POLL_INTERVAL_MS} to an integer + value in milliseconds. +\endlist +*/ diff --git a/src/nfc/doc/src/qt6-changes.qdoc b/src/nfc/doc/src/qt6-changes.qdoc new file mode 100644 index 0000000..5b25571 --- /dev/null +++ b/src/nfc/doc/src/qt6-changes.qdoc @@ -0,0 +1,149 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \page qtnfc-changes-qt6.html + \title Changes to Qt NFC + \ingroup changes-qt-5-to-6 + \brief Migrate Qt NFC to Qt 6. + + Qt 6 is a result of the conscious effort to make the framework more + efficient and easy to use. + + We try to maintain binary and source compatibility for all the public + APIs in each release. But some changes were inevitable in an effort to + make Qt a better framework. + + In this topic we summarize those changes in Qt NFC, and provide guidance + to handle them. + + \section1 New Features and Methods + + \section2 Added \l QNdefRecord::clear() + + Use this method to clear an NDEF record. + + \section2 Added \l QNdefFilter::match() + + Use this method to check if a \l QNdefMessage matches the given filter. + The method returns \c true in case of successful match and \c false + otherwise. + + \section2 Extended \l QNearFieldTarget::Type + + The enum was extended with two more types: + \list + \li \l QNearFieldTarget::NfcTagType4A + \li \l QNearFieldTarget::NfcTagType4B + \endlist + + \section1 Changes in the Features and Methods + + \section2 Renamed QNearFieldManager::isAvailable() + + The \c QNearFieldManager::isAvailable() was renamed to + \l QNearFieldManager::isEnabled(). + + \section2 Added access method argument to \l QNearFieldManager::isSupported + + The \c accessMethod argument allows to check if a specific feature is + supported. This is relevant because different platforms or versions of + operating systems can support different options. + + \section2 Added access method argument to \l QNearFieldManager::startTargetDetection + + The \c accessMethod argument allows to scan for NFC tags with the given + access method. + + \section2 Changed \l QNdefNfcSmartPosterRecord::typeInfo from \l QByteArray to \l QString + + According to NDEF Smart Poster specification, the type is a UTF-8 formatted + string. + This affects the \l QNdefNfcSmartPosterRecord::typeInfo() and + \l QNdefNfcSmartPosterRecord::setTypeInfo() methods. + + \section2 Updated return type of \l QNdefFilter::appendRecord + + \l QNdefFilter::appendRecord now performs a basic validation of input + parameters and returns a boolean value indicating if the record is appended + to the filter or not. + + \section1 Removed Features and Methods + + \section2 Removed QNearFieldTarget::url + + The method was never implemented in the existing subclasses of + \l QNearFieldTarget. + + \section2 Removed QNearFieldTarget::sendCommands + + In Qt 5, the method was not very helpful because it didn't provide a way to + track the results of intermediate commands. Normally, an additional command + needs to be sent only when the previous command is successfully executed. + + The correct approach would be to manually create a queue of commands, + use \l QNearFieldTarget::sendCommand to send a command and + \l QNearFieldTarget::requestCompleted or \l QNearFieldTarget::error to + handle the results of each command individually. + + \section2 Removed QNearFieldTarget::keepConnection + + The methods \c QNearFieldTarget::keepConnection() and + \c QNearFieldTarget::setKeepConnection() were removed. Keeping the + connection is the default behavior for now. + + \section2 Removed QNearFieldTarget::isProcessingCommand + + The method was never implemented and always returned \c false. + + \section2 Made QNearFieldTarget::setResponseForRequest private API + + The method should not be exposed as a public API. Use + \l QNearFieldTarget::ndefMessageRead or \l QNearFieldTarget::requestResponse + to read the data from an NFC tag. + + \section2 Removed QNearFieldTarget::handleResponse + + The method was removed as it just forwarded the call to + \c QNearFieldManager::setResponseForRequest, which became private API. + + \section2 Made QNearFieldTarget::reportError private API + + A \l QNearFieldTarget::error signal can be used instead. + + \section2 Removed QNearFieldTarget::ndefMessagesWritten signal + + The \l QNearFieldTarget::requestCompleted signal is used for both NDEF + messages and custom commands. The \c id parameter can be used to check which + request is actually completed. + + \section2 Removed QNearFieldManager::(un)registerNdefMessageHandler + + The methods \c QNearFieldTarget::registerNdefMessageHandler and + \c QNearFieldTarget::unregisterNdefMessageHandler were removed. + + Use \l QNearFieldTarget::ndefMessageRead() and \l QNdefFilter::match() to + detect the NDEF messages and filter the required ones. + + \note The application can still be automatically started once the NDEF Tag + is touched. The \l {annotatedurl}{Annotated URL} example shows how to + achieve it on Android. + + \section2 Removed QNearFieldManager::TargetAccessModes + + The \c TargetAccessModes enum was removed together with the getter and + setter methods (\c QNearFieldManager::setTargetAccessModes() and + \c {QNearFieldManager::targetAccessModes()}). + + The feature is not supported on Android and iOS platforms. + + \section2 Removed QNearFieldShareManager and QNearFieldShareTarget + + File sharing via NFC is deprecated on Android in API 29. Other technologies + should be used instead. + + \section2 Removed QML API + + The support for QML API is discontinued. + +*/ diff --git a/src/nfc/ios/qiosndefnotifier.cpp b/src/nfc/ios/qiosndefnotifier.cpp new file mode 100644 index 0000000..20e01f0 --- /dev/null +++ b/src/nfc/ios/qiosndefnotifier.cpp @@ -0,0 +1,11 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qiosndefnotifier_p.h" + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(QT_IOS_NFC, "qt.nfc.ios") + +QT_END_NAMESPACE + diff --git a/src/nfc/ios/qiosndefnotifier_p.h b/src/nfc/ios/qiosndefnotifier_p.h new file mode 100644 index 0000000..fadade4 --- /dev/null +++ b/src/nfc/ios/qiosndefnotifier_p.h @@ -0,0 +1,56 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QIOSNDEFNOTIFIER_P_H +#define QIOSNDEFNOTIFIER_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 "qnearfieldmanager.h" +#include "qnearfieldtarget.h" + +QT_BEGIN_NAMESPACE + +class QNdefMessage; +class QString; + +class QNfcNdefNotifier : public QObject +{ + Q_OBJECT + +public: + QNfcNdefNotifier() = default; + +Q_SIGNALS: + void tagDetected(void *tag); + void invalidateWithError(bool restart); + void tagLost(void *tag); + + void tagError(QNearFieldTarget::Error code, QNearFieldTarget::RequestId request); + + void ndefMessageWritten(QNearFieldTarget::RequestId request); + void ndefMessageRead(const QNdefMessage &message, QNearFieldTarget::RequestId request); + +private: + Q_DISABLE_COPY_MOVE(QNfcNdefNotifier); +}; + +Q_DECLARE_LOGGING_CATEGORY(QT_IOS_NFC) + +QT_END_NAMESPACE + +#endif //QIOSNDEFNOTIFIER_P_H diff --git a/src/nfc/ios/qiosnfcndefsessiondelegate.mm b/src/nfc/ios/qiosnfcndefsessiondelegate.mm new file mode 100644 index 0000000..4db39ed --- /dev/null +++ b/src/nfc/ios/qiosnfcndefsessiondelegate.mm @@ -0,0 +1,298 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qiosnfcndefsessiondelegate_p.h" +#include "qiosndefnotifier_p.h" + +#include "qndefmessage.h" + +#include +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +dispatch_queue_t qt_Nfc_Queue() +{ + static dispatch_queue_t nfcQueue = []{ + auto queue = dispatch_queue_create("qt-NFC-queue", DISPATCH_QUEUE_SERIAL); + if (!queue) + qCWarning(QT_IOS_NFC, "Failed to create the QtNfc's dispatch queue"); + return queue; + }(); + static const auto queueGuard = qScopeGuard([]{ + if (nfcQueue) + dispatch_release(nfcQueue); + }); + return nfcQueue; +} + +QT_END_NAMESPACE + +QT_USE_NAMESPACE + +@implementation QIosNfcNdefSessionDelegate +{ + std::unique_ptr notifier; + QString alertMessage; + NFCNDEFStatus tagStatus; + NSUInteger capacity; + QNearFieldTarget::RequestId requestId; +} + +-(instancetype)initWithNotifier:(QNfcNdefNotifier *)aNotifier +{ + Q_ASSERT(aNotifier); + + if (self = [super init]) { + auto queue = qt_Nfc_Queue(); + if (!queue) + return self; + + tagStatus = NFCNDEFStatusNotSupported; + capacity = 0; + notifier.reset(aNotifier); + } + + return self; +} + +-(void)dealloc +{ + [self abort]; + [super dealloc]; +} + +-(QNfcNdefNotifier *)ndefNotifier +{ + return notifier.get(); +} + +-(void)abort +{ + notifier.reset(nullptr); + [self reset]; +} + +-(bool)startSession +{ + if (self.session) + return true; + + auto queue = qt_Nfc_Queue(); + Q_ASSERT(queue); + self.session = [[NFCNDEFReaderSession alloc] initWithDelegate:self queue:queue invalidateAfterFirstRead:NO]; + if (alertMessage.size()) + self.session.alertMessage = alertMessage.toNSString(); + + if (!self.session) + return false; + + qCDebug(QT_IOS_NFC, "Starting NFC NDEF reader session"); + [self.session beginSession]; + return true; +} + +-(void)reset +{ + self.session = nil; // Strong property, releases. + self.ndefTag = nil; // Strong property, releases. + requestId = {}; + tagStatus = NFCNDEFStatusNotSupported; + capacity = 0; +} + +-(void)stopSession:(const QString &)message +{ + if (!self.session) + return; + + if (self.ndefTag && notifier.get()) + emit notifier->tagLost(self.ndefTag); + + if (message.size()) + [self.session invalidateSessionWithErrorMessage:message.toNSString()]; + else + [self.session invalidateSession]; + + [self reset]; +} + +-(void)setAlertMessage:(const QString &)message +{ + alertMessage = message; +} + +-(void)readerSession:(NFCNDEFReaderSession *)session + didInvalidateWithError:(NSError *)error +{ + if (session != self.session) // If we stopped the session, this maybe the case. + return; + + if (!notifier.get()) // Aborted. + return; + + NSLog(@"session did invalidate with error %@", error); + + if (error.code != NFCReaderSessionInvalidationErrorUserCanceled && error.code != NFCReaderErrorUnsupportedFeature) { + if (self.ndefTag) + emit notifier->tagError(QNearFieldTarget::TimeoutError, {}); + + emit notifier->invalidateWithError(true); + [self reset]; + } + + // Native errors: + // + // NFCReaderErrorRadioDisabled + // NFCReaderErrorUnsupportedFeature + // NFCReaderErrorSecurityViolation + // NFCReaderErrorInvalidParameter + // NFCReaderErrorParameterOutOfBound + // NFCReaderErrorInvalidParameterLength + // NFCReaderTransceiveErrorTagConnectionLost + // NFCReaderTransceiveErrorRetryExceeded + // NFCReaderTransceiveErrorSessionInvalidated + // NFCReaderTransceiveErrorTagNotConnected + // NFCReaderTransceiveErrorPacketTooLong + // NFCReaderSessionInvalidationErrorUserCanceled + // NFCReaderSessionInvalidationErrorSessionTimeout + // NFCReaderSessionInvalidationErrorSessionTerminatedUnexpectedly + // NFCReaderSessionInvalidationErrorSystemIsBusy + // NFCReaderSessionInvalidationErrorFirstNDEFTagRead + // NFCTagCommandConfigurationErrorInvalidParameters + // NFCNdefReaderSessionErrorTagNotWritable + // NFCNdefReaderSessionErrorTagUpdateFailure + // NFCNdefReaderSessionErrorTagSizeTooSmall + //NFCNdefReaderSessionErrorZeroLengthMessage + + // And these are what Qt has ... + /* + enum Error { + NoError, + UnknownError, + UnsupportedError, + TargetOutOfRangeError, + NoResponseError, + ChecksumMismatchError, + InvalidParametersError, + ConnectionError, + NdefReadError, + NdefWriteError, + CommandError, + TimeoutError + }; + */ + // TODO: try to map those native errors to Qt ones ... +} + +-(void)readerSession:(NFCNDEFReaderSession *)session + didDetectNDEFs:(NSArray *)messages +{ + Q_UNUSED(session); + Q_UNUSED(messages); + // It's intentionally a noop and should never be called, because + // we implement the other method, giving us access to a tag. + Q_UNREACHABLE(); +} + +-(void)restartPolling +{ + if (!self.session) + return; + + auto queue = qt_Nfc_Queue(); + Q_ASSERT(queue); + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, + int64_t(100./1000. * NSEC_PER_SEC)),//100 ms + queue, + ^{ + [self.session restartPolling]; + }); +} + +-(void)tag:(id)tag didUpdateNDEFStatus:(NFCNDEFStatus)status + capacity:(NSUInteger)aCapacity error:(NSError *)error +{ + if (!notifier.get()) // Aborted. + return; + + if (tag != self.ndefTag) + return; + + if (error) { + NSLog(@"Querying NDEF tag's status failed: %@, restarting polling ...", error); + self.ndefTag = nil; + return [self restartPolling]; + } + + tagStatus = status; + capacity = aCapacity; + + if (status == NFCNDEFStatusNotSupported) { + qCDebug(QT_IOS_NFC, "The discovered tag does not support NDEF."); + return [self restartPolling]; + } + + if (status == NFCNDEFStatusReadWrite) + qCDebug(QT_IOS_NFC, "NDEF read/write capable tag found"); + + if (status == NFCNDEFStatusReadOnly) + qCDebug(QT_IOS_NFC, "The discovered tag is read only"); + + qCInfo(QT_IOS_NFC) << "The max message size for the tag is:" << capacity; + + [self.session connectToTag:self.ndefTag completionHandler:^(NSError * _Nullable error) { + if (!error) { + if (notifier.get()) + emit notifier->tagDetected(self.ndefTag); + } else { + NSLog(@"Failed to connect to NDEF-capable tag, error: %@", error); + [self restartPolling]; + } + }]; +} + + +-(void)readerSession:(NFCNDEFReaderSession *)session + didDetectTags:(NSArray<__kindof id> *)tags +{ + if (!notifier.get()) + return; // Aborted by Qt. + + if (session != self.session) // We stopped _that_ session. + return; + + if (tags.count != 1) { + qCWarning(QT_IOS_NFC, "Unexpected number of NDEF tags, restarting ..."); + [self restartPolling]; + return; + } + + NSLog(@"detected a tag! %@", tags[0]); + + id tag = tags[0]; + self.ndefTag = tag; // Strong reference, retains. + tagStatus = NFCNDEFStatusNotSupported; + capacity = 0; + + [self.ndefTag queryNDEFStatusWithCompletionHandler: + ^(NFCNDEFStatus status, NSUInteger aCapacity, NSError * _Nullable error) { + [self tag:tag didUpdateNDEFStatus:status capacity:aCapacity error:error]; + }]; +} + +-(void)readerSessionDidBecomeActive:(NFCNDEFReaderSession *)session +{ + if (session != self.session) + return [session invalidateSession]; + + qCInfo(QT_IOS_NFC, "session is active now"); +} + +@end + diff --git a/src/nfc/ios/qiosnfcndefsessiondelegate_p.h b/src/nfc/ios/qiosnfcndefsessiondelegate_p.h new file mode 100644 index 0000000..5ec1c12 --- /dev/null +++ b/src/nfc/ios/qiosnfcndefsessiondelegate_p.h @@ -0,0 +1,88 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QIOSNFCNDEFSESSIONDELEFATE_P_H +#define QIOSNFCNDEFSESSIONDELEFATE_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 "qnearfieldmanager.h" +#include "qnearfieldtarget.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +class QNearFieldManagerPrivateImpl; +class QNfcNdefNotifier; +class QNearFieldTarget; +class QNdefMessage; +class QString; + +dispatch_queue_t qt_Nfc_Queue(); + +QT_END_NAMESPACE + +QT_USE_NAMESPACE + +@interface QT_MANGLE_NAMESPACE(QIosNfcNdefSessionDelegate) : NSObject + +@property (strong, nonatomic) NFCNDEFReaderSession *session; +@property (strong, nonatomic) id ndefTag; + + +-(instancetype)initWithNotifier:(QNfcNdefNotifier *)aNotifier; +-(void)dealloc; + +-(QNfcNdefNotifier *)ndefNotifier; + +-(void)setAlertMessage:(const QString &)message; + +// Those methods to be called on the session.sessionQueue: +-(bool)startSession; +-(void)stopSession:(const QString &)message; +-(void)abort; + +// Delegate's methods, implementing the protocol NFCNDEFReaderSessionDelegate. +// Those methods not to be called by the Qt. + +// "Gets called when a session becomes invalid. At this point the client is expected to +// discard the returned session object." +-(void)readerSession:(NFCNDEFReaderSession *)session + didInvalidateWithError:(NSError *)error; + +// "Gets called when the reader detects NFC tag(s) with NDEF messages in the polling sequence. +// Polling is automatically restarted once the detected tag is removed from the reader's read +// range. This method is only get call if the optional -readerSession:didDetectTags: method +// is not implemented." +-(void)readerSession:(NFCNDEFReaderSession *)session + didDetectNDEFs:(NSArray *)messages; + +// "Gets called when the reader detects NDEF tag(s) in the RF field. Presence of this method +// overrides -readerSession:didDetectNDEFs: and enables read-write capability for the session." +-(void)readerSession:(NFCNDEFReaderSession *)session + didDetectTags:(NSArray<__kindof id> *)tags; + +// "Gets called when the NFC reader session has become active. RF is enabled and reader is +// scanning for tags." +-(void)readerSessionDidBecomeActive:(NFCNDEFReaderSession *)session; + +@end + +QT_NAMESPACE_ALIAS_OBJC_CLASS(QIosNfcNdefSessionDelegate); + +#endif // QIOSNFCNDEFSESSIONDELEFATE_P_H diff --git a/src/nfc/ios/qiostagreaderdelegate.mm b/src/nfc/ios/qiostagreaderdelegate.mm new file mode 100644 index 0000000..fd7db02 --- /dev/null +++ b/src/nfc/ios/qiostagreaderdelegate.mm @@ -0,0 +1,110 @@ +// Copyright (C) 2020 Governikus GmbH & Co. KG +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qiostagreaderdelegate_p.h" + +#include "qnearfieldmanager_ios_p.h" + +#import +#import + +QT_USE_NAMESPACE + +@implementation QT_MANGLE_NAMESPACE(QIosTagReaderDelegate) + +- (instancetype)initWithListener:(QNearFieldManagerPrivateImpl *)listener +{ + self = [super init]; + if (self) { + self.listener = listener; + self.sessionStoppedByApplication = false; + self.message = nil; + self.session = nil; + } + + return self; +} + +- (void)startSession +{ + if (self.session && !self.sessionStoppedByApplication) { + [self.session invalidateSession]; + self.sessionStoppedByApplication = true; + } + + if (self.sessionStoppedByApplication) { + Q_EMIT self.listener->didInvalidateWithError(true); + return; + } + + self.session = [[[NFCTagReaderSession alloc] initWithPollingOption:NFCPollingISO14443 delegate:self queue:nil] autorelease]; + if (self.session) { + if (self.message) + self.session.alertMessage = self.message; + [self.session beginSession]; + } else { + Q_EMIT self.listener->didInvalidateWithError(true); + } +} + +- (void)stopSession:(QString)message +{ + if (self.session && !self.sessionStoppedByApplication) { + if (message.isNull()) + [self.session invalidateSession]; + else + [self.session invalidateSessionWithErrorMessage:message.toNSString()]; + self.sessionStoppedByApplication = true; + } +} + +- (void)alertMessage:(QString)message +{ + if (self.session && !self.sessionStoppedByApplication) + self.session.alertMessage = message.toNSString(); + else + self.message = message.toNSString(); +} + +- (void)tagReaderSessionDidBecomeActive:(NFCTagReaderSession*)session +{ + if (session != self.session) + [session invalidateSession]; +} + +- (void)tagReaderSession:(NFCTagReaderSession*)session didInvalidateWithError:(NSError*)error +{ + if (session != self.session) + return; + + self.session = nil; + if (self.sessionStoppedByApplication) { + self.sessionStoppedByApplication = false; + return; + } + + const bool doRestart = + !(error.code == NFCReaderError::NFCReaderSessionInvalidationErrorUserCanceled + || error.code == NFCReaderError::NFCReaderErrorUnsupportedFeature); + Q_EMIT self.listener->didInvalidateWithError(doRestart); +} + +- (void)tagReaderSession:(NFCTagReaderSession*)session didDetectTags:(NSArray<__kindof id>*)tags +{ + if (session != self.session) + return; + + bool foundTag = false; + for (id tag in tags) { + if (tag.type == NFCTagTypeISO7816Compatible) { + foundTag = true; + [tag retain]; + Q_EMIT self.listener->tagDiscovered(tag); + } + } + + if (!foundTag) + [session restartPolling]; +} + +@end diff --git a/src/nfc/ios/qiostagreaderdelegate_p.h b/src/nfc/ios/qiostagreaderdelegate_p.h new file mode 100644 index 0000000..7defcd4 --- /dev/null +++ b/src/nfc/ios/qiostagreaderdelegate_p.h @@ -0,0 +1,48 @@ +// Copyright (C) 2020 Governikus GmbH & Co. KG +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QIOSTAGREADERDELEGATE_P_H +#define QIOSTAGREADERDELEGATE_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 + +#import +#import +#import + +QT_BEGIN_NAMESPACE + +class QNearFieldManagerPrivateImpl; + +QT_END_NAMESPACE + +API_AVAILABLE(ios(13.0)) +@interface QT_MANGLE_NAMESPACE(QIosTagReaderDelegate) + : NSObject + +@property QNearFieldManagerPrivateImpl *listener; +@property bool sessionStoppedByApplication; +@property (nonatomic, strong) NSString *message; +@property (nonatomic, strong) NFCTagReaderSession *session; + +- (instancetype)initWithListener:(QNearFieldManagerPrivateImpl *)listener; + +- (void)startSession; +- (void)stopSession:(QString)message; + +- (void)alertMessage:(QString)message; + +@end + +#endif // QIOSTAGREADERDELEGATE_P_H diff --git a/src/nfc/ndef/qndefaccessfsm_p.h b/src/nfc/ndef/qndefaccessfsm_p.h new file mode 100644 index 0000000..2a175bc --- /dev/null +++ b/src/nfc/ndef/qndefaccessfsm_p.h @@ -0,0 +1,103 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QNDEFACCESSFSM_P_H +#define QNDEFACCESSFSM_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 "qndefmessage.h" + +QT_BEGIN_NAMESPACE + +/* + Base class for FSMs that can be used to exchange NDEF messages with cards. + + The user may call one of these methods to start a task: + + - detectNdefSupport() + - readMessages() + - writeMessages() + + The user is then expected to perform actions indicated by Action type. +*/ +class QNdefAccessFsm +{ + Q_DISABLE_COPY_MOVE(QNdefAccessFsm) +public: + QNdefAccessFsm() = default; + virtual ~QNdefAccessFsm() = default; + + enum Action { + // The requested task has successfully completed. New tasks can be started. + Done, + // The requested task has failed. New tasks can be started. + Failed, + // An NDEF message was successfully read. The user must call getMessage(). + GetMessage, + // The user's call was unexpected. The FSM may be in an invalid state. + Unexpected, + // The user must call getCommand() and then send the returned command to the card. + SendCommand, + // The user must call provideResponse() with the result of the last sent command. + ProvideResponse + }; + + /* + Returns a command to send to the card. + + This method must be called if the FMS has requested SendCommand action. + + Next action will be ProvideResponse or Unexpected. + */ + virtual QByteArray getCommand(Action &nextAction) = 0; + + /* + This method must be called by the user to provide response for + a completed command. + + An empty QByteArray can be provided to indicate that the command + has failed. + */ + virtual Action provideResponse(const QByteArray &response) = 0; + + /* + Returns an NDEF message that was read from the card. + + This method must be called if the FSM has requested GetMessage action. + */ + virtual QNdefMessage getMessage(Action &nextAction) = 0; + + /* + Start NDEF support detection. + */ + virtual Action detectNdefSupport() = 0; + + /* + Start reading NDEF messages. + + This call also performs NDEF support detection if it was not performed + earlier. + */ + virtual Action readMessages() = 0; + + /* + Start writing the given messages to the card. + + This call also performs NDEF detection if is was not performed earlier. + */ + virtual Action writeMessages(const QList &messages) = 0; +}; + +QT_END_NAMESPACE + +#endif // QNDEFACCESSFSM_P_H diff --git a/src/nfc/ndef/qnfctagtype4ndeffsm.cpp b/src/nfc/ndef/qnfctagtype4ndeffsm.cpp new file mode 100644 index 0000000..c21608e --- /dev/null +++ b/src/nfc/ndef/qnfctagtype4ndeffsm.cpp @@ -0,0 +1,374 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qnfctagtype4ndeffsm_p.h" +#include +#include + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(QT_NFC_T4T, "qt.nfc.t4t") + +/* + NDEF support for NFC Type 4 tags. + + Based on Type 4 Tag Operation Specification, Version 2.0 (T4TOP 2.0). +*/ + +QByteArray QNfcTagType4NdefFsm::getCommand(QNdefAccessFsm::Action &nextAction) +{ + // ID of the NDEF Tag Application + static constexpr uint8_t NtagApplicationIdV2[] { 0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01 }; + // Capability container file ID. + static constexpr uint8_t CapabilityContainerId[] { 0xE1, 0x03 }; + // Shortcut for specifying zero length of NDEF message data. + static constexpr uint8_t ZeroLength[] { 0x00, 0x00 }; + + nextAction = ProvideResponse; + + switch (m_currentState) { + case SelectApplicationForProbe: + case SelectApplicationForRead: + case SelectApplicationForWrite: + return QCommandApdu::build(0x00, QCommandApdu::Select, 0x04, 0x00, + QByteArrayView::fromArray(NtagApplicationIdV2), 256); + case SelectCCFile: + return QCommandApdu::build(0x00, QCommandApdu::Select, 0x00, 0x0C, + QByteArrayView::fromArray(CapabilityContainerId)); + case ReadCCFile: + return QCommandApdu::build(0x00, QCommandApdu::ReadBinary, 0x00, 0x00, {}, 15); + case SelectNdefFileForRead: + case SelectNdefFileForWrite: + return QCommandApdu::build(0x00, QCommandApdu::Select, 0x00, 0x0C, m_ndefFileId); + case ReadNdefMessageLength: + return QCommandApdu::build(0x00, QCommandApdu::ReadBinary, 0x00, 0x00, {}, 2); + case ReadNdefMessage: { + uint16_t readSize = qMin(m_fileSize, m_maxReadSize); + + return QCommandApdu::build(0x00, QCommandApdu::ReadBinary, m_fileOffset >> 8, + m_fileOffset & 0xFF, {}, readSize); + } + case ClearNdefLength: + m_fileOffset = 2; + m_fileSize = m_ndefData.size(); + return QCommandApdu::build(0x00, QCommandApdu::UpdateBinary, 0x00, 0x00, + QByteArrayView::fromArray(ZeroLength)); + case WriteNdefFile: { + uint16_t updateSize = qMin(m_fileSize, m_maxUpdateSize); + uint16_t fileOffset = m_fileOffset; + + m_fileOffset += updateSize; + m_fileSize -= updateSize; + + return QCommandApdu::build(0x00, QCommandApdu::UpdateBinary, fileOffset >> 8, + fileOffset & 0xFF, m_ndefData.mid(fileOffset - 2, updateSize)); + } + case WriteNdefLength: { + QByteArray data(2, Qt::Uninitialized); + qToUnaligned(qToBigEndian(m_ndefData.size()), data.data()); + + return QCommandApdu::build(0x00, QCommandApdu::UpdateBinary, 0x00, 0x00, data); + } + default: + nextAction = Unexpected; + return {}; + } +} + +QNdefMessage QNfcTagType4NdefFsm::getMessage(QNdefAccessFsm::Action &nextAction) +{ + if (m_currentState == NdefMessageRead) { + auto message = QNdefMessage::fromByteArray(m_ndefData); + m_ndefData.clear(); + m_currentState = NdefSupportDetected; + nextAction = Done; + return message; + } + + nextAction = Unexpected; + return {}; +} + +QNdefAccessFsm::Action QNfcTagType4NdefFsm::detectNdefSupport() +{ + switch (m_currentState) { + case SelectApplicationForProbe: + m_targetState = NdefSupportDetected; + return SendCommand; + case NdefSupportDetected: + return Done; + case NdefNotSupported: + return Failed; + default: + return Unexpected; + } +} + +QNdefAccessFsm::Action QNfcTagType4NdefFsm::readMessages() +{ + switch (m_currentState) { + case SelectApplicationForProbe: + m_targetState = NdefMessageRead; + return SendCommand; + case NdefSupportDetected: + m_currentState = SelectApplicationForRead; + m_targetState = NdefMessageRead; + return SendCommand; + case NdefNotSupported: + return Failed; + default: + return Unexpected; + } +} + +QNdefAccessFsm::Action QNfcTagType4NdefFsm::writeMessages(const QList &messages) +{ + // Only one message per tag is supported + if (messages.isEmpty() || messages.size() > 1) + return Failed; + + auto messageData = messages.first().toByteArray(); + if (messageData.size() > m_maxNdefSize - 2) + return Failed; + + m_ndefData = messageData; + + m_targetState = NdefMessageWritten; + + switch (m_currentState) { + case SelectApplicationForProbe: + return SendCommand; + + case NdefNotSupported: + return Failed; + + case NdefSupportDetected: + if (!m_writable) + return Failed; + + m_currentState = SelectApplicationForWrite; + return SendCommand; + + default: + return Unexpected; + }; +} + +QNdefAccessFsm::Action QNfcTagType4NdefFsm::provideResponse(const QByteArray &response) +{ + QResponseApdu apdu(response); + + switch (m_currentState) { + case SelectApplicationForProbe: + return handleSimpleResponse(apdu, SelectCCFile, NdefNotSupported); + case SelectCCFile: + return handleSimpleResponse(apdu, ReadCCFile, NdefNotSupported); + case ReadCCFile: + return handleReadCCResponse(apdu); + + case SelectApplicationForRead: + return handleSimpleResponse(apdu, SelectNdefFileForRead, NdefSupportDetected); + case SelectNdefFileForRead: + return handleSimpleResponse(apdu, ReadNdefMessageLength, NdefSupportDetected); + case ReadNdefMessageLength: + return handleReadFileLengthResponse(apdu); + case ReadNdefMessage: + return handleReadFileResponse(apdu); + + case SelectApplicationForWrite: + return handleSimpleResponse(apdu, SelectNdefFileForWrite, NdefSupportDetected); + case SelectNdefFileForWrite: + return handleSimpleResponse(apdu, ClearNdefLength, NdefSupportDetected); + case ClearNdefLength: + return handleSimpleResponse(apdu, WriteNdefFile, NdefSupportDetected); + case WriteNdefFile: + return handleWriteNdefFileResponse(apdu); + case WriteNdefLength: + return handleSimpleResponse(apdu, NdefSupportDetected, NdefSupportDetected, Done); + + default: + return Unexpected; + } +} + +QNdefAccessFsm::Action QNfcTagType4NdefFsm::handleSimpleResponse( + const QResponseApdu &response, QNfcTagType4NdefFsm::State okState, + QNfcTagType4NdefFsm::State failedState, QNdefAccessFsm::Action okAction) +{ + if (!response.isOk()) { + m_currentState = failedState; + return Failed; + } + + m_currentState = okState; + return okAction; +} + +QNdefAccessFsm::Action QNfcTagType4NdefFsm::handleReadCCResponse(const QResponseApdu &response) +{ + m_currentState = NdefNotSupported; + + if (!response.isOk()) + return Failed; + + if (response.data().size() < 15) { + qCDebug(QT_NFC_T4T) << "Invalid response size"; + return Failed; + } + + qsizetype idx = 0; + auto readU8 = [&data = response.data(), &idx]() { + return static_cast(data.at(idx++)); + }; + auto readU16 = [&data = response.data(), &idx]() { + Q_ASSERT(idx >= 0 && idx <= data.size() - 2); + uint16_t res = qFromBigEndian(qFromUnaligned(data.constData() + idx)); + idx += 2; + return res; + }; + auto readBytes = [&data = response.data(), &idx](qsizetype count) { + auto res = data.sliced(idx, count); + idx += count; + return res; + }; + auto ccLen = readU16(); + if (ccLen < 15) { + qCDebug(QT_NFC_T4T) << "CC length is too small"; + return Failed; + } + auto mapping = readU8(); + if ((mapping & 0xF0) != 0x20) { + qCDebug(QT_NFC_T4T) << "Unsupported mapping:" << Qt::hex << mapping; + return Failed; + } + m_maxReadSize = readU16(); + if (m_maxReadSize < 0xF) { + qCDebug(QT_NFC_T4T) << "Invalid maxReadSize" << m_maxReadSize; + return Failed; + } + + m_maxUpdateSize = readU16(); + auto tlvTag = readU8(); + if (tlvTag != 0x04) { + qCDebug(QT_NFC_T4T) << "Invalid TLV tag"; + return Failed; + } + auto tlvSize = readU8(); + if (tlvSize == 0xFF || tlvSize < 6) { + qCDebug(QT_NFC_T4T) << "Invalid TLV size"; + return Failed; + } + m_ndefFileId = readBytes(2); + + m_maxNdefSize = readU16(); + if (m_maxNdefSize < 2) { + qCDebug(QT_NFC_T4T) << "No space for NDEF file length"; + return Failed; + } + + /* + The specification defined value 0 for read access and write access + fields to mean that access is granted without any security, all + other values are either reserved, proprietary, or indicate than no + access is granted at all. Here all non-zero value are handled as + no access is granted. + */ + auto readAccess = readU8(); + if (readAccess != 0) { + qCDebug(QT_NFC_T4T) << "No read access"; + return Failed; + } + auto writeAccess = readU8(); + // It's not possible to atomically clear the length field if update + // size is < 2, so handle such tags as read-only. This also simplifies + // the update logic (no need to ever split ClearNdefLength/WriteNdefLength + // states) + m_writable = writeAccess == 0 && m_maxUpdateSize >= 2; + + m_currentState = NdefSupportDetected; + + if (m_targetState == NdefSupportDetected) { + return Done; + } else if (m_targetState == NdefMessageRead) { + // Skip extra application select + m_currentState = SelectNdefFileForRead; + return SendCommand; + } else if (m_targetState == NdefMessageWritten) { + if (m_writable) { + if (m_ndefData.size() > m_maxNdefSize - 2) { + qCDebug(QT_NFC_T4T) << "Message is too large"; + return Failed; + } + + // Skip extra application select + m_currentState = SelectNdefFileForWrite; + return SendCommand; + } else { + return Failed; + } + } + + return Unexpected; +} + +QNdefAccessFsm::Action +QNfcTagType4NdefFsm::handleReadFileLengthResponse(const QResponseApdu &response) +{ + if (!response.isOk() || response.data().size() < 2) { + m_currentState = NdefSupportDetected; + return Failed; + } + + m_fileSize = qFromBigEndian(qFromUnaligned(response.data().constData())); + if (m_fileSize > m_maxNdefSize - 2) { + m_currentState = NdefSupportDetected; + return Failed; + } + + m_fileOffset = 2; + m_ndefData.clear(); + + if (m_fileSize == 0) { + m_currentState = NdefMessageRead; + return GetMessage; + } + + m_currentState = ReadNdefMessage; + return SendCommand; +} + +QNdefAccessFsm::Action QNfcTagType4NdefFsm::handleReadFileResponse(const QResponseApdu &response) +{ + if (!response.isOk() || response.data().size() == 0) { + m_currentState = NdefSupportDetected; + return Failed; + } + + auto readSize = qMin(m_fileSize, response.data().size()); + m_ndefData.append(response.data().first(readSize)); + m_fileOffset += readSize; + m_fileSize -= readSize; + + if (m_fileSize == 0) { + m_currentState = NdefMessageRead; + return GetMessage; + } + + return SendCommand; +} + +QNdefAccessFsm::Action +QNfcTagType4NdefFsm::handleWriteNdefFileResponse(const QResponseApdu &response) +{ + if (!response.isOk()) { + m_currentState = NdefSupportDetected; + return Failed; + } + + if (m_fileSize == 0) + m_currentState = WriteNdefLength; + + return SendCommand; +} + +QT_END_NAMESPACE diff --git a/src/nfc/ndef/qnfctagtype4ndeffsm_p.h b/src/nfc/ndef/qnfctagtype4ndeffsm_p.h new file mode 100644 index 0000000..0ec8c37 --- /dev/null +++ b/src/nfc/ndef/qnfctagtype4ndeffsm_p.h @@ -0,0 +1,82 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QNFCTAGTYPE4NDEFFSM_P_H +#define QNFCTAGTYPE4NDEFFSM_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 "qndefaccessfsm_p.h" +#include "qapduutils_p.h" + +QT_BEGIN_NAMESPACE + +class QNfcTagType4NdefFsm : public QNdefAccessFsm +{ +public: + QByteArray getCommand(Action &nextAction) override; + QNdefMessage getMessage(Action &nextAction) override; + Action provideResponse(const QByteArray &response) override; + + Action detectNdefSupport() override; + Action readMessages() override; + Action writeMessages(const QList &messages) override; + +private: + enum State { + SelectApplicationForProbe, + SelectCCFile, + ReadCCFile, + NdefSupportDetected, + NdefNotSupported, + + SelectApplicationForRead, + SelectNdefFileForRead, + ReadNdefMessageLength, + ReadNdefMessage, + NdefMessageRead, + + SelectApplicationForWrite, + SelectNdefFileForWrite, + ClearNdefLength, + WriteNdefFile, + WriteNdefLength, + NdefMessageWritten // Only for target state, it is never actually reached + }; + + State m_currentState = SelectApplicationForProbe; + State m_targetState = SelectApplicationForProbe; + + // Initialized during the detection phase + uint16_t m_maxReadSize; + uint16_t m_maxUpdateSize; + QByteArray m_ndefFileId; + uint16_t m_maxNdefSize = 0xFFFF; + bool m_writable; + + // Used during the read and write operations + uint16_t m_fileSize; + uint16_t m_fileOffset; + QByteArray m_ndefData; + + Action handleSimpleResponse(const QResponseApdu &response, State okState, State failedState, + Action okAction = SendCommand); + + Action handleReadCCResponse(const QResponseApdu &response); + Action handleReadFileLengthResponse(const QResponseApdu &response); + Action handleReadFileResponse(const QResponseApdu &response); + Action handleWriteNdefFileResponse(const QResponseApdu &response); +}; + +QT_END_NAMESPACE + +#endif // QNFCTAGTYPE4NDEFFSM_P_H diff --git a/src/nfc/pcsc/qpcsc.cpp b/src/nfc/pcsc/qpcsc.cpp new file mode 100644 index 0000000..ec8bdd2 --- /dev/null +++ b/src/nfc/pcsc/qpcsc.cpp @@ -0,0 +1,32 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qpcsc_p.h" + +QT_BEGIN_NAMESPACE + +using namespace Qt::StringLiterals; + +namespace QPcsc { + +QString errorMessage(LONG error) +{ +#ifdef Q_OS_WIN + return (u"0x%1"_s).arg(error, 8, 16, QLatin1Char('0')); +#else + return QString::fromUtf8(pcsc_stringify_error(error)); +#endif +} + +} // namespace QPcsc + +qsizetype QPcscSlotName::nameSize(QPcscSlotName::CPtr p) +{ +#ifdef Q_OS_WIN + return wcslen(p); +#else + return strlen(p); +#endif +} + +QT_END_NAMESPACE diff --git a/src/nfc/pcsc/qpcsc_p.h b/src/nfc/pcsc/qpcsc_p.h new file mode 100644 index 0000000..fba1085 --- /dev/null +++ b/src/nfc/pcsc/qpcsc_p.h @@ -0,0 +1,72 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QPCSC_P_H +#define QPCSC_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 Q_OS_WIN +# include +#endif +#include +#ifdef Q_OS_DARWIN +# include +# include +#else +# include +#endif +#include +#include + +QT_BEGIN_NAMESPACE + +namespace QPcsc { +struct RawCommandResult +{ + LONG ret = SCARD_E_READER_UNAVAILABLE; + QByteArray response; + + bool isOk() const { return ret == SCARD_S_SUCCESS; } +}; + +QString errorMessage(LONG error); + +} // namespace QPcsc + +class QPcscSlotName : public +#ifdef Q_OS_WIN + QString +#else + QByteArray +#endif +{ +public: +#ifdef Q_OS_WIN + using CPtr = LPCWSTR; + using Ptr = LPWSTR; + explicit QPcscSlotName(CPtr p) : QString(reinterpret_cast(p)) { } +#else + using CPtr = LPCSTR; + using Ptr = LPSTR; + explicit QPcscSlotName(CPtr p) : QByteArray(p) { } +#endif + + CPtr ptr() const noexcept { return reinterpret_cast(constData()); } + Ptr ptr() { return reinterpret_cast(data()); } + + static qsizetype nameSize(CPtr p); +}; + +QT_END_NAMESPACE + +#endif // QPCSC_P_H diff --git a/src/nfc/pcsc/qpcsccard.cpp b/src/nfc/pcsc/qpcsccard.cpp new file mode 100644 index 0000000..e06ac6f --- /dev/null +++ b/src/nfc/pcsc/qpcsccard.cpp @@ -0,0 +1,419 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qpcsccard_p.h" +#include "ndef/qnfctagtype4ndeffsm_p.h" +#include "qapduutils_p.h" +#include +#include + +#if defined(Q_OS_DARWIN) +# define SCARD_ATTR_MAXINPUT 0x0007A007 +#elif !defined(Q_OS_WIN) +# include +#endif + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_NFC_PCSC) + +/* + Windows SCardBeginTransaction() documentation says the following: + + If a transaction is held on the card for more than five seconds with no + operations happening on that card, then the card is reset. Calling any + of the Smart Card and Reader Access Functions or Direct Card Access + Functions on the card that is transacted results in the timer being + reset to continue allowing the transaction to be used. + + We use a timer to ensure that transactions do not timeout unexpectedly. +*/ +static constexpr int KeepAliveIntervalMs = 2500; + +/* + Start a temporary transaction if a persistent transaction was not already + started due to call to onSendCommandRequest(). + + If a temporary transaction was initiated, it is ended when this object is + destroyed. +*/ +QPcscCard::Transaction::Transaction(QPcscCard *card) : m_card(card) +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + if (!m_card->isValid() || m_card->m_inAutoTransaction) + return; + + auto ret = SCardBeginTransaction(m_card->m_handle); + if (ret != SCARD_S_SUCCESS) { + qCWarning(QT_NFC_PCSC) << "SCardBeginTransaction failed:" << QPcsc::errorMessage(ret); + m_card->invalidate(); + return; + } + + m_initiated = true; +} + +QPcscCard::Transaction::~Transaction() +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + if (!m_initiated || !m_card->isValid()) + return; + + auto ret = SCardEndTransaction(m_card->m_handle, SCARD_LEAVE_CARD); + + if (ret != SCARD_S_SUCCESS) { + qCWarning(QT_NFC_PCSC) << "SCardEndTransaction failed:" << QPcsc::errorMessage(ret); + m_card->invalidate(); + } +} + +QPcscCard::QPcscCard(SCARDHANDLE handle, DWORD protocol, QObject *parent) + : QObject(parent), m_handle(handle) +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + + m_keepAliveTimer = new QTimer(this); + m_keepAliveTimer->setInterval(KeepAliveIntervalMs); + connect(m_keepAliveTimer, &QTimer::timeout, this, &QPcscCard::onKeepAliveTimeout); + + m_ioPci.dwProtocol = protocol; + m_ioPci.cbPciLength = sizeof(m_ioPci); + + // Assume that everything is NFC Tag Type 4 for now + m_tagDetectionFsm = std::make_unique(); + + performNdefDetection(); +} + +QPcscCard::~QPcscCard() +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + invalidate(); +} + +void QPcscCard::performNdefDetection() +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + + if (!m_isValid) + return; + + Transaction transaction(this); + + auto action = m_tagDetectionFsm->detectNdefSupport(); + + while (action == QNdefAccessFsm::SendCommand) { + auto command = m_tagDetectionFsm->getCommand(action); + + if (action == QNdefAccessFsm::ProvideResponse) { + auto result = sendCommand(command, NoAutoTransaction); + action = m_tagDetectionFsm->provideResponse(result.response); + } + } + + qCDebug(QT_NFC_PCSC) << "NDEF detection result" << action; + + m_supportsNdef = action == QNdefAccessFsm::Done; + qCDebug(QT_NFC_PCSC) << "NDEF supported:" << m_supportsNdef; +} + +/* + Release the resource associated with the card and notify the NFC target + about disconnection. The card is deleted when automatic deletion is enabled. +*/ +void QPcscCard::invalidate() +{ + if (!m_isValid) + return; + + SCardDisconnect(m_handle, m_inAutoTransaction ? SCARD_RESET_CARD : SCARD_LEAVE_CARD); + + m_isValid = false; + m_inAutoTransaction = false; + + Q_EMIT disconnected(); + Q_EMIT invalidated(); + + if (m_autodelete) + deleteLater(); +} + +/* + Send the given command to the card. + + Start an automatic transaction if autoTransaction is StartAutoTransaction + and it is not already started. This automatic transaction lasts until the + invalidate() or onDisconnectRequest() is called. + + The automatic transaction is used to ensure that other applications do not + interfere with commands sent by the user application. + + If autoTransaction is NoAutoTransaction, then the calling code should ensure + that either the command is atomic or that a temporary transaction is started + using Transaction object. +*/ +QPcsc::RawCommandResult QPcscCard::sendCommand(const QByteArray &command, + QPcscCard::AutoTransaction autoTransaction) +{ + if (!m_isValid) + return {}; + + if (!m_inAutoTransaction && autoTransaction == StartAutoTransaction) { + qCDebug(QT_NFC_PCSC) << "Starting transaction"; + + // FIXME: Is there a timeout on this? + auto ret = SCardBeginTransaction(m_handle); + if (ret != SCARD_S_SUCCESS) { + qCWarning(QT_NFC_PCSC) << "SCardBeginTransaction failed:" << QPcsc::errorMessage(ret); + invalidate(); + return {}; + } + m_inAutoTransaction = true; + m_keepAliveTimer->start(); + } + + QPcsc::RawCommandResult result; + result.response.resize(0xFFFF + 2); + DWORD recvLength = result.response.size(); + + qCDebug(QT_NFC_PCSC) << "TX:" << command.toHex(':'); + + result.ret = SCardTransmit(m_handle, &m_ioPci, reinterpret_cast(command.constData()), + command.size(), nullptr, + reinterpret_cast(result.response.data()), &recvLength); + if (result.ret != SCARD_S_SUCCESS) { + qCWarning(QT_NFC_PCSC) << "SCardTransmit failed:" << QPcsc::errorMessage(result.ret); + result.response.clear(); + invalidate(); + } else { + result.response.resize(recvLength); + qCDebug(QT_NFC_PCSC) << "RX:" << result.response.toHex(':'); + } + + return result; +} + +void QPcscCard::onKeepAliveTimeout() +{ + if (!m_isValid || !m_inAutoTransaction) { + m_keepAliveTimer->stop(); + return; + } + + checkCardPresent(); +} + +QByteArray QPcscCard::readUid() +{ + QByteArray command = QCommandApdu::build(0xFF, QCommandApdu::GetData, 0x00, 0x00, {}, 256); + + // Atomic command, no need for transaction. + QResponseApdu res(sendCommand(command, NoAutoTransaction).response); + if (!res.isOk()) + return {}; + return res.data(); +} + +void QPcscCard::onReadNdefMessagesRequest(const QNearFieldTarget::RequestId &request) +{ + if (!m_isValid) { + Q_EMIT requestCompleted(request, QNearFieldTarget::ConnectionError, {}); + return; + } + + if (!m_supportsNdef) { + Q_EMIT requestCompleted(request, QNearFieldTarget::UnsupportedError, {}); + return; + } + + Transaction transaction(this); + + QList messages; + + auto nextState = m_tagDetectionFsm->readMessages(); + + while (true) { + if (nextState == QNdefAccessFsm::SendCommand) { + auto command = m_tagDetectionFsm->getCommand(nextState); + + if (nextState == QNdefAccessFsm::ProvideResponse) { + auto result = sendCommand(command, NoAutoTransaction); + nextState = m_tagDetectionFsm->provideResponse(result.response); + } + } else if (nextState == QNdefAccessFsm::GetMessage) { + auto message = m_tagDetectionFsm->getMessage(nextState); + Q_EMIT ndefMessageRead(message); + } else { + break; + } + } + + qCDebug(QT_NFC_PCSC) << "Final state:" << nextState; + auto errorCode = (nextState == QNdefAccessFsm::Done) ? QNearFieldTarget::NoError + : QNearFieldTarget::NdefReadError; + Q_EMIT requestCompleted(request, errorCode, {}); +} + +/* + Ends the persistent transaction and resets the card if sendCommand() was + used by user. + + Resetting the card ensures that the current state of the card does not get + shared with other processes. +*/ +void QPcscCard::onDisconnectRequest() +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + + if (!m_isValid) + return; + + LONG ret; + if (m_inAutoTransaction) { + // NOTE: PCSCLite does not automatically release transaction in + // SCardReconnect(): https://salsa.debian.org/rousseau/PCSC/-/issues/11 + ret = SCardEndTransaction(m_handle, SCARD_RESET_CARD); + if (ret != SCARD_S_SUCCESS) { + qCWarning(QT_NFC_PCSC) << "SCardEndTransaction failed:" << QPcsc::errorMessage(ret); + invalidate(); + return; + } + + m_inAutoTransaction = false; + } + + DWORD activeProtocol; + ret = SCardReconnect(m_handle, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, + SCARD_LEAVE_CARD, &activeProtocol); + if (ret != SCARD_S_SUCCESS) { + qCWarning(QT_NFC_PCSC) << "SCardReconnect failed:" << QPcsc::errorMessage(ret); + invalidate(); + return; + } + + Q_EMIT disconnected(); +} + +void QPcscCard::onTargetDestroyed() +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + invalidate(); +} + +void QPcscCard::onSendCommandRequest(const QNearFieldTarget::RequestId &request, + const QByteArray &command) +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + + if (!m_isValid) { + Q_EMIT requestCompleted(request, QNearFieldTarget::ConnectionError, {}); + return; + } + + auto result = sendCommand(command, StartAutoTransaction); + if (result.isOk()) + Q_EMIT requestCompleted(request, QNearFieldTarget::NoError, result.response); + else + Q_EMIT requestCompleted(request, QNearFieldTarget::CommandError, {}); +} + +void QPcscCard::onWriteNdefMessagesRequest(const QNearFieldTarget::RequestId &request, + const QList &messages) +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + + if (!m_isValid) { + Q_EMIT requestCompleted(request, QNearFieldTarget::ConnectionError, {}); + return; + } + + if (!m_supportsNdef) { + Q_EMIT requestCompleted(request, QNearFieldTarget::UnsupportedError, {}); + return; + } + + Transaction transaction(this); + + auto nextState = m_tagDetectionFsm->writeMessages(messages); + + while (nextState == QNdefAccessFsm::SendCommand) { + auto command = m_tagDetectionFsm->getCommand(nextState); + if (nextState == QNdefAccessFsm::ProvideResponse) { + auto result = sendCommand(command, NoAutoTransaction); + nextState = m_tagDetectionFsm->provideResponse(result.response); + } + } + + auto errorCode = (nextState == QNdefAccessFsm::Done) ? QNearFieldTarget::NoError + : QNearFieldTarget::NdefWriteError; + Q_EMIT requestCompleted(request, errorCode, {}); +} + +/* + Enable automatic card deletion when the connection is closed by the user + or the card otherwise becomes unavailable. + + The automatic deletion is prevented initially so that + QNearFieldManagerPrivate can safely establish connections between this + object and a QNearFieldTargetPrivate proxy. +*/ +void QPcscCard::enableAutodelete() +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + + m_autodelete = true; + if (!m_isValid) + deleteLater(); +} + +/* + Check if the card is still present in the reader. + + Invalidates the object if card is not present. +*/ +bool QPcscCard::checkCardPresent() +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + + if (!m_isValid) + return false; + + DWORD state; + auto ret = SCardStatus(m_handle, nullptr, nullptr, &state, nullptr, nullptr, nullptr); + if (ret != SCARD_S_SUCCESS) { + qCWarning(QT_NFC_PCSC) << "SCardStatus failed:" << QPcsc::errorMessage(ret); + invalidate(); + return false; + } + + qCDebug(QT_NFC_PCSC) << "State:" << Qt::hex << state; + + return (state & SCARD_PRESENT) != 0; +} + +int QPcscCard::readMaxInputLength() +{ + if (!m_isValid) + return 0; + + // Maximum standard APDU length + static constexpr int DefaultMaxInputLength = 261; + + uint32_t maxInput; + DWORD attrSize = sizeof(maxInput); + auto ret = SCardGetAttrib(m_handle, SCARD_ATTR_MAXINPUT, reinterpret_cast(&maxInput), + &attrSize); + if (ret != SCARD_S_SUCCESS) { + qCDebug(QT_NFC_PCSC) << "SCardGetAttrib failed:" << QPcsc::errorMessage(ret); + return DefaultMaxInputLength; + } + + if (attrSize != sizeof(maxInput)) { + qCWarning(QT_NFC_PCSC) << "Unexpected attribute size for SCARD_ATTR_MAXINPUT:" << attrSize; + return DefaultMaxInputLength; + } + + return static_cast(maxInput); +} + +QT_END_NAMESPACE diff --git a/src/nfc/pcsc/qpcsccard_p.h b/src/nfc/pcsc/qpcsccard_p.h new file mode 100644 index 0000000..0fe580e --- /dev/null +++ b/src/nfc/pcsc/qpcsccard_p.h @@ -0,0 +1,96 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QPCSCCARD_P_H +#define QPCSCCARD_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 "qpcsc_p.h" +#include "qndefmessage.h" +#include "qnearfieldtarget.h" +#include "ndef/qndefaccessfsm_p.h" + +QT_BEGIN_NAMESPACE + +class QTimer; + +class QPcscCard : public QObject +{ + Q_OBJECT +public: + QPcscCard(SCARDHANDLE handle, DWORD protocol, QObject *parent = nullptr); + ~QPcscCard(); + + bool isValid() const { return m_isValid; } + void invalidate(); + + bool checkCardPresent(); + Q_INVOKABLE void enableAutodelete(); + + QByteArray readUid(); + int readMaxInputLength(); + + bool supportsNdef() const { return m_supportsNdef; } + +private: + SCARDHANDLE m_handle; + SCARD_IO_REQUEST m_ioPci; + bool m_isValid = true; + bool m_supportsNdef; + bool m_autodelete = false; + // Indicates that an _automatic_ transaction was started + bool m_inAutoTransaction = false; + QTimer *m_keepAliveTimer; + + std::unique_ptr m_tagDetectionFsm; + + enum AutoTransaction { NoAutoTransaction, StartAutoTransaction }; + + QPcsc::RawCommandResult sendCommand(const QByteArray &command, AutoTransaction autoTransaction); + void performNdefDetection(); + + class Transaction + { + public: + Transaction(QPcscCard *card); + ~Transaction(); + + private: + QPcscCard *m_card; + bool m_initiated = false; + }; + +public Q_SLOTS: + void onDisconnectRequest(); + void onTargetDestroyed(); + void onSendCommandRequest(const QNearFieldTarget::RequestId &request, + const QByteArray &command); + void onReadNdefMessagesRequest(const QNearFieldTarget::RequestId &request); + void onWriteNdefMessagesRequest(const QNearFieldTarget::RequestId &request, + const QList &messages); + +private Q_SLOTS: + void onKeepAliveTimeout(); + +Q_SIGNALS: + void disconnected(); + void invalidated(); + + void requestCompleted(const QNearFieldTarget::RequestId &request, + QNearFieldTarget::Error reason, const QVariant &result); + void ndefMessageRead(const QNdefMessage &message); +}; + +QT_END_NAMESPACE + +#endif // QPCSCCARD_P_H diff --git a/src/nfc/pcsc/qpcscmanager.cpp b/src/nfc/pcsc/qpcscmanager.cpp new file mode 100644 index 0000000..f5b358a --- /dev/null +++ b/src/nfc/pcsc/qpcscmanager.cpp @@ -0,0 +1,357 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qpcscmanager_p.h" +#include "qpcscslot_p.h" +#include "qpcsccard_p.h" +#include +#include +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_NFC_PCSC) + +static constexpr auto PollIntervalEnvVar = "QT_NFC_POLL_INTERVAL_MS"; +static constexpr int DefaultPollIntervalMs = 100; + +QPcscManager::QPcscManager(QObject *parent) : QObject(parent) +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + + int pollInterval = DefaultPollIntervalMs; + QByteArray intervalEnv = qgetenv(PollIntervalEnvVar); + if (!intervalEnv.isEmpty()) { + if (int intervalFromEnv = intervalEnv.toInt(); intervalFromEnv > 0) + pollInterval = intervalFromEnv; + else + qCWarning(QT_NFC_PCSC) << PollIntervalEnvVar << "set to an invalid value"; + } + + m_stateUpdateTimer = new QTimer(this); + m_stateUpdateTimer->setInterval(pollInterval); + connect(m_stateUpdateTimer, &QTimer::timeout, this, &QPcscManager::onStateUpdate); +} + +QPcscManager::~QPcscManager() +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + if (m_hasContext) { + // Destroy all card handles before destroying the PCSC context. + for (auto slot : std::as_const(m_slots)) + slot->invalidateInsertedCard(); + SCardReleaseContext(m_context); + } + + // Stop the worker thread. + thread()->quit(); +} + +void QPcscManager::processSlotUpdates() +{ + for (auto &state : m_slotStates) { + auto slot = static_cast(state.pvUserData); + Q_ASSERT(slot != nullptr); + + if ((state.dwEventState & SCARD_STATE_UNKNOWN) != 0) + continue; + + if (state.dwEventState == state.dwCurrentState) + continue; + + qCDebug(QT_NFC_PCSC) << Qt::hex << state.dwCurrentState << "=>" << state.dwEventState << ":" + << slot->name(); + + state.dwCurrentState = state.dwEventState; + slot->processStateChange(state.dwEventState, m_targetDetectionRunning); + } +} + +/* + Remove slots that no longer need to be tracked. +*/ +void QPcscManager::removeSlots() +{ + for (auto &state : m_slotStates) { + auto slot = static_cast(state.pvUserData); + Q_ASSERT(slot != nullptr); + + // Remove slots that no longer exist, or all slots without cards if + // target detection is stopped. + if ((state.dwEventState & SCARD_STATE_UNKNOWN) != 0 + || !(m_targetDetectionRunning || slot->hasCard())) { + qCDebug(QT_NFC_PCSC) << "Removing slot:" << slot; + state.dwEventState = SCARD_STATE_UNKNOWN; + slot->invalidateInsertedCard(); + m_slots.remove(slot->name()); + slot->deleteLater(); + state.pvUserData = nullptr; + } + } + + // Remove state tracking entries for slots that no longer exist. + m_slotStates.removeIf( + [](const auto &state) { return (state.dwEventState & SCARD_STATE_UNKNOWN) != 0; }); +} + +/* + Reads the system slot lists and marks slots that no longer exists, also + creates new slot entries if target detection is currently running. +*/ +void QPcscManager::updateSlotList() +{ + Q_ASSERT(m_hasContext); + +#ifndef SCARD_AUTOALLOCATE + // macOS does not support automatic allocation. Try using a fixed-size + // buffer first, extending it if it is not sufficient. +#define LIST_READER_BUFFER_EXTRA 1024 + QPcscSlotName buf(nullptr); + DWORD listSize = LIST_READER_BUFFER_EXTRA; + buf.resize(listSize); + QPcscSlotName::Ptr list = buf.ptr(); + + auto ret = SCardListReaders(m_context, nullptr, list, &listSize); +#else + QPcscSlotName::Ptr list; + DWORD listSize = SCARD_AUTOALLOCATE; + auto ret = SCardListReaders(m_context, nullptr, reinterpret_cast(&list), + &listSize); +#endif + + if (ret == LONG(SCARD_E_NO_READERS_AVAILABLE)) { + list = nullptr; + ret = SCARD_S_SUCCESS; + } +#ifndef SCARD_AUTOALLOCATE + else if (ret == LONG(SCARD_E_INSUFFICIENT_BUFFER)) { + // SCardListReaders() has set listSize to the required size. We add + // extra space to reduce possibility of failure if the reader list has + // changed since the last call. + listSize += LIST_READER_BUFFER_EXTRA; + buf.resize(listSize); + list = buf.ptr(); + + ret = SCardListReaders(m_context, nullptr, list, &listSize); + if (ret == LONG(SCARD_E_NO_READERS_AVAILABLE)) { + list = nullptr; + ret = SCARD_S_SUCCESS; + } + } +#undef LIST_READER_BUFFER_EXTRA +#endif + + if (ret != SCARD_S_SUCCESS) { + qCDebug(QT_NFC_PCSC) << "Failed to list readers:" << QPcsc::errorMessage(ret); + return; + } + +#ifdef SCARD_AUTOALLOCATE + auto freeList = qScopeGuard([this, list] { + if (list) { + Q_ASSERT(m_hasContext); + SCardFreeMemory(m_context, list); + } + }); +#endif + + QSet presentSlots; + + if (list != nullptr) { + for (const auto *p = list; *p; p += QPcscSlotName::nameSize(p) + 1) + presentSlots.insert(QPcscSlotName(p)); + } + + // Check current state list and mark slots that are not present anymore to + // be removed later. + for (auto &state : m_slotStates) { + auto slot = static_cast(state.pvUserData); + Q_ASSERT(slot != nullptr); + + if (presentSlots.contains(slot->name())) + presentSlots.remove(slot->name()); + else + state.dwEventState = SCARD_STATE_UNKNOWN; + } + + if (!m_targetDetectionRunning) + return; + + // Add new slots + for (auto &&slotName : std::as_const(presentSlots)) { + QPcscSlot *slot = new QPcscSlot(slotName, this); + qCDebug(QT_NFC_PCSC) << "New slot:" << slot; + + m_slots[slotName] = slot; + + SCARD_READERSTATE state {}; + state.pvUserData = slot; + state.szReader = slot->name().ptr(); + state.dwCurrentState = SCARD_STATE_UNAWARE; + + m_slotStates.append(state); + } +} + +bool QPcscManager::establishContext() +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + + Q_ASSERT(!m_hasContext); + + LONG ret = SCardEstablishContext(SCARD_SCOPE_USER, nullptr, nullptr, &m_context); + if (ret != SCARD_S_SUCCESS) { + qCWarning(QT_NFC_PCSC) << "Failed to establish context:" << QPcsc::errorMessage(ret); + return false; + } + m_hasContext = true; + + return true; +} + +void QPcscManager::onStateUpdate() +{ + if (!m_hasContext) { + if (!m_targetDetectionRunning) { + m_stateUpdateTimer->stop(); + return; + } + + if (!establishContext()) + return; + } + + updateSlotList(); + removeSlots(); + + if (m_slotStates.isEmpty()) { + if (!m_targetDetectionRunning) { + // Free the context if it is no longer needed to card tracking. + SCardReleaseContext(m_context); + m_hasContext = false; + + m_stateUpdateTimer->stop(); + } + return; + } + + // Both Windows and PCSCLite support interruptable continuos state detection + // where SCardCancel() can be used to abort it from another thread. + // But that introduces a problem of reliable cancelling of the status change + // call and no other. Reliable use of SCardCancel() would probably require + // some form of synchronization and polling, and would make the code much + // more complicated. + // Alternatively, the state detection code could run in a yet another thread + // that will not need to be cancelled too often. + // For simplicity, the current code just checks for status changes every + // second. + LONG ret = SCardGetStatusChange(m_context, 0, m_slotStates.data(), m_slotStates.size()); + + if (ret == SCARD_S_SUCCESS || ret == LONG(SCARD_E_UNKNOWN_READER)) { + processSlotUpdates(); + removeSlots(); + } else if (ret == LONG(SCARD_E_CANCELLED) || ret == LONG(SCARD_E_UNKNOWN_READER) + || ret == LONG(SCARD_E_TIMEOUT)) { + /* ignore */ + } else { + qCWarning(QT_NFC_PCSC) << "SCardGetStatusChange failed:" << QPcsc::errorMessage(ret); + + // Unknown failure. It is likely that the current context will not + // recover from it, so destroy it and try to create a new context at the + // next iteration. + Q_ASSERT(m_hasContext); + m_hasContext = false; + for (auto slot : std::as_const(m_slots)) { + slot->invalidateInsertedCard(); + slot->deleteLater(); + } + SCardReleaseContext(m_context); + m_slots.clear(); + m_slotStates.clear(); + } +} + +void QPcscManager::onStartTargetDetectionRequest(QNearFieldTarget::AccessMethod accessMethod) +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + + m_requestedMethod = accessMethod; + + if (m_targetDetectionRunning) + return; + + m_targetDetectionRunning = true; + m_stateUpdateTimer->start(); +} + +void QPcscManager::onStopTargetDetectionRequest() +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + m_targetDetectionRunning = false; +} + +QPcscCard *QPcscManager::connectToCard(QPcscSlot *slot) +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + Q_ASSERT(slot != nullptr); + Q_ASSERT(m_hasContext); + + SCARDHANDLE cardHandle; + DWORD activeProtocol; + + LONG ret = SCardConnect(m_context, slot->name().ptr(), SCARD_SHARE_SHARED, + SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &cardHandle, &activeProtocol); + if (ret != SCARD_S_SUCCESS) { + qCDebug(QT_NFC_PCSC) << "Failed to connect to card:" << QPcsc::errorMessage(ret); + retryCardDetection(slot); + return nullptr; + } + + auto card = new QPcscCard(cardHandle, activeProtocol, this); + auto uid = card->readUid(); + auto maxInputLength = card->readMaxInputLength(); + + QNearFieldTarget::AccessMethods accessMethods = QNearFieldTarget::TagTypeSpecificAccess; + if (card->supportsNdef()) + accessMethods |= QNearFieldTarget::NdefAccess; + + if (m_requestedMethod != QNearFieldTarget::UnknownAccess + && (accessMethods & m_requestedMethod) == 0) { + qCDebug(QT_NFC_PCSC) << "Dropping card without required access support"; + card->deleteLater(); + return nullptr; + } + + if (!card->isValid()) { + qCDebug(QT_NFC_PCSC) << "Card became invalid"; + card->deleteLater(); + + retryCardDetection(slot); + + return nullptr; + } + + Q_EMIT cardInserted(card, uid, accessMethods, maxInputLength); + + return card; +} + +/* + Setup states list so that the card detection for the given slot will + be retried on the next iteration. + + This is useful to try to get cards working after reset. +*/ +void QPcscManager::retryCardDetection(const QPcscSlot *slot) +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + + for (auto &state : m_slotStates) { + if (state.pvUserData == slot) { + state.dwCurrentState = SCARD_STATE_UNAWARE; + break; + } + } +} + +QT_END_NAMESPACE diff --git a/src/nfc/pcsc/qpcscmanager_p.h b/src/nfc/pcsc/qpcscmanager_p.h new file mode 100644 index 0000000..d35edf5 --- /dev/null +++ b/src/nfc/pcsc/qpcscmanager_p.h @@ -0,0 +1,65 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QPCSCMANAGER_P_H +#define QPCSCMANAGER_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 "qpcsc_p.h" +#include "qnearfieldtarget.h" + +QT_BEGIN_NAMESPACE + +class QPcscSlot; +class QPcscCard; +class QTimer; + +class QPcscManager : public QObject +{ + Q_OBJECT +public: + explicit QPcscManager(QObject *parent = nullptr); + ~QPcscManager() override; + + QPcscCard *connectToCard(QPcscSlot *slot); + +private: + QTimer *m_stateUpdateTimer; + bool m_targetDetectionRunning = false; + bool m_hasContext = false; + SCARDCONTEXT m_context; + QMap m_slots; + QList m_slotStates; + QNearFieldTarget::AccessMethod m_requestedMethod; + + [[nodiscard]] bool establishContext(); + void processSlotUpdates(); + void updateSlotList(); + void removeSlots(); + void retryCardDetection(const QPcscSlot *slot); + +public Q_SLOTS: + void onStartTargetDetectionRequest(QNearFieldTarget::AccessMethod accessMethod); + void onStopTargetDetectionRequest(); + +private Q_SLOTS: + void onStateUpdate(); + +Q_SIGNALS: + void cardInserted(QPcscCard *card, const QByteArray &uid, + QNearFieldTarget::AccessMethods accessMethods, int maxInputLength); +}; + +QT_END_NAMESPACE + +#endif // QPCSCMANAGER_P_H diff --git a/src/nfc/pcsc/qpcscslot.cpp b/src/nfc/pcsc/qpcscslot.cpp new file mode 100644 index 0000000..cf55cf7 --- /dev/null +++ b/src/nfc/pcsc/qpcscslot.cpp @@ -0,0 +1,57 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qpcscslot_p.h" +#include "qpcscmanager_p.h" +#include "qpcsccard_p.h" +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_NFC_PCSC) + +QPcscSlot::QPcscSlot(const QPcscSlotName &name, QPcscManager *manager) + : QObject(manager), m_name(name) +{ +} + +QPcscSlot::~QPcscSlot() +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO << this; + if (m_insertedCard) + m_insertedCard->invalidate(); +} + +void QPcscSlot::processStateChange(DWORD eventId, bool createCards) +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + + // Check if the currently inserted card is still valid + if (!m_insertedCard.isNull()) { + if (m_insertedCard->checkCardPresent()) + return; + qCDebug(QT_NFC_PCSC) << "Removing card from slot" << m_name; + m_insertedCard->invalidate(); + m_insertedCard.clear(); + } + + auto manager = qobject_cast(parent()); + + if (manager != nullptr && createCards + && (eventId + & (SCARD_STATE_PRESENT | SCARD_STATE_MUTE | SCARD_STATE_UNPOWERED + | SCARD_STATE_EXCLUSIVE)) + == SCARD_STATE_PRESENT) { + qCDebug(QT_NFC_PCSC) << "New card in slot" << m_name; + + m_insertedCard = manager->connectToCard(this); + } +} + +void QPcscSlot::invalidateInsertedCard() +{ + if (m_insertedCard) + m_insertedCard->invalidate(); +} + +QT_END_NAMESPACE diff --git a/src/nfc/pcsc/qpcscslot_p.h b/src/nfc/pcsc/qpcscslot_p.h new file mode 100644 index 0000000..c335b47 --- /dev/null +++ b/src/nfc/pcsc/qpcscslot_p.h @@ -0,0 +1,46 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QPCSCSLOT_P_H +#define QPCSCSLOT_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 "qpcsc_p.h" +#include +#include + +QT_BEGIN_NAMESPACE + +class QPcscManager; +class QPcscCard; + +class QPcscSlot : public QObject +{ + Q_OBJECT +public: + QPcscSlot(const QPcscSlotName &name, QPcscManager *manager); + ~QPcscSlot() override; + + const QPcscSlotName &name() const { return m_name; } + void processStateChange(DWORD eventId, bool createCards); + bool hasCard() const { return !m_insertedCard.isNull(); } + void invalidateInsertedCard(); + +private: + const QPcscSlotName m_name; + QPointer m_insertedCard; +}; + +QT_END_NAMESPACE + +#endif // QPCSCSLOT_P_H diff --git a/src/nfc/qapduutils.cpp b/src/nfc/qapduutils.cpp new file mode 100644 index 0000000..057e434 --- /dev/null +++ b/src/nfc/qapduutils.cpp @@ -0,0 +1,81 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qapduutils_p.h" +#include + +QT_BEGIN_NAMESPACE + +/* + Utilities for handling smart card application protocol data units (APDU). + + The structure of APDUs is defined by ISO/IEC 7816-4 Organization, security + and commands for interchange. The summary can be found on Wikipedia: + + https://en.wikipedia.org/wiki/Smart_card_application_protocol_data_unit +*/ + +/* + Parses a response APDU from the raw data. + + If the data is too short to contain SW bytes, the returned responses SW + is set to QResponseApdu::Empty. +*/ +QResponseApdu::QResponseApdu(const QByteArray &response) +{ + if (response.size() < 2) { + m_status = Empty; + m_data = response; + } else { + const auto dataSize = response.size() - 2; + m_status = qFromBigEndian(qFromUnaligned(response.constData() + dataSize)); + m_data = response.left(dataSize); + } +} + +/* + Builds a command APDU from components according to ISO/IEC 7816. +*/ +QByteArray QCommandApdu::build(uint8_t cla, uint8_t ins, uint8_t p1, uint8_t p2, + QByteArrayView data, uint16_t ne) +{ + Q_ASSERT(data.size() <= 0xFFFF); + + QByteArray apdu; + apdu.append(static_cast(cla)); + apdu.append(static_cast(ins)); + apdu.append(static_cast(p1)); + apdu.append(static_cast(p2)); + + bool extendedLc = false; + uint16_t nc = data.size(); + + if (nc > 0) { + if (nc < 256) { + apdu.append(static_cast(nc)); + } else { + extendedLc = true; + apdu.append('\0'); + apdu.append(static_cast(nc >> 8)); + apdu.append(static_cast(nc & 0xFF)); + } + apdu.append(data); + } + + if (ne) { + if (ne < 256) { + apdu.append(static_cast(ne)); + } else if (ne == 256) { + apdu.append(static_cast('\0')); + } else { + if (!extendedLc) + apdu.append('\0'); + apdu.append(static_cast(ne >> 8)); + apdu.append(static_cast(ne & 0xFF)); + } + } + + return apdu; +} + +QT_END_NAMESPACE diff --git a/src/nfc/qapduutils_p.h b/src/nfc/qapduutils_p.h new file mode 100644 index 0000000..dd777b0 --- /dev/null +++ b/src/nfc/qapduutils_p.h @@ -0,0 +1,53 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QAPDUUTILS_P_H +#define QAPDUUTILS_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 QResponseApdu +{ +public: + static constexpr uint16_t Empty = 0x0000; + static constexpr uint16_t Success = 0x9000; + + explicit QResponseApdu(const QByteArray &response = {}); + + const QByteArray &data() const { return m_data; } + uint16_t status() const { return m_status; } + bool isOk() const { return m_status == Success; } + +private: + QByteArray m_data; + uint16_t m_status; +}; + +namespace QCommandApdu { + +// INS byte values for command APDUs +constexpr uint8_t Select = 0xA4; +constexpr uint8_t ReadBinary = 0xB0; +constexpr uint8_t GetData = 0xCA; +constexpr uint8_t UpdateBinary = 0xD6; + +QByteArray build(uint8_t cla, uint8_t ins, uint8_t p1, uint8_t p2, QByteArrayView data, + uint16_t ne = 0); +}; + +QT_END_NAMESPACE + +#endif // QAPDUUTILS_P_H diff --git a/src/nfc/qndeffilter.cpp b/src/nfc/qndeffilter.cpp new file mode 100644 index 0000000..4bbd0ef --- /dev/null +++ b/src/nfc/qndeffilter.cpp @@ -0,0 +1,487 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qndeffilter.h" +#include "qndefmessage.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \class QNdefFilter + \brief The QNdefFilter class provides a filter for matching NDEF messages. + + \ingroup connectivity-nfc + \inmodule QtNfc + \since 5.2 + + The QNdefFilter encapsulates the structure of an NDEF message and is used for + matching messages that have a particular structure. + + The following filter matches NDEF messages that contain a single smart poster record: + + \code + QNdefFilter filter; + filter.append(QNdefRecord::NfcRtd, "Sp"); + \endcode + + The following filter matches NDEF messages that contain a URI, a localized piece of text and an + optional JPEG image. The order of the records must be in the order specified: + + \code + QNdefFilter filter; + filter.setOrderMatch(true); + filter.appendRecord(QNdefRecord::NfcRtd, "U"); + filter.appendRecord(); + filter.appendRecord(QNdefRecord::Mime, "image/jpeg", 0, 1); + \endcode + + The \l match() method can be used to check if a message matches the filter. + + \section1 Matching Algorithms + + The filter behavior depends on the value of \l orderMatch() parameter. + + \note In the discussion below we will consider the filter records to be + equal if their \c typeNameFormat and \c type parameters match. Joining + two records means adding their \c minimum and \c maximum values, + respectively. + + \section2 Unordered Matching + + If the record order is not taken into account, all the equal records in the + filter can be joined. The resulting filter will contain only unique records, + each with the updated \c minimum and \c maximum value. + + Consider the following example: + + \code + QNdefFilter filter; + filter.appendRecord(0, 1); + filter.appendRecord(0, 1); + filter.appendRecord(QNdefRecord::Mime, "", 1, 1); + filter.appendRecord(1, 1); + filter.setOrderMatch(false); + \endcode + + With the unordered matching, the filter will be simplified to the following: + + \code + QNdefFilter filter; + filter.appendRecord(1, 3); + filter.appendRecord(QNdefRecord::Mime, "", 1, 1); + filter.setOrderMatch(false); + \endcode + + Once the filter contains only the unique records, the matching algorithm + iterates through the message and calculates the actual amount of records of + each type. If all the actual amounts fit in the corresponding + [minimum, maximum] ranges, the matching algorithm returns \c true. + + \section2 Ordered Matching + + If the record order is important, a different approach is applied. In this + case the equal records can't be simply joined together. However, the + consecutive equal records can still be joined. Then, the matching + algorithm iterates through the message, this time also taking the positions + of the records into account. + + \section2 Handling Empty Type in Filter Record + + It's possible to add a filter record with an empty \c type. In this case + the empty type will act as a wildcard for any type. + + For example, the filter can be defined as follows: + + \code + QNdefFilter filter; + filter.addRecord(QNdefRecord::Mime, "", 1, 1); + \endcode + + This filter specifies that the message must contain exactly one NDEF record + with \l {QNdefRecord::}{Mime} \l {QNdefRecord::}{typeNameFormat}(), and any + \l {QNdefRecord::}{type}(). + + \section2 Handling Extra Records in the Message + + If the message contains some records that do not match \e any record in the + filter, the matching algorithm will return \c false. + + \section2 Filter Examples + + In the table below, each filter record is specified by the following + parameters (in the given order): + + \list + \li \c typeNameFormat - contains the \l {QNdefRecord::}{typeNameFormat}() of + the record. + \li \c type - contains the \l {QNdefRecord::}{type}() of the record. + \li \c minimum - contains the minimum amount of occurrences of the record + in the message. + \li \c maximum - contains the maximum amount of occurrences of the record + in the message. + \endlist + + The filter contains multiple records. + + The message consists of multiple \l {QNdefRecord}s. In the table below, only + the \l {QNdefRecord::}{typeNameFormat}() and \l {QNdefRecord::}{type}() of + each record will be shown, because the other parameters do not matter for + filtering. + + \table + \header + \li Filter + \li Message + \li Match Result + \li Comment + \row + \li Empty filter + \li Empty message + \li Match + \li + \row + \li Empty filter + \li Non-empty message + \li No match + \li + \row + \li Non-empty filter + \li Empty message + \li No match + \li + \row + \li {1, 2}[(QNdefRecord::NfcRtd, "T", 1, 2), + (QNdefRecord::Mime, "", 1, 1), (QNdefRecord::Empty, "", 0, 100)] + \li {1, 2}[(QNdefRecord::Mime, "image/jpeg"), (QNdefRecord::Empty, ""), + (QNdefRecord::NfcRtd, "T"), (QNdefRecord::Empty, ""), + (QNdefRecord::NfcRtd, "T")] + \li Unordered: match + \li {1, 2} Ordered filter does not match because the message must start + with a QNdefRecord::NfcRtd record, but it starts with + QNdefRecord::Mime. + \row + \li Ordered: no match + \row + \li {1, 2}[(QNdefRecord::NfcRtd, "T", 0, 2), + (QNdefRecord::Mime, "", 1, 1), (QNdefRecord::NfcRtd, "T", 1, 1)] + \li {1, 2}[(QNdefRecord::NfcRtd, "T"), (QNdefRecord::NfcRtd, "T"), + (QNdefRecord::Mime, "image/jpeg")] + \li Unordered: match + \li {1, 2} Ordered filter does not match because an QNdefRecord::NfcRtd + record is expected after QNdefRecord::Mime, but the message does not + have it. + \row + \li Ordered: no match + \row + \li {1, 2}[(QNdefRecord::NfcRtd, "T", 0, 2), + (QNdefRecord::NfcRtd, "T", 1, 1), (QNdefRecord::Mime, "", 1, 1)] + \li {1, 2}[(QNdefRecord::NfcRtd, "T"), + (QNdefRecord::Mime, "image/jpeg")] + \li Unordered: match + \li {1, 2} Both cases match because the message contains the required + minimum of records in the correct order. + \row + \li Ordered: match + \endtable + +*/ + +/*! + \class QNdefFilter::Record + \brief The QNdefFilter::Record struct contains the information about a + filter record. + + \ingroup connectivity-nfc + \inmodule QtNfc + \since 5.2 + + The QNdefFilter::Record struct is used to populate the QNdefFilter object. + Each record contains the following information: + \list + \li \l {QNdefRecord::TypeNameFormat} of the corresponding \l QNdefRecord. + \li Type of the \l QNdefRecord. + \li Minimum and maximum amount of the records with such parameters in the + filter. + \endlist +*/ + +/*! + \fn template bool QNdefFilter::appendRecord(unsigned int min, unsigned int max) + + Appends a record matching the template parameter to the NDEF filter. + The record must occur between \a min and \a max times in the NDEF message. + + Returns \c true if the record was appended successfully. Otherwise returns + \c false. +*/ + +class QNdefFilterPrivate : public QSharedData +{ +public: + QNdefFilterPrivate(); + + bool orderMatching; + QList filterRecords; +}; + +QNdefFilterPrivate::QNdefFilterPrivate() +: orderMatching(false) +{ +} + +/*! + Constructs a new NDEF filter. +*/ +QNdefFilter::QNdefFilter() +: d(new QNdefFilterPrivate) +{ +} + +/*! + Constructs a new NDEF filter that is a copy of \a other. +*/ +QNdefFilter::QNdefFilter(const QNdefFilter &other) +: d(other.d) +{ +} + +/*! + Destroys the NDEF filter. +*/ +QNdefFilter::~QNdefFilter() +{ +} + +/*! + Assigns \a other to this filter and returns a reference to this filter. +*/ +QNdefFilter &QNdefFilter::operator=(const QNdefFilter &other) +{ + if (d != other.d) + d = other.d; + + return *this; +} + +/*! + \since 6.2 + + Returns \c true if the \a message matches the given filter. + Otherwise returns \c false. + + See \l {Matching Algorithms} for more detailed explanation of matching. +*/ +bool QNdefFilter::match(const QNdefMessage &message) const +{ + // empty filter matches only empty message + if (d->filterRecords.isEmpty()) + return message.isEmpty(); + + bool matched = true; + int totalCount = 0; + + if (!d->orderMatching) { + // Order is not important. The most reliable way is to merge all the + // similar records, and then simply check the amount of occurrences. + using MapKey = QPair; + + // Creating a map from the list of filter records. + QMap joinedFilterRecords; + for (const auto &rec : d->filterRecords) { + const auto key = qMakePair(rec.typeNameFormat, rec.type); + if (joinedFilterRecords.contains(key)) { + joinedFilterRecords[key].minimum += rec.minimum; + joinedFilterRecords[key].maximum += rec.maximum; + } else { + joinedFilterRecords.insert(key, rec); + } + } + // Checking the message, calculate occurrences. + QMap counts; // current number of occurrences + for (const auto &record : message) { + const auto key = qMakePair(record.typeNameFormat(), record.type()); + // Do not forget that we handle an empty type as "any type". + const auto emptyTypeKey = qMakePair(record.typeNameFormat(), QByteArray()); + + if (joinedFilterRecords.contains(key)) + counts[key] += 1; + else if (joinedFilterRecords.contains(emptyTypeKey)) + counts[emptyTypeKey] += 1; + } + // Check that the occurrences match [min; max] range. + for (auto it = joinedFilterRecords.cbegin(); it != joinedFilterRecords.cend(); ++it) { + const auto count = counts.value(it.key(), 0); + totalCount += count; + if (count < it.value().minimum || count > it.value().maximum) { + matched = false; + break; + } + } + } else { + // Order *is* important. Need to iterate the list. + + // Here we need to merge consecutive records with the same parameters. + QList mergedRecords; + // we know that filer is not empty here + Record currentRecord = d->filterRecords.first(); + for (qsizetype i = 1; i < d->filterRecords.size(); ++i) { + const auto &rec = d->filterRecords.at(i); + if (rec.typeNameFormat == currentRecord.typeNameFormat + && rec.type == currentRecord.type) { + currentRecord.minimum += rec.minimum; + currentRecord.maximum += rec.maximum; + } else { + mergedRecords.push_back(currentRecord); + currentRecord = rec; + } + } + mergedRecords.push_back(currentRecord); + + // The list contains the current number of occurrences of each record. + QList counts(mergedRecords.size(), 0); + + // Iterate through the messages and calculate the number of occurrences. + qsizetype filterIndex = 0; + for (qsizetype messageIndex = 0; matched && messageIndex < message.size(); ++messageIndex) { + const auto &messageRec = message.at(messageIndex); + // Try to find a filter record that matches the message record. + // We start from the last processed filter record, not from the very + // beginning (because the order matters). + qsizetype idx = filterIndex; + for (; idx < mergedRecords.size(); ++idx) { + const auto &filterRec = mergedRecords.at(idx); + if (filterRec.typeNameFormat == messageRec.typeNameFormat() + && (filterRec.type == messageRec.type() || filterRec.type.isEmpty())) { + counts[idx] += 1; + break; + } else if (counts[idx] < filterRec.minimum || counts[idx] > filterRec.maximum) { + // The current message record does not match the current + // filter record, but we didn't get enough records to + // fulfill the filter => that's an error. + matched = false; + break; + } + } + filterIndex = idx; + } + + if (matched) { + // Check that the occurrences match [min; max] range. + for (qsizetype i = 0; i < mergedRecords.size(); ++i) { + const auto &rec = mergedRecords.at(i); + totalCount += counts[i]; + if (counts[i] < rec.minimum || counts[i] > rec.maximum) { + matched = false; + break; + } + } + } + } + + // Check if the message has records that do not match any record from the + // filter. To do it we just need to compare the total count of records, + // detected by filter, with the full message size. If they do not match, + // we have some records, that are not covered by the filter. + if (matched && (totalCount != message.size())) { + matched = false; + } + + return matched; +} + +/*! + Clears the filter. +*/ +void QNdefFilter::clear() +{ + d->orderMatching = false; + d->filterRecords.clear(); +} + +/*! + Sets the ordering requirements of the filter. If \a on is \c {true}, the + filter will only match if the order of records in the filter matches the + order of the records in the NDEF message. If \a on is \c {false}, the order + of the records is not taken into account when matching. + + By default record order is not taken into account. +*/ +void QNdefFilter::setOrderMatch(bool on) +{ + d->orderMatching = on; +} + +/*! + Returns \c true if the filter takes NDEF record order into account when + matching. Otherwise returns \c false. +*/ +bool QNdefFilter::orderMatch() const +{ + return d->orderMatching; +} + +/*! + Appends a record with type name format \a typeNameFormat and type \a type + to the NDEF filter. The record must occur between \a min and \a max times + in the NDEF message. + + Returns \c true if the record was appended successfully. Otherwise returns + \c false. +*/ +bool QNdefFilter::appendRecord(QNdefRecord::TypeNameFormat typeNameFormat, const QByteArray &type, + unsigned int min, unsigned int max) +{ + QNdefFilter::Record record; + + record.typeNameFormat = typeNameFormat; + record.type = type; + record.minimum = min; + record.maximum = max; + + return appendRecord(record); +} + +static bool verifyRecord(const QNdefFilter::Record &record) +{ + return record.minimum <= record.maximum; +} + +/*! + Verifies the \a record and appends it to the NDEF filter. + + Returns \c true if the record was appended successfully. Otherwise returns + \c false. +*/ +bool QNdefFilter::appendRecord(const Record &record) +{ + if (verifyRecord(record)) { + d->filterRecords.append(record); + return true; + } + return false; +} + +/*! + Returns the NDEF record at index \a i. + + \a i must be a valid index (i.e. 0 <= i < \l recordCount()). + + \sa recordCount() +*/ +QNdefFilter::Record QNdefFilter::recordAt(qsizetype i) const +{ + return d->filterRecords.at(i); +} + +/*! + Returns the number of NDEF records in the filter. +*/ +qsizetype QNdefFilter::recordCount() const +{ + return d->filterRecords.size(); +} + +QT_END_NAMESPACE diff --git a/src/nfc/qndeffilter.h b/src/nfc/qndeffilter.h new file mode 100644 index 0000000..693342e --- /dev/null +++ b/src/nfc/qndeffilter.h @@ -0,0 +1,62 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QNDEFFILTER_H +#define QNDEFFILTER_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QNdefMessage; + +class QNdefFilterPrivate; +class Q_NFC_EXPORT QNdefFilter +{ +public: + QNdefFilter(); + QNdefFilter(const QNdefFilter &other); + ~QNdefFilter(); + + void clear(); + + void setOrderMatch(bool on); + bool orderMatch() const; + + struct Record { + QNdefRecord::TypeNameFormat typeNameFormat; + QByteArray type; + unsigned int minimum; + unsigned int maximum; + }; + + template + bool appendRecord(unsigned int min = 1, unsigned int max = 1); + bool appendRecord(QNdefRecord::TypeNameFormat typeNameFormat, const QByteArray &type, + unsigned int min = 1, unsigned int max = 1); + bool appendRecord(const Record &record); + + qsizetype recordCount() const; + Record recordAt(qsizetype i) const; + + QNdefFilter &operator=(const QNdefFilter &other); + + bool match(const QNdefMessage &message) const; + +private: + QSharedDataPointer d; +}; + +template +bool QNdefFilter::appendRecord(unsigned int min, unsigned int max) +{ + T record; + + return appendRecord(record.typeNameFormat(), record.type(), min, max); +} + +QT_END_NAMESPACE + +#endif // QNDEFFILTER_H diff --git a/src/nfc/qndefmessage.cpp b/src/nfc/qndefmessage.cpp new file mode 100644 index 0000000..443d43e --- /dev/null +++ b/src/nfc/qndefmessage.cpp @@ -0,0 +1,325 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qndefmessage.h" +#include "qndefrecord_p.h" + +QT_BEGIN_NAMESPACE + +QT_IMPL_METATYPE_EXTERN(QNdefMessage) + +/*! + \class QNdefMessage + \brief The QNdefMessage class provides an NFC NDEF message. + + \ingroup connectivity-nfc + \inmodule QtNfc + \since Qt 5.2 + + A QNdefMessage is a collection of 0 or more QNdefRecords. QNdefMessage inherits from + QList and therefore the standard QList functions can be used to manipulate the + NDEF records in the message. + + NDEF messages can be parsed from a byte array conforming to the NFC Data Exchange Format + technical specification by using the fromByteArray() static function. Conversely QNdefMessages + can be converted into a byte array with the toByteArray() function. +*/ + +/*! + \fn QNdefMessage::QNdefMessage() + + Constructs a new empty NDEF message. +*/ + +/*! + \fn QNdefMessage::QNdefMessage(const QNdefRecord &record) + + Constructs a new NDEF message containing a single record \a record. +*/ + +/*! + \fn QNdefMessage::QNdefMessage(const QNdefMessage &message) + + Constructs a new NDEF message that is a copy of \a message. +*/ + +/*! + \fn QNdefMessage::QNdefMessage(const QList &records) + + Constructs a new NDEF message that contains all of the records in \a records. +*/ + +/*! + Returns an NDEF message parsed from the contents of \a message. + + The \a message parameter is interpreted as the raw message format defined in the NFC Data + Exchange Format technical specification. + + If a parse error occurs an empty NDEF message is returned. +*/ +QNdefMessage QNdefMessage::fromByteArray(const QByteArray &message) +{ + QNdefMessage result; + + bool seenMessageBegin = false; + bool seenMessageEnd = false; + + QByteArray partialChunk; + QNdefRecord record; + + qsizetype idx = 0; + while (idx < message.size()) { + quint8 flags = message.at(idx); + + const bool messageBegin = flags & 0x80; + const bool messageEnd = flags & 0x40; + + const bool cf = flags & 0x20; + const bool sr = flags & 0x10; + const bool il = flags & 0x08; + const quint8 typeNameFormat = flags & 0x07; + + if (messageBegin && seenMessageBegin) { + qWarning("Got message begin but already parsed some records"); + return QNdefMessage(); + } else if (!messageBegin && !seenMessageBegin) { + qWarning("Haven't got message begin yet"); + return QNdefMessage(); + } else if (messageBegin && !seenMessageBegin) { + seenMessageBegin = true; + } + if (messageEnd && seenMessageEnd) { + qWarning("Got message end but already parsed final record"); + return QNdefMessage(); + } else if (messageEnd && !seenMessageEnd) { + seenMessageEnd = true; + } + // TNF must be 0x06 even for the last chunk, when cf == 0. + if ((typeNameFormat != 0x06) && !partialChunk.isEmpty()) { + qWarning("Partial chunk not empty, but TNF not 0x06 as expected"); + return QNdefMessage(); + } + + int headerLength = 1; + headerLength += (sr) ? 1 : 4; + headerLength += (il) ? 1 : 0; + + if (idx + headerLength >= message.size()) { + qWarning("Unexpected end of message"); + return QNdefMessage(); + } + + const quint8 typeLength = message.at(++idx); + + if ((typeNameFormat == 0x06) && (typeLength != 0)) { + qWarning("Invalid chunked data, TYPE_LENGTH != 0"); + return QNdefMessage(); + } + + quint32 payloadLength; + if (sr) + payloadLength = quint8(message.at(++idx)); + else { + payloadLength = quint8(message.at(++idx)) << 24; + payloadLength |= quint8(message.at(++idx)) << 16; + payloadLength |= quint8(message.at(++idx)) << 8; + payloadLength |= quint8(message.at(++idx)) << 0; + } + + quint8 idLength; + if (il) + idLength = message.at(++idx); + else + idLength = 0; + + // On 32-bit systems this can overflow + const qsizetype convertedPayloadLength = static_cast(payloadLength); + const qsizetype contentLength = convertedPayloadLength + typeLength + idLength; + + // On a 32 bit platform the payload can theoretically exceed the max. + // size of a QByteArray. This will never happen in practice with correct + // data because there are no NFC tags that can store such data sizes, + // but still can be possible if the data is corrupted. + if ((contentLength < 0) || (convertedPayloadLength < 0) + || ((std::numeric_limits::max() - idx) < contentLength)) { + qWarning("Payload can't fit into QByteArray"); + return QNdefMessage(); + } + + if (idx + contentLength >= message.size()) { + qWarning("Unexpected end of message"); + return QNdefMessage(); + } + + if ((typeNameFormat == 0x06) && il) { + qWarning("Invalid chunked data, IL != 0"); + return QNdefMessage(); + } + + if (typeNameFormat != 0x06) + record.setTypeNameFormat(QNdefRecord::TypeNameFormat(typeNameFormat)); + + if (typeLength > 0) { + QByteArray type(&message.constData()[++idx], typeLength); + record.setType(type); + idx += typeLength - 1; + } + + if (idLength > 0) { + QByteArray id(&message.constData()[++idx], idLength); + record.setId(id); + idx += idLength - 1; + } + + if (payloadLength > 0) { + QByteArray payload(&message.constData()[++idx], payloadLength); + + if (cf) { + // chunked payload, except last + partialChunk.append(payload); + } else if (typeNameFormat == 0x06) { + // last chunk of chunked payload + record.setPayload(partialChunk + payload); + partialChunk.clear(); + } else { + // non-chunked payload + record.setPayload(payload); + } + + idx += payloadLength - 1; + } + + if (!cf) { + result.append(record); + record = QNdefRecord(); + } + + if (!cf && seenMessageEnd) + break; + + // move to start of next record + ++idx; + } + + if (!seenMessageBegin || !seenMessageEnd) { + qWarning("Malformed NDEF Message, missing begin or end"); + return QNdefMessage(); + } + + return result; +} + +/*! + \fn QNdefMessage &QNdefMessage::operator=(const QNdefMessage &other) + \overload + \since 6.2 + + Copy assignment operator from QList. Assigns the + \a other list of NDEF records to this NDEF record list. + + After the operation, \a other and \c *this will be equal. +*/ + +/*! + \fn QNdefMessage &QNdefMessage::operator=(QNdefMessage &&other) + \overload + \since 6.2 + + Move assignment operator from QList. Moves the + \a other list of NDEF records to this NDEF record list. + + After the operation, \a other will be empty. +*/ + +/*! + Returns \c true if this NDEF message is equivalent to \a other; otherwise + returns \c false. + + An empty message (i.e. isEmpty() returns \c true) is equivalent to a NDEF + message containing a single record of type \l QNdefRecord::Empty. +*/ +bool QNdefMessage::operator==(const QNdefMessage &other) const +{ + // both records are empty + if (isEmpty() && other.isEmpty()) + return true; + + // compare empty to really empty + if (isEmpty() && other.size() == 1 && other.first().typeNameFormat() == QNdefRecord::Empty) + return true; + if (other.isEmpty() && size() == 1 && first().typeNameFormat() == QNdefRecord::Empty) + return true; + + if (size() != other.size()) + return false; + + for (qsizetype i = 0; i < size(); ++i) { + if (at(i) != other.at(i)) + return false; + } + + return true; +} + +/*! + Returns the NDEF message as a byte array. + + The return value of this function conforms to the format defined in the NFC Data Exchange + Format technical specification. +*/ +QByteArray QNdefMessage::toByteArray() const +{ + // An empty message is treated as a message containing a single empty record. + if (isEmpty()) + return QNdefMessage(QNdefRecord()).toByteArray(); + + QByteArray m; + + for (qsizetype i = 0; i < size(); ++i) { + const QNdefRecord &record = at(i); + + quint8 flags = record.typeNameFormat(); + + if (i == 0) + flags |= 0x80; + if (i == size() - 1) + flags |= 0x40; + + // cf (chunked records) not supported yet + + if (record.payload().size() < 255) + flags |= 0x10; + + if (!record.id().isEmpty()) + flags |= 0x08; + + m.append(flags); + m.append(record.type().size()); + + if (flags & 0x10) { + m.append(quint8(record.payload().size())); + } else { + quint32 length = record.payload().size(); + m.append(length >> 24); + m.append(length >> 16); + m.append(length >> 8); + m.append(length & 0x000000ff); + } + + if (flags & 0x08) + m.append(record.id().size()); + + if (!record.type().isEmpty()) + m.append(record.type()); + + if (!record.id().isEmpty()) + m.append(record.id()); + + if (!record.payload().isEmpty()) + m.append(record.payload()); + } + + return m; +} + +QT_END_NAMESPACE diff --git a/src/nfc/qndefmessage.h b/src/nfc/qndefmessage.h new file mode 100644 index 0000000..ba840d1 --- /dev/null +++ b/src/nfc/qndefmessage.h @@ -0,0 +1,50 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QNDEFMESSAGE_H +#define QNDEFMESSAGE_H + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +// This class used to be exported exposing QList methods, see QTBUG-102367. +#if defined(QT_BUILD_NFC_LIB) +# define Q_NFC_EXPORT_COMPAT QT6_ONLY(Q_NFC_EXPORT) +#else +# define Q_NFC_EXPORT_COMPAT +#endif + +class QNdefMessage : public QList +{ +public: + Q_NFC_EXPORT_COMPAT + QNdefMessage() = default; + Q_NFC_EXPORT_COMPAT + explicit QNdefMessage(const QNdefRecord &record) { append(record); } + Q_NFC_EXPORT_COMPAT + QNdefMessage(const QNdefMessage &message) = default; + Q_NFC_EXPORT_COMPAT + QNdefMessage(const QList &records) : QList(records) { } + + Q_NFC_EXPORT_COMPAT + QNdefMessage &operator=(const QNdefMessage &other) = default; + Q_NFC_EXPORT_COMPAT + QNdefMessage &operator=(QNdefMessage &&other) noexcept = default; + + Q_NFC_EXPORT bool operator==(const QNdefMessage &other) const; + + Q_NFC_EXPORT QByteArray toByteArray() const; + + Q_NFC_EXPORT static QNdefMessage fromByteArray(const QByteArray &message); +}; + +QT_END_NAMESPACE + +QT_DECL_METATYPE_EXTERN(QNdefMessage, Q_NFC_EXPORT) + +#endif // QNDEFMESSAGE_H diff --git a/src/nfc/qndefnfcsmartposterrecord.cpp b/src/nfc/qndefnfcsmartposterrecord.cpp new file mode 100644 index 0000000..866abee --- /dev/null +++ b/src/nfc/qndefnfcsmartposterrecord.cpp @@ -0,0 +1,782 @@ +// Copyright (C) 2016 - 2012 Research In Motion +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include +#include "qndefnfcsmartposterrecord_p.h" +#include + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \class QNdefNfcIconRecord + \brief The QNdefNfcIconRecord class provides an NFC MIME record to hold an + icon. + + \ingroup connectivity-nfc + \inmodule QtNfc + \since Qt 5.2 + + This class wraps the image data into an NDEF message. + It provides an NDEF record of type \l QNdefRecord::Mime. + The \l {QNdefRecord::}{payload}() contains the raw image data. +*/ + +/*! + \fn QNdefNfcIconRecord::QNdefNfcIconRecord() + + Constructs an empty NDEF record of type \l QNdefRecord::Mime. +*/ + +/*! + \fn QNdefNfcIconRecord::QNdefNfcIconRecord(const QNdefRecord &other) + + Constructs an NDEF icon record that is a copy of \a other. +*/ + +/*! + \class QNdefNfcSmartPosterRecord + \brief The QNdefNfcSmartPosterRecord class provides an NFC RTD-SmartPoster. + + \ingroup connectivity-nfc + \inmodule QtNfc + \since Qt 5.2 + + RTD-SmartPoster encapsulates a Smart Poster. + */ + +/*! + \enum QNdefNfcSmartPosterRecord::Action + + This enum describes the course of action that a device should take with the content. + + \value UnspecifiedAction The action is not defined. + \value DoAction Do the action (send the SMS, launch the browser, make the telephone call). + \value SaveAction Save for later (store the SMS in INBOX, put the URI in a bookmark, save the telephone number in contacts). + \value EditAction Open for editing (open an SMS in the SMS editor, open the URI in a URI editor, open the telephone number for editing). + */ + +/*! + Constructs a new empty smart poster. +*/ +QNdefNfcSmartPosterRecord::QNdefNfcSmartPosterRecord() + : QNdefRecord(QNdefRecord::NfcRtd, "Sp"), + d(new QNdefNfcSmartPosterRecordPrivate) +{ +} + +/*! + Constructs a new smart poster that is a copy of \a other. +*/ +QNdefNfcSmartPosterRecord::QNdefNfcSmartPosterRecord(const QNdefRecord &other) + : QNdefRecord(other, QNdefRecord::NfcRtd, "Sp"), + d(new QNdefNfcSmartPosterRecordPrivate) +{ + // Need to set payload again to create internal structure + setPayload(other.payload()); +} + +/*! + Constructs a new smart poster that is a copy of \a other. +*/ +QNdefNfcSmartPosterRecord::QNdefNfcSmartPosterRecord(const QNdefNfcSmartPosterRecord &other) + : QNdefRecord(other, QNdefRecord::NfcRtd, "Sp"), d(other.d) +{ +} + +/*! + Assigns the \a other smart poster record to this record and returns a reference to + this record. +*/ +QNdefNfcSmartPosterRecord &QNdefNfcSmartPosterRecord::operator=(const QNdefNfcSmartPosterRecord &other) +{ + if (this != &other) + d = other.d; + + return *this; +} + +/*! + Destroys the smart poster. +*/ +QNdefNfcSmartPosterRecord::~QNdefNfcSmartPosterRecord() +{ +} + +void QNdefNfcSmartPosterRecord::cleanup() +{ + if (d) { + // Clean-up existing internal structure + d->m_titleList.clear(); + if (d->m_uri) delete d->m_uri; + if (d->m_action) delete d->m_action; + d->m_iconList.clear(); + if (d->m_size) delete d->m_size; + if (d->m_type) delete d->m_type; + } +} + +/*! + \internal + Sets the payload of the NDEF record to \a payload +*/ +void QNdefNfcSmartPosterRecord::setPayload(const QByteArray &payload) +{ + QNdefRecord::setPayload(payload); + + cleanup(); + + if (!payload.isEmpty()) { + // Create new structure + const QNdefMessage message = QNdefMessage::fromByteArray(payload); + + // Iterate through all the records contained in the payload's message. + for (const QNdefRecord& record : message) { + // Title + if (record.isRecordType()) { + addTitleInternal(record); + } + + // URI + else if (record.isRecordType()) { + d->m_uri = new QNdefNfcUriRecord(record); + } + + // Action + else if (record.isRecordType()) { + d->m_action = new QNdefNfcActRecord(record); + } + + // Icon + else if (record.isRecordType()) { + addIconInternal(record); + } + + // Size + else if (record.isRecordType()) { + d->m_size = new QNdefNfcSizeRecord(record); + } + + // Type + else if (record.isRecordType()) { + d->m_type = new QNdefNfcTypeRecord(record); + } + } + } +} + +void QNdefNfcSmartPosterRecord::convertToPayload() +{ + QNdefMessage message; + + // Title + for (qsizetype t = 0; t < titleCount(); t++) + message.append(titleRecord(t)); + + // URI + if (d->m_uri) + message.append(*(d->m_uri)); + + // Action + if (d->m_action) + message.append(*(d->m_action)); + + // Icon + for (qsizetype i = 0; i < iconCount(); i++) + message.append(iconRecord(i)); + + // Size + if (d->m_size) + message.append(*(d->m_size)); + + // Type + if (d->m_type) + message.append(*(d->m_type)); + + QNdefRecord::setPayload(message.toByteArray()); +} + +/*! + Returns \c true if the smart poster contains a title record using the locale + \a locale. If \a locale is empty, then \c true is returned if the smart + poster contains at least one title record. In all other cases, \c false is + returned. + */ +bool QNdefNfcSmartPosterRecord::hasTitle(const QString &locale) const +{ + for (qsizetype i = 0; i < d->m_titleList.size(); ++i) { + const QNdefNfcTextRecord &text = d->m_titleList[i]; + + if (locale.isEmpty() || text.locale() == locale) + return true; + } + + return false; +} + +/*! + Returns \c true if the smart poster contains an action record, otherwise + returns \c false. + */ +bool QNdefNfcSmartPosterRecord::hasAction() const +{ + return d->m_action != nullptr; +} + +/*! + Returns \c true if the smart poster contains an icon record using the type + \a mimetype. If \a mimetype is empty, then \c true is returned if the smart + poster contains at least one icon record. + In all other cases, \c false is returned. + */ +bool QNdefNfcSmartPosterRecord::hasIcon(const QByteArray &mimetype) const +{ + for (qsizetype i = 0; i < d->m_iconList.size(); ++i) { + const QNdefNfcIconRecord &icon = d->m_iconList[i]; + + if (mimetype.isEmpty() || icon.type() == mimetype) + return true; + } + + return false; +} + +/*! + Returns \c true if the smart poster contains a size record, otherwise + returns \c false. + */ +bool QNdefNfcSmartPosterRecord::hasSize() const +{ + return d->m_size != nullptr; +} + +/*! + Returns \c true if the smart poster contains a type record, otherwise + returns \c false. + */ +bool QNdefNfcSmartPosterRecord::hasTypeInfo() const +{ + return d->m_type != nullptr; +} + +/*! + Returns the number of title records contained inside the smart poster. + */ +qsizetype QNdefNfcSmartPosterRecord::titleCount() const +{ + return d->m_titleList.size(); +} + +/*! + Returns the title record corresponding to the index \a index inside the + smart poster, where \a index is a value between 0 and titleCount() - 1. + Values outside of this range return an empty record. + */ +QNdefNfcTextRecord QNdefNfcSmartPosterRecord::titleRecord(qsizetype index) const +{ + if (index >= 0 && index < d->m_titleList.size()) + return d->m_titleList[index]; + + return QNdefNfcTextRecord(); +} + +/*! + Returns the title record text associated with locale \a locale if available. If \a locale + is empty then the title text of the first available record is returned. In all other + cases an empty string is returned. + */ +QString QNdefNfcSmartPosterRecord::title(const QString &locale) const +{ + for (qsizetype i = 0; i < d->m_titleList.size(); ++i) { + const QNdefNfcTextRecord &text = d->m_titleList[i]; + + if (locale.isEmpty() || text.locale() == locale) + return text.text(); + } + + return QString(); +} + +/*! + Returns a copy of all title records inside the smart poster. + */ +QList QNdefNfcSmartPosterRecord::titleRecords() const +{ + return d->m_titleList; +} + +/*! + Attempts to add a title record \a text to the smart poster. If the smart poster does not already + contain a title record with the same locale as title record \a text, then the title record is added + and the function returns \c true. Otherwise \c false is returned. + */ +bool QNdefNfcSmartPosterRecord::addTitle(const QNdefNfcTextRecord &text) +{ + const bool status = addTitleInternal(text); + + // Convert to payload if the title is added + if (status) + convertToPayload(); + + return status; +} + +bool QNdefNfcSmartPosterRecord::addTitleInternal(const QNdefNfcTextRecord &text) +{ + for (qsizetype i = 0; i < d->m_titleList.size(); ++i) { + const QNdefNfcTextRecord &rec = d->m_titleList[i]; + + if (rec.locale() == text.locale()) + return false; + } + + d->m_titleList.append(text); + return true; +} + +/*! + Attempts to add a new title record with title \a text, locale \a locale and encoding \a encoding. + If the smart poster does not already contain a title record with locale \a locale, then the title record + is added and the function returns \c true. Otherwise \c false is returned. + */ +bool QNdefNfcSmartPosterRecord::addTitle(const QString &text, const QString &locale, QNdefNfcTextRecord::Encoding encoding) +{ + QNdefNfcTextRecord rec; + rec.setText(text); + rec.setLocale(locale); + rec.setEncoding(encoding); + + return addTitle(rec); +} + +/*! + Attempts to remove the title record \a text from the smart poster. Removes + the record and returns \c true if the smart poster contains a matching + record, otherwise \c false is returned. + */ +bool QNdefNfcSmartPosterRecord::removeTitle(const QNdefNfcTextRecord &text) +{ + bool status = false; + + for (qsizetype i = 0; i < d->m_titleList.size(); ++i) { + const QNdefNfcTextRecord &rec = d->m_titleList[i]; + + if (rec.text() == text.text() && rec.locale() == text.locale() && rec.encoding() == text.encoding()) { + d->m_titleList.removeAt(i); + status = true; + break; + } + } + + // Convert to payload if the title list has changed + if (status) + convertToPayload(); + + return status; +} + +/*! + Attempts to remove a title record with the locale \a locale from the smart + poster. Removes the record and returns \c true if the smart poster contains + a matching record, otherwise \c false is returned. + */ +bool QNdefNfcSmartPosterRecord::removeTitle(const QString &locale) +{ + bool status = false; + + for (qsizetype i = 0; i < d->m_titleList.size(); ++i) { + const QNdefNfcTextRecord &rec = d->m_titleList[i]; + + if (rec.locale() == locale) { + d->m_titleList.removeAt(i); + status = true; + break; + } + } + + // Convert to payload if the title list has changed + if (status) + convertToPayload(); + + return status; +} + +/*! + Adds the title record list \a titles to the smart poster. Any existing records are overwritten. + */ +void QNdefNfcSmartPosterRecord::setTitles(const QList &titles) +{ + d->m_titleList.clear(); + + for (qsizetype i = 0; i < titles.size(); ++i) { + d->m_titleList.append(titles[i]); + } + + // Convert to payload + convertToPayload(); +} + +/*! + Returns the URI from the smart poster's URI record if set. Otherwise an empty URI is returned. + */ +QUrl QNdefNfcSmartPosterRecord::uri() const +{ + if (d->m_uri) + return d->m_uri->uri(); + + return QUrl(); +} + +/*! + Returns the smart poster's URI record if set. Otherwise an empty URI is returned. + */ +QNdefNfcUriRecord QNdefNfcSmartPosterRecord::uriRecord() const +{ + if (d->m_uri) + return *(d->m_uri); + + return QNdefNfcUriRecord(); +} + +/*! + Sets the URI record to \a url + */ +void QNdefNfcSmartPosterRecord::setUri(const QNdefNfcUriRecord &url) +{ + if (d->m_uri) + delete d->m_uri; + + d->m_uri = new QNdefNfcUriRecord(url); + + // Convert to payload + convertToPayload(); +} + +/*! + Constructs a URI record and sets its content inside the smart poster to \a url + */ +void QNdefNfcSmartPosterRecord::setUri(const QUrl &url) +{ + QNdefNfcUriRecord rec; + rec.setUri(url); + + setUri(rec); +} + +/*! + Returns the action from the action record if available. Otherwise \l UnspecifiedAction is returned. + */ +QNdefNfcSmartPosterRecord::Action QNdefNfcSmartPosterRecord::action() const +{ + if (d->m_action) + return d->m_action->action(); + + return UnspecifiedAction; +} + +/*! + Sets the action record to \a act + */ +void QNdefNfcSmartPosterRecord::setAction(Action act) +{ + if (!d->m_action) + d->m_action = new QNdefNfcActRecord(); + + d->m_action->setAction(act); + + // Convert to payload + convertToPayload(); +} + +/*! + Returns the number of icon records contained inside the smart poster. + */ +qsizetype QNdefNfcSmartPosterRecord::iconCount() const +{ + return d->m_iconList.size(); +} + +/*! + Returns the icon record corresponding to the index \a index inside the smart + poster, where \a index is a value between 0 and \l iconCount() - 1. + Values outside of this range return an empty record. + */ +QNdefNfcIconRecord QNdefNfcSmartPosterRecord::iconRecord(qsizetype index) const +{ + if (index >= 0 && index < d->m_iconList.size()) + return d->m_iconList[index]; + + return QNdefNfcIconRecord(); +} + +/*! + Returns the associated icon record data if the smart poster contains an icon record with MIME type \a mimetype. + If \a mimetype is omitted or empty then the first icon's record data is returned. In all other cases, an empty array is returned. + */ +QByteArray QNdefNfcSmartPosterRecord::icon(const QByteArray& mimetype) const +{ + for (qsizetype i = 0; i < d->m_iconList.size(); ++i) { + const QNdefNfcIconRecord &icon = d->m_iconList[i]; + + if (mimetype.isEmpty() || icon.type() == mimetype) + return icon.data(); + } + + return QByteArray(); +} + +/*! + Returns a copy of all icon records inside the smart poster. + */ +QList QNdefNfcSmartPosterRecord::iconRecords() const +{ + return d->m_iconList; +} + +/*! + Adds an icon record \a icon to the smart poster. If the smart poster already contains an icon + record with the same type then the existing icon record is replaced. + */ +void QNdefNfcSmartPosterRecord::addIcon(const QNdefNfcIconRecord &icon) +{ + addIconInternal(icon); + + // Convert to payload + convertToPayload(); +} + +void QNdefNfcSmartPosterRecord::addIconInternal(const QNdefNfcIconRecord &icon) +{ + for (qsizetype i = 0; i < d->m_iconList.size(); ++i) { + const QNdefNfcIconRecord &rec = d->m_iconList[i]; + + if (rec.type() == icon.type()) + d->m_iconList.removeAt(i); + } + + d->m_iconList.append(icon); +} + +/*! + Adds an icon record with type \a type and data \a data to the smart poster. If the smart poster + already contains an icon record with the same type then the existing icon record is replaced. + */ +void QNdefNfcSmartPosterRecord::addIcon(const QByteArray &type, const QByteArray &data) +{ + QNdefNfcIconRecord rec; + rec.setType(type); + rec.setData(data); + + addIcon(rec); +} + +/*! + Attempts to remove the icon record \a icon from the smart poster. + Removes the record and returns \c true if the smart poster contains + a matching record, otherwise \c false is returned. + */ +bool QNdefNfcSmartPosterRecord::removeIcon(const QNdefNfcIconRecord &icon) +{ + bool status = false; + + for (qsizetype i = 0; i < d->m_iconList.size(); ++i) { + const QNdefNfcIconRecord &rec = d->m_iconList[i]; + + if (rec.type() == icon.type() && rec.data() == icon.data()) { + d->m_iconList.removeAt(i); + status = true; + break; + } + } + + // Convert to payload if the icon list has changed + if (status) + convertToPayload(); + + return status; +} + +/*! + Attempts to remove the icon record with the type \a type from the smart + poster. Removes the record and returns \c true if the smart poster contains + a matching record, otherwise \c false is returned. + */ +bool QNdefNfcSmartPosterRecord::removeIcon(const QByteArray &type) +{ + bool status = false; + + for (qsizetype i = 0; i < d->m_iconList.size(); ++i) { + const QNdefNfcIconRecord &rec = d->m_iconList[i]; + + if (rec.type() == type) { + d->m_iconList.removeAt(i); + status = true; + break; + } + } + + // Convert to payload if the icon list has changed + if (status) + convertToPayload(); + + return status; +} + +/*! + Adds the icon record list \a icons to the smart poster. + Any existing records are overwritten. + + \sa hasIcon(), icon() + */ +void QNdefNfcSmartPosterRecord::setIcons(const QList &icons) +{ + d->m_iconList.clear(); + + for (qsizetype i = 0; i < icons.size(); ++i) { + d->m_iconList.append(icons[i]); + } + + // Convert to payload + convertToPayload(); +} + +/*! + Returns the size from the size record if available; otherwise returns 0. + + The value is optional and contains the size in bytes of the object + that the URI refers to. It may be used by the device to determine + whether it can accommodate the object. + + \sa setSize() + */ +quint32 QNdefNfcSmartPosterRecord::size() const +{ + if (d->m_size) + return d->m_size->size(); + + return 0; +} + +/*! + Sets the record \a size. The value contains the size in bytes of + the object that the URI refers to. + + \sa size(), hasSize() + */ +void QNdefNfcSmartPosterRecord::setSize(quint32 size) +{ + if (!d->m_size) + d->m_size = new QNdefNfcSizeRecord(); + + d->m_size->setSize(size); + + // Convert to payload + convertToPayload(); +} + +/*! + Returns the MIME type that describes the type of the objects that can be + reached via uri(). + + If the type is not known, the returned QString is empty. + + \sa setTypeInfo(), hasTypeInfo() + */ +QString QNdefNfcSmartPosterRecord::typeInfo() const +{ + if (d->m_type) + return d->m_type->typeInfo(); + + return QString(); +} + +/*! + Sets the type record to \a type. \a type describes the type of the object + referenced by uri(). + + \sa typeInfo() + */ +void QNdefNfcSmartPosterRecord::setTypeInfo(const QString &type) +{ + if (d->m_type) + delete d->m_type; + + d->m_type = new QNdefNfcTypeRecord(); + d->m_type->setTypeInfo(type); + + // Convert to payload + convertToPayload(); +} + +void QNdefNfcActRecord::setAction(QNdefNfcSmartPosterRecord::Action action) +{ + QByteArray data(1, action); + + setPayload(data); +} + +QNdefNfcSmartPosterRecord::Action QNdefNfcActRecord::action() const +{ + const QByteArray p = payload(); + QNdefNfcSmartPosterRecord::Action value = + QNdefNfcSmartPosterRecord::UnspecifiedAction; + + if (!p.isEmpty()) + value = QNdefNfcSmartPosterRecord::Action(static_cast(p[0])); + + return value; +} + +/*! + Sets the contents of the icon record to \a data. +*/ +void QNdefNfcIconRecord::setData(const QByteArray &data) +{ + setPayload(data); +} + +/*! + Returns the icon data as \l QByteArray. +*/ +QByteArray QNdefNfcIconRecord::data() const +{ + return payload(); +} + +void QNdefNfcSizeRecord::setSize(quint32 size) +{ + QByteArray data(4, 0); + + data[0] = (int) ((size & 0xFF000000) >> 24); + data[1] = (int) ((size & 0x00FF0000) >> 16); + data[2] = (int) ((size & 0x0000FF00) >> 8); + data[3] = (int) ((size & 0x000000FF)); + + setPayload(data); +} + +quint32 QNdefNfcSizeRecord::size() const +{ + const QByteArray p = payload(); + + if (p.isEmpty()) + return 0; + + return ((p[0] << 24) & 0xFF000000) + ((p[1] << 16) & 0x00FF0000) + + ((p[2] << 8) & 0x0000FF00) + (p[3] & 0x000000FF); +} + +void QNdefNfcTypeRecord::setTypeInfo(const QString &type) +{ + setPayload(type.toUtf8()); +} + +QString QNdefNfcTypeRecord::typeInfo() const +{ + return QString::fromUtf8(payload()); +} + +QT_END_NAMESPACE diff --git a/src/nfc/qndefnfcsmartposterrecord.h b/src/nfc/qndefnfcsmartposterrecord.h new file mode 100644 index 0000000..0424e05 --- /dev/null +++ b/src/nfc/qndefnfcsmartposterrecord.h @@ -0,0 +1,117 @@ +// Copyright (C) 2016 - 2012 Research In Motion +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QNDEFNFCSMARTPOSTERRECORD_H +#define QNDEFNFCSMARTPOSTERRECORD_H + +#include +#include +#include +#include +#include +#include + +QT_FORWARD_DECLARE_CLASS(QUrl) + +QT_BEGIN_NAMESPACE + +class QNdefNfcSmartPosterRecordPrivate; + +#define Q_DECLARE_ISRECORDTYPE_FOR_MIME_NDEF_RECORD(className) \ + QT_BEGIN_NAMESPACE \ + template<> inline bool QNdefRecord::isRecordType() const\ + { \ + return (typeNameFormat() == QNdefRecord::Mime); \ + } \ + QT_END_NAMESPACE + +#define Q_DECLARE_MIME_NDEF_RECORD(className, initialPayload) \ + className() : QNdefRecord(QNdefRecord::Mime, "") { setPayload(initialPayload); } \ + className(const QNdefRecord &other) : QNdefRecord(other, QNdefRecord::Mime) { } + +class Q_NFC_EXPORT QNdefNfcIconRecord : public QNdefRecord +{ +public: + Q_DECLARE_MIME_NDEF_RECORD(QNdefNfcIconRecord, QByteArray(0, char(0))) + + void setData(const QByteArray &data); + QByteArray data() const; +}; + +class Q_NFC_EXPORT QNdefNfcSmartPosterRecord : public QNdefRecord +{ +public: + enum Action { + UnspecifiedAction = -1, + DoAction = 0, + SaveAction = 1, + EditAction = 2 + }; + + QNdefNfcSmartPosterRecord(); + QNdefNfcSmartPosterRecord(const QNdefRecord &other); + QNdefNfcSmartPosterRecord(const QNdefNfcSmartPosterRecord &other); + QNdefNfcSmartPosterRecord &operator=(const QNdefNfcSmartPosterRecord &other); + ~QNdefNfcSmartPosterRecord(); + + void setPayload(const QByteArray &payload); + + bool hasTitle(const QString &locale = QString()) const; + bool hasAction() const; + bool hasIcon(const QByteArray &mimetype = QByteArray()) const; + bool hasSize() const; + bool hasTypeInfo() const; + + qsizetype titleCount() const; + QNdefNfcTextRecord titleRecord(qsizetype index) const; + QString title(const QString &locale = QString()) const; + QList titleRecords() const; + + bool addTitle(const QNdefNfcTextRecord &text); + bool addTitle(const QString &text, const QString &locale, QNdefNfcTextRecord::Encoding encoding); + bool removeTitle(const QNdefNfcTextRecord &text); + bool removeTitle(const QString &locale); + void setTitles(const QList &titles); + + QUrl uri() const; + QNdefNfcUriRecord uriRecord() const; + void setUri(const QNdefNfcUriRecord &url); + void setUri(const QUrl &url); + + Action action() const; + void setAction(Action act); + + qsizetype iconCount() const; + QNdefNfcIconRecord iconRecord(qsizetype index) const; + QByteArray icon(const QByteArray& mimetype = QByteArray()) const; + + QList iconRecords() const; + + void addIcon(const QNdefNfcIconRecord &icon); + void addIcon(const QByteArray &type, const QByteArray &data); + bool removeIcon(const QNdefNfcIconRecord &icon); + bool removeIcon(const QByteArray &type); + void setIcons(const QList &icons); + + quint32 size() const; + void setSize(quint32 size); + + QString typeInfo() const; + void setTypeInfo(const QString &type); + +private: + QSharedDataPointer d; + + void cleanup(); + void convertToPayload(); + + bool addTitleInternal(const QNdefNfcTextRecord &text); + void addIconInternal(const QNdefNfcIconRecord &icon); +}; + +QT_END_NAMESPACE + +Q_DECLARE_ISRECORDTYPE_FOR_NDEF_RECORD(QNdefNfcSmartPosterRecord, QNdefRecord::NfcRtd, "Sp") +Q_DECLARE_ISRECORDTYPE_FOR_MIME_NDEF_RECORD(QNdefNfcIconRecord) + +#endif // QNDEFNFCSMARTPOSTERRECORD_H diff --git a/src/nfc/qndefnfcsmartposterrecord_p.h b/src/nfc/qndefnfcsmartposterrecord_p.h new file mode 100644 index 0000000..cab8575 --- /dev/null +++ b/src/nfc/qndefnfcsmartposterrecord_p.h @@ -0,0 +1,67 @@ +// Copyright (C) 2016 - 2012 Research In Motion +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QNDEFNFCSMARTPOSTERRECORD_P_H +#define QNDEFNFCSMARTPOSTERRECORD_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 QNdefNfcActRecord : public QNdefRecord +{ +public: + Q_DECLARE_NDEF_RECORD(QNdefNfcActRecord, QNdefRecord::NfcRtd, "act", QByteArray(0, char(0))) + + void setAction(QNdefNfcSmartPosterRecord::Action action); + QNdefNfcSmartPosterRecord::Action action() const; +}; + +class QNdefNfcSizeRecord : public QNdefRecord +{ +public: + Q_DECLARE_NDEF_RECORD(QNdefNfcSizeRecord, QNdefRecord::NfcRtd, "s", QByteArray(0, char(0))) + + void setSize(quint32 size); + quint32 size() const; +}; + +class QNdefNfcTypeRecord : public QNdefRecord +{ +public: + Q_DECLARE_NDEF_RECORD(QNdefNfcTypeRecord, QNdefRecord::NfcRtd, "t", QByteArray(0, char(0))) + + void setTypeInfo(const QString &type); + QString typeInfo() const; +}; + +class QNdefNfcSmartPosterRecordPrivate : public QSharedData +{ +public: + QNdefNfcSmartPosterRecordPrivate() {} + +public: + QList m_titleList; + QNdefNfcUriRecord *m_uri = nullptr; + QNdefNfcActRecord *m_action = nullptr; + QList m_iconList; + QNdefNfcSizeRecord *m_size = nullptr; + QNdefNfcTypeRecord *m_type = nullptr; +}; + +QT_END_NAMESPACE + +Q_DECLARE_ISRECORDTYPE_FOR_NDEF_RECORD(QNdefNfcActRecord, QNdefRecord::NfcRtd, "act") +Q_DECLARE_ISRECORDTYPE_FOR_NDEF_RECORD(QNdefNfcSizeRecord, QNdefRecord::NfcRtd, "s") +Q_DECLARE_ISRECORDTYPE_FOR_NDEF_RECORD(QNdefNfcTypeRecord, QNdefRecord::NfcRtd, "t") + +#endif // QNDEFNFCSMARTPOSTERRECORD_P_H diff --git a/src/nfc/qndefnfctextrecord.cpp b/src/nfc/qndefnfctextrecord.cpp new file mode 100644 index 0000000..a8d9b09 --- /dev/null +++ b/src/nfc/qndefnfctextrecord.cpp @@ -0,0 +1,169 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \class QNdefNfcTextRecord + \brief The QNdefNfcTextRecord class provides an NFC RTD-Text. + + \ingroup connectivity-nfc + \inmodule QtNfc + \since 5.2 + + RTD-Text encapsulates a user displayable text record. +*/ + +/*! + \enum QNdefNfcTextRecord::Encoding + + This enum describes the text encoding standard used. + + \value Utf8 The text is encoded with UTF-8. + \value Utf16 The text is encoding with UTF-16. +*/ + +/*! + \fn QNdefNfcTextRecord::QNdefNfcTextRecord() + + Constructs an empty NFC text record of type \l QNdefRecord::NfcRtd. +*/ + +/*! + \fn QNdefNfcTextRecord::QNdefNfcTextRecord(const QNdefRecord& other) + + Constructs a new NFC text record that is a copy of \a other. +*/ + +/*! + Returns the locale of the text record. +*/ +QString QNdefNfcTextRecord::locale() const +{ + const QByteArray p = payload(); + + if (p.isEmpty()) + return QString(); + + quint8 status = p.at(0); + + quint8 codeLength = status & 0x3f; + + return QString::fromLatin1(p.constData() + 1, codeLength); +} + +/*! + Sets the locale of the text record to \a locale. +*/ +void QNdefNfcTextRecord::setLocale(const QString &locale) +{ + QByteArray p = payload(); + + quint8 status = p.isEmpty() ? 0 : p.at(0); + + quint8 codeLength = status & 0x3f; + + quint8 newStatus = (status & 0xd0) | locale.size(); + + p[0] = newStatus; + p.replace(1, codeLength, locale.toLatin1()); + + setPayload(p); +} + +/*! + Returns the contents of the text record as a string. +*/ +QString QNdefNfcTextRecord::text() const +{ + const QByteArray p = payload(); + + if (p.isEmpty()) + return QString(); + + quint8 status = p.at(0); + bool utf16 = status & 0x80; + quint8 codeLength = status & 0x3f; + + auto toUnicode = QStringDecoder( + utf16 ? QStringDecoder::Encoding::Utf16BE : QStringDecoder::Encoding::Utf8, + QStringDecoder::Flag::Stateless); + + return toUnicode(QByteArrayView(p.constData() + 1 + codeLength, p.size() - 1 - codeLength)); +} + +/*! + Sets the contents of the text record to \a text. +*/ +void QNdefNfcTextRecord::setText(const QString text) +{ + if (payload().isEmpty()) + setLocale(QLocale().name()); + + QByteArray p = payload(); + + quint8 status = p.at(0); + + bool utf16 = status & 0x80; + quint8 codeLength = status & 0x3f; + + p.truncate(1 + codeLength); + + auto fromUnicode = QStringEncoder( + utf16? QStringEncoder::Encoding::Utf16BE : QStringEncoder::Encoding::Utf8, + QStringEncoder::Flag::Stateless|QStringEncoder::Flag::WriteBom); + + p += fromUnicode(text); + + setPayload(p); +} + +/*! + Returns the encoding of the contents. +*/ +QNdefNfcTextRecord::Encoding QNdefNfcTextRecord::encoding() const +{ + if (payload().isEmpty()) + return Utf8; + + QByteArray p = payload(); + + quint8 status = p.at(0); + + bool utf16 = status & 0x80; + + if (utf16) + return Utf16; + else + return Utf8; +} + +/*! + Sets the enconding of the contents to \a encoding. +*/ +void QNdefNfcTextRecord::setEncoding(Encoding encoding) +{ + QByteArray p = payload(); + + quint8 status = p.isEmpty() ? 0 : p.at(0); + + QString string = text(); + + if (encoding == Utf8) + status &= ~0x80; + else + status |= 0x80; + + p[0] = status; + + setPayload(p); + + setText(string); +} + +QT_END_NAMESPACE diff --git a/src/nfc/qndefnfctextrecord.h b/src/nfc/qndefnfctextrecord.h new file mode 100644 index 0000000..103669b --- /dev/null +++ b/src/nfc/qndefnfctextrecord.h @@ -0,0 +1,41 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QNDEFNFCTEXTRECORD_H +#define QNDEFNFCTEXTRECORD_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class Q_NFC_EXPORT QNdefNfcTextRecord : public QNdefRecord +{ +public: +#ifndef Q_QDOC + Q_DECLARE_NDEF_RECORD(QNdefNfcTextRecord, QNdefRecord::NfcRtd, "T", QByteArray(1, char(0))) +#else + QNdefNfcTextRecord(); + QNdefNfcTextRecord(const QNdefRecord& other); +#endif + + QString locale() const; + void setLocale(const QString &locale); + + QString text() const; + void setText(const QString text); + + enum Encoding { + Utf8, + Utf16 + }; + + Encoding encoding() const; + void setEncoding(Encoding encoding); +}; + +QT_END_NAMESPACE + +Q_DECLARE_ISRECORDTYPE_FOR_NDEF_RECORD(QNdefNfcTextRecord, QNdefRecord::NfcRtd, "T") + +#endif // QNDEFNFCTEXTRECORD_H diff --git a/src/nfc/qndefnfcurirecord.cpp b/src/nfc/qndefnfcurirecord.cpp new file mode 100644 index 0000000..690e184 --- /dev/null +++ b/src/nfc/qndefnfcurirecord.cpp @@ -0,0 +1,118 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qndefnfcurirecord.h" + +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +/*! + \class QNdefNfcUriRecord + \brief The QNdefNfcUriRecord class provides an NFC RTD-URI. + + \ingroup connectivity-nfc + \inmodule QtNfc + \since 5.2 + + RTD-URI encapsulates a URI. +*/ + +/*! + \fn QNdefNfcUriRecord::QNdefNfcUriRecord() + + Constructs an empty NFC uri record. +*/ + +/*! + \fn QNdefNfcUriRecord::QNdefNfcUriRecord(const QNdefRecord& other) + + Constructs a new NFC uri record that is a copy of \a other. +*/ +static const char * const abbreviations[] = { + 0, + "http://www.", + "https://www.", + "http://", + "https://", + "tel:", + "mailto:", + "ftp://anonymous:anonymous@", + "ftp://ftp.", + "ftps://", + "sftp://", + "smb://", + "nfs://", + "ftp://", + "dav://", + "news:", + "telnet://", + "imap:", + "rtsp://", + "urn:", + "pop:", + "sip:", + "sips:", + "tftp:", + "btspp://", + "btl2cap://", + "btgoep://", + "tcpobex://", + "irdaobex://", + "file://", + "urn:epc:id:", + "urn:epc:tag:", + "urn:epc:pat:", + "urn:epc:raw:", + "urn:epc:", + "urn:nfc:", +}; + +/*! + Returns the URI of this URI record. +*/ +QUrl QNdefNfcUriRecord::uri() const +{ + QByteArray p = payload(); + + if (p.isEmpty()) + return QUrl(); + + quint8 code = p.at(0); + if (code >= sizeof(abbreviations) / sizeof(*abbreviations)) + code = 0; + p.remove(0, 1); + if (const char *abbreviation = abbreviations[code]) + p.insert(0, abbreviation); + return QUrl(QString::fromUtf8(p)); +} + +/*! + Sets the URI of this URI record to \a uri. +*/ +void QNdefNfcUriRecord::setUri(const QUrl &uri) +{ + int abbrevs = sizeof(abbreviations) / sizeof(*abbreviations); + + for (int i = 1; i < abbrevs; ++i) { + if (uri.toString().startsWith(QLatin1String(abbreviations[i]))) { + QByteArray p(1, i); + + p += uri.toString().mid(qstrlen(abbreviations[i])).toUtf8(); + + setPayload(p); + + return; + } + } + + QByteArray p(1, 0); + p += uri.toString().toUtf8(); + + setPayload(p); +} + +QT_END_NAMESPACE diff --git a/src/nfc/qndefnfcurirecord.h b/src/nfc/qndefnfcurirecord.h new file mode 100644 index 0000000..9a59d8e --- /dev/null +++ b/src/nfc/qndefnfcurirecord.h @@ -0,0 +1,32 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QNDEFNFCURIRECORD_H +#define QNDEFNFCURIRECORD_H + +#include +#include + +QT_FORWARD_DECLARE_CLASS(QUrl) + +QT_BEGIN_NAMESPACE + +class Q_NFC_EXPORT QNdefNfcUriRecord : public QNdefRecord +{ +public: +#ifndef Q_QDOC + Q_DECLARE_NDEF_RECORD(QNdefNfcUriRecord, QNdefRecord::NfcRtd, "U", QByteArray(0, char(0))) +#else + QNdefNfcUriRecord(); + QNdefNfcUriRecord(const QNdefRecord& other); +#endif + + QUrl uri() const; + void setUri(const QUrl &uri); +}; + +QT_END_NAMESPACE + +Q_DECLARE_ISRECORDTYPE_FOR_NDEF_RECORD(QNdefNfcUriRecord, QNdefRecord::NfcRtd, "U") + +#endif // QNDEFNFCURIRECORD_H diff --git a/src/nfc/qndefrecord.cpp b/src/nfc/qndefrecord.cpp new file mode 100644 index 0000000..51df2ab --- /dev/null +++ b/src/nfc/qndefrecord.cpp @@ -0,0 +1,354 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + + +#include "qndefrecord.h" +#include "qndefrecord_p.h" + +#include + +QT_BEGIN_NAMESPACE + +/*! + \class QNdefRecord + \brief The QNdefRecord class provides an NFC NDEF record. + + \ingroup connectivity-nfc + \inmodule QtNfc + \since 5.2 + + QNdefRecord and derived classes are used to parse the contents of + \l {QNdefMessage}{NDEF messages} and create new NDEF messages. + + Use typeNameFormat() and setTypeNameFormat() to + get and set the type name format of the NDEF record. + + Use type() and setType() to get and set the type of the NDEF record. + + Use id() and setId() to get and set the id of the NDEF record. + + Use payload() and setPayload() to get and set the NDEF record payload. isEmpty() can be used + to test if the payload is empty. + + QNdefRecord is an implicitly shared class. This means you can efficiently convert between + QNdefRecord and specialized record classes. The isRecordType() template function can be used + to test if a conversion is possible. The following example shows how to test if a QNdefRecord + is an NFC RTD Text record and extract the text information from it. + + \snippet nfc.cpp Record conversion + + \section1 Creating Specialized NDEF Record Classes + + Specialized NDEF record classes can be easily created with the Q_DECLARE_NDEF_RECORD() and + Q_DECLARE_ISRECORDTYPE_FOR_NDEF_RECORD() macros. The following example shows the class + declaration of the hypothetical \e {example.com:f} record type that encapsulates a single int + property foo. + + \snippet nfc.cpp Specialized class definition + + The developer only needs to provide implementations for the \c {foo()} and \c {setFoo()} + functions that parse and set the contents of the NDEF record's payload. +*/ + +/*! + \enum QNdefRecord::TypeNameFormat + + This enum describes the type name format of an NDEF record. + + \value Empty An empty NDEF record, the record does not contain a payload + \value NfcRtd The NDEF record type is defined by an NFC RTD Specification + \value Mime The NDEF record type follows the construct described in RFC 2046 + \value Uri The NDEF record type follows the construct described in RFC 3986 + \value ExternalRtd The NDEF record type follows the construct for external type names + described the NFC RTD Specification + \value Unknown The type of the record is unknown and should be treated similar to content + with MIME type 'application/octet-stream' without further context +*/ + +/*! + \fn template bool QNdefRecord::isRecordType() const + + Returns \c true if the NDEF record is of the specified record type; + otherwise returns \c false. +*/ + +/*! + \fn bool QNdefRecord::operator!=(const QNdefRecord &other) const + + Returns \c true if this NDEF record does not equal \a other; + otherwise return \c false. +*/ + +/*! + \macro Q_DECLARE_NDEF_RECORD(className, typeNameFormat, type, initialPayload) + \relates QNdefRecord + + This macro declares default and copy constructors for specialized NDEF record classes. + + \a className is the name of the specialized class, \a typeNameFormat is the appropriate + QNdefRecord::TypeNameFormat for the custom type and \a type is the type without the NID or NSS + prefixes. That is \e {example.com:f} not \e {urn:nfc:ext:example.com:f}. \a initialPayload + is the initial payload of an empty record, it must be a QByteArray or a type that can be + implicitly converted into a QByteArray. + + See the section on \l {Creating specialized NDEF record classes} for details. + + \sa Q_DECLARE_ISRECORDTYPE_FOR_NDEF_RECORD() +*/ + +/*! + \macro Q_DECLARE_ISRECORDTYPE_FOR_NDEF_RECORD(className, typeNameFormat, type) + \relates QNdefRecord + + This macro declares a template specialization for the QNdefRecord::isRecordType() function. + + This macro should be used in the header file directly after the definition of a specialized + NDEF record class. + + \a className is the name of the specialized class, \a typeNameFormat is the appropriate + QNdefRecord::TypeNameFormat for the custom type and \a type is the type without the NID or NSS + prefixes. That is \e {example.com:f} not \e {urn:nfc:ext:example.com:f}. + + See the section on \l {Creating specialized NDEF record classes} for details. + + \sa Q_DECLARE_NDEF_RECORD() +*/ + +size_t qHash(const QNdefRecord &key) +{ + return qHash(key.type() + key.id() + key.payload()); +} + +/*! + Constructs a new empty NDEF record. +*/ +QNdefRecord::QNdefRecord() +{ +} + +/*! + Constructs a new NDEF record that is a copy of \a other. +*/ +QNdefRecord::QNdefRecord(const QNdefRecord &other) +{ + d = other.d; +} + +/*! + \internal + + Constructs an NDEF record that is a copy of \a other if \a other is of the expected type name + format identified by \a typeNameFormat and type as identified by \a type; otherwise an empty + NDEF record of the expected type name format and type is created. +*/ +QNdefRecord::QNdefRecord(const QNdefRecord &other, TypeNameFormat typeNameFormat, + const QByteArray &type) +{ + if (other.d->typeNameFormat == quint8(typeNameFormat) && other.d->type == type) { + d = other.d; + } else { + d = new QNdefRecordPrivate; + d->typeNameFormat = typeNameFormat; + d->type = type; + } +} + +/*! + \internal + + Constructs an NDEF record that is a copy of \a other if \a other is of the expected type name + format identified by \a typeNameFormat; otherwise an empty NDEF record of the expected type + name format and type is created. +*/ +QNdefRecord::QNdefRecord(const QNdefRecord &other, TypeNameFormat typeNameFormat) +{ + if (other.d->typeNameFormat == quint8(typeNameFormat)) { + d = other.d; + } else { + d = new QNdefRecordPrivate; + d->typeNameFormat = typeNameFormat; + } +} + +/*! + \internal + + Constructs an NDEF record with a type name format identified by \a typeNameFormat and type as + identified by \a type. +*/ +QNdefRecord::QNdefRecord(TypeNameFormat typeNameFormat, const QByteArray &type) +: d(new QNdefRecordPrivate) +{ + d->typeNameFormat = typeNameFormat; + d->type = type; +} + +/*! + Destroys the NDEF record. +*/ +QNdefRecord::~QNdefRecord() +{ +} + +/*! + Assigns this NDEF record to \a other. +*/ +QNdefRecord &QNdefRecord::operator=(const QNdefRecord &other) +{ + if (this != &other) + d = other.d; + + return *this; +} + +/*! + Sets the type name format of the NDEF record to \a typeNameFormat. +*/ +void QNdefRecord::setTypeNameFormat(TypeNameFormat typeNameFormat) +{ + if (!d) + d = new QNdefRecordPrivate; + + d->typeNameFormat = typeNameFormat; +} + +/*! + Returns the type name format of the NDEF record. +*/ +QNdefRecord::TypeNameFormat QNdefRecord::typeNameFormat() const +{ + if (!d) + return Empty; + + if (d->typeNameFormat > 0x05) + return Unknown; + + return TypeNameFormat(d->typeNameFormat); +} + +/*! + Sets the type of the NDEF record to \a type. +*/ +void QNdefRecord::setType(const QByteArray &type) +{ + if (!d) + d = new QNdefRecordPrivate; + + d->type = type; +} + +/*! + Returns the type of the NDEF record. +*/ +QByteArray QNdefRecord::type() const +{ + if (!d) + return QByteArray(); + + return d->type; +} + +/*! + Sets the id of the NDEF record to \a id. +*/ +void QNdefRecord::setId(const QByteArray &id) +{ + if (!d) + d = new QNdefRecordPrivate; + + d->id = id; +} + +/*! + Returns the id of the NDEF record. +*/ +QByteArray QNdefRecord::id() const +{ + if (!d) + return QByteArray(); + + return d->id; +} + +/*! + Sets the payload of the NDEF record to \a payload. +*/ +void QNdefRecord::setPayload(const QByteArray &payload) +{ + if (!d) + d = new QNdefRecordPrivate; + + d->payload = payload; +} + +/*! + Returns the payload of the NDEF record. +*/ +QByteArray QNdefRecord::payload() const +{ + if (!d) + return QByteArray(); + + return d->payload; +} + +/*! + Returns \c true if the NDEF record contains an empty payload; + otherwise returns \c false. + + This is equivalent to calling \c {payload().isEmpty()}. +*/ +bool QNdefRecord::isEmpty() const +{ + if (!d) + return true; + + return d->payload.isEmpty(); +} + +/*! + Returns \c true if \a other and this NDEF record are the same. + Otherwise returns \c false. +*/ +bool QNdefRecord::operator==(const QNdefRecord &other) const +{ + if (d == other.d) + return true; + + if (!d || !other.d) + return false; + + if (d->typeNameFormat != other.d->typeNameFormat) + return false; + + if (d->type != other.d->type) + return false; + + if (d->id != other.d->id) + return false; + + if (d->payload != other.d->payload) + return false; + + return true; +} + +/*! + \since 6.2 + + Clear the NDEF record. + + An \l isEmpty() call returns \c true for a cleared record. The record + \l type() is set to \l {QNdefRecord::}{Empty}. +*/ +void QNdefRecord::clear() +{ + if (d) { + d->typeNameFormat = 0; + d->type.clear(); + d->id.clear(); + d->payload.clear(); + } +} + +QT_END_NAMESPACE diff --git a/src/nfc/qndefrecord.h b/src/nfc/qndefrecord.h new file mode 100644 index 0000000..1d9c65e --- /dev/null +++ b/src/nfc/qndefrecord.h @@ -0,0 +1,84 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QNDEFRECORD_H +#define QNDEFRECORD_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QNdefRecordPrivate; + +class Q_NFC_EXPORT QNdefRecord +{ +public: + enum TypeNameFormat { + Empty = 0x00, + NfcRtd = 0x01, + Mime = 0x02, + Uri = 0x03, + ExternalRtd = 0x04, + Unknown = 0x05 + }; + + QNdefRecord(); + ~QNdefRecord(); + + QNdefRecord(const QNdefRecord &other); + QNdefRecord &operator=(const QNdefRecord &other); + + void setTypeNameFormat(TypeNameFormat typeNameFormat); + TypeNameFormat typeNameFormat() const; + + void setType(const QByteArray &type); + QByteArray type() const; + + void setId(const QByteArray &id); + QByteArray id() const; + + void setPayload(const QByteArray &payload); + QByteArray payload() const; + + bool isEmpty() const; + + template + inline bool isRecordType() const + { + T dummy; + return (typeNameFormat() == dummy.typeNameFormat() && type() == dummy.type()); + } + + bool operator==(const QNdefRecord &other) const; + inline bool operator!=(const QNdefRecord &other) const { return !operator==(other); } + + void clear(); + +protected: + QNdefRecord(const QNdefRecord &other, TypeNameFormat typeNameFormat, const QByteArray &type); + QNdefRecord(const QNdefRecord &other, TypeNameFormat typeNameFormat); + QNdefRecord(TypeNameFormat typeNameFormat, const QByteArray &type); + +private: + QSharedDataPointer d; +}; + +#define Q_DECLARE_NDEF_RECORD(className, typeNameFormat, type, initialPayload) \ + className() : QNdefRecord(typeNameFormat, type) { setPayload(initialPayload); } \ + className(const QNdefRecord &other) : QNdefRecord(other, typeNameFormat, type) { } + +#define Q_DECLARE_ISRECORDTYPE_FOR_NDEF_RECORD(className, typeNameFormat_, type_) \ + QT_BEGIN_NAMESPACE \ + template<> inline bool QNdefRecord::isRecordType() const\ + { \ + return (typeNameFormat() == typeNameFormat_ && type() == type_); \ + } \ + QT_END_NAMESPACE + +Q_NFC_EXPORT size_t qHash(const QNdefRecord &key); + +QT_END_NAMESPACE + +#endif // QNDEFRECORD_H diff --git a/src/nfc/qndefrecord_p.h b/src/nfc/qndefrecord_p.h new file mode 100644 index 0000000..f9f64d9 --- /dev/null +++ b/src/nfc/qndefrecord_p.h @@ -0,0 +1,42 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QNDEFRECORD_P_H +#define QNDEFRECORD_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 "qtnfcglobal.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +class QNdefRecordPrivate : public QSharedData +{ +public: + QNdefRecordPrivate() : QSharedData() + { + typeNameFormat = 0; //TypeNameFormat::Empty + } + + unsigned int typeNameFormat : 3; + + QByteArray type; + QByteArray id; + QByteArray payload; +}; + +QT_END_NAMESPACE + +#endif // QNDEFRECORD_P_H diff --git a/src/nfc/qnearfieldmanager.cpp b/src/nfc/qnearfieldmanager.cpp new file mode 100644 index 0000000..50ab9f0 --- /dev/null +++ b/src/nfc/qnearfieldmanager.cpp @@ -0,0 +1,269 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qnearfieldmanager.h" +#include "qnearfieldmanager_p.h" + +#if defined(QT_SIMULATOR) +#include "qnearfieldmanager_simulator_p.h" +#elif defined(ANDROID_NFC) +#include "qnearfieldmanager_android_p.h" +#elif defined(IOS_NFC) +#include "qnearfieldmanager_ios_p.h" +#elif defined(PCSC_NFC) +#include "qnearfieldmanager_pcsc_p.h" +#else +#include "qnearfieldmanager_generic_p.h" +#endif + +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \class QNearFieldManager + \brief The QNearFieldManager class provides access to notifications for NFC events. + + \ingroup connectivity-nfc + \inmodule QtNfc + \since 5.2 + + NFC Forum devices support two modes of communications. The first mode, peer-to-peer + communications, is used to communicate between two NFC Forum devices. The second mode, + master/slave communications, is used to communicate between an NFC Forum device and an NFC + Forum Tag or Contactless Card. The targetDetected() signal is emitted when a target device + enters communications range. Communications can be initiated from the slot connected to this + signal. + + NFC Forum devices generally operate as the master in master/slave communications. Some devices + are also capable of operating as the slave, so called Card Emulation mode. In this mode the + local NFC device emulates a NFC Forum Tag or Contactless Card. + + Applications can connect to the targetDetected() and targetLost() signals to get notified when + an NFC Forum Tag enters or leaves proximity. Before these signals are emitted target detection + must be started with the startTargetDetection() function. Target detection can be stopped with + the stopTargetDetection() function. When the target is no longer required the target should be + deleted as other applications may be blocked from accessing the target. +*/ + +/*! + \enum QNearFieldManager::AdapterState + + \since 5.12 + + This enum describes the different states a NFC adapter can have. + + \value Offline The nfc adapter is offline. + \value TurningOn The nfc adapter is turning on. + \value Online The nfc adapter is online. + \value TurningOff The nfc adapter is turning off. +*/ + +/*! + \fn void QNearFieldManager::adapterStateChanged(AdapterState state) + + \since 5.12 + + This signal is emitted whenever the \a state of the NFC adapter changed. + + \note Currently, this signal is only emitted on Android. +*/ + +/*! + \fn void QNearFieldManager::targetDetectionStopped() + + \since 6.2 + + This signal is emitted whenever the target detection is stopped. + + \note Mostly this signal is emitted when \l stopTargetDetection() has been called. + Additionally the user is able to stop the detection on iOS within a popup shown + by the system during the scan, which also leads to emitting this signal. +*/ + +/*! + \fn void QNearFieldManager::targetDetected(QNearFieldTarget *target) + + This signal is emitted whenever a target is detected. The \a target parameter represents the + detected target. + + This signal will be emitted for all detected targets. + + QNearFieldManager maintains ownership of \a target, however, it will not be destroyed until + the QNearFieldManager destructor is called. Ownership may be transferred by calling + setParent(). + + Do not delete \a target from the slot connected to this signal, instead call deleteLater(). + + \note that if \a target is deleted before it moves out of proximity the targetLost() signal + will not be emitted. + + \sa targetLost() +*/ + +/*! + \fn void QNearFieldManager::targetLost(QNearFieldTarget *target) + + This signal is emitted whenever a target moves out of proximity. The \a target parameter + represents the lost target. + + Do not delete \a target from the slot connected to this signal, instead use deleteLater(). + + \sa QNearFieldTarget::disconnected() +*/ + +/*! + Constructs a new near field manager with \a parent. +*/ +QNearFieldManager::QNearFieldManager(QObject *parent) +: QObject(parent), d_ptr(new QNearFieldManagerPrivateImpl) +{ + qRegisterMetaType(); + + connect(d_ptr, &QNearFieldManagerPrivate::adapterStateChanged, + this, &QNearFieldManager::adapterStateChanged); + connect(d_ptr, &QNearFieldManagerPrivate::targetDetectionStopped, + this, &QNearFieldManager::targetDetectionStopped); + connect(d_ptr, &QNearFieldManagerPrivate::targetDetected, + this, &QNearFieldManager::targetDetected); + connect(d_ptr, &QNearFieldManagerPrivate::targetLost, + this, &QNearFieldManager::targetLost); +} + +/*! + \internal + + Constructs a new near field manager with the specified \a backend and with \a parent. + + \note: This constructor is only enable for internal builds and is used for testing the + simulator backend. +*/ +QNearFieldManager::QNearFieldManager(QNearFieldManagerPrivate *backend, QObject *parent) +: QObject(parent), d_ptr(backend) +{ + qRegisterMetaType(); + + connect(d_ptr, &QNearFieldManagerPrivate::adapterStateChanged, + this, &QNearFieldManager::adapterStateChanged); + connect(d_ptr, &QNearFieldManagerPrivate::targetDetectionStopped, + this, &QNearFieldManager::targetDetectionStopped); + connect(d_ptr, &QNearFieldManagerPrivate::targetDetected, + this, &QNearFieldManager::targetDetected); + connect(d_ptr, &QNearFieldManagerPrivate::targetLost, + this, &QNearFieldManager::targetLost); +} + +/*! + Destroys the near field manager. +*/ +QNearFieldManager::~QNearFieldManager() +{ + delete d_ptr; +} + +/*! + \since 6.2 + + Returns \c true if the device has a NFC adapter and + it is turned on; otherwise returns \c false. + + \sa isSupported() +*/ +bool QNearFieldManager::isEnabled() const +{ + Q_D(const QNearFieldManager); + + return d->isEnabled(); +} + +/*! + \since 5.12 + + Returns \c true if the underlying device has a NFC adapter; otherwise + returns \c false. If an \a accessMethod is given, the function returns + \c true only if the NFC adapter supports the given \a accessMethod. + + \sa isEnabled() +*/ +bool QNearFieldManager::isSupported(QNearFieldTarget::AccessMethod accessMethod) const +{ + Q_D(const QNearFieldManager); + + return d->isSupported(accessMethod); +} + +/*! + \fn bool QNearFieldManager::startTargetDetection(QNearFieldTarget::AccessMethod accessMethod) + + Starts detecting targets and returns \c true if target detection is + successfully started; otherwise returns \c false. Causes the targetDetected() signal to be emitted + when a target is within proximity. Only tags with the given \a accessMethod will be delivered. + Active detection continues until \l stopTargetDetection() has been called. + + To detect targets with a different \a accessMethod, stopTargetDetection() must be called first. + + \note On iOS it is impossible to start target detection for both NdefAccess and TagTypeSpecificAccess + at the same time. So if AnyAccess is selected, NdefAccess will be used instead. + + \sa stopTargetDetection() +*/ +bool QNearFieldManager::startTargetDetection(QNearFieldTarget::AccessMethod accessMethod) +{ + Q_D(QNearFieldManager); + + return d->startTargetDetection(accessMethod); +} + +/*! + Stops detecting targets. The \l targetDetected() signal will no longer be emitted until another + call to \l startTargetDetection() is made. Targets detected before are still valid. + + \note On iOS, detected targets become invalid after this call (e.g. an attempt to write or + read NDEF messages will result in an error). + + If an \a errorMessage is provided, this is a hint to the system that the goal, the application + had, was not reached. The \a errorMessage and a matching error icon are shown to the user. + Calling this function with an empty \a errorMessage, implies a successful operation end; + otherwise an \a errorMessage should be passed to this function. + + \note Currently, \a errorMessage only has an effect on iOS because a popup is shown by the + system during the scan where the \a errorMessage is visible. Other platforms will ignore this + parameter. + + \sa setUserInformation() +*/ +void QNearFieldManager::stopTargetDetection(const QString &errorMessage) +{ + Q_D(QNearFieldManager); + + d->stopTargetDetection(errorMessage); +} + +/*! + \since 6.2 + + Sets the message shown to the user by the system. If the target detection is running the + \a message will be updated immediately and can be used as a progress message. The last message + set before a call to \l startTargetDetection() without an error message is used as a success + message. If the target detection is not running the \a message will be used as the initial + message when the next detection is started. By default no message is shown to the user. + + \note Currently, this function only has an effect on iOS because a popup is shown by the system + during the scan. On iOS, this \a message is mapped to the alert message which is shown upon + successful completion of the scan. Other platforms will ignore \a message. + + \sa startTargetDetection(), stopTargetDetection() +*/ +void QNearFieldManager::setUserInformation(const QString &message) +{ + Q_D(QNearFieldManager); + + d->setUserInformation(message); +} + +QT_END_NAMESPACE + +#include "moc_qnearfieldmanager_p.cpp" + +#include "moc_qnearfieldmanager.cpp" diff --git a/src/nfc/qnearfieldmanager.h b/src/nfc/qnearfieldmanager.h new file mode 100644 index 0000000..833245b --- /dev/null +++ b/src/nfc/qnearfieldmanager.h @@ -0,0 +1,56 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QNEARFIELDMANAGER_H +#define QNEARFIELDMANAGER_H + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QNearFieldManagerPrivate; +class Q_NFC_EXPORT QNearFieldManager : public QObject +{ + Q_OBJECT + + Q_DECLARE_PRIVATE(QNearFieldManager) + +public: + enum class AdapterState { + Offline = 1, + TurningOn = 2, + Online = 3, + TurningOff = 4 + }; + Q_ENUM(AdapterState) + + explicit QNearFieldManager(QObject *parent = nullptr); + explicit QNearFieldManager(QNearFieldManagerPrivate *backend, QObject *parent = nullptr); + ~QNearFieldManager(); + + bool isEnabled() const; + bool isSupported(QNearFieldTarget::AccessMethod accessMethod + = QNearFieldTarget::AnyAccess) const; + + bool startTargetDetection(QNearFieldTarget::AccessMethod accessMethod); + void stopTargetDetection(const QString &errorMessage = QString()); + + void setUserInformation(const QString &message); + +Q_SIGNALS: + void adapterStateChanged(QNearFieldManager::AdapterState state); + void targetDetectionStopped(); + void targetDetected(QNearFieldTarget *target); + void targetLost(QNearFieldTarget *target); + +private: + QNearFieldManagerPrivate *d_ptr; +}; + +QT_END_NAMESPACE + +#endif // QNEARFIELDMANAGER_H diff --git a/src/nfc/qnearfieldmanager_android.cpp b/src/nfc/qnearfieldmanager_android.cpp new file mode 100644 index 0000000..63cc847 --- /dev/null +++ b/src/nfc/qnearfieldmanager_android.cpp @@ -0,0 +1,153 @@ +// Copyright (C) 2016 Centria research and development +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qnearfieldmanager_android_p.h" + +#include "qndefmessage.h" +#include "qbytearray.h" +#include "qcoreapplication.h" + +#include + +QT_BEGIN_NAMESPACE + +extern "C" +{ + JNIEXPORT void JNICALL Java_org_qtproject_qt_android_nfc_QtNfcBroadcastReceiver_jniOnReceive( + JNIEnv */*env*/, jobject /*javaObject*/, jlong qtObject, jint state) + { + QNearFieldManager::AdapterState adapterState = + static_cast(state); + auto obj = reinterpret_cast(qtObject); + Q_ASSERT(obj != nullptr); + obj->adapterStateChanged(adapterState); + } +} + +Q_GLOBAL_STATIC(QMainNfcNewIntentListener, newIntentListener) + +QNearFieldManagerPrivateImpl::QNearFieldManagerPrivateImpl() : + detecting(false) +{ + qRegisterMetaType("QJniObject"); + qRegisterMetaType("QNdefMessage"); + + broadcastReceiver = QJniObject::construct( + reinterpret_cast(this), QNativeInterface::QAndroidApplication::context()); +} + +QNearFieldManagerPrivateImpl::~QNearFieldManagerPrivateImpl() +{ + broadcastReceiver.callMethod("unregisterReceiver"); +} + +void QNearFieldManagerPrivateImpl::onTargetDetected(QNearFieldTargetPrivateImpl *target) +{ + if (target->q_ptr) { + Q_EMIT targetDetected(target->q_ptr); + return; + } + + Q_EMIT targetDetected(new QNearFieldTarget(target, this)); +} + +void QNearFieldManagerPrivateImpl::onTargetLost(QNearFieldTargetPrivateImpl *target) +{ + Q_EMIT targetLost(target->q_ptr); +} + +bool QNearFieldManagerPrivateImpl::isEnabled() const +{ + return QtNfc::isEnabled(); +} + +bool QNearFieldManagerPrivateImpl::isSupported(QNearFieldTarget::AccessMethod accessMethod) const +{ + if (accessMethod == QNearFieldTarget::UnknownAccess) + return false; + + return QtNfc::isSupported(); +} + +bool QNearFieldManagerPrivateImpl::startTargetDetection(QNearFieldTarget::AccessMethod accessMethod) +{ + if (detecting) + return false; // Already detecting targets + + if (newIntentListener.isDestroyed()) + return false; + + detecting = true; + requestedMethod = accessMethod; + newIntentListener->registerListener(this); + return true; +} + +void QNearFieldManagerPrivateImpl::stopTargetDetection(const QString &) +{ + detecting = false; + if (newIntentListener.exists()) + newIntentListener->unregisterListener(this); + Q_EMIT targetDetectionStopped(); +} + +void QNearFieldManagerPrivateImpl::newIntent(QJniObject intent) +{ + // This function is called from different thread and is used to move intent to main thread. + QMetaObject::invokeMethod(this, [this, intent] { + this->onTargetDiscovered(intent); + }, Qt::QueuedConnection); +} + +QByteArray QNearFieldManagerPrivateImpl::getUid(const QJniObject &intent) +{ + if (!intent.isValid()) + return QByteArray(); + + QJniObject tag = QtNfc::getTag(intent); + return getUidforTag(tag); +} + +void QNearFieldManagerPrivateImpl::onTargetDiscovered(QJniObject intent) +{ + // Getting UID + QByteArray uid = getUid(intent); + + // Accepting all targets but only sending signal of requested types. + QNearFieldTargetPrivateImpl *&target = detectedTargets[uid]; + if (target) { + target->setIntent(intent); // Updating existing target + } else { + target = new QNearFieldTargetPrivateImpl(intent, uid); + + if (target->accessMethods() & requestedMethod) { + connect(target, &QNearFieldTargetPrivateImpl::targetDestroyed, this, &QNearFieldManagerPrivateImpl::onTargetDestroyed); + connect(target, &QNearFieldTargetPrivateImpl::targetLost, this, &QNearFieldManagerPrivateImpl::onTargetLost); + onTargetDetected(target); + } else { + delete target; + detectedTargets.remove(uid); + } + } +} + +void QNearFieldManagerPrivateImpl::onTargetDestroyed(const QByteArray &uid) +{ + detectedTargets.remove(uid); +} + +QByteArray QNearFieldManagerPrivateImpl::getUidforTag(const QJniObject &tag) +{ + if (!tag.isValid()) + return QByteArray(); + + QJniEnvironment env; + QJniObject tagId = tag.callMethod("getId"); + QByteArray uid; + jsize len = env->GetArrayLength(tagId.object()); + uid.resize(len); + env->GetByteArrayRegion(tagId.object(), 0, len, reinterpret_cast(uid.data())); + return uid; +} + +QT_END_NAMESPACE diff --git a/src/nfc/qnearfieldmanager_android_p.h b/src/nfc/qnearfieldmanager_android_p.h new file mode 100644 index 0000000..76a5fd2 --- /dev/null +++ b/src/nfc/qnearfieldmanager_android_p.h @@ -0,0 +1,64 @@ +// Copyright (C) 2016 Centria research and development +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QNEARFIELDMANAGER_ANDROID_P_H +#define QNEARFIELDMANAGER_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 "qnearfieldmanager_p.h" +#include "qnearfieldtarget_android_p.h" +#include "android/androidjninfc_p.h" +#include "android/androidmainnewintentlistener_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +class QByteArray; +class QNearFieldManagerPrivateImpl : public QNearFieldManagerPrivate, + public QAndroidNfcListenerInterface +{ + Q_OBJECT + +public: + QNearFieldManagerPrivateImpl(); + ~QNearFieldManagerPrivateImpl() override; + + bool isEnabled() const override; + bool isSupported(QNearFieldTarget::AccessMethod accessMethod) const override; + bool startTargetDetection(QNearFieldTarget::AccessMethod accessMethod) override; + void stopTargetDetection(const QString &errorMessage) override; + void newIntent(QJniObject intent) override; + QByteArray getUid(const QJniObject &intent); + +protected: + static QByteArray getUidforTag(const QJniObject &tag); + +private: + bool detecting; + QNearFieldTarget::AccessMethod requestedMethod; + QHash detectedTargets; + + QJniObject broadcastReceiver; + +private slots: + void onTargetDiscovered(QJniObject intent); + void onTargetDestroyed(const QByteArray &uid); + void onTargetDetected(QNearFieldTargetPrivateImpl *target); + void onTargetLost(QNearFieldTargetPrivateImpl *target); +}; + +QT_END_NAMESPACE + +#endif // QNEARFIELDMANAGER_ANDROID_P_H diff --git a/src/nfc/qnearfieldmanager_generic.cpp b/src/nfc/qnearfieldmanager_generic.cpp new file mode 100644 index 0000000..1a8df2c --- /dev/null +++ b/src/nfc/qnearfieldmanager_generic.cpp @@ -0,0 +1,24 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include + +#include "qnearfieldmanager_generic_p.h" + +QT_BEGIN_NAMESPACE + +/* + Constructs a new near field manager private implementation. +*/ +QNearFieldManagerPrivateImpl::QNearFieldManagerPrivateImpl() +{ +} + +/* + Destroys the near field manager private implementation. +*/ +QNearFieldManagerPrivateImpl::~QNearFieldManagerPrivateImpl() +{ +} + +QT_END_NAMESPACE diff --git a/src/nfc/qnearfieldmanager_generic_p.h b/src/nfc/qnearfieldmanager_generic_p.h new file mode 100644 index 0000000..b01cd9a --- /dev/null +++ b/src/nfc/qnearfieldmanager_generic_p.h @@ -0,0 +1,31 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QNEARFIELDMANAGERIMPL_P_H +#define QNEARFIELDMANAGERIMPL_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 "qnearfieldmanager_p.h" + +QT_BEGIN_NAMESPACE + +class QNearFieldManagerPrivateImpl : public QNearFieldManagerPrivate +{ +public: + QNearFieldManagerPrivateImpl(); + ~QNearFieldManagerPrivateImpl() override; +}; + +QT_END_NAMESPACE + +#endif // QNEARFIELDMANAGERIMPL_P_H diff --git a/src/nfc/qnearfieldmanager_ios.mm b/src/nfc/qnearfieldmanager_ios.mm new file mode 100644 index 0000000..4ab00a5 --- /dev/null +++ b/src/nfc/qnearfieldmanager_ios.mm @@ -0,0 +1,278 @@ +// Copyright (C) 2020 Governikus GmbH & Co. KG +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qnearfieldmanager_ios_p.h" + +#include "ios/qiosnfcndefsessiondelegate_p.h" +#include "ios/qiostagreaderdelegate_p.h" +#include "ios/qiosndefnotifier_p.h" + +#include "qnearfieldtarget_ios_p.h" + +#include + +#include + +#import +#import +#import + +QT_BEGIN_NAMESPACE + +QNearFieldManagerPrivateImpl::QNearFieldManagerPrivateImpl() +{ + auto notifier = std::make_unique(); + + if (@available(iOS 13, *)) + delegate = [[QT_MANGLE_NAMESPACE(QIosTagReaderDelegate) alloc] initWithListener:this]; + + connect(this, &QNearFieldManagerPrivateImpl::tagDiscovered, + this, &QNearFieldManagerPrivateImpl::onTagDiscovered, + Qt::QueuedConnection); + connect(this, &QNearFieldManagerPrivateImpl::didInvalidateWithError, + this, &QNearFieldManagerPrivateImpl::onDidInvalidateWithError, + Qt::QueuedConnection); + + ndefDelegate = [[QIosNfcNdefSessionDelegate alloc] initWithNotifier:notifier.get()]; + if (ndefDelegate) { + auto watchDog = notifier.release(); // Delegate took the ownership. + + connect(watchDog, &QNfcNdefNotifier::tagDetected, + this, &QNearFieldManagerPrivateImpl::onTagDiscovered, + Qt::QueuedConnection); + connect(watchDog, &QNfcNdefNotifier::invalidateWithError, + this, &QNearFieldManagerPrivateImpl::onDidInvalidateWithError, + Qt::QueuedConnection); + } else { + qCWarning(QT_IOS_NFC, "Failed to allocate NDEF reading session's delegate"); + } + + sessionTimer.setInterval(2000); + sessionTimer.setSingleShot(true); + connect(&sessionTimer, &QTimer::timeout, this, &QNearFieldManagerPrivateImpl::onSessionTimer); +} + +QNearFieldManagerPrivateImpl::~QNearFieldManagerPrivateImpl() +{ + if (@available(iOS 13, *)) + [delegate release]; + + if (!ndefDelegate) + return; + + if (auto queue = qt_Nfc_Queue()) { + dispatch_sync(queue, ^{ + [ndefDelegate abort]; + }); + } + + [ndefDelegate release]; +} + +bool QNearFieldManagerPrivateImpl::isSupported(QNearFieldTarget::AccessMethod accessMethod) const +{ + switch (accessMethod) { + case QNearFieldTarget::AnyAccess: + case QNearFieldTarget::NdefAccess: + return NFCNDEFReaderSession.readingAvailable; + case QNearFieldTarget::TagTypeSpecificAccess: + if (@available(iOS 13, *)) + return NFCTagReaderSession.readingAvailable; + Q_FALLTHROUGH(); + case QNearFieldTarget::UnknownAccess: + return false; + } +} + +bool QNearFieldManagerPrivateImpl::startTargetDetection(QNearFieldTarget::AccessMethod accessMethod) +{ + if (detectionRunning) + return false; + + activeAccessMethod = QNearFieldTarget::UnknownAccess; + + switch (accessMethod) { + case QNearFieldTarget::UnknownAccess: + case QNearFieldTarget::AnyAccess: + return false; + case QNearFieldTarget::TagTypeSpecificAccess: + if (@available(iOS 13, *)) + if (NFCTagReaderSession.readingAvailable) { + detectionRunning = scheduleSession(accessMethod); + if (detectionRunning) + activeAccessMethod = accessMethod; + return detectionRunning; + } + return false; + case QNearFieldTarget::NdefAccess: + if (NFCNDEFReaderSession.readingAvailable) { + detectionRunning = scheduleSession(accessMethod); + if (detectionRunning) + activeAccessMethod = accessMethod; + return detectionRunning; + } + return false; + } + + return false; +} + +void QNearFieldManagerPrivateImpl::stopTargetDetection(const QString &errorMessage) +{ + if (!detectionRunning) + return; + + isSessionScheduled = false; + + if (activeAccessMethod == QNearFieldTarget::TagTypeSpecificAccess) { + stopSession(errorMessage); + } else if (activeAccessMethod == QNearFieldTarget::NdefAccess) { + stopNdefSession(errorMessage); + } else { + qCWarning(QT_IOS_NFC, "Unknown access method, cannot stop target detection"); + return; + } + + detectionRunning = false; + Q_EMIT targetDetectionStopped(); +} + +bool QNearFieldManagerPrivateImpl::scheduleSession(QNearFieldTarget::AccessMethod accessMethod) +{ + if (sessionTimer.isActive()) { + isSessionScheduled = true; + return true; + } + isSessionScheduled = false; + + if (accessMethod == QNearFieldTarget::TagTypeSpecificAccess) { + startSession(); + return true; + } else if (accessMethod == QNearFieldTarget::NdefAccess) { + return startNdefSession(); + } + + return false; +} + +void QNearFieldManagerPrivateImpl::startSession() +{ + if (@available(iOS 13, *)) { + [delegate startSession]; + } +} + +bool QNearFieldManagerPrivateImpl::startNdefSession() +{ + if (!ndefDelegate) + return false; + + if (auto queue = qt_Nfc_Queue()) { + __block bool startSessionSucceded = false; + dispatch_sync(queue, ^{ startSessionSucceded = [ndefDelegate startSession]; }); + return startSessionSucceded; + } + + return false; +} + +void QNearFieldManagerPrivateImpl::stopSession(const QString &error) +{ + Q_ASSERT(activeAccessMethod == QNearFieldTarget::TagTypeSpecificAccess); + + clearTargets(); + + if (@available(iOS 13, *)) { + [delegate stopSession:error]; + } +} + +void QNearFieldManagerPrivateImpl::stopNdefSession(const QString &error) +{ + Q_ASSERT(activeAccessMethod == QNearFieldTarget::NdefAccess); + + clearTargets(); + + if (auto queue = qt_Nfc_Queue()) { + dispatch_sync(queue, ^{ + [ndefDelegate stopSession:error]; + }); + } +} + +void QNearFieldManagerPrivateImpl::clearTargets() +{ + auto i = detectedTargets.begin(); + while (i != detectedTargets.end()) { + (*i)->invalidate(); + i = detectedTargets.erase(i); + } +} + + +void QNearFieldManagerPrivateImpl::setUserInformation(const QString &message) +{ + if (activeAccessMethod != QNearFieldTarget::NdefAccess) + [delegate alertMessage:message]; + + if (detectionRunning) { + // Too late! + qCWarning(QT_IOS_NFC, + "User information must be set prior before the target detection started"); + return; + } + + if (auto queue = qt_Nfc_Queue()) { + dispatch_sync(queue, ^{ + [ndefDelegate setAlertMessage:message]; + }); + } +} + +void QNearFieldManagerPrivateImpl::onTagDiscovered(void *tag) +{ + QNearFieldTargetPrivateImpl *target = nullptr; + if (activeAccessMethod == QNearFieldTarget::NdefAccess) { + [id(tag) retain]; + target = new QNearFieldTargetPrivateImpl(ndefDelegate, tag); + } else { + target = new QNearFieldTargetPrivateImpl(tag); + } + + detectedTargets += target; + + connect(target, &QNearFieldTargetPrivateImpl::targetLost, + this, &QNearFieldManagerPrivateImpl::onTargetLost); + Q_EMIT targetDetected(new QNearFieldTarget(target, this)); +} + +void QNearFieldManagerPrivateImpl::onTargetLost(QNearFieldTargetPrivateImpl *target) +{ + detectedTargets.removeOne(target); + Q_EMIT targetLost(target->q_ptr); + + if (detectionRunning && detectedTargets.isEmpty()) + onDidInvalidateWithError(true); +} + +void QNearFieldManagerPrivateImpl::onDidInvalidateWithError(bool doRestart) +{ + clearTargets(); + sessionTimer.start(); + + if (detectionRunning && doRestart && scheduleSession(activeAccessMethod)) + return; + + detectionRunning = false; + Q_EMIT targetDetectionStopped(); +} + +void QNearFieldManagerPrivateImpl::onSessionTimer() +{ + if (isSessionScheduled && !scheduleSession(activeAccessMethod)) { + detectionRunning = false; + Q_EMIT targetDetectionStopped(); + } +} + +QT_END_NAMESPACE diff --git a/src/nfc/qnearfieldmanager_ios_p.h b/src/nfc/qnearfieldmanager_ios_p.h new file mode 100644 index 0000000..ef638ec --- /dev/null +++ b/src/nfc/qnearfieldmanager_ios_p.h @@ -0,0 +1,84 @@ +// Copyright (C) 2020 Governikus GmbH & Co. KG +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QNEARFIELDMANAGER_IOS_P_H +#define QNEARFIELDMANAGER_IOS_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 "qnearfieldmanager_p.h" + +#include + +#import + +Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QIosTagReaderDelegate)); + +Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QIosNfcNdefSessionDelegate)); +QT_NAMESPACE_ALIAS_OBJC_CLASS(QIosNfcNdefSessionDelegate); + +QT_BEGIN_NAMESPACE + +class QNearFieldTargetPrivateImpl; + +class QNearFieldManagerPrivateImpl : public QNearFieldManagerPrivate +{ + Q_OBJECT + +public: + QNearFieldManagerPrivateImpl(); + ~QNearFieldManagerPrivateImpl(); + + bool isEnabled() const override + { + return true; + } + + bool isSupported(QNearFieldTarget::AccessMethod accessMethod) const override; + + bool startTargetDetection(QNearFieldTarget::AccessMethod accessMethod) override; + void stopTargetDetection(const QString &errorMessage) override; + + void setUserInformation(const QString &message) override; + +Q_SIGNALS: + void tagDiscovered(void *tag); + void didInvalidateWithError(bool doRestart); + +private: + QT_MANGLE_NAMESPACE(QIosTagReaderDelegate) *delegate API_AVAILABLE(ios(13.0)) = nullptr; + QIosNfcNdefSessionDelegate *ndefDelegate = nullptr; + bool detectionRunning = false; + bool isSessionScheduled = false; + QTimer sessionTimer; + QList detectedTargets; + QNearFieldTarget::AccessMethod activeAccessMethod = QNearFieldTarget::UnknownAccess; + + bool scheduleSession(QNearFieldTarget::AccessMethod accessMethod); + void startSession(); + bool startNdefSession(); + void stopSession(const QString &error); + void stopNdefSession(const QString &error); + void clearTargets(); + +private Q_SLOTS: + void onTagDiscovered(void *target); + void onTargetLost(QNearFieldTargetPrivateImpl *target); + void onDidInvalidateWithError(bool doRestart); + void onSessionTimer(); +}; + + +QT_END_NAMESPACE + +#endif // QNEARFIELDMANAGER_IOS_P_H diff --git a/src/nfc/qnearfieldmanager_p.h b/src/nfc/qnearfieldmanager_p.h new file mode 100644 index 0000000..6ec8ff0 --- /dev/null +++ b/src/nfc/qnearfieldmanager_p.h @@ -0,0 +1,76 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QNEARFIELDMANAGER_P_H +#define QNEARFIELDMANAGER_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 "qnearfieldmanager.h" +#include "qnearfieldtarget.h" +#include "qndefrecord.h" + +#include "qtnfcglobal.h" + +#include + +QT_BEGIN_NAMESPACE + +class QNdefFilter; + +class Q_AUTOTEST_EXPORT QNearFieldManagerPrivate : public QObject +{ + Q_OBJECT + +public: + explicit QNearFieldManagerPrivate(QObject *parent = nullptr) + : QObject(parent) + { + } + + virtual ~QNearFieldManagerPrivate() + { + } + + virtual bool isEnabled() const + { + return false; + } + + virtual bool isSupported(QNearFieldTarget::AccessMethod) const + { + return false; + } + + virtual bool startTargetDetection(QNearFieldTarget::AccessMethod) + { + return false; + } + + virtual void stopTargetDetection(const QString &) + { + } + + virtual void setUserInformation(const QString &) + { + } + +signals: + void adapterStateChanged(QNearFieldManager::AdapterState state); + void targetDetectionStopped(); + void targetDetected(QNearFieldTarget *target); + void targetLost(QNearFieldTarget *target); +}; + +QT_END_NAMESPACE + +#endif // QNEARFIELDMANAGER_P_H diff --git a/src/nfc/qnearfieldmanager_pcsc.cpp b/src/nfc/qnearfieldmanager_pcsc.cpp new file mode 100644 index 0000000..2ce795d --- /dev/null +++ b/src/nfc/qnearfieldmanager_pcsc.cpp @@ -0,0 +1,140 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qnearfieldmanager_pcsc_p.h" +#include "qnearfieldtarget_pcsc_p.h" +#include "pcsc/qpcscmanager_p.h" +#include "pcsc/qpcsccard_p.h" +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace Qt::StringLiterals; + +Q_DECLARE_LOGGING_CATEGORY(QT_NFC_PCSC) + +/* + Constructs a new near field manager private implementation. + + This object creates a worker thread with an instance of QPcscManager in + it. All the communication with QPcscManager is done using signal-slot + mechanism. +*/ +QNearFieldManagerPrivateImpl::QNearFieldManagerPrivateImpl() +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + + m_worker = new QPcscManager; + m_workerThread = new QThread(this); + m_workerThread->setObjectName(u"QtNfcThread"_s); + m_worker->moveToThread(m_workerThread); + + connect(m_worker, &QPcscManager::cardInserted, this, + &QNearFieldManagerPrivateImpl::onCardInserted); + connect(this, &QNearFieldManagerPrivateImpl::startTargetDetectionRequest, m_worker, + &QPcscManager::onStartTargetDetectionRequest); + connect(this, &QNearFieldManagerPrivateImpl::stopTargetDetectionRequest, m_worker, + &QPcscManager::onStopTargetDetectionRequest); + + m_workerThread->start(); +} + +/* + Destroys the near field manager private implementation. +*/ +QNearFieldManagerPrivateImpl::~QNearFieldManagerPrivateImpl() +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + + // Destroy the worker. It calls QThread::quit() on the working thread in + // its destructor. + QMetaObject::invokeMethod(m_worker, &QObject::deleteLater, Qt::QueuedConnection); + m_workerThread->wait(); +} + +bool QNearFieldManagerPrivateImpl::isEnabled() const +{ + return true; +} + +bool QNearFieldManagerPrivateImpl::isSupported(QNearFieldTarget::AccessMethod accessMethod) const +{ + switch (accessMethod) { + case QNearFieldTarget::TagTypeSpecificAccess: + case QNearFieldTarget::NdefAccess: + return true; + default: + return false; + } +} + +bool QNearFieldManagerPrivateImpl::startTargetDetection(QNearFieldTarget::AccessMethod accessMethod) +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + + Q_EMIT startTargetDetectionRequest(accessMethod); + + return true; +} + +void QNearFieldManagerPrivateImpl::stopTargetDetection(const QString &errorMessage) +{ + Q_UNUSED(errorMessage); + + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + + Q_EMIT stopTargetDetectionRequest(); +} + +/* + Invoked when the worker has detected a new card. + + The worker will ensure that the card object remains valid until the manager + emits targetCreatedForCard() signal. +*/ +void QNearFieldManagerPrivateImpl::onCardInserted(QPcscCard *card, const QByteArray &uid, + QNearFieldTarget::AccessMethods accessMethods, + int maxInputLength) +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + + auto priv = new QNearFieldTargetPrivateImpl(uid, accessMethods, maxInputLength, this); + + connect(priv, &QNearFieldTargetPrivateImpl::disconnectRequest, card, + &QPcscCard::onDisconnectRequest); + connect(priv, &QNearFieldTargetPrivateImpl::destroyed, card, &QPcscCard::onTargetDestroyed); + connect(priv, &QNearFieldTargetPrivateImpl::sendCommandRequest, card, + &QPcscCard::onSendCommandRequest); + connect(priv, &QNearFieldTargetPrivateImpl::readNdefMessagesRequest, card, + &QPcscCard::onReadNdefMessagesRequest); + connect(priv, &QNearFieldTargetPrivateImpl::writeNdefMessagesRequest, card, + &QPcscCard::onWriteNdefMessagesRequest); + + connect(priv, &QNearFieldTargetPrivateImpl::targetLost, this, + &QNearFieldManagerPrivateImpl::onTargetLost); + + connect(card, &QPcscCard::disconnected, priv, &QNearFieldTargetPrivateImpl::onDisconnected); + connect(card, &QPcscCard::invalidated, priv, &QNearFieldTargetPrivateImpl::onInvalidated); + connect(card, &QPcscCard::requestCompleted, priv, + &QNearFieldTargetPrivateImpl::onRequestCompleted); + connect(card, &QPcscCard::ndefMessageRead, priv, + &QNearFieldTargetPrivateImpl::onNdefMessageRead); + + auto target = new QNearFieldTarget(priv, this); + + Q_EMIT targetDetected(target); + + // Let the worker know that the card object can be deleted if it is no + // longer needed. + QMetaObject::invokeMethod(card, &QPcscCard::enableAutodelete, Qt::QueuedConnection); +} + +void QNearFieldManagerPrivateImpl::onTargetLost(QNearFieldTargetPrivate *target) +{ + Q_EMIT targetLost(target->q_ptr); +} + +Q_LOGGING_CATEGORY(QT_NFC_PCSC, "qt.nfc.pcsc") + +QT_END_NAMESPACE diff --git a/src/nfc/qnearfieldmanager_pcsc_p.h b/src/nfc/qnearfieldmanager_pcsc_p.h new file mode 100644 index 0000000..a74322a --- /dev/null +++ b/src/nfc/qnearfieldmanager_pcsc_p.h @@ -0,0 +1,55 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QNEARFIELDMANAGER_PCSC_P_H +#define QNEARFIELDMANAGER_PCSC_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 "qnearfieldmanager_p.h" + +QT_BEGIN_NAMESPACE + +class QPcscManager; +class QPcscCard; +class QThread; + +class QNearFieldManagerPrivateImpl : public QNearFieldManagerPrivate +{ + Q_OBJECT +public: + QNearFieldManagerPrivateImpl(); + ~QNearFieldManagerPrivateImpl() override; + + bool isEnabled() const override; + bool isSupported(QNearFieldTarget::AccessMethod accessMethod) const override; + + bool startTargetDetection(QNearFieldTarget::AccessMethod accessMethod) override; + void stopTargetDetection(const QString &errorMessage) override; + +public Q_SLOTS: + void onCardInserted(QPcscCard *card, const QByteArray &uid, + QNearFieldTarget::AccessMethods accessMethods, int maxInputLength); + void onTargetLost(QNearFieldTargetPrivate *target); + +Q_SIGNALS: + void startTargetDetectionRequest(QNearFieldTarget::AccessMethod accessMethod); + void stopTargetDetectionRequest(); + +private: + QThread *m_workerThread; + QPcscManager *m_worker; +}; + +QT_END_NAMESPACE + +#endif // QNEARFIELDMANAGER_PCSC_P_H diff --git a/src/nfc/qnearfieldtarget.cpp b/src/nfc/qnearfieldtarget.cpp new file mode 100644 index 0000000..dbcca2b --- /dev/null +++ b/src/nfc/qnearfieldtarget.cpp @@ -0,0 +1,415 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qnearfieldtarget.h" +#include "qnearfieldtarget_p.h" +#include "qndefmessage.h" + +#include +#include + +#include + +#include + +QT_BEGIN_NAMESPACE + +QT_IMPL_METATYPE_EXTERN_TAGGED(QNearFieldTarget::RequestId, QNearFieldTarget__RequestId) + +/*! + \class QNearFieldTarget + \brief The QNearFieldTarget class provides an interface for communicating with a target + device. + + \ingroup connectivity-nfc + \inmodule QtNfc + \since 5.2 + + QNearFieldTarget provides a generic interface for communicating with an NFC target device. + Both NFC Forum devices and NFC Forum Tag targets are supported by this class. All target + specific classes subclass this class. + + The type() function can be used to get the type of the target device. The uid() function + returns the unique identifier of the target. The AccessMethods flags returns from the + accessMethods() function can be tested to determine which access methods are supported by the + target. + + If the target supports NdefAccess, hasNdefMessage() can be called to test if the target has a + stored NDEF message, readNdefMessages() and writeNdefMessages() functions can be used to get + and set the NDEF message. + + If the target supports TagTypeSpecificAccess, sendCommand() can be used to send a single + proprietary command to the target and retrieve the response. +*/ + +/*! + \enum QNearFieldTarget::Type + + This enum describes the type of tag the target is detected as. + + \value ProprietaryTag An unidentified proprietary target tag. + \value NfcTagType1 An NFC tag type 1 target. + \value NfcTagType2 An NFC tag type 2 target. + \value NfcTagType3 An NFC tag type 3 target. + \value NfcTagType4 An NFC tag type 4 target. This value is used if the NfcTagType4 + cannot be further refined by NfcTagType4A or NfcTagType4B below. + \value NfcTagType4A An NFC tag type 4 target based on ISO/IEC 14443-3A. + \value NfcTagType4B An NFC tag type 4 target based on ISO/IEC 14443-3B. + \value MifareTag A Mifare target. +*/ + +/*! + \enum QNearFieldTarget::AccessMethod + + This enum describes the access methods a near field target supports. + + \value UnknownAccess The target supports an unknown access type. + \value NdefAccess The target supports reading and writing NDEF messages using + readNdefMessages() and writeNdefMessages(). + \value TagTypeSpecificAccess The target supports sending tag type specific commands using + sendCommand(). + \value AnyAccess The target supports any of the known access types. +*/ + +/*! + \enum QNearFieldTarget::Error + + This enum describes the error codes that a near field target reports. + + \value NoError No error has occurred. + \value UnknownError An unidentified error occurred. + \value UnsupportedError The requested operation is unsupported by this near field + target. + \value TargetOutOfRangeError The target is no longer within range. + \value NoResponseError The target did not respond. + \value ChecksumMismatchError The checksum has detected a corrupted response. + \value InvalidParametersError Invalid parameters were passed to a tag type specific function. + \value ConnectionError Failed to connect to the target. + \value NdefReadError Failed to read NDEF messages from the target. + \value NdefWriteError Failed to write NDEF messages to the target. + \value CommandError Failed to send a command to the target. + \value TimeoutError The request could not be completed within the time + specified in waitForRequestCompleted(). +*/ + +/*! + \fn void QNearFieldTarget::disconnected() + + This signal is emitted when the near field target moves out of proximity. +*/ + +/*! + \fn void QNearFieldTarget::ndefMessageRead(const QNdefMessage &message) + + This signal is emitted when a complete NDEF \a message has been read from the target. + + \sa readNdefMessages() +*/ + +/*! + \fn void QNearFieldTarget::requestCompleted(const QNearFieldTarget::RequestId &id) + + This signal is emitted when a request \a id completes. + + \sa sendCommand() +*/ + +/*! + \fn void QNearFieldTarget::error(QNearFieldTarget::Error error, const QNearFieldTarget::RequestId &id) + + This signal is emitted when an error occurs while processing request \a id. The \a error + parameter describes the error. +*/ + +/*! + \class QNearFieldTarget::RequestId + \inmodule QtNfc + \inheaderfile QNearFieldTarget + \brief A request id handle. +*/ + +/*! + Constructs a new invalid request id handle. +*/ +QNearFieldTarget::RequestId::RequestId() +{ +} + +/*! + Constructs a new request id handle that is a copy of \a other. +*/ +QNearFieldTarget::RequestId::RequestId(const RequestId &other) +: d(other.d) +{ +} + +/*! + \internal +*/ +QNearFieldTarget::RequestId::RequestId(RequestIdPrivate *p) +: d(p) +{ +} + +/*! + Destroys the request id handle. +*/ +QNearFieldTarget::RequestId::~RequestId() +{ +} + +/*! + Returns \c true if this is a valid request id; otherwise returns \c false. +*/ +bool QNearFieldTarget::RequestId::isValid() const +{ + return d; +} + +/*! + Returns the current reference count of the request id. +*/ +int QNearFieldTarget::RequestId::refCount() const +{ + if (d) + return d->ref.loadRelaxed(); + + return 0; +} + +/*! + \internal +*/ +bool QNearFieldTarget::RequestId::operator<(const RequestId &other) const +{ + return std::less()(d.constData(), other.d.constData()); +} + +/*! + \internal +*/ +bool QNearFieldTarget::RequestId::operator==(const RequestId &other) const +{ + return d == other.d; +} + +/*! + \internal +*/ +bool QNearFieldTarget::RequestId::operator!=(const RequestId &other) const +{ + return d != other.d; +} + +/*! + Assigns a copy of \a other to this request id and returns a reference to this request id. +*/ +QNearFieldTarget::RequestId &QNearFieldTarget::RequestId::operator=(const RequestId &other) +{ + d = other.d; + return *this; +} + +/*! + Constructs a new near field target with \a parent. +*/ +QNearFieldTarget::QNearFieldTarget(QObject *parent) +: QNearFieldTarget(new QNearFieldTargetPrivate(this), parent) +{ +} + +/*! + Destroys the near field target. +*/ +QNearFieldTarget::~QNearFieldTarget() +{ + Q_D(QNearFieldTarget); + + d->disconnect(); +} + +/*! + Returns the UID of the near field target. + + \note On iOS, this function returns an empty QByteArray for + a near field target discovered using NdefAccess method. + + \sa QNearFieldTarget::AccessMethod +*/ +QByteArray QNearFieldTarget::uid() const +{ + Q_D(const QNearFieldTarget); + + return d->uid(); +} + +/*! + Returns the type of tag type of this near field target. +*/ +QNearFieldTarget::Type QNearFieldTarget::type() const +{ + Q_D(const QNearFieldTarget); + + return d->type(); +} + +/*! + Returns the access methods supported by this near field target. +*/ +QNearFieldTarget::AccessMethods QNearFieldTarget::accessMethods() const +{ + Q_D(const QNearFieldTarget); + + return d->accessMethods(); +} + +/*! + \since 5.9 + + Closes the connection to the target to enable communication with the target + from a different instance. The connection will also be closed, when the + QNearFieldTarget is destroyed. A connection to the target device is + (re)created to process a command or read/write a NDEF messages. + + Returns \c true only if an existing connection was successfully closed; + otherwise returns \c false. +*/ +bool QNearFieldTarget::disconnect() +{ + Q_D(QNearFieldTarget); + + return d->disconnect(); +} + +/*! + Returns \c true if at least one NDEF message is stored on the near field + target; otherwise returns \c false. +*/ +bool QNearFieldTarget::hasNdefMessage() +{ + Q_D(QNearFieldTarget); + + return d->hasNdefMessage(); +} + +/*! + Starts reading NDEF messages stored on the near field target. Returns a request id which can + be used to track the completion status of the request. An invalid request id will be returned + if the target does not support reading NDEF messages. + + An ndefMessageRead() signal will be emitted for each NDEF message. The requestCompleted() + signal will be emitted was all NDEF messages have been read. The error() signal is emitted if + an error occurs. + + \note An attempt to read an NDEF message from a tag, that is in INITIALIZED + state as defined by NFC Forum, will fail with the \l NdefReadError, as the + tag is formatted to support NDEF but does not contain a message yet. +*/ +QNearFieldTarget::RequestId QNearFieldTarget::readNdefMessages() +{ + Q_D(QNearFieldTarget); + + return d->readNdefMessages(); +} + +/*! + Writes the NDEF messages in \a messages to the target. Returns a request id which can be used + to track the completion status of the request. An invalid request id will be returned if the + target does not support reading NDEF messages. + + The requestCompleted() signal will be emitted when the write operation completes + successfully; otherwise the error() signal is emitted. +*/ +QNearFieldTarget::RequestId QNearFieldTarget::writeNdefMessages(const QList &messages) +{ + Q_D(QNearFieldTarget); + + return d->writeNdefMessages(messages); +} + +/*! + \since 5.9 + + Returns the maximum number of bytes that can be sent with sendCommand. 0 will + be returned if the target does not support sending tag type specific commands. + + \sa sendCommand() +*/ +int QNearFieldTarget::maxCommandLength() const +{ + Q_D(const QNearFieldTarget); + + return d->maxCommandLength(); +} + +/*! + Sends \a command to the near field target. Returns a request id which can be used to track the + completion status of the request. An invalid request id will be returned if the target does not + support sending tag type specific commands. + + The requestCompleted() signal will be emitted on successful completion of the request; + otherwise the error() signal will be emitted. + + Once the request completes successfully the response can be retrieved from the + requestResponse() function. The response of this request will be a QByteArray. + + \sa requestCompleted(), waitForRequestCompleted() +*/ +QNearFieldTarget::RequestId QNearFieldTarget::sendCommand(const QByteArray &command) +{ + Q_D(QNearFieldTarget); + + return d->sendCommand(command); +} + +/*! + Waits up to \a msecs milliseconds for the request \a id to complete. + Returns \c true if the request completes successfully and the + requestCompeted() signal is emitted; otherwise returns \c false. +*/ +bool QNearFieldTarget::waitForRequestCompleted(const RequestId &id, int msecs) +{ + Q_D(QNearFieldTarget); + + return d->waitForRequestCompleted(id, msecs); +} + +/*! + Returns the decoded response for request \a id. If the request is unknown or has not yet been + completed an invalid QVariant is returned. +*/ +QVariant QNearFieldTarget::requestResponse(const RequestId &id) const +{ + Q_D(const QNearFieldTarget); + + return d->requestResponse(id); +} + +/*! + \internal +*/ +QNearFieldTarget::QNearFieldTarget(QNearFieldTargetPrivate *backend, QObject *parent) +: QObject(parent), d_ptr(backend) +{ + Q_D(QNearFieldTarget); + + d->q_ptr = this; + d->setParent(this); + + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + + connect(d, &QNearFieldTargetPrivate::disconnected, + this, &QNearFieldTarget::disconnected); + connect(d, &QNearFieldTargetPrivate::ndefMessageRead, + this, &QNearFieldTarget::ndefMessageRead); + connect(d, &QNearFieldTargetPrivate::requestCompleted, + this, &QNearFieldTarget::requestCompleted); + connect(d, &QNearFieldTargetPrivate::error, + this, &QNearFieldTarget::error); +} + +QT_END_NAMESPACE + +#include "moc_qnearfieldtarget.cpp" diff --git a/src/nfc/qnearfieldtarget.h b/src/nfc/qnearfieldtarget.h new file mode 100644 index 0000000..0d67011 --- /dev/null +++ b/src/nfc/qnearfieldtarget.h @@ -0,0 +1,131 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QNEARFIELDTARGET_H +#define QNEARFIELDTARGET_H + +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QNdefMessage; +class QNearFieldTargetPrivate; +class QNearFieldManagerPrivateImpl; + +class Q_NFC_EXPORT QNearFieldTarget : public QObject +{ + Q_OBJECT + + Q_DECLARE_PRIVATE(QNearFieldTarget) + friend class QNearFieldManagerPrivateImpl; + +public: + enum Type { + ProprietaryTag, + NfcTagType1, + NfcTagType2, + NfcTagType3, + NfcTagType4, + NfcTagType4A, + NfcTagType4B, + MifareTag + }; + Q_ENUM(Type) + + enum AccessMethod { + UnknownAccess = 0x00, + NdefAccess = 0x01, + TagTypeSpecificAccess = 0x02, + AnyAccess = 0xff + }; + Q_ENUM(AccessMethod) + Q_DECLARE_FLAGS(AccessMethods, AccessMethod) + + enum Error { + NoError, + UnknownError, + UnsupportedError, + TargetOutOfRangeError, + NoResponseError, + ChecksumMismatchError, + InvalidParametersError, + ConnectionError, + NdefReadError, + NdefWriteError, + CommandError, + TimeoutError + }; + Q_ENUM(Error) + + class RequestIdPrivate; + class Q_NFC_EXPORT RequestId + { + public: + RequestId(); + RequestId(const RequestId &other); + RequestId(RequestIdPrivate *p); + ~RequestId(); + + bool isValid() const; + + int refCount() const; + + bool operator<(const RequestId &other) const; + bool operator==(const RequestId &other) const; + bool operator!=(const RequestId &other) const; + RequestId &operator=(const RequestId &other); + + QSharedDataPointer d; + }; + + explicit QNearFieldTarget(QObject *parent = nullptr); + ~QNearFieldTarget(); + + QByteArray uid() const; + Type type() const; + AccessMethods accessMethods() const; + + bool disconnect(); + + // NdefAccess + bool hasNdefMessage(); + RequestId readNdefMessages(); + RequestId writeNdefMessages(const QList &messages); + + // TagTypeSpecificAccess + int maxCommandLength() const; + RequestId sendCommand(const QByteArray &command); + + bool waitForRequestCompleted(const RequestId &id, int msecs = 5000); + QVariant requestResponse(const RequestId &id) const; + +Q_SIGNALS: + void disconnected(); + + void ndefMessageRead(const QNdefMessage &message); + + void requestCompleted(const QNearFieldTarget::RequestId &id); + + void error(QNearFieldTarget::Error error, const QNearFieldTarget::RequestId &id); + +protected: + QNearFieldTarget(QNearFieldTargetPrivate *backend, QObject *parent = nullptr); + +private: + QNearFieldTargetPrivate *d_ptr; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QNearFieldTarget::AccessMethods) + +QT_END_NAMESPACE + +QT_DECL_METATYPE_EXTERN_TAGGED(QNearFieldTarget::RequestId, QNearFieldTarget__RequestId, + Q_NFC_EXPORT) + +#endif // QNEARFIELDTARGET_H diff --git a/src/nfc/qnearfieldtarget_android.cpp b/src/nfc/qnearfieldtarget_android.cpp new file mode 100644 index 0000000..c7f842a --- /dev/null +++ b/src/nfc/qnearfieldtarget_android.cpp @@ -0,0 +1,494 @@ +// Copyright (C) 2016 Centria research and development +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qnearfieldtarget_android_p.h" +#include "android/androidjninfc_p.h" +#include "qdebug.h" + +#define NDEFTECHNOLOGY QStringLiteral("android.nfc.tech.Ndef") +#define NDEFFORMATABLETECHNOLOGY QStringLiteral("android.nfc.tech.NdefFormatable") +#define ISODEPTECHNOLOGY QStringLiteral("android.nfc.tech.IsoDep") +#define NFCATECHNOLOGY QStringLiteral("android.nfc.tech.NfcA") +#define NFCBTECHNOLOGY QStringLiteral("android.nfc.tech.NfcB") +#define NFCFTECHNOLOGY QStringLiteral("android.nfc.tech.NfcF") +#define NFCVTECHNOLOGY QStringLiteral("android.nfc.tech.NfcV") +#define MIFARECLASSICTECHNOLOGY QStringLiteral("android.nfc.tech.MifareClassic") +#define MIFARECULTRALIGHTTECHNOLOGY QStringLiteral("android.nfc.tech.MifareUltralight") + +#define MIFARETAG QStringLiteral("com.nxp.ndef.mifareclassic") +#define NFCTAGTYPE1 QStringLiteral("org.nfcforum.ndef.type1") +#define NFCTAGTYPE2 QStringLiteral("org.nfcforum.ndef.type2") +#define NFCTAGTYPE3 QStringLiteral("org.nfcforum.ndef.type3") +#define NFCTAGTYPE4 QStringLiteral("org.nfcforum.ndef.type4") + +QNearFieldTargetPrivateImpl::QNearFieldTargetPrivateImpl(QJniObject intent, + const QByteArray uid, + QObject *parent) +: QNearFieldTargetPrivate(parent), + targetIntent(intent), + targetUid(uid) +{ + updateTechList(); + updateType(); + setupTargetCheckTimer(); +} + +QNearFieldTargetPrivateImpl::~QNearFieldTargetPrivateImpl() +{ + releaseIntent(); + Q_EMIT targetDestroyed(targetUid); +} + +QByteArray QNearFieldTargetPrivateImpl::uid() const +{ + return targetUid; +} + +QNearFieldTarget::Type QNearFieldTargetPrivateImpl::type() const +{ + return tagType; +} + +QNearFieldTarget::AccessMethods QNearFieldTargetPrivateImpl::accessMethods() const +{ + QNearFieldTarget::AccessMethods result = QNearFieldTarget::UnknownAccess; + + if (techList.contains(NDEFTECHNOLOGY) + || techList.contains(NDEFFORMATABLETECHNOLOGY)) + result |= QNearFieldTarget::NdefAccess; + + if (techList.contains(ISODEPTECHNOLOGY) + || techList.contains(NFCATECHNOLOGY) + || techList.contains(NFCBTECHNOLOGY) + || techList.contains(NFCFTECHNOLOGY) + || techList.contains(NFCVTECHNOLOGY)) + result |= QNearFieldTarget::TagTypeSpecificAccess; + + return result; +} + +bool QNearFieldTargetPrivateImpl::disconnect() +{ + if (!tagTech.isValid()) + return false; + QJniEnvironment env; + bool connected = tagTech.callMethod("isConnected"); + if (!connected) + return false; + auto methodId = env.findMethod(tagTech.objectClass(), "close"); + if (!methodId) + return false; + env->CallVoidMethod(tagTech.object(), methodId); + return !env.checkAndClearExceptions(); +} + +bool QNearFieldTargetPrivateImpl::hasNdefMessage() +{ + return techList.contains(NDEFTECHNOLOGY); +} + +QNearFieldTarget::RequestId QNearFieldTargetPrivateImpl::readNdefMessages() +{ + // Making sure that target has NDEF messages + if (!hasNdefMessage()) + return QNearFieldTarget::RequestId(); + + // Making sure that target is still in range + QNearFieldTarget::RequestId requestId(new QNearFieldTarget::RequestIdPrivate); + if (!targetIntent.isValid()) { + reportError(QNearFieldTarget::TargetOutOfRangeError, requestId); + return requestId; + } + + // Getting Ndef technology object + if (!setTagTechnology({NDEFTECHNOLOGY})) { + reportError(QNearFieldTarget::UnsupportedError, requestId); + return requestId; + } + + // Connect + if (!connect()) { + reportError(QNearFieldTarget::ConnectionError, requestId); + return requestId; + } + + // Get NdefMessage object + QJniObject ndefMessage = tagTech.callMethod("getNdefMessage"); + if (!ndefMessage.isValid()) { + reportError(QNearFieldTarget::NdefReadError, requestId); + return requestId; + } + + // Convert to byte array + QJniObject ndefMessageBA = ndefMessage.callMethod("toByteArray"); + QByteArray ndefMessageQBA = jbyteArrayToQByteArray(ndefMessageBA.object()); + + // Sending QNdefMessage, requestCompleted and exit. + QNdefMessage qNdefMessage = QNdefMessage::fromByteArray(ndefMessageQBA); + QMetaObject::invokeMethod(this, [this, qNdefMessage]() { + Q_EMIT this->q_ptr->ndefMessageRead(qNdefMessage); + }, Qt::QueuedConnection); + QMetaObject::invokeMethod(this, [this, requestId]() { + Q_EMIT this->requestCompleted(requestId); + }, Qt::QueuedConnection); + QMetaObject::invokeMethod(this, [this, qNdefMessage, requestId]() { + //TODO This is an Android specific signal in NearFieldTarget. + // We need to check if it is still necessary. + Q_EMIT this->ndefMessageRead(qNdefMessage, requestId); + }, Qt::QueuedConnection); + return requestId; +} + +int QNearFieldTargetPrivateImpl::maxCommandLength() const +{ + QJniObject tagTech; + if (techList.contains(ISODEPTECHNOLOGY)) + tagTech = getTagTechnology(ISODEPTECHNOLOGY); + else if (techList.contains(NFCATECHNOLOGY)) + tagTech = getTagTechnology(NFCATECHNOLOGY); + else if (techList.contains(NFCBTECHNOLOGY)) + tagTech = getTagTechnology(NFCBTECHNOLOGY); + else if (techList.contains(NFCFTECHNOLOGY)) + tagTech = getTagTechnology(NFCFTECHNOLOGY); + else if (techList.contains(NFCVTECHNOLOGY)) + tagTech = getTagTechnology(NFCVTECHNOLOGY); + else + return 0; + + return tagTech.callMethod("getMaxTransceiveLength"); +} + +QNearFieldTarget::RequestId QNearFieldTargetPrivateImpl::sendCommand(const QByteArray &command) +{ + if (command.size() == 0 || command.size() > maxCommandLength()) { + Q_EMIT error(QNearFieldTarget::InvalidParametersError, QNearFieldTarget::RequestId()); + return QNearFieldTarget::RequestId(); + } + + // Making sure that target has commands + if (!(accessMethods() & QNearFieldTarget::TagTypeSpecificAccess)) + return QNearFieldTarget::RequestId(); + + QJniEnvironment env; + + if (!setTagTechnology({ISODEPTECHNOLOGY, NFCATECHNOLOGY, NFCBTECHNOLOGY, NFCFTECHNOLOGY, NFCVTECHNOLOGY})) { + Q_EMIT error(QNearFieldTarget::UnsupportedError, QNearFieldTarget::RequestId()); + return QNearFieldTarget::RequestId(); + } + + // Connecting + QNearFieldTarget::RequestId requestId = QNearFieldTarget::RequestId(new QNearFieldTarget::RequestIdPrivate()); + if (!connect()) { + reportError(QNearFieldTarget::ConnectionError, requestId); + return requestId; + } + + // Making QByteArray + QByteArray ba(command); + jbyteArray jba = env->NewByteArray(ba.size()); + env->SetByteArrayRegion(jba, 0, ba.size(), reinterpret_cast(ba.data())); + + // Writing + QJniObject myNewVal = tagTech.callMethod("transceive", jba); + if (!myNewVal.isValid()) { + // Some devices (Samsung, Huawei) throw an exception when the card is lost: + // "android.nfc.TagLostException: Tag was lost". But there seems to be a bug that + // isConnected still reports true. So we need to invalidate the target as soon as + // possible and treat the card as lost. + handleTargetLost(); + + reportError(QNearFieldTarget::CommandError, requestId); + return requestId; + } + QByteArray result = jbyteArrayToQByteArray(myNewVal.object()); + env->DeleteLocalRef(jba); + + setResponseForRequest(requestId, result, false); + + QMetaObject::invokeMethod(this, [this, requestId]() { + Q_EMIT this->requestCompleted(requestId); + }, Qt::QueuedConnection); + + return requestId; +} + +QNearFieldTarget::RequestId QNearFieldTargetPrivateImpl::writeNdefMessages(const QList &messages) +{ + if (messages.size() == 0) + return QNearFieldTarget::RequestId(); + + if (messages.size() > 1) + qWarning("QNearFieldTarget::writeNdefMessages: Android supports writing only one NDEF message per tag."); + + QJniEnvironment env; + const char *writeMethod; + + if (!setTagTechnology({NDEFFORMATABLETECHNOLOGY, NDEFTECHNOLOGY})) + return QNearFieldTarget::RequestId(); + + // Getting write method + if (selectedTech == NDEFFORMATABLETECHNOLOGY) + writeMethod = "format"; + else + writeMethod = "writeNdefMessage"; + + // Connecting + QNearFieldTarget::RequestId requestId = QNearFieldTarget::RequestId(new QNearFieldTarget::RequestIdPrivate()); + if (!connect()) { + reportError(QNearFieldTarget::ConnectionError, requestId); + return requestId; + } + + // Making NdefMessage object + const QNdefMessage &message = messages.first(); + QByteArray ba = message.toByteArray(); + QJniObject jba = env->NewByteArray(ba.size()); + env->SetByteArrayRegion(jba.object(), 0, ba.size(), reinterpret_cast(ba.data())); + QJniObject jmessage = QJniObject::construct(jba.object()); + if (!jmessage.isValid()) { + reportError(QNearFieldTarget::UnknownError, requestId); + return requestId; + } + + // Writing + auto methodId = + env.findMethod(tagTech.objectClass(), writeMethod); + if (methodId) + env->CallVoidMethod(tagTech.object(), methodId, jmessage.object()); + if (!methodId || env.checkAndClearExceptions()) { + reportError(QNearFieldTarget::NdefWriteError, requestId); + return requestId; + } + + QMetaObject::invokeMethod(this, [this, requestId]() { + Q_EMIT this->requestCompleted(requestId); + }, Qt::QueuedConnection); + return requestId; +} + +void QNearFieldTargetPrivateImpl::setIntent(QJniObject intent) +{ + if (targetIntent == intent) + return; + + releaseIntent(); + targetIntent = intent; + if (targetIntent.isValid()) { + // Updating tech list and type in case of there is another tag with same UID as one before. + updateTechList(); + updateType(); + targetCheckTimer->start(); + } +} + +void QNearFieldTargetPrivateImpl::checkIsTargetLost() +{ + if (!targetIntent.isValid() || !setTagTechnology({selectedTech})) { + handleTargetLost(); + return; + } + + QJniEnvironment env; + bool connected = false; + auto methodId = env.findMethod(tagTech.objectClass(), "isConnected"); + if (methodId) + connected = env->CallBooleanMethod(tagTech.object(), methodId); + if (!methodId || env.checkAndClearExceptions()) { + handleTargetLost(); + return; + } + + if (connected) + return; + + methodId = env.findMethod(tagTech.objectClass(), "connect"); + if (methodId) + env->CallVoidMethod(tagTech.object(), methodId); + if (!methodId || env.checkAndClearExceptions(QJniEnvironment::OutputMode::Silent)) { + handleTargetLost(); + return; + } + methodId = env.findMethod(tagTech.objectClass(), "close"); + if (methodId) + env->CallVoidMethod(tagTech.object(), methodId); + if (!methodId || env.checkAndClearExceptions(QJniEnvironment::OutputMode::Silent)) + handleTargetLost(); +} + +void QNearFieldTargetPrivateImpl::releaseIntent() +{ + targetCheckTimer->stop(); + + targetIntent = QJniObject(); +} + +void QNearFieldTargetPrivateImpl::updateTechList() +{ + if (!targetIntent.isValid()) + return; + + // Getting tech list + QJniEnvironment env; + QJniObject tag = QtNfc::getTag(targetIntent); + Q_ASSERT_X(tag.isValid(), "updateTechList", "could not get Tag object"); + + QJniObject techListArray = tag.callMethod("getTechList"); + if (!techListArray.isValid()) { + handleTargetLost(); + return; + } + + // Converting tech list array to QStringList. + techList.clear(); + jsize techCount = env->GetArrayLength(techListArray.object()); + for (jsize i = 0; i < techCount; ++i) { + QJniObject tech = env->GetObjectArrayElement(techListArray.object(), i); + techList.append(tech.callMethod("toString").toString()); + } +} + +void QNearFieldTargetPrivateImpl::updateType() +{ + tagType = getTagType(); +} + +QNearFieldTarget::Type QNearFieldTargetPrivateImpl::getTagType() const +{ + if (techList.contains(NDEFTECHNOLOGY)) { + QJniObject ndef = getTagTechnology(NDEFTECHNOLOGY); + QString qtype = ndef.callMethod("getType").toString(); + + if (qtype.compare(MIFARETAG) == 0) + return QNearFieldTarget::MifareTag; + if (qtype.compare(NFCTAGTYPE1) == 0) + return QNearFieldTarget::NfcTagType1; + if (qtype.compare(NFCTAGTYPE2) == 0) + return QNearFieldTarget::NfcTagType2; + if (qtype.compare(NFCTAGTYPE3) == 0) + return QNearFieldTarget::NfcTagType3; + if (qtype.compare(NFCTAGTYPE4) == 0) + return QNearFieldTarget::NfcTagType4; + return QNearFieldTarget::ProprietaryTag; + } else if (techList.contains(NFCATECHNOLOGY)) { + if (techList.contains(MIFARECLASSICTECHNOLOGY)) + return QNearFieldTarget::MifareTag; + + // Checking ATQA/SENS_RES + // xxx0 0000 xxxx xxxx: Identifies tag Type 1 platform + QJniObject nfca = getTagTechnology(NFCATECHNOLOGY); + QJniObject atqaBA = nfca.callMethod("getAtqa"); + QByteArray atqaQBA = jbyteArrayToQByteArray(atqaBA.object()); + if (atqaQBA.isEmpty()) + return QNearFieldTarget::ProprietaryTag; + if ((atqaQBA[0] & 0x1F) == 0x00) + return QNearFieldTarget::NfcTagType1; + + // Checking SAK/SEL_RES + // xxxx xxxx x00x x0xx: Identifies tag Type 2 platform + // xxxx xxxx x01x x0xx: Identifies tag Type 4 platform + jshort sakS = nfca.callMethod("getSak"); + if ((sakS & 0x0064) == 0x0000) + return QNearFieldTarget::NfcTagType2; + else if ((sakS & 0x0064) == 0x0020) + return QNearFieldTarget::NfcTagType4A; + return QNearFieldTarget::ProprietaryTag; + } else if (techList.contains(NFCBTECHNOLOGY)) { + return QNearFieldTarget::NfcTagType4B; + } else if (techList.contains(NFCFTECHNOLOGY)) { + return QNearFieldTarget::NfcTagType3; + } + + return QNearFieldTarget::ProprietaryTag; +} + +void QNearFieldTargetPrivateImpl::setupTargetCheckTimer() +{ + targetCheckTimer = new QTimer(this); + targetCheckTimer->setInterval(1000); + QObject::connect(targetCheckTimer, &QTimer::timeout, this, &QNearFieldTargetPrivateImpl::checkIsTargetLost); + targetCheckTimer->start(); +} + +void QNearFieldTargetPrivateImpl::handleTargetLost() +{ + releaseIntent(); + Q_EMIT targetLost(this); +} + +QJniObject QNearFieldTargetPrivateImpl::getTagTechnology(const QString &tech) const +{ + QString techClass(tech); + techClass.replace(QLatin1Char('.'), QLatin1Char('/')); + + // Getting requested technology + QJniObject tag = QtNfc::getTag(targetIntent); + Q_ASSERT_X(tag.isValid(), "getTagTechnology", "could not get Tag object"); + + const QString sig = QString::fromUtf8("(Landroid/nfc/Tag;)L%1;"); + QJniObject tagTech = QJniObject::callStaticObjectMethod(techClass.toUtf8().constData(), "get", + sig.arg(techClass).toUtf8().constData(), tag.object()); + + return tagTech; +} + +bool QNearFieldTargetPrivateImpl::setTagTechnology(const QStringList &technologies) +{ + for (const QString &tech : technologies) { + if (techList.contains(tech)) { + if (selectedTech == tech) { + return true; + } + selectedTech = tech; + tagTech = getTagTechnology(tech); + return tagTech.isValid(); + } + } + + return false; +} + +bool QNearFieldTargetPrivateImpl::connect() +{ + if (!tagTech.isValid()) + return false; + + QJniEnvironment env; + auto methodId = env.findMethod(tagTech.objectClass(), "isConnected"); + bool connected = false; + if (methodId) + connected = env->CallBooleanMethod(tagTech.object(), methodId); + if (!methodId || env.checkAndClearExceptions()) + return false; + + if (connected) + return true; + + setCommandTimeout(2000); + methodId = env.findMethod(tagTech.objectClass(), "connect"); + if (!methodId) + return false; + env->CallVoidMethod(tagTech.object(), methodId); + return !env.checkAndClearExceptions(); +} + +bool QNearFieldTargetPrivateImpl::setCommandTimeout(int timeout) +{ + if (!tagTech.isValid()) + return false; + + QJniEnvironment env; + auto methodId = env.findMethod(tagTech.objectClass(), "setTimeout"); + if (methodId) + env->CallVoidMethod(tagTech.object(), methodId, timeout); + return methodId && !env.checkAndClearExceptions(); +} + +QByteArray QNearFieldTargetPrivateImpl::jbyteArrayToQByteArray(const jbyteArray &byteArray) const +{ + QJniEnvironment env; + QByteArray resultArray; + jsize len = env->GetArrayLength(byteArray); + resultArray.resize(len); + env->GetByteArrayRegion(byteArray, 0, len, reinterpret_cast(resultArray.data())); + return resultArray; +} diff --git a/src/nfc/qnearfieldtarget_android_p.h b/src/nfc/qnearfieldtarget_android_p.h new file mode 100644 index 0000000..bdfe6b1 --- /dev/null +++ b/src/nfc/qnearfieldtarget_android_p.h @@ -0,0 +1,88 @@ +// Copyright (C) 2016 Centria research and development +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QNEARFIELDTARGET_ANDROID_P_H +#define QNEARFIELDTARGET_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 "android/androidjninfc_p.h" +#include "qnearfieldtarget_p.h" +#include "qndefmessage.h" +#include "qlist.h" +#include "qstringlist.h" +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +class QNearFieldTargetPrivateImpl : public QNearFieldTargetPrivate +{ + Q_OBJECT +public: + QNearFieldTargetPrivateImpl(QJniObject intent, + const QByteArray uid, + QObject *parent = nullptr); + ~QNearFieldTargetPrivateImpl() override; + + QByteArray uid() const override; + QNearFieldTarget::Type type() const override; + QNearFieldTarget::AccessMethods accessMethods() const override; + + bool disconnect() override; + + bool hasNdefMessage() override; + QNearFieldTarget::RequestId readNdefMessages() override; + QNearFieldTarget::RequestId writeNdefMessages(const QList &messages) override; + + int maxCommandLength() const override; + QNearFieldTarget::RequestId sendCommand(const QByteArray &command) override; + + void setIntent(QJniObject intent); + +signals: + void targetDestroyed(const QByteArray &tagId); + void targetLost(QNearFieldTargetPrivateImpl *target); + void ndefMessageRead(const QNdefMessage &message, const QNearFieldTarget::RequestId &id); + +protected slots: + void checkIsTargetLost(); + +protected: + void releaseIntent(); + void updateTechList(); + void updateType(); + QNearFieldTarget::Type getTagType() const; + void setupTargetCheckTimer(); + void handleTargetLost(); + QJniObject getTagTechnology(const QString &tech) const; + bool setTagTechnology(const QStringList &technologies); + bool connect(); + bool setCommandTimeout(int timeout); + QByteArray jbyteArrayToQByteArray(const jbyteArray &byteArray) const; + +protected: + QJniObject targetIntent; + QByteArray targetUid; + QTimer *targetCheckTimer; + + QString selectedTech; + QStringList techList; + QNearFieldTarget::Type tagType; + QJniObject tagTech; +}; + +QT_END_NAMESPACE + +#endif // QNEARFIELDTARGET_ANDROID_P_H diff --git a/src/nfc/qnearfieldtarget_ios.mm b/src/nfc/qnearfieldtarget_ios.mm new file mode 100644 index 0000000..b058ad7 --- /dev/null +++ b/src/nfc/qnearfieldtarget_ios.mm @@ -0,0 +1,467 @@ +// Copyright (C) 2020 Governikus GmbH & Co. KG +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "ios/qiosnfcndefsessiondelegate_p.h" +#include "ios/qiosndefnotifier_p.h" + +#include "qnearfieldtarget_ios_p.h" + +#import +#import +#import +#import +#import + +#include +#include + +QT_BEGIN_NAMESPACE + +Q_APPLICATION_STATIC(ResponseProvider, responseProvider) + +void ResponseProvider::provideResponse(QNearFieldTarget::RequestId requestId, bool success, QByteArray recvBuffer) { + Q_EMIT responseReceived(requestId, success, recvBuffer); +} + +void NfcDeleter::operator()(void *obj) +{ + id some = static_cast(obj); + + if ([some conformsToProtocol:@protocol(NFCNDEFTag)]) + [static_cast>(some) release]; + else if ([some conformsToProtocol:@protocol(NFCTag)]) + [static_cast>(some) release]; + else + Q_UNREACHABLE(); +} + +QNearFieldTargetPrivateImpl:: QNearFieldTargetPrivateImpl(void *tag, QObject *parent) : + QNearFieldTargetPrivate(parent), + nfcTag(tag) +{ + Q_ASSERT(nfcTag); + + QObject::connect(this, &QNearFieldTargetPrivate::error, this, &QNearFieldTargetPrivateImpl::onTargetError); + QObject::connect(responseProvider, &ResponseProvider::responseReceived, this, &QNearFieldTargetPrivateImpl::onResponseReceived); + QObject::connect(&targetCheckTimer, &QTimer::timeout, this, &QNearFieldTargetPrivateImpl::onTargetCheck); + targetCheckTimer.start(500); +} + +QNearFieldTargetPrivateImpl:: QNearFieldTargetPrivateImpl(void *delegate, void *tag, QObject *parent) : + QNearFieldTargetPrivate(parent), + nfcTag(tag) +{ + Q_ASSERT(delegate && tag); + Q_ASSERT([id(tag) conformsToProtocol:@protocol(NFCNDEFTag)]); + + auto qtDelegate = static_cast(sessionDelegate = delegate); + notifier = [qtDelegate ndefNotifier]; + Q_ASSERT(notifier); + + // The 'notifier' lives on a (potentially different, unspecified) thread, + // thus connection is 'queued'. + QObject::connect(notifier, &QNfcNdefNotifier::tagError, this, + &QNearFieldTargetPrivate::error, Qt::QueuedConnection); + + QObject::connect(this, &QNearFieldTargetPrivate::error, this, &QNearFieldTargetPrivateImpl::onTargetError); + QObject::connect(&targetCheckTimer, &QTimer::timeout, this, &QNearFieldTargetPrivateImpl::onTargetCheck); + + targetCheckTimer.start(500); +} + +QNearFieldTargetPrivateImpl::~QNearFieldTargetPrivateImpl() +{ +} + +void QNearFieldTargetPrivateImpl::invalidate() +{ + queue.clear(); + ndefOperations.clear(); + + if (isNdefTag()) { + Q_ASSERT(notifier); + + QObject::disconnect(notifier, nullptr, this, nullptr); + notifier = nullptr; + } + + nfcTag.reset(); + sessionDelegate = nil; + + targetCheckTimer.stop(); + + QMetaObject::invokeMethod(this, [this]() { + Q_EMIT targetLost(this); + }, Qt::QueuedConnection); +} + +QByteArray QNearFieldTargetPrivateImpl::uid() const +{ + if (!nfcTag || isNdefTag()) // NFCNDEFTag does not have this information ... + return {}; + + if (@available(iOS 13, *)) { + id tag = static_cast>(nfcTag.get()); + id iso7816Tag = tag.asNFCISO7816Tag; + if (iso7816Tag) + return QByteArray::fromNSData(iso7816Tag.identifier); + } + + return {}; +} + +QNearFieldTarget::Type QNearFieldTargetPrivateImpl::type() const +{ + if (!nfcTag || isNdefTag()) // No information provided by NFCNDEFTag. + return QNearFieldTarget::ProprietaryTag; + + if (@available(iOS 13, *)) { + id tag = static_cast>(nfcTag.get()); + id iso7816Tag = tag.asNFCISO7816Tag; + + if (tag.type != NFCTagTypeISO7816Compatible || iso7816Tag == nil) + return QNearFieldTarget::ProprietaryTag; + + if (iso7816Tag.historicalBytes != nil && iso7816Tag.applicationData == nil) + return QNearFieldTarget::NfcTagType4A; + + if (iso7816Tag.historicalBytes == nil && iso7816Tag.applicationData != nil) + return QNearFieldTarget::NfcTagType4B; + + return QNearFieldTarget::NfcTagType4; + } + + return QNearFieldTarget::ProprietaryTag; +} + +QNearFieldTarget::AccessMethods QNearFieldTargetPrivateImpl::accessMethods() const +{ + if (isNdefTag()) + return QNearFieldTarget::NdefAccess; + + if (@available(iOS 13, *)) { + id tag = static_cast>(nfcTag.get()); + if (tag && [tag conformsToProtocol:@protocol(NFCISO7816Tag)]) + return QNearFieldTarget::TagTypeSpecificAccess; + } + + return QNearFieldTarget::UnknownAccess; +} + +int QNearFieldTargetPrivateImpl::maxCommandLength() const +{ + if (accessMethods() & QNearFieldTarget::TagTypeSpecificAccess) + return 0xFEFF; + + // TODO: check if 'capacity' of NFCNDEFTag can be used? + return 0; +} + +QNearFieldTarget::RequestId QNearFieldTargetPrivateImpl::sendCommand(const QByteArray &command) +{ + QNearFieldTarget::RequestId requestId = QNearFieldTarget::RequestId(new QNearFieldTarget::RequestIdPrivate()); + + if (!(accessMethods() & QNearFieldTarget::TagTypeSpecificAccess)) { + reportError(QNearFieldTarget::UnsupportedError, requestId); + return requestId; + } + + queue.enqueue(std::pair(requestId, command)); + + if (!connect()) { + reportError(QNearFieldTarget::TargetOutOfRangeError, requestId); + return requestId; + } + + onExecuteRequest(); + return requestId; +} + +bool QNearFieldTargetPrivateImpl::hasNdefMessage() +{ + return hasNDEFMessage; +} + +QNearFieldTarget::RequestId QNearFieldTargetPrivateImpl::readNdefMessages() +{ + hasNDEFMessage = false; + + QNearFieldTarget::RequestId requestId = QNearFieldTarget::RequestId(new QNearFieldTarget::RequestIdPrivate); + + if (!(accessMethods() & QNearFieldTarget::NdefAccess) || !isNdefTag()) { + qCWarning(QT_IOS_NFC, "Target does not allow to read NDEF messages, " + "was not detected as NDEF tag by the reader session?"); + reportError(QNearFieldTarget::UnsupportedError, requestId); + return requestId; + } + + NdefOperation op; + op.type = NdefOperation::Read; + op.requestId = requestId; + + ndefOperations.push_back(op); + onExecuteRequest(); + + return requestId; +} + +QNearFieldTarget::RequestId QNearFieldTargetPrivateImpl::writeNdefMessages(const QList &messages) +{ + auto requestId = QNearFieldTarget::RequestId(new QNearFieldTarget::RequestIdPrivate); + + if (!(accessMethods() & QNearFieldTarget::NdefAccess) || !isNdefTag()) { + qCWarning(QT_IOS_NFC, "Target does not allow to write NDEF messages, " + "was not detected as NDEF tag by the reader session?"); + reportError(QNearFieldTarget::UnsupportedError, requestId); + return requestId; + } + + if (messages.size() != 1) { + // The native framework does not allow to write 'messages', only _one_ message + // at a time. Not to multiply the complexity of having 'ndefOperations' queue + // with some queue inside the delegate's code (plus some unpredictable errors + // handling) - require a single message as a single request. + qCWarning(QT_IOS_NFC, "Only one NDEF message per request ID can be written"); + return requestId; + } + + NdefOperation op; + op.type = NdefOperation::Write; + op.requestId = requestId; + op.message = messages.first(); + + ndefOperations.push_back(op); + onExecuteRequest(); + + return requestId; +} + +bool QNearFieldTargetPrivateImpl::isAvailable() const +{ + if (requestInProgress.isValid()) + return true; + + const auto tagIsAvailable = [this](auto tag) { + return tag && (!connected || tag.available); + }; + + if (isNdefTag()) + return tagIsAvailable(static_cast>(nfcTag.get())); + + if (@available(iOS 13, *)) + return tagIsAvailable(static_cast>(nfcTag.get())); + + return false; +} + +bool QNearFieldTargetPrivateImpl::connect() +{ + if (connected || requestInProgress.isValid()) + return true; + + if (isNdefTag()) + return connected = true; + + if (!isAvailable() || queue.isEmpty()) + return false; + + if (@available(iOS 13, *)) { + requestInProgress = queue.head().first; + id tag = static_cast>(nfcTag.get()); + NFCTagReaderSession* session = tag.session; + [session connectToTag: tag completionHandler: ^(NSError* error){ + const bool success = error == nil; + QMetaObject::invokeMethod(this, [this, success] { + requestInProgress = QNearFieldTarget::RequestId(); + if (success) { + connected = true; + onExecuteRequest(); + } else { + const auto requestId = queue.dequeue().first; + reportError(QNearFieldTarget::ConnectionError, requestId); + invalidate(); + } + }); + }]; + return true; + } + + return false; +} + +bool QNearFieldTargetPrivateImpl::isNdefTag() const +{ + const id tag = static_cast(nfcTag.get()); + if ([tag conformsToProtocol:@protocol(NFCMiFareTag)]) + return false; + if ([tag conformsToProtocol:@protocol(NFCFeliCaTag)]) + return false; + if ([tag conformsToProtocol:@protocol(NFCISO15693Tag)]) + return false; + if ([tag conformsToProtocol:@protocol(NFCISO7816Tag)]) + return false; + return [tag conformsToProtocol:@protocol(NFCNDEFTag)]; +} + +void QNearFieldTargetPrivateImpl::onTargetCheck() +{ + if (!isAvailable()) + invalidate(); +} + +void QNearFieldTargetPrivateImpl::onTargetError(QNearFieldTarget::Error error, const QNearFieldTarget::RequestId &id) +{ + Q_UNUSED(id); + + if (error == QNearFieldTarget::TimeoutError) + invalidate(); +} + +namespace { + +QNdefMessage ndefToQtNdefMessage(NFCNDEFMessage *nativeMessage) +{ + if (!nativeMessage) + return {}; + + QList ndefRecords; + for (NFCNDEFPayload *ndefRecord in nativeMessage.records) { + QNdefRecord qtNdefRecord; + if (ndefRecord.typeNameFormat != NFCTypeNameFormatUnchanged) // Does not match anything in Qt. + qtNdefRecord.setTypeNameFormat(QNdefRecord::TypeNameFormat(ndefRecord.typeNameFormat)); + if (ndefRecord.identifier) + qtNdefRecord.setId(QByteArray::fromNSData(ndefRecord.identifier)); + if (ndefRecord.type) + qtNdefRecord.setType(QByteArray::fromNSData(ndefRecord.type)); + if (ndefRecord.payload) + qtNdefRecord.setPayload(QByteArray::fromNSData(ndefRecord.payload)); + ndefRecords.push_back(qtNdefRecord); + } + + return QNdefMessage{ndefRecords}; +} + +} // Unnamed namespace. + +void QNearFieldTargetPrivateImpl::onExecuteRequest() +{ + if (!nfcTag || requestInProgress.isValid()) + return; + + if (isNdefTag()) { + if (ndefOperations.empty()) + return; + + auto *ndefDelegate = static_cast(sessionDelegate); + Q_ASSERT(ndefDelegate); + + Q_ASSERT(qt_Nfc_Queue()); // This is where callbacks get called. + + const auto op = ndefOperations.front(); + ndefOperations.pop_front(); + requestInProgress = op.requestId; + auto requestId = requestInProgress; // Copy so we capture by value in the block. + + id ndefTag = static_cast>(nfcTag.get()); + + std::unique_ptr guard(new QNfcNdefNotifier); + auto *cbNotifier = guard.get(); + + QObject::connect(cbNotifier, &QNfcNdefNotifier::tagError, this, + &QNearFieldTargetPrivate::error, Qt::QueuedConnection); + + if (op.type == NdefOperation::Read) { + QObject::connect(cbNotifier, &QNfcNdefNotifier::ndefMessageRead, + this, &QNearFieldTargetPrivateImpl::messageRead, + Qt::QueuedConnection); + + // We call it here, but the callback will be executed on an unspecified thread. + [ndefTag readNDEFWithCompletionHandler:^(NFCNDEFMessage * _Nullable msg, NSError * _Nullable err) { + const std::unique_ptr notifierGuard(cbNotifier); + if (err) { + NSLog(@"Reading NDEF messaged ended with error: %@", err); + emit cbNotifier->tagError(QNearFieldTarget::NdefReadError, requestId); + return; + } + + const QNdefMessage ndefMessage(ndefToQtNdefMessage(msg)); + emit cbNotifier->ndefMessageRead(ndefMessage, requestId); + }]; + } else { + QObject::connect(cbNotifier, &QNfcNdefNotifier::ndefMessageWritten, + this, &QNearFieldTargetPrivateImpl::messageWritten, + Qt::QueuedConnection); + + NSData *ndefData = op.message.toByteArray().toNSData(); // autoreleased. + Q_ASSERT(ndefData); + + NFCNDEFMessage *ndefMessage = [NFCNDEFMessage ndefMessageWithData:ndefData]; // autoreleased. + Q_ASSERT(ndefMessage); + + [ndefTag writeNDEF:ndefMessage completionHandler:^(NSError *err) { + const std::unique_ptr notifierGuard(cbNotifier); + if (err) { + NSLog(@"Writing NDEF messaged ended with error: %@", err); + emit cbNotifier->tagError(QNearFieldTarget::NdefWriteError, requestId); + return; + } + + emit cbNotifier->ndefMessageWritten(requestId); + }]; + } + guard.release(); // Owned by the completion handler now. + return; + } + + if (@available(iOS 13, *)) { + if (queue.isEmpty()) + return; + const auto request = queue.dequeue(); + requestInProgress = request.first; + const auto tag = static_cast>(nfcTag.get()); + auto *apdu = [[[NFCISO7816APDU alloc] initWithData: request.second.toNSData()] autorelease]; + [tag sendCommandAPDU: apdu completionHandler: ^(NSData* responseData, uint8_t sw1, uint8_t sw2, NSError* error){ + QByteArray recvBuffer = QByteArray::fromNSData(responseData); + recvBuffer += static_cast(sw1); + recvBuffer += static_cast(sw2); + const bool success = error == nil; + responseProvider->provideResponse(request.first, success, recvBuffer); + }]; + } +} + +void QNearFieldTargetPrivateImpl::onResponseReceived(QNearFieldTarget::RequestId requestId, bool success, QByteArray recvBuffer) +{ + if (requestInProgress != requestId) + return; + + requestInProgress = QNearFieldTarget::RequestId(); + if (success) { + setResponseForRequest(requestId, recvBuffer, true); + onExecuteRequest(); + } else { + reportError(QNearFieldTarget::CommandError, requestId); + invalidate(); + } +} + +void QNearFieldTargetPrivateImpl::messageRead(const QNdefMessage &message, QNearFieldTarget::RequestId requestId) +{ + hasNDEFMessage = message.size() != 0; + + setResponseForRequest(requestId, message.toByteArray(), true); + requestInProgress = {}; // Invalidating, so we can execute the next one. + onExecuteRequest(); + + Q_EMIT ndefMessageRead(message); +} + +void QNearFieldTargetPrivateImpl::messageWritten(QNearFieldTarget::RequestId requestId) +{ + requestInProgress = {}; // Invalidating, so we can execute the next one. + onExecuteRequest(); + + Q_EMIT requestCompleted(requestId); +} + +QT_END_NAMESPACE diff --git a/src/nfc/qnearfieldtarget_ios_p.h b/src/nfc/qnearfieldtarget_ios_p.h new file mode 100644 index 0000000..c0cde0b --- /dev/null +++ b/src/nfc/qnearfieldtarget_ios_p.h @@ -0,0 +1,119 @@ +// Copyright (C) 2020 Governikus GmbH & Co. KG +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QNEARFIELDTARGET_IOS_P_H +#define QNEARFIELDTARGET_IOS_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 "qnearfieldtarget_p.h" +#include "qnearfieldtarget.h" + +#include "qndefmessage.h" + +#include +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +class ResponseProvider : public QObject +{ + Q_OBJECT + + public: + void provideResponse(QNearFieldTarget::RequestId requestId, bool success, QByteArray recvBuffer); + + Q_SIGNALS: + void responseReceived(QNearFieldTarget::RequestId requestId, bool success, QByteArray recvBuffer); +}; + +struct NfcDeleter +{ + void operator()(void *tag); +}; + +struct NdefOperation +{ + enum Type { + Read, + Write + } type = Read; + + QNearFieldTarget::RequestId requestId; + QNdefMessage message; +}; + +class QNfcNdefNotifier; + +class QNearFieldTargetPrivateImpl : public QNearFieldTargetPrivate +{ + Q_OBJECT + +public: + QNearFieldTargetPrivateImpl(void *tag, QObject *parent = nullptr); + QNearFieldTargetPrivateImpl(void *sessionDelegate, void *tag, QObject *parent = nullptr); + ~QNearFieldTargetPrivateImpl() override; + void invalidate(); + + QByteArray uid() const override; + QNearFieldTarget::Type type() const override; + QNearFieldTarget::AccessMethods accessMethods() const override; + + int maxCommandLength() const override; + QNearFieldTarget::RequestId sendCommand(const QByteArray &command) override; + + // NdefAccess + bool hasNdefMessage() override; + QNearFieldTarget::RequestId readNdefMessages() override; + QNearFieldTarget::RequestId writeNdefMessages(const QList &messages) override; + + + bool isAvailable() const; + +Q_SIGNALS: + void targetLost(QNearFieldTargetPrivateImpl *target); + +private: + std::unique_ptr nfcTag; + + // Owned by the near field manager. + void *sessionDelegate = nil; + // Owned by the session delegate. + QNfcNdefNotifier *notifier = nullptr; + bool hasNDEFMessage = false; + + bool connected = false; + QTimer targetCheckTimer; + QNearFieldTarget::RequestId requestInProgress; + QQueue> queue; + std::deque ndefOperations; + + bool connect(); + + bool isNdefTag() const; + +private Q_SLOTS: + void onTargetCheck(); + void onTargetError(QNearFieldTarget::Error error, const QNearFieldTarget::RequestId &id); + void onExecuteRequest(); + void onResponseReceived(QNearFieldTarget::RequestId requestId, bool success, QByteArray recvBuffer); + // NDEF: + void messageRead(const QNdefMessage &ndefMessage, QNearFieldTarget::RequestId request); + void messageWritten(QNearFieldTarget::RequestId request); +}; + +QT_END_NAMESPACE + +#endif // QNEARFIELDTARGET_IOS_P_H diff --git a/src/nfc/qnearfieldtarget_p.cpp b/src/nfc/qnearfieldtarget_p.cpp new file mode 100644 index 0000000..ff69eec --- /dev/null +++ b/src/nfc/qnearfieldtarget_p.cpp @@ -0,0 +1,134 @@ +// Copyright (C) 2017 Governikus GmbH & Co. K +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qnearfieldtarget_p.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + + +QNearFieldTargetPrivate::QNearFieldTargetPrivate(QObject *parent) +: QObject(parent) +, q_ptr(nullptr) +{ +} + +QByteArray QNearFieldTargetPrivate::uid() const +{ + return QByteArray(); +} + +QNearFieldTarget::Type QNearFieldTargetPrivate::type() const +{ + return QNearFieldTarget::Type::ProprietaryTag; +} + +QNearFieldTarget::AccessMethods QNearFieldTargetPrivate::accessMethods() const +{ + return QNearFieldTarget::AccessMethod::UnknownAccess; +} + +bool QNearFieldTargetPrivate::disconnect() +{ + return false; +} + +// NdefAccess +bool QNearFieldTargetPrivate::hasNdefMessage() +{ + return false; +} + +QNearFieldTarget::RequestId QNearFieldTargetPrivate::readNdefMessages() +{ + const QNearFieldTarget::RequestId id; + Q_EMIT error(QNearFieldTarget::UnsupportedError, id); + return id; +} + +QNearFieldTarget::RequestId +QNearFieldTargetPrivate::writeNdefMessages(const QList &messages) +{ + Q_UNUSED(messages); + + const QNearFieldTarget::RequestId id; + Q_EMIT error(QNearFieldTarget::UnsupportedError, id); + return id; +} + +// TagTypeSpecificAccess +int QNearFieldTargetPrivate::maxCommandLength() const +{ + return 0; +} + +QNearFieldTarget::RequestId QNearFieldTargetPrivate::sendCommand(const QByteArray &command) +{ + Q_UNUSED(command); + + const QNearFieldTarget::RequestId id; + Q_EMIT error(QNearFieldTarget::UnsupportedError, id); + return id; +} + +bool QNearFieldTargetPrivate::waitForRequestCompleted(const QNearFieldTarget::RequestId &id, + int msecs) +{ + QElapsedTimer timer; + timer.start(); + + const QPointer weakThis = this; + + do { + if (!weakThis) + return false; + + if (m_decodedResponses.contains(id)) + return true; + else + QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents, 1); + } while (timer.elapsed() <= msecs); + + reportError(QNearFieldTarget::TimeoutError, id); + + return false; +} + +QVariant QNearFieldTargetPrivate::requestResponse(const QNearFieldTarget::RequestId &id) const +{ + return m_decodedResponses.value(id); +} + +void QNearFieldTargetPrivate::setResponseForRequest(const QNearFieldTarget::RequestId &id, + const QVariant &response, + bool emitRequestCompleted) +{ + for (auto i = m_decodedResponses.begin(), end = m_decodedResponses.end(); i != end; /* erasing */) { + // no more external references + if (i.key().refCount() == 1) + i = m_decodedResponses.erase(i); + else + ++i; + } + + m_decodedResponses.insert(id, response); + + if (emitRequestCompleted) + Q_EMIT requestCompleted(id); +} + +void QNearFieldTargetPrivate::reportError(QNearFieldTarget::Error error, + const QNearFieldTarget::RequestId &id) +{ + setResponseForRequest(id, QVariant(), false); + QMetaObject::invokeMethod(this, [this, error, id]() { + Q_EMIT this->error(error, id); + }, Qt::QueuedConnection); +} + +QT_END_NAMESPACE + +#include "moc_qnearfieldtarget_p.cpp" diff --git a/src/nfc/qnearfieldtarget_p.h b/src/nfc/qnearfieldtarget_p.h new file mode 100644 index 0000000..dd7550a --- /dev/null +++ b/src/nfc/qnearfieldtarget_p.h @@ -0,0 +1,82 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QNEARFIELDTARGET_P_H +#define QNEARFIELDTARGET_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 "qnearfieldtarget.h" + +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QNearFieldTarget::RequestIdPrivate : public QSharedData +{ +}; + +class Q_AUTOTEST_EXPORT QNearFieldTargetPrivate : public QObject +{ + Q_OBJECT + +public: + QNearFieldTarget *q_ptr; + + explicit QNearFieldTargetPrivate(QObject *parent = nullptr); + virtual ~QNearFieldTargetPrivate() = default; + + virtual QByteArray uid() const; + virtual QNearFieldTarget::Type type() const; + virtual QNearFieldTarget::AccessMethods accessMethods() const; + + virtual bool disconnect(); + + // NdefAccess + virtual bool hasNdefMessage(); + virtual QNearFieldTarget::RequestId readNdefMessages(); + virtual QNearFieldTarget::RequestId writeNdefMessages(const QList &messages); + + // TagTypeSpecificAccess + virtual int maxCommandLength() const; + virtual QNearFieldTarget::RequestId sendCommand(const QByteArray &command); + + bool waitForRequestCompleted(const QNearFieldTarget::RequestId &id, int msecs = 5000); + QVariant requestResponse(const QNearFieldTarget::RequestId &id) const; + +Q_SIGNALS: + void disconnected(); + + void ndefMessageRead(const QNdefMessage &message); + + void requestCompleted(const QNearFieldTarget::RequestId &id); + + void error(QNearFieldTarget::Error error, const QNearFieldTarget::RequestId &id); + +protected: + QMap m_decodedResponses; + + virtual void setResponseForRequest(const QNearFieldTarget::RequestId &id, + const QVariant &response, + bool emitRequestCompleted = true); + + void reportError(QNearFieldTarget::Error error, const QNearFieldTarget::RequestId &id); +}; + +QT_END_NAMESPACE + +#endif // QNEARFIELDTARGET_P_H diff --git a/src/nfc/qnearfieldtarget_pcsc.cpp b/src/nfc/qnearfieldtarget_pcsc.cpp new file mode 100644 index 0000000..76bc685 --- /dev/null +++ b/src/nfc/qnearfieldtarget_pcsc.cpp @@ -0,0 +1,161 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qnearfieldtarget_pcsc_p.h" +#include "qndefmessage.h" +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_NFC_PCSC) + +/* + Construct QNearFieldTargetPrivateImpl instance. + + This object communicates with a QPcscCard object that lives inside the + worker thread via signal-slot mechanism. +*/ +QNearFieldTargetPrivateImpl::QNearFieldTargetPrivateImpl( + const QByteArray &uid, QNearFieldTarget::AccessMethods accessMethods, int maxInputLength, + QObject *parent) + : QNearFieldTargetPrivate(parent), + m_uid(uid), + m_accessMethods(accessMethods), + m_maxInputLength(maxInputLength) +{ + qCDebug(QT_NFC_PCSC) << "New card with UID" << m_uid.toHex(':'); +} + +QNearFieldTargetPrivateImpl::~QNearFieldTargetPrivateImpl() +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; +} + +QByteArray QNearFieldTargetPrivateImpl::uid() const +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + return m_uid; +} + +QNearFieldTarget::Type QNearFieldTargetPrivateImpl::type() const +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + + // Currently NDEF access is only supported for Type 4 tags + if (m_accessMethods & QNearFieldTarget::NdefAccess) + return QNearFieldTarget::NfcTagType4; + + return QNearFieldTarget::ProprietaryTag; +} + +QNearFieldTarget::AccessMethods QNearFieldTargetPrivateImpl::accessMethods() const +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + return m_accessMethods; +} + +bool QNearFieldTargetPrivateImpl::disconnect() +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + + if (!m_connected || !m_isValid) + return false; + + Q_EMIT disconnectRequest(); + return true; +} + +int QNearFieldTargetPrivateImpl::maxCommandLength() const +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + return m_maxInputLength; +} + +void QNearFieldTargetPrivateImpl::onRequestCompleted(const QNearFieldTarget::RequestId &request, + QNearFieldTarget::Error reason, + const QVariant &result) +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + + if (reason == QNearFieldTarget::NoError) + setResponseForRequest(request, result); + else + reportError(reason, request); +} + +void QNearFieldTargetPrivateImpl::onNdefMessageRead(const QNdefMessage &message) +{ + Q_EMIT ndefMessageRead(message); +} + +QNearFieldTarget::RequestId QNearFieldTargetPrivateImpl::sendCommand(const QByteArray &command) +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + + if (!m_isValid) + return QNearFieldTarget::RequestId(nullptr); + + m_connected = true; + + QNearFieldTarget::RequestId reqId(new QNearFieldTarget::RequestIdPrivate); + Q_EMIT sendCommandRequest(reqId, command); + + return reqId; +} + +QNearFieldTarget::RequestId QNearFieldTargetPrivateImpl::readNdefMessages() +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + + if (!m_isValid) + return QNearFieldTarget::RequestId(nullptr); + + m_connected = true; + + QNearFieldTarget::RequestId reqId(new QNearFieldTarget::RequestIdPrivate); + Q_EMIT readNdefMessagesRequest(reqId); + + return reqId; +} + +QNearFieldTarget::RequestId +QNearFieldTargetPrivateImpl::writeNdefMessages(const QList &messages) +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + + if (!m_isValid) + return QNearFieldTarget::RequestId(nullptr); + + m_connected = true; + + QNearFieldTarget::RequestId reqId(new QNearFieldTarget::RequestIdPrivate); + Q_EMIT writeNdefMessagesRequest(reqId, messages); + + return reqId; +} + +void QNearFieldTargetPrivateImpl::onDisconnected() +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + + if (!m_connected) + return; + + m_connected = false; + + Q_EMIT disconnected(); +} + +void QNearFieldTargetPrivateImpl::onInvalidated() +{ + qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; + + if (!m_isValid) + return; + + m_isValid = false; + + Q_EMIT targetLost(this); +} + +QT_END_NAMESPACE diff --git a/src/nfc/qnearfieldtarget_pcsc_p.h b/src/nfc/qnearfieldtarget_pcsc_p.h new file mode 100644 index 0000000..c5631af --- /dev/null +++ b/src/nfc/qnearfieldtarget_pcsc_p.h @@ -0,0 +1,67 @@ +// Copyright (C) 2022q The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QNEARFIELDTARGET_PCSC_P_H +#define QNEARFIELDTARGET_PCSC_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 "qnearfieldtarget_p.h" + +QT_BEGIN_NAMESPACE + +class QNearFieldTargetPrivateImpl : public QNearFieldTargetPrivate +{ + Q_OBJECT +public: + QNearFieldTargetPrivateImpl(const QByteArray &uid, + QNearFieldTarget::AccessMethods accessMethods, int maxInputLength, + QObject *parent); + ~QNearFieldTargetPrivateImpl() override; + + QByteArray uid() const override; + QNearFieldTarget::Type type() const override; + QNearFieldTarget::AccessMethods accessMethods() const override; + + bool disconnect() override; + + int maxCommandLength() const override; + QNearFieldTarget::RequestId sendCommand(const QByteArray &command) override; + QNearFieldTarget::RequestId readNdefMessages() override; + QNearFieldTarget::RequestId writeNdefMessages(const QList &messages) override; + +private: + const QByteArray m_uid; + QNearFieldTarget::AccessMethods m_accessMethods; + int m_maxInputLength; + bool m_connected = false; + bool m_isValid = true; + +public Q_SLOTS: + void onDisconnected(); + void onInvalidated(); + void onRequestCompleted(const QNearFieldTarget::RequestId &request, + QNearFieldTarget::Error reason, const QVariant &result); + void onNdefMessageRead(const QNdefMessage &message); + +Q_SIGNALS: + void disconnectRequest(); + void sendCommandRequest(const QNearFieldTarget::RequestId &request, const QByteArray &command); + void readNdefMessagesRequest(const QNearFieldTarget::RequestId &request); + void writeNdefMessagesRequest(const QNearFieldTarget::RequestId &request, + const QList &messages); + void targetLost(QNearFieldTargetPrivate *target); +}; + +QT_END_NAMESPACE + +#endif // QNEARFIELDTARGET_PCSC_P_H diff --git a/src/nfc/qtnfcglobal.h b/src/nfc/qtnfcglobal.h new file mode 100644 index 0000000..d80b25b --- /dev/null +++ b/src/nfc/qtnfcglobal.h @@ -0,0 +1,10 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QTNFC_H +#define QTNFC_H + +#include +#include + +#endif // QTNFC_H diff --git a/src/nfc/qtnfcglobal_p.h b/src/nfc/qtnfcglobal_p.h new file mode 100644 index 0000000..f4ec049 --- /dev/null +++ b/src/nfc/qtnfcglobal_p.h @@ -0,0 +1,23 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QTNFCGLOBAL_P_H +#define QTNFCGLOBAL_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 + +#endif // QTNFCGLOBAL_P_H diff --git a/src/tools/sdpscanner/CMakeLists.txt b/src/tools/sdpscanner/CMakeLists.txt new file mode 100644 index 0000000..a490605 --- /dev/null +++ b/src/tools/sdpscanner/CMakeLists.txt @@ -0,0 +1,20 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## sdpscanner Tool: +##################################################################### + +if(NOT TARGET PkgConfig::BLUEZ) + qt_find_package(BlueZ PROVIDED_TARGETS PkgConfig::BLUEZ) +endif() + +qt_internal_add_app(sdpscanner + INSTALL_DIR "${INSTALL_LIBEXECDIR}" + SOURCES + main.cpp + DEFINES + QT_NO_CONTEXTLESS_CONNECT + LIBRARIES + PkgConfig::BLUEZ +) diff --git a/src/tools/sdpscanner/main.cpp b/src/tools/sdpscanner/main.cpp new file mode 100644 index 0000000..4a7f7d2 --- /dev/null +++ b/src/tools/sdpscanner/main.cpp @@ -0,0 +1,402 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include +#include +#include +#include +#include +#include +#include +#include + +#define RETURN_SUCCESS 0 +#define RETURN_USAGE 1 +#define RETURN_INVALPARAM 2 +#define RETURN_SDP_ERROR 3 + +void usage() +{ + fprintf(stderr, "Usage:\n"); + fprintf(stderr, "\tsdpscanner [Options] ({uuids})\n\n"); + fprintf(stderr, "Performs an SDP scan on remote device, using the SDP server\n" + "represented by the local Bluetooth device.\n\n" + "Options:\n" + " -p Show scan results in human-readable form\n" + " -u [list of uuids] List of uuids which should be scanned for.\n" + " Each uuid must be enclosed in {}.\n" + " If the list is empty PUBLIC_BROWSE_GROUP scan is used.\n"); +} + +#define BUFFER_SIZE 1024 + +static void parseAttributeValues(sdp_data_t *data, int indentation, QByteArray &xmlOutput) +{ + if (!data) + return; + + const int length = indentation*2 + 1; + QByteArray indentString(length, ' '); + + char snBuffer[BUFFER_SIZE]; + + xmlOutput.append(indentString); + + // deal with every dtd type + switch (data->dtd) { + case SDP_DATA_NIL: + xmlOutput.append("\n"); + break; + case SDP_UINT8: + qsnprintf(snBuffer, BUFFER_SIZE, "\n", data->val.uint8); + xmlOutput.append(snBuffer); + break; + case SDP_UINT16: + qsnprintf(snBuffer, BUFFER_SIZE, "\n", data->val.uint16); + xmlOutput.append(snBuffer); + break; + case SDP_UINT32: + qsnprintf(snBuffer, BUFFER_SIZE, "\n", data->val.uint32); + xmlOutput.append(snBuffer); + break; + case SDP_UINT64: + qsnprintf(snBuffer, BUFFER_SIZE, "\n", data->val.uint64); + xmlOutput.append(snBuffer); + break; + case SDP_UINT128: + xmlOutput.append("val.uint128.data[i]); + xmlOutput.append(snBuffer); + xmlOutput.append("\"/>\n"); + break; + case SDP_INT8: + qsnprintf(snBuffer, BUFFER_SIZE, "/n", data->val.int8); + xmlOutput.append(snBuffer); + break; + case SDP_INT16: + qsnprintf(snBuffer, BUFFER_SIZE, "/n", data->val.int16); + xmlOutput.append(snBuffer); + break; + case SDP_INT32: + qsnprintf(snBuffer, BUFFER_SIZE, "/n", data->val.int32); + xmlOutput.append(snBuffer); + break; + case SDP_INT64: + qsnprintf(snBuffer, BUFFER_SIZE, "/n", data->val.int64); + xmlOutput.append(snBuffer); + break; + case SDP_INT128: + xmlOutput.append("val.int128.data[i]); + xmlOutput.append(snBuffer); + xmlOutput.append("\"/>\n"); + break; + case SDP_UUID_UNSPEC: + break; + case SDP_UUID16: + case SDP_UUID32: + xmlOutput.append("val.uuid), snBuffer, BUFFER_SIZE); + xmlOutput.append(snBuffer); + xmlOutput.append("\"/>\n"); + break; + case SDP_UUID128: + xmlOutput.append("val.uuid), snBuffer, BUFFER_SIZE); + xmlOutput.append(snBuffer); + xmlOutput.append("\"/>\n"); + break; + case SDP_TEXT_STR_UNSPEC: + break; + case SDP_TEXT_STR8: + case SDP_TEXT_STR16: + case SDP_TEXT_STR32: + { + xmlOutput.append("val.str, data->unitSize); + + bool hasNonPrintableChar = false; + for (qsizetype i = 0; i < text.size(); ++i) { + if (text[i] == '\0') { + text.resize(i); // cut trailing content + break; + } else if (!isprint(text[i])) { + hasNonPrintableChar = true; + const auto firstNullIdx = text.indexOf('\0'); + if (firstNullIdx > 0) + text.resize(firstNullIdx); // cut trailing content + break; + } + } + + if (hasNonPrintableChar) { + xmlOutput.append("encoding=\"hex\" value=\""); + xmlOutput.append(text.toHex()); + } else { + text.replace('&', "&"); + text.replace('<', "<"); + text.replace('>', ">"); + text.replace('"', """); + + xmlOutput.append("value=\""); + xmlOutput.append(text); + } + + xmlOutput.append("\"/>\n"); + break; + } + case SDP_BOOL: + if (data->val.uint8) + xmlOutput.append("\n"); + else + xmlOutput.append("\n"); + break; + case SDP_SEQ_UNSPEC: + break; + case SDP_SEQ8: + case SDP_SEQ16: + case SDP_SEQ32: + xmlOutput.append("\n"); + parseAttributeValues(data->val.dataseq, indentation + 1, xmlOutput); + xmlOutput.append(indentString); + xmlOutput.append("\n"); + break; + case SDP_ALT_UNSPEC: + break; + case SDP_ALT8: + case SDP_ALT16: + case SDP_ALT32: + xmlOutput.append("\n"); + parseAttributeValues(data->val.dataseq, indentation + 1, xmlOutput); + xmlOutput.append(indentString); + xmlOutput.append("\n"); + break; + case SDP_URL_STR_UNSPEC: + break; + case SDP_URL_STR8: + case SDP_URL_STR16: + case SDP_URL_STR32: + { + xmlOutput.append("val.str, qstrnlen(data->val.str, data->unitSize)); + const QUrl url = QUrl::fromEncoded(urlData); + // Encoded url %-encodes all of the XML special characters except '&', + // so we need to do that manually + xmlOutput.append(url.toEncoded().replace('&', "&")); + xmlOutput.append("\"/>\n"); + break; + } + default: + fprintf(stderr, "Unknown dtd type\n"); + } + + parseAttributeValues(data->next, indentation, xmlOutput); +} + +static void parseAttribute(void *value, void *extraData) +{ + sdp_data_t *data = (sdp_data_t *) value; + QByteArray *xmlOutput = static_cast(extraData); + + char buffer[BUFFER_SIZE]; + + ::qsnprintf(buffer, BUFFER_SIZE, " \n", data->attrId); + xmlOutput->append(buffer); + + parseAttributeValues(data, 2, *xmlOutput); + + xmlOutput->append(" \n"); +} + +// the resulting xml output is based on the already used xml parser +QByteArray parseSdpRecord(sdp_record_t *record) +{ + if (!record || !record->attrlist) + return QByteArray(); + + QByteArray xmlOutput; + + xmlOutput.append("\n\n"); + + sdp_list_foreach(record->attrlist, parseAttribute, &xmlOutput); + xmlOutput.append(""); + + return xmlOutput; +} + + +int main(int argc, char **argv) +{ + if (argc < 3) { + usage(); + return RETURN_USAGE; + } + + fprintf(stderr, "SDP for %s %s\n", argv[1], argv[2]); + + bdaddr_t remote; + bdaddr_t local; + int result = str2ba(argv[1], &remote); + if (result < 0) { + fprintf(stderr, "Invalid remote address: %s\n", argv[1]); + return RETURN_INVALPARAM; + } + + result = str2ba(argv[2], &local); + if (result < 0) { + fprintf(stderr, "Invalid local address: %s\n", argv[2]); + return RETURN_INVALPARAM; + } + + bool showHumanReadable = false; + std::vector targetServices; + + for (int i = 3; i < argc; i++) { + if (argv[i][0] != '-') { + usage(); + return RETURN_USAGE; + } + + switch (argv[i][1]) + { + case 'p': + showHumanReadable = true; + break; + case 'u': + i++; + + for ( ; i < argc && argv[i][0] == '{'; i++) + targetServices.push_back(argv[i]); + + i--; // outer loop increments again + break; + default: + fprintf(stderr, "Wrong argument: %s\n", argv[i]); + usage(); + return RETURN_USAGE; + } + } + + std::vector uuids; + for (std::vector::const_iterator iter = targetServices.cbegin(); + iter != targetServices.cend(); ++iter) { + + uint128_t temp128; + uint16_t field1, field2, field3, field5; + uint32_t field0, field4; + + fprintf(stderr, "Target scan for %s\n", (*iter).c_str()); + if (sscanf((*iter).c_str(), "{%08x-%04hx-%04hx-%04hx-%08x%04hx}", &field0, + &field1, &field2, &field3, &field4, &field5) != 6) { + fprintf(stderr, "Skipping invalid uuid: %s\n", ((*iter).c_str())); + continue; + } + + // we need uuid_t conversion based on + // http://www.spinics.net/lists/linux-bluetooth/msg20356.html + field0 = htonl(field0); + field4 = htonl(field4); + field1 = htons(field1); + field2 = htons(field2); + field3 = htons(field3); + field5 = htons(field5); + + uint8_t* temp = (uint8_t*) &temp128; + memcpy(&temp[0], &field0, 4); + memcpy(&temp[4], &field1, 2); + memcpy(&temp[6], &field2, 2); + memcpy(&temp[8], &field3, 2); + memcpy(&temp[10], &field4, 4); + memcpy(&temp[14], &field5, 2); + + uuid_t sdpUuid; + sdp_uuid128_create(&sdpUuid, &temp128); + uuids.push_back(sdpUuid); + } + + sdp_session_t *session = sdp_connect( &local, &remote, SDP_RETRY_IF_BUSY); + if (!session) { + //try one more time if first time failed + session = sdp_connect( &local, &remote, SDP_RETRY_IF_BUSY); + } + + if (!session) { + fprintf(stderr, "Cannot establish sdp session\n"); + return RETURN_SDP_ERROR; + } + + // set the filter for service matches + if (uuids.empty()) { + fprintf(stderr, "Using PUBLIC_BROWSE_GROUP for SDP search\n"); + uuid_t publicBrowseGroupUuid; + sdp_uuid16_create(&publicBrowseGroupUuid, PUBLIC_BROWSE_GROUP); + uuids.push_back(publicBrowseGroupUuid); + } + + uint32_t attributeRange = 0x0000ffff; //all attributes + sdp_list_t *attributes; + attributes = sdp_list_append(nullptr, &attributeRange); + + sdp_list_t *sdpResults, *sdpIter; + sdp_list_t *totalResults = nullptr; + sdp_list_t* serviceFilter; + + for (uuid_t &uuid : uuids) { // can't be const, d/t sdp_list_append signature + serviceFilter = sdp_list_append(nullptr, &uuid); + result = sdp_service_search_attr_req(session, serviceFilter, + SDP_ATTR_REQ_RANGE, + attributes, &sdpResults); + sdp_list_free(serviceFilter, nullptr); + if (result != 0) { + fprintf(stderr, "sdp_service_search_attr_req failed\n"); + sdp_list_free(attributes, nullptr); + sdp_close(session); + return RETURN_SDP_ERROR; + } + + if (!sdpResults) + continue; + + if (!totalResults) { + totalResults = sdpResults; + sdpIter = totalResults; + } else { + // attach each new result list to the end of totalResults + sdpIter->next = sdpResults; + } + + while (sdpIter->next) // skip to end of list + sdpIter = sdpIter->next; + } + sdp_list_free(attributes, nullptr); + + // start XML generation from the front + sdpResults = totalResults; + + QByteArray total; + while (sdpResults) { + sdp_record_t *record = (sdp_record_t *) sdpResults->data; + + const QByteArray xml = parseSdpRecord(record); + total += xml; + + sdpIter = sdpResults; + sdpResults = sdpResults->next; + free(sdpIter); + sdp_record_free(record); + } + + if (!total.isEmpty()) { + if (showHumanReadable) + printf("%s", total.constData()); + else + printf("%s", total.toBase64().constData()); + } + + sdp_close(session); + + return RETURN_SUCCESS; +} diff --git a/src/tools/sdpscanner/qt_attribution.json b/src/tools/sdpscanner/qt_attribution.json new file mode 100644 index 0000000..9524a33 --- /dev/null +++ b/src/tools/sdpscanner/qt_attribution.json @@ -0,0 +1,16 @@ +{ + "Id": "bluez", + "Name": "BlueZ", + "QDocModule": "qtbluetooth", + "QtUsage": "On Linux, Qt Bluetooth uses a separate executable, sdpscanner, +to integrate with the official Linux Bluetooth protocol stack (BlueZ). The usage is limited +to service discovery via SDP. The Qt Bluetooth library itself does NOT link against BlueZ. +Communication between sdpscanner and QtBluetooth happens via stdin/stdout. Therefore +QtBluetooth and user code linking to it is not considered a derivative work, and does not +have to be released under GPL too.", + "Description": "SDP Search via BlueZ", + "Homepage": "http://www.bluez.org/", + "LicenseId": "GPL-2.0-only", + "License": "GNU General Public License v2.0 only (This does not force user code to be GPL'ed. For more info see details.)", + "Copyright": "Copyright (C) 2000-2016 BlueZ Project." +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..ddf3dbf --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,17 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +if(QT_BUILD_STANDALONE_TESTS) + # Add qt_find_package calls for extra dependencies that need to be found when building + # the standalone tests here. +endif() + +if(TARGET Qt::Bluetooth) + if(TARGET Qt::Quick) + add_subdirectory(bttestui) + endif() + + add_subdirectory(bluetoothtestdevice) +endif() + +qt_build_tests() diff --git a/tests/auto/CMakeLists.txt b/tests/auto/CMakeLists.txt new file mode 100644 index 0000000..3b32a86 --- /dev/null +++ b/tests/auto/CMakeLists.txt @@ -0,0 +1,32 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +if(TARGET Qt::Bluetooth) + add_subdirectory(qbluetoothaddress) + add_subdirectory(qbluetoothdevicediscoveryagent) + add_subdirectory(qbluetoothdeviceinfo) + add_subdirectory(qbluetoothlocaldevice) + add_subdirectory(qbluetoothhostinfo) + add_subdirectory(qbluetoothservicediscoveryagent) + add_subdirectory(qbluetoothserviceinfo) + add_subdirectory(qbluetoothsocket) + add_subdirectory(qbluetoothuuid) + add_subdirectory(qbluetoothserver) + add_subdirectory(qlowenergycharacteristic) + add_subdirectory(qlowenergydescriptor) + add_subdirectory(qlowenergycontroller) + add_subdirectory(qlowenergycontroller-gattserver) + add_subdirectory(qlowenergyservice) +endif() +if(TARGET Qt::Nfc) + add_subdirectory(qndefmessage) + add_subdirectory(qndefrecord) + add_subdirectory(qnearfieldmanager) + add_subdirectory(qnearfieldtagtype1) + add_subdirectory(qnearfieldtagtype2) + add_subdirectory(qndefnfcsmartposterrecord) + add_subdirectory(qndeffilter) +endif() +if(TARGET Qt::Bluetooth AND TARGET Qt::Nfc) + add_subdirectory(cmake) +endif() diff --git a/tests/auto/bic/data/QtBluetooth.5.10.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtBluetooth.5.10.0.linux-gcc-amd64.txt new file mode 100644 index 0000000..d8b4312 --- /dev/null +++ b/tests/auto/bic/data/QtBluetooth.5.10.0.linux-gcc-amd64.txt @@ -0,0 +1,4988 @@ +Class std::__failure_type + size=1 align=1 + base size=0 base align=1 +std::__failure_type (0x0x7f0c00290240) 0 empty + +Class std::__do_is_destructible_impl + size=1 align=1 + base size=0 base align=1 +std::__do_is_destructible_impl (0x0x7f0c002d89c0) 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 (0x0x7f0c002d8c00) 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 (0x0x7f0c002d8e40) 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 (0x0x7f0bfdf050c0) 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 (0x0x7f0bfdf05240) 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 (0x0x7f0bfdf05600) 0 empty + +Class std::__do_common_type_impl + size=1 align=1 + base size=0 base align=1 +std::__do_common_type_impl (0x0x7f0bfdf8fd80) 0 empty + +Class std::__do_member_type_wrapper + size=1 align=1 + base size=0 base align=1 +std::__do_member_type_wrapper (0x0x7f0bfdf8fe40) 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 (0x0x7f0bfdfc31e0) 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 (0x0x7f0bfdfc32a0) 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 (0x0x7f0bfdfc3360) 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 (0x0x7f0bfdfc3420) 0 empty + +Class std::__result_of_other_impl + size=1 align=1 + base size=0 base align=1 +std::__result_of_other_impl (0x0x7f0bfdfc36c0) 0 empty + +Class std::piecewise_construct_t + size=1 align=1 + base size=0 base align=1 +std::piecewise_construct_t (0x0x7f0bfdfc38a0) 0 empty + +Class std::__true_type + size=1 align=1 + base size=0 base align=1 +std::__true_type (0x0x7f0bfdfc3d20) 0 empty + +Class std::__false_type + size=1 align=1 + base size=0 base align=1 +std::__false_type (0x0x7f0bfdfc3d80) 0 empty + +Class std::input_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::input_iterator_tag (0x0x7f0bfe076a20) 0 empty + +Class std::output_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::output_iterator_tag (0x0x7f0bfe076a80) 0 empty + +Class std::forward_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::forward_iterator_tag (0x0x7f0bfdf67af8) 0 empty + std::input_iterator_tag (0x0x7f0bfe076ae0) 0 empty + +Class std::bidirectional_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::bidirectional_iterator_tag (0x0x7f0bfdf67b60) 0 empty + std::forward_iterator_tag (0x0x7f0bfdf67bc8) 0 empty + std::input_iterator_tag (0x0x7f0bfe076b40) 0 empty + +Class std::random_access_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::random_access_iterator_tag (0x0x7f0bfdf67c30) 0 empty + std::bidirectional_iterator_tag (0x0x7f0bfdf67c98) 0 empty + std::forward_iterator_tag (0x0x7f0bfdf67d00) 0 empty + std::input_iterator_tag (0x0x7f0bfe076ba0) 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 (0x0x7f0bfe0b4840) 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 (0x0x7f0bfe0b48a0) 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 (0x0x7f0bfe0b4900) 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 (0x0x7f0bfe0b4960) 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 (0x0x7f0bfe0b49c0) 0 empty + +Class wait + size=4 align=4 + base size=4 base align=4 +wait (0x0x7f0bfdd914e0) 0 + +Class __locale_struct + size=232 align=8 + base size=232 base align=8 +__locale_struct (0x0x7f0bfdd91720) 0 + +Class timespec + size=16 align=8 + base size=16 base align=8 +timespec (0x0x7f0bfdd917e0) 0 + +Class timeval + size=16 align=8 + base size=16 base align=8 +timeval (0x0x7f0bfdd91840) 0 + +Class pthread_attr_t + size=56 align=8 + base size=56 base align=8 +pthread_attr_t (0x0x7f0bfdd91900) 0 + +Class __pthread_internal_list + size=16 align=8 + base size=16 base align=8 +__pthread_internal_list (0x0x7f0bfdd91960) 0 + +Class random_data + size=48 align=8 + base size=48 base align=8 +random_data (0x0x7f0bfdd91de0) 0 + +Class drand48_data + size=24 align=8 + base size=24 base align=8 +drand48_data (0x0x7f0bfdd91e40) 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 (0x0x7f0bfdd91ea0) 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 (0x0x7f0bfe0ce270) 0 nearly-empty + vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16u) + std::exception (0x0x7f0bfdd91f00) 0 nearly-empty + primary-for std::bad_exception (0x0x7f0bfe0ce270) + +Class std::__exception_ptr::exception_ptr + size=8 align=8 + base size=8 base align=8 +std::__exception_ptr::exception_ptr (0x0x7f0bfdd91f60) 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 (0x0x7f0bfdee8000) 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 (0x0x7f0bfe0ce478) 0 nearly-empty + vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16u) + std::exception (0x0x7f0bfdee8420) 0 nearly-empty + primary-for std::bad_alloc (0x0x7f0bfe0ce478) + +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 (0x0x7f0bfe0ce4e0) 0 nearly-empty + vptr=((& std::bad_array_new_length::_ZTVSt20bad_array_new_length) + 16u) + std::bad_alloc (0x0x7f0bfe0ce548) 0 nearly-empty + primary-for std::bad_array_new_length (0x0x7f0bfe0ce4e0) + std::exception (0x0x7f0bfdee8480) 0 nearly-empty + primary-for std::bad_alloc (0x0x7f0bfe0ce548) + +Class std::nothrow_t + size=1 align=1 + base size=0 base align=1 +std::nothrow_t (0x0x7f0bfdee84e0) 0 empty + +Class __exception + size=40 align=8 + base size=40 base align=8 +__exception (0x0x7f0bfdba3120) 0 + +Class lconv + size=96 align=8 + base size=96 base align=8 +lconv (0x0x7f0bfdba3de0) 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 (0x0x7f0bfdba3e40) 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 (0x0x7f0bfd9e7d20) 0 + +Class __sched_param + size=4 align=4 + base size=4 base align=4 +__sched_param (0x0x7f0bfd9e7d80) 0 + +Class timex + size=208 align=8 + base size=208 base align=8 +timex (0x0x7f0bfd9e7e40) 0 + +Class tm + size=56 align=8 + base size=56 base align=8 +tm (0x0x7f0bfd9e7ea0) 0 + +Class itimerspec + size=32 align=8 + base size=32 base align=8 +itimerspec (0x0x7f0bfd9e7f00) 0 + +Class _pthread_cleanup_buffer + size=32 align=8 + base size=32 base align=8 +_pthread_cleanup_buffer (0x0x7f0bfd9e7f60) 0 + +Class __pthread_cleanup_frame + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_frame (0x0x7f0bfda930c0) 0 + +Class __pthread_cleanup_class + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_class (0x0x7f0bfda93120) 0 + +Class _IO_marker + size=24 align=8 + base size=24 base align=8 +_IO_marker (0x0x7f0bfda93540) 0 + +Class _IO_FILE + size=216 align=8 + base size=216 base align=8 +_IO_FILE (0x0x7f0bfda935a0) 0 + +Class std::_Hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Hash_impl (0x0x7f0bfd8b7d80) 0 empty + +Class std::_Fnv_hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Fnv_hash_impl (0x0x7f0bfd8b7de0) 0 empty + +Class std::__numeric_limits_base + size=1 align=1 + base size=0 base align=1 +std::__numeric_limits_base (0x0x7f0bfd579d80) 0 empty + +Class std::_Bit_reference + size=16 align=8 + base size=16 base align=8 +std::_Bit_reference (0x0x7f0bfd320ba0) 0 + +Class std::_Bit_iterator_base + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator_base (0x0x7f0bfd318138) 0 + std::iterator (0x0x7f0bfd320c60) 0 empty + +Class std::_Bit_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator (0x0x7f0bfd3181a0) 0 + std::_Bit_iterator_base (0x0x7f0bfd318208) 0 + std::iterator (0x0x7f0bfd320cc0) 0 empty + +Class std::_Bit_const_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_const_iterator (0x0x7f0bfd318270) 0 + std::_Bit_iterator_base (0x0x7f0bfd3182d8) 0 + std::iterator (0x0x7f0bfd320d20) 0 empty + +Class std::random_device + size=5000 align=8 + base size=5000 base align=8 +std::random_device (0x0x7f0bfd106b40) 0 + +Class std::bernoulli_distribution::param_type + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution::param_type (0x0x7f0bfd235900) 0 + +Class std::bernoulli_distribution + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution (0x0x7f0bfd2358a0) 0 + +Class std::seed_seq + size=24 align=8 + base size=24 base align=8 +std::seed_seq (0x0x7f0bfcfd48a0) 0 + +Class qIsNull(double)::U + size=8 align=8 + base size=8 base align=8 +qIsNull(double)::U (0x0x7f0bfbb913c0) 0 + +Class qIsNull(float)::U + size=4 align=4 + base size=4 base align=4 +qIsNull(float)::U (0x0x7f0bfbb91420) 0 + +Class QSysInfo + size=1 align=1 + base size=0 base align=1 +QSysInfo (0x0x7f0bfbc36ea0) 0 empty + +Class QMessageLogContext + size=32 align=8 + base size=32 base align=8 +QMessageLogContext (0x0x7f0bfbc36f00) 0 + +Class QMessageLogger + size=32 align=8 + base size=32 base align=8 +QMessageLogger (0x0x7f0bfbc36f60) 0 + +Class QFlag + size=4 align=4 + base size=4 base align=4 +QFlag (0x0x7f0bfbc94000) 0 + +Class QIncompatibleFlag + size=4 align=4 + base size=4 base align=4 +QIncompatibleFlag (0x0x7f0bfbc942a0) 0 + +Class std::__atomic_flag_base + size=1 align=1 + base size=1 base align=1 +std::__atomic_flag_base (0x0x7f0bfbc947e0) 0 + +Class std::atomic_flag + size=1 align=1 + base size=1 base align=1 +std::atomic_flag (0x0x7f0bfbcaf1a0) 0 + std::__atomic_flag_base (0x0x7f0bfbc94840) 0 + +Class QAtomicInt + size=4 align=4 + base size=4 base align=4 +QAtomicInt (0x0x7f0bfbcaf8f0) 0 + QAtomicInteger (0x0x7f0bfbcaf958) 0 + QBasicAtomicInteger (0x0x7f0bfba1ef60) 0 + +Class QInternal + size=1 align=1 + base size=0 base align=1 +QInternal (0x0x7f0bfb2fd540) 0 empty + +Class QtPrivate::QSlotObjectBase + size=16 align=8 + base size=16 base align=8 +QtPrivate::QSlotObjectBase (0x0x7f0bfb0f15a0) 0 + +Class QGenericArgument + size=16 align=8 + base size=16 base align=8 +QGenericArgument (0x0x7f0bfb0f16c0) 0 + +Class QGenericReturnArgument + size=16 align=8 + base size=16 base align=8 +QGenericReturnArgument (0x0x7f0bfb0ee3a8) 0 + QGenericArgument (0x0x7f0bfb0f1720) 0 + +Class QMetaObject + size=48 align=8 + base size=48 base align=8 +QMetaObject (0x0x7f0bfb0f18a0) 0 + +Class QMetaObject::Connection + size=8 align=8 + base size=8 base align=8 +QMetaObject::Connection (0x0x7f0bfb0f1960) 0 + +Class QLatin1Char + size=1 align=1 + base size=1 base align=1 +QLatin1Char (0x0x7f0bfb1da9c0) 0 + +Class QChar + size=2 align=2 + base size=2 base align=2 +QChar (0x0x7f0bfb1daa20) 0 + +Class QtPrivate::RefCount + size=4 align=4 + base size=4 base align=4 +QtPrivate::RefCount (0x0x7f0bfb1dacc0) 0 + +Class QArrayData + size=24 align=8 + base size=24 base align=8 +QArrayData (0x0x7f0bfb1dad20) 0 + +Class QtPrivate::QContainerImplHelper + size=1 align=1 + base size=0 base align=1 +QtPrivate::QContainerImplHelper (0x0x7f0bfaefe0c0) 0 empty + +Class std::locale + size=8 align=8 + base size=8 base align=8 +std::locale (0x0x7f0bfaefe120) 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 (0x0x7f0bfaefe180) 0 + vptr=((& std::locale::facet::_ZTVNSt6locale5facetE) + 16u) + +Class std::locale::id + size=8 align=8 + base size=8 base align=8 +std::locale::id (0x0x7f0bfaefe1e0) 0 + +Class std::locale::_Impl + size=40 align=8 + base size=40 base align=8 +std::locale::_Impl (0x0x7f0bfaefe240) 0 + +Class std::__cow_string + size=8 align=8 + base size=8 base align=8 +std::__cow_string (0x0x7f0bfaefe600) 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 (0x0x7f0bfaef19c0) 0 + vptr=((& std::logic_error::_ZTVSt11logic_error) + 16u) + std::exception (0x0x7f0bfaefe6c0) 0 nearly-empty + primary-for std::logic_error (0x0x7f0bfaef19c0) + +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 (0x0x7f0bfaef1a28) 0 + vptr=((& std::domain_error::_ZTVSt12domain_error) + 16u) + std::logic_error (0x0x7f0bfaef1a90) 0 + primary-for std::domain_error (0x0x7f0bfaef1a28) + std::exception (0x0x7f0bfaefe720) 0 nearly-empty + primary-for std::logic_error (0x0x7f0bfaef1a90) + +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 (0x0x7f0bfaef1af8) 0 + vptr=((& std::invalid_argument::_ZTVSt16invalid_argument) + 16u) + std::logic_error (0x0x7f0bfaef1b60) 0 + primary-for std::invalid_argument (0x0x7f0bfaef1af8) + std::exception (0x0x7f0bfaefe780) 0 nearly-empty + primary-for std::logic_error (0x0x7f0bfaef1b60) + +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 (0x0x7f0bfaef1bc8) 0 + vptr=((& std::length_error::_ZTVSt12length_error) + 16u) + std::logic_error (0x0x7f0bfaef1c30) 0 + primary-for std::length_error (0x0x7f0bfaef1bc8) + std::exception (0x0x7f0bfaefe7e0) 0 nearly-empty + primary-for std::logic_error (0x0x7f0bfaef1c30) + +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 (0x0x7f0bfaef1c98) 0 + vptr=((& std::out_of_range::_ZTVSt12out_of_range) + 16u) + std::logic_error (0x0x7f0bfaef1d00) 0 + primary-for std::out_of_range (0x0x7f0bfaef1c98) + std::exception (0x0x7f0bfaefe840) 0 nearly-empty + primary-for std::logic_error (0x0x7f0bfaef1d00) + +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 (0x0x7f0bfaef1d68) 0 + vptr=((& std::runtime_error::_ZTVSt13runtime_error) + 16u) + std::exception (0x0x7f0bfaefe8a0) 0 nearly-empty + primary-for std::runtime_error (0x0x7f0bfaef1d68) + +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 (0x0x7f0bfaef1dd0) 0 + vptr=((& std::range_error::_ZTVSt11range_error) + 16u) + std::runtime_error (0x0x7f0bfaef1e38) 0 + primary-for std::range_error (0x0x7f0bfaef1dd0) + std::exception (0x0x7f0bfaefe900) 0 nearly-empty + primary-for std::runtime_error (0x0x7f0bfaef1e38) + +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 (0x0x7f0bfaef1ea0) 0 + vptr=((& std::overflow_error::_ZTVSt14overflow_error) + 16u) + std::runtime_error (0x0x7f0bfaef1f08) 0 + primary-for std::overflow_error (0x0x7f0bfaef1ea0) + std::exception (0x0x7f0bfaefe960) 0 nearly-empty + primary-for std::runtime_error (0x0x7f0bfaef1f08) + +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 (0x0x7f0bfaef1f70) 0 + vptr=((& std::underflow_error::_ZTVSt15underflow_error) + 16u) + std::runtime_error (0x0x7f0bfaef16e8) 0 + primary-for std::underflow_error (0x0x7f0bfaef1f70) + std::exception (0x0x7f0bfaefe9c0) 0 nearly-empty + primary-for std::runtime_error (0x0x7f0bfaef16e8) + +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 (0x0x7f0bfaefeb40) 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 (0x0x7f0bfaefed80) 0 + +Class std::error_condition + size=16 align=8 + base size=16 base align=8 +std::error_condition (0x0x7f0bfaefef00) 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 (0x0x7f0bfafb3410) 0 + vptr=((& std::system_error::_ZTVSt12system_error) + 16u) + std::runtime_error (0x0x7f0bfafb3478) 0 + primary-for std::system_error (0x0x7f0bfafb3410) + std::exception (0x0x7f0bfaff0180) 0 nearly-empty + primary-for std::runtime_error (0x0x7f0bfafb3478) + +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 (0x0x7f0bfb03f068) 0 + vptr=((& std::ios_base::failure::_ZTVNSt8ios_base7failureB5cxx11E) + 16u) + std::system_error (0x0x7f0bfb03f0d0) 0 + primary-for std::ios_base::failure (0x0x7f0bfb03f068) + std::runtime_error (0x0x7f0bfb03f138) 0 + primary-for std::system_error (0x0x7f0bfb03f0d0) + std::exception (0x0x7f0bfaff0480) 0 nearly-empty + primary-for std::runtime_error (0x0x7f0bfb03f138) + +Class std::ios_base::_Callback_list + size=24 align=8 + base size=24 base align=8 +std::ios_base::_Callback_list (0x0x7f0bfaff04e0) 0 + +Class std::ios_base::_Words + size=16 align=8 + base size=16 base align=8 +std::ios_base::_Words (0x0x7f0bfaff0540) 0 + +Class std::ios_base::Init + size=1 align=1 + base size=0 base align=1 +std::ios_base::Init (0x0x7f0bfaff05a0) 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 (0x0x7f0bfaff0420) 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 (0x0x7f0bfaff0d20) 0 empty + +Class std::__num_base + size=1 align=1 + base size=0 base align=1 +std::__num_base (0x0x7f0bfad6f420) 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 (0x0x7f0bfac91b60 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 (0x0x7f0bfac91c30 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 (0x0x7f0bfac910d0 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 (0x0x7f0bfac91208 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 (0x0x7f0bfab04c60) 0 + +Class QByteArray + size=8 align=8 + base size=8 base align=8 +QByteArray (0x0x7f0bfab04cc0) 0 + +Class QByteRef + size=16 align=8 + base size=12 base align=8 +QByteRef (0x0x7f0bfaa62060) 0 + +Class QStringDataPtr + size=8 align=8 + base size=8 base align=8 +QStringDataPtr (0x0x7f0bfaa623c0) 0 + +Class QStringView + size=16 align=8 + base size=16 base align=8 +QStringView (0x0x7f0bfaa62840) 0 + +Class QLatin1String + size=16 align=8 + base size=16 base align=8 +QLatin1String (0x0x7f0bfa7626c0) 0 + +Class QString::Null + size=1 align=1 + base size=0 base align=1 +QString::Null (0x0x7f0bfa762d20) 0 empty + +Class QString + size=8 align=8 + base size=8 base align=8 +QString (0x0x7f0bfa762cc0) 0 + +Class QCharRef + size=16 align=8 + base size=12 base align=8 +QCharRef (0x0x7f0bfa565de0) 0 + +Class QStringRef + size=16 align=8 + base size=16 base align=8 +QStringRef (0x0x7f0bfa66fa20) 0 + +Class QtPrivate::QHashCombine + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombine (0x0x7f0bfa3a3660) 0 empty + +Class QtPrivate::QHashCombineCommutative + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombineCommutative (0x0x7f0bfa3a36c0) 0 empty + +Class std::__detail::_List_node_base + size=16 align=8 + base size=16 base align=8 +std::__detail::_List_node_base (0x0x7f0bfa3a3720) 0 + +Class QListData::NotArrayCompatibleLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotArrayCompatibleLayout (0x0x7f0bfa3a3ae0) 0 empty + +Class QListData::NotIndirectLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotIndirectLayout (0x0x7f0bfa3a3b40) 0 empty + +Class QListData::ArrayCompatibleLayout + size=1 align=1 + base size=1 base align=1 +QListData::ArrayCompatibleLayout (0x0x7f0bfa38c958) 0 empty + QListData::NotIndirectLayout (0x0x7f0bfa3a3ba0) 0 empty + +Class QListData::InlineWithPaddingLayout + size=1 align=1 + base size=1 base align=1 +QListData::InlineWithPaddingLayout (0x0x7f0bfa1b88c0) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7f0bfa3a3c00) 0 empty + QListData::NotIndirectLayout (0x0x7f0bfa3a3c60) 0 empty + +Class QListData::IndirectLayout + size=1 align=1 + base size=1 base align=1 +QListData::IndirectLayout (0x0x7f0bfa38c9c0) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7f0bfa3a3cc0) 0 empty + +Class QListData::Data + size=24 align=8 + base size=24 base align=8 +QListData::Data (0x0x7f0bfa3a3d20) 0 + +Class QListData + size=8 align=8 + base size=8 base align=8 +QListData (0x0x7f0bfa3a3a80) 0 + +Class QRegExp + size=8 align=8 + base size=8 base align=8 +QRegExp (0x0x7f0bfa29b1e0) 0 + +Class QStringMatcher::Data + size=272 align=8 + base size=272 base align=8 +QStringMatcher::Data (0x0x7f0bf9f6f420) 0 + +Class QStringMatcher + size=1048 align=8 + base size=1048 base align=8 +QStringMatcher (0x0x7f0bf9f6f3c0) 0 + +Class QStringList + size=8 align=8 + base size=8 base align=8 +QStringList (0x0x7f0bf9f70410) 0 + QList (0x0x7f0bf9f70478) 0 + QListSpecialMethods (0x0x7f0bf9f6f600) 0 empty + +Class QScopedPointerPodDeleter + size=1 align=1 + base size=0 base align=1 +QScopedPointerPodDeleter (0x0x7f0bf9f6fa20) 0 empty + +Class std::_Rb_tree_node_base + size=32 align=8 + base size=32 base align=8 +std::_Rb_tree_node_base (0x0x7f0bfa06e540) 0 + +Class std::allocator_arg_t + size=1 align=1 + base size=0 base align=1 +std::allocator_arg_t (0x0x7f0bfa06eba0) 0 empty + +Class std::__uses_alloc_base + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc_base (0x0x7f0bfa06ed20) 0 empty + +Class std::__uses_alloc0::_Sink + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc0::_Sink (0x0x7f0bfa06ede0) 0 empty + +Class std::__uses_alloc0 + size=1 align=1 + base size=1 base align=1 +std::__uses_alloc0 (0x0x7f0bf9f70d68) 0 + std::__uses_alloc_base (0x0x7f0bfa06ed80) 0 empty + +Class std::_Swallow_assign + size=1 align=1 + base size=0 base align=1 +std::_Swallow_assign (0x0x7f0bf9e21e40) 0 empty + +Class QtPrivate::AbstractDebugStreamFunction + size=16 align=8 + base size=16 base align=8 +QtPrivate::AbstractDebugStreamFunction (0x0x7f0bf9b6c0c0) 0 + +Class QtPrivate::AbstractComparatorFunction + size=24 align=8 + base size=24 base align=8 +QtPrivate::AbstractComparatorFunction (0x0x7f0bf9b6c180) 0 + +Class QtPrivate::AbstractConverterFunction + size=8 align=8 + base size=8 base align=8 +QtPrivate::AbstractConverterFunction (0x0x7f0bf9b6c2a0) 0 + +Class QMetaType + size=80 align=8 + base size=80 base align=8 +QMetaType (0x0x7f0bf9b6c420) 0 + +Class QtMetaTypePrivate::VariantData + size=24 align=8 + base size=20 base align=8 +QtMetaTypePrivate::VariantData (0x0x7f0bf9b6c840) 0 + +Class QtMetaTypePrivate::VectorBoolElements + size=1 align=1 + base size=0 base align=1 +QtMetaTypePrivate::VectorBoolElements (0x0x7f0bf9b6c960) 0 empty + +Class QtMetaTypePrivate::QSequentialIterableImpl + size=104 align=8 + base size=104 base align=8 +QtMetaTypePrivate::QSequentialIterableImpl (0x0x7f0bf9cda300) 0 + +Class QtMetaTypePrivate::QAssociativeIterableImpl + size=112 align=8 + base size=112 base align=8 +QtMetaTypePrivate::QAssociativeIterableImpl (0x0x7f0bf9cda720) 0 + +Class QtMetaTypePrivate::QPairVariantInterfaceImpl + size=40 align=8 + base size=40 base align=8 +QtMetaTypePrivate::QPairVariantInterfaceImpl (0x0x7f0bf9cdaa20) 0 + +Class std::chrono::_V2::system_clock + size=1 align=1 + base size=0 base align=1 +std::chrono::_V2::system_clock (0x0x7f0bf976a2a0) 0 empty + +Class std::chrono::_V2::steady_clock + size=1 align=1 + base size=0 base align=1 +std::chrono::_V2::steady_clock (0x0x7f0bf98b3120) 0 empty + +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 (0x0x7f0bf98b3180) 0 + vptr=((& QObjectData::_ZTV11QObjectData) + 16u) + +Class QObject::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObject::QPrivateSignal (0x0x7f0bf98b3360) 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 (0x0x7f0bf98b3300) 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 (0x0x7f0bf9590600) 0 nearly-empty + vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16u) + +Class QSignalBlocker + size=16 align=8 + base size=10 base align=8 +QSignalBlocker (0x0x7f0bf9590660) 0 + +Class QAbstractAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractAnimation::QPrivateSignal (0x0x7f0bf9590720) 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 (0x0x7f0bf9548680) 0 + vptr=((& QAbstractAnimation::_ZTV18QAbstractAnimation) + 16u) + QObject (0x0x7f0bf95906c0) 0 + primary-for QAbstractAnimation (0x0x7f0bf9548680) + +Class QAnimationDriver::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationDriver::QPrivateSignal (0x0x7f0bf95907e0) 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 (0x0x7f0bf95d2000) 0 + vptr=((& QAnimationDriver::_ZTV16QAnimationDriver) + 16u) + QObject (0x0x7f0bf9590780) 0 + primary-for QAnimationDriver (0x0x7f0bf95d2000) + +Class QEventLoop::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventLoop::QPrivateSignal (0x0x7f0bf95908a0) 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 (0x0x7f0bf95d2068) 0 + vptr=((& QEventLoop::_ZTV10QEventLoop) + 16u) + QObject (0x0x7f0bf9590840) 0 + primary-for QEventLoop (0x0x7f0bf95d2068) + +Class QEventLoopLocker + size=8 align=8 + base size=8 base align=8 +QEventLoopLocker (0x0x7f0bf9590a80) 0 + +Class QAbstractEventDispatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractEventDispatcher::QPrivateSignal (0x0x7f0bf9590b40) 0 empty + +Class QAbstractEventDispatcher::TimerInfo + size=12 align=4 + base size=12 base align=4 +QAbstractEventDispatcher::TimerInfo (0x0x7f0bf9590ba0) 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 (0x0x7f0bf95d21a0) 0 + vptr=((& QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher) + 16u) + QObject (0x0x7f0bf9590ae0) 0 + primary-for QAbstractEventDispatcher (0x0x7f0bf95d21a0) + +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 (0x0x7f0bf9590e40) 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 (0x0x7f0bf95d23a8) 0 nearly-empty + vptr=((& std::bad_cast::_ZTVSt8bad_cast) + 16u) + std::exception (0x0x7f0bf9590ea0) 0 nearly-empty + primary-for std::bad_cast (0x0x7f0bf95d23a8) + +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 (0x0x7f0bf95d2410) 0 nearly-empty + vptr=((& std::bad_typeid::_ZTVSt10bad_typeid) + 16u) + std::exception (0x0x7f0bf9590f00) 0 nearly-empty + primary-for std::bad_typeid (0x0x7f0bf95d2410) + +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 (0x0x7f0bf9351680) 0 nearly-empty + vptr=((& std::bad_function_call::_ZTVSt17bad_function_call) + 16u) + std::exception (0x0x7f0bf93da000) 0 nearly-empty + primary-for std::bad_function_call (0x0x7f0bf9351680) + +Class std::_Nocopy_types + size=16 align=8 + base size=16 base align=8 +std::_Nocopy_types (0x0x7f0bf93da0c0) 0 + +Class std::_Any_data + size=16 align=8 + base size=16 base align=8 +std::_Any_data (0x0x7f0bf93da120) 0 + +Class std::_Function_base + size=24 align=8 + base size=24 base align=8 +std::_Function_base (0x0x7f0bf93da240) 0 + +Class QMapNodeBase + size=24 align=8 + base size=24 base align=8 +QMapNodeBase (0x0x7f0bf93da720) 0 + +Class QMapDataBase + size=40 align=8 + base size=40 base align=8 +QMapDataBase (0x0x7f0bf93dac60) 0 + +Class QHashData::Node + size=16 align=8 + base size=16 base align=8 +QHashData::Node (0x0x7f0bf9175060) 0 + +Class QHashData + size=48 align=8 + base size=44 base align=8 +QHashData (0x0x7f0bf9175000) 0 + +Class QHashDummyValue + size=1 align=1 + base size=0 base align=1 +QHashDummyValue (0x0x7f0bf91750c0) 0 empty + +Class QVariant::PrivateShared + size=16 align=8 + base size=12 base align=8 +QVariant::PrivateShared (0x0x7f0bf9175960) 0 + +Class QVariant::Private::Data + size=8 align=8 + base size=8 base align=8 +QVariant::Private::Data (0x0x7f0bf9175a20) 0 + +Class QVariant::Private + size=16 align=8 + base size=12 base align=8 +QVariant::Private (0x0x7f0bf91759c0) 0 + +Class QVariant::Handler + size=72 align=8 + base size=72 base align=8 +QVariant::Handler (0x0x7f0bf9175a80) 0 + +Class QVariant + size=16 align=8 + base size=16 base align=8 +QVariant (0x0x7f0bf9175900) 0 + +Class QVariantComparisonHelper + size=8 align=8 + base size=8 base align=8 +QVariantComparisonHelper (0x0x7f0bf8fca5a0) 0 + +Class QSequentialIterable::const_iterator + size=112 align=8 + base size=112 base align=8 +QSequentialIterable::const_iterator (0x0x7f0bf8fcac00) 0 + +Class QSequentialIterable + size=104 align=8 + base size=104 base align=8 +QSequentialIterable (0x0x7f0bf8fcaba0) 0 + +Class QAssociativeIterable::const_iterator + size=120 align=8 + base size=120 base align=8 +QAssociativeIterable::const_iterator (0x0x7f0bf8fcacc0) 0 + +Class QAssociativeIterable + size=112 align=8 + base size=112 base align=8 +QAssociativeIterable (0x0x7f0bf8fcac60) 0 + +Class QModelIndex + size=24 align=8 + base size=24 base align=8 +QModelIndex (0x0x7f0bf8e17000) 0 + +Class QPersistentModelIndex + size=8 align=8 + base size=8 base align=8 +QPersistentModelIndex (0x0x7f0bf8e176c0) 0 + +Class QAbstractItemModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractItemModel::QPrivateSignal (0x0x7f0bf8ac2de0) 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 (0x0x7f0bf8ade410) 0 + vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16u) + QObject (0x0x7f0bf8ac2d80) 0 + primary-for QAbstractItemModel (0x0x7f0bf8ade410) + +Class QAbstractTableModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTableModel::QPrivateSignal (0x0x7f0bf8b4d180) 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 (0x0x7f0bf8ade618) 0 + vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16u) + QAbstractItemModel (0x0x7f0bf8ade680) 0 + primary-for QAbstractTableModel (0x0x7f0bf8ade618) + QObject (0x0x7f0bf8b4d120) 0 + primary-for QAbstractItemModel (0x0x7f0bf8ade680) + +Class QAbstractListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractListModel::QPrivateSignal (0x0x7f0bf8b4d240) 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 (0x0x7f0bf8ade6e8) 0 + vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16u) + QAbstractItemModel (0x0x7f0bf8ade750) 0 + primary-for QAbstractListModel (0x0x7f0bf8ade6e8) + QObject (0x0x7f0bf8b4d1e0) 0 + primary-for QAbstractItemModel (0x0x7f0bf8ade750) + +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 (0x0x7f0bf8b4d4e0) 0 + vptr=((& QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter) + 16u) + +Class QAbstractProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractProxyModel::QPrivateSignal (0x0x7f0bf8b4d5a0) 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 (0x0x7f0bf8ade888) 0 + vptr=((& QAbstractProxyModel::_ZTV19QAbstractProxyModel) + 16u) + QAbstractItemModel (0x0x7f0bf8ade8f0) 0 + primary-for QAbstractProxyModel (0x0x7f0bf8ade888) + QObject (0x0x7f0bf8b4d540) 0 + primary-for QAbstractItemModel (0x0x7f0bf8ade8f0) + +Class QAbstractState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractState::QPrivateSignal (0x0x7f0bf8b4d660) 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 (0x0x7f0bf8ade958) 0 + vptr=((& QAbstractState::_ZTV14QAbstractState) + 16u) + QObject (0x0x7f0bf8b4d600) 0 + primary-for QAbstractState (0x0x7f0bf8ade958) + +Class QAbstractTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTransition::QPrivateSignal (0x0x7f0bf8b4d720) 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 (0x0x7f0bf8ade9c0) 0 + vptr=((& QAbstractTransition::_ZTV19QAbstractTransition) + 16u) + QObject (0x0x7f0bf8b4d6c0) 0 + primary-for QAbstractTransition (0x0x7f0bf8ade9c0) + +Class QAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationGroup::QPrivateSignal (0x0x7f0bf8b4d7e0) 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 (0x0x7f0bf8adea28) 0 + vptr=((& QAnimationGroup::_ZTV15QAnimationGroup) + 16u) + QAbstractAnimation (0x0x7f0bf8adea90) 0 + primary-for QAnimationGroup (0x0x7f0bf8adea28) + QObject (0x0x7f0bf8b4d780) 0 + primary-for QAbstractAnimation (0x0x7f0bf8adea90) + +Class QBasicTimer + size=4 align=4 + base size=4 base align=4 +QBasicTimer (0x0x7f0bf8c5f540) 0 + +Class QBitArray + size=8 align=8 + base size=8 base align=8 +QBitArray (0x0x7f0bf8c5f7e0) 0 + +Class QBitRef + size=16 align=8 + base size=12 base align=8 +QBitRef (0x0x7f0bf8c5f8a0) 0 + +Class QIODevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIODevice::QPrivateSignal (0x0x7f0bf8c5fba0) 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 (0x0x7f0bf88e6138) 0 + vptr=((& QIODevice::_ZTV9QIODevice) + 16u) + QObject (0x0x7f0bf8c5fb40) 0 + primary-for QIODevice (0x0x7f0bf88e6138) + +Class QBuffer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBuffer::QPrivateSignal (0x0x7f0bf8c5fde0) 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 (0x0x7f0bf88e6270) 0 + vptr=((& QBuffer::_ZTV7QBuffer) + 16u) + QIODevice (0x0x7f0bf88e62d8) 0 + primary-for QBuffer (0x0x7f0bf88e6270) + QObject (0x0x7f0bf8c5fd80) 0 + primary-for QIODevice (0x0x7f0bf88e62d8) + +Class QByteArrayMatcher::Data + size=272 align=8 + base size=272 base align=8 +QByteArrayMatcher::Data (0x0x7f0bf8c5fea0) 0 + +Class QByteArrayMatcher + size=1040 align=8 + base size=1040 base align=8 +QByteArrayMatcher (0x0x7f0bf8c5fe40) 0 + +Class QStaticByteArrayMatcherBase::Skiptable + size=256 align=1 + base size=256 base align=1 +QStaticByteArrayMatcherBase::Skiptable (0x0x7f0bf8957000) 0 + +Class QStaticByteArrayMatcherBase + size=256 align=16 + base size=256 base align=16 +QStaticByteArrayMatcherBase (0x0x7f0bf8c5ff60) 0 + +Class QSharedData + size=4 align=4 + base size=4 base align=4 +QSharedData (0x0x7f0bf89571e0) 0 + +Class QLocale + size=8 align=8 + base size=8 base align=8 +QLocale (0x0x7f0bf89573c0) 0 + +Class QCollatorSortKey + size=8 align=8 + base size=8 base align=8 +QCollatorSortKey (0x0x7f0bf89579c0) 0 + +Class QCollator + size=8 align=8 + base size=8 base align=8 +QCollator (0x0x7f0bf8957a80) 0 + +Class QCommandLineOption + size=8 align=8 + base size=8 base align=8 +QCommandLineOption (0x0x7f0bf86eaa80) 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 (0x0x7f0bf86eaf00) 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 (0x0x7f0bf86f47b8) 0 + vptr=((& QTimerEvent::_ZTV11QTimerEvent) + 16u) + QEvent (0x0x7f0bf86eaf60) 0 + primary-for QTimerEvent (0x0x7f0bf86f47b8) + +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 (0x0x7f0bf86f4820) 0 + vptr=((& QChildEvent::_ZTV11QChildEvent) + 16u) + QEvent (0x0x7f0bf8769000) 0 + primary-for QChildEvent (0x0x7f0bf86f4820) + +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 (0x0x7f0bf86f4d68) 0 + vptr=((& QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent) + 16u) + QEvent (0x0x7f0bf87694e0) 0 + primary-for QDynamicPropertyChangeEvent (0x0x7f0bf86f4d68) + +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 (0x0x7f0bf86f4dd0) 0 + vptr=((& QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent) + 16u) + QEvent (0x0x7f0bf8769540) 0 + primary-for QDeferredDeleteEvent (0x0x7f0bf86f4dd0) + +Class QCoreApplication::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QCoreApplication::QPrivateSignal (0x0x7f0bf8769600) 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 (0x0x7f0bf86f4e38) 0 + vptr=((& QCoreApplication::_ZTV16QCoreApplication) + 16u) + QObject (0x0x7f0bf87695a0) 0 + primary-for QCoreApplication (0x0x7f0bf86f4e38) + +Class QCommandLineParser + size=8 align=8 + base size=8 base align=8 +QCommandLineParser (0x0x7f0bf8769660) 0 + +Class QContiguousCacheData + size=24 align=4 + base size=24 base align=4 +QContiguousCacheData (0x0x7f0bf87696c0) 0 + +Class QCryptographicHash + size=8 align=8 + base size=8 base align=8 +QCryptographicHash (0x0x7f0bf8769cc0) 0 + +Class QDataStream + size=32 align=8 + base size=32 base align=8 +QDataStream (0x0x7f0bf8769d20) 0 + +Class QtPrivate::StreamStateSaver + size=16 align=8 + base size=12 base align=8 +QtPrivate::StreamStateSaver (0x0x7f0bf8769de0) 0 + +Class QDate + size=8 align=8 + base size=8 base align=8 +QDate (0x0x7f0bf8848300) 0 + +Class QTime + size=4 align=4 + base size=4 base align=4 +QTime (0x0x7f0bf88485a0) 0 + +Class QDateTime::ShortData + size=8 align=8 + base size=8 base align=8 +QDateTime::ShortData (0x0x7f0bf8848d20) 0 + +Class QDateTime::Data + size=8 align=8 + base size=8 base align=8 +QDateTime::Data (0x0x7f0bf8848d80) 0 + +Class QDateTime + size=8 align=8 + base size=8 base align=8 +QDateTime (0x0x7f0bf8848cc0) 0 + +Class QElapsedTimer + size=16 align=8 + base size=16 base align=8 +QElapsedTimer (0x0x7f0bf8557ea0) 0 + +Class QDeadlineTimer + size=16 align=8 + base size=16 base align=8 +QDeadlineTimer (0x0x7f0bf85943c0) 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 (0x0x7f0bf82c1360) 0 + vptr=((& QTextStream::_ZTV11QTextStream) + 16u) + +Class QTextStreamManipulator + size=40 align=8 + base size=38 base align=8 +QTextStreamManipulator (0x0x7f0bf82c1600) 0 + +Class QtSharedPointer::NormalDeleter + size=1 align=1 + base size=0 base align=1 +QtSharedPointer::NormalDeleter (0x0x7f0bf82c1840) 0 empty + +Class QtSharedPointer::ExternalRefCountData + size=16 align=8 + base size=16 base align=8 +QtSharedPointer::ExternalRefCountData (0x0x7f0bf82c19c0) 0 + +Class QDebug::Stream + size=80 align=8 + base size=76 base align=8 +QDebug::Stream (0x0x7f0bf82c1f00) 0 + +Class QDebug + size=8 align=8 + base size=8 base align=8 +QDebug (0x0x7f0bf82c1ea0) 0 + +Class QDebugStateSaver + size=8 align=8 + base size=8 base align=8 +QDebugStateSaver (0x0x7f0bf814b420) 0 + +Class QNoDebug + size=1 align=1 + base size=0 base align=1 +QNoDebug (0x0x7f0bf814b4e0) 0 empty + +Class QFileDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileDevice::QPrivateSignal (0x0x7f0bf8209660) 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 (0x0x7f0bf8201068) 0 + vptr=((& QFileDevice::_ZTV11QFileDevice) + 16u) + QIODevice (0x0x7f0bf8201410) 0 + primary-for QFileDevice (0x0x7f0bf8201068) + QObject (0x0x7f0bf8209600) 0 + primary-for QIODevice (0x0x7f0bf8201410) + +Class QFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFile::QPrivateSignal (0x0x7f0bf82098a0) 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 (0x0x7f0bf8201750) 0 + vptr=((& QFile::_ZTV5QFile) + 16u) + QFileDevice (0x0x7f0bf82018f0) 0 + primary-for QFile (0x0x7f0bf8201750) + QIODevice (0x0x7f0bf8201af8) 0 + primary-for QFileDevice (0x0x7f0bf82018f0) + QObject (0x0x7f0bf8209840) 0 + primary-for QIODevice (0x0x7f0bf8201af8) + +Class QFileInfo + size=8 align=8 + base size=8 base align=8 +QFileInfo (0x0x7f0bf8209a80) 0 + +Class QDir + size=8 align=8 + base size=8 base align=8 +QDir (0x0x7f0bf8209ea0) 0 + +Class QDirIterator + size=8 align=8 + base size=8 base align=8 +QDirIterator (0x0x7f0bf7ef78a0) 0 + +Class QEasingCurve + size=8 align=8 + base size=8 base align=8 +QEasingCurve (0x0x7f0bf7ef7ae0) 0 + +Class QEventTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventTransition::QPrivateSignal (0x0x7f0bf801df00) 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 (0x0x7f0bf8032208) 0 + vptr=((& QEventTransition::_ZTV16QEventTransition) + 16u) + QAbstractTransition (0x0x7f0bf8032270) 0 + primary-for QEventTransition (0x0x7f0bf8032208) + QObject (0x0x7f0bf801dea0) 0 + primary-for QAbstractTransition (0x0x7f0bf8032270) + +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 (0x0x7f0bf80322d8) 0 nearly-empty + vptr=((& QException::_ZTV10QException) + 16u) + std::exception (0x0x7f0bf801df60) 0 nearly-empty + primary-for QException (0x0x7f0bf80322d8) + +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 (0x0x7f0bf8032340) 0 nearly-empty + vptr=((& QUnhandledException::_ZTV19QUnhandledException) + 16u) + QException (0x0x7f0bf80323a8) 0 nearly-empty + primary-for QUnhandledException (0x0x7f0bf8032340) + std::exception (0x0x7f0bf7c85000) 0 nearly-empty + primary-for QException (0x0x7f0bf80323a8) + +Class QtPrivate::ExceptionHolder + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionHolder (0x0x7f0bf7c85060) 0 + +Class QtPrivate::ExceptionStore + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionStore (0x0x7f0bf7c85120) 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 (0x0x7f0bf7c85180) 0 nearly-empty + vptr=((& QFactoryInterface::_ZTV17QFactoryInterface) + 16u) + +Class QFileSelector::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSelector::QPrivateSignal (0x0x7f0bf7c852a0) 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 (0x0x7f0bf8032410) 0 + vptr=((& QFileSelector::_ZTV13QFileSelector) + 16u) + QObject (0x0x7f0bf7c85240) 0 + primary-for QFileSelector (0x0x7f0bf8032410) + +Class QFileSystemWatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSystemWatcher::QPrivateSignal (0x0x7f0bf7c85360) 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 (0x0x7f0bf8032478) 0 + vptr=((& QFileSystemWatcher::_ZTV18QFileSystemWatcher) + 16u) + QObject (0x0x7f0bf7c85300) 0 + primary-for QFileSystemWatcher (0x0x7f0bf8032478) + +Class QFinalState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFinalState::QPrivateSignal (0x0x7f0bf7c85420) 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 (0x0x7f0bf80324e0) 0 + vptr=((& QFinalState::_ZTV11QFinalState) + 16u) + QAbstractState (0x0x7f0bf8032548) 0 + primary-for QFinalState (0x0x7f0bf80324e0) + QObject (0x0x7f0bf7c853c0) 0 + primary-for QAbstractState (0x0x7f0bf8032548) + +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 (0x0x7f0bf7c85480) 0 + vptr=((& QRunnable::_ZTV9QRunnable) + 16u) + +Class QBasicMutex + size=8 align=8 + base size=8 base align=8 +QBasicMutex (0x0x7f0bf7c854e0) 0 + +Class QMutex + size=8 align=8 + base size=8 base align=8 +QMutex (0x0x7f0bf8032680) 0 + QBasicMutex (0x0x7f0bf7c856c0) 0 + +Class QMutexLocker + size=8 align=8 + base size=8 base align=8 +QMutexLocker (0x0x7f0bf7c85720) 0 + +Class QtPrivate::ResultItem + size=16 align=8 + base size=16 base align=8 +QtPrivate::ResultItem (0x0x7f0bf7c85780) 0 + +Class QtPrivate::ResultIteratorBase + size=16 align=8 + base size=12 base align=8 +QtPrivate::ResultIteratorBase (0x0x7f0bf7c857e0) 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 (0x0x7f0bf7c85900) 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 (0x0x7f0bf7dbe180) 0 + vptr=((& QFutureInterfaceBase::_ZTV20QFutureInterfaceBase) + 16u) + +Class QFutureWatcherBase::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFutureWatcherBase::QPrivateSignal (0x0x7f0bf7dbe960) 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 (0x0x7f0bf7dd57b8) 0 + vptr=((& QFutureWatcherBase::_ZTV18QFutureWatcherBase) + 16u) + QObject (0x0x7f0bf7dbe900) 0 + primary-for QFutureWatcherBase (0x0x7f0bf7dd57b8) + +Class QHistoryState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QHistoryState::QPrivateSignal (0x0x7f0bf7dbef60) 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 (0x0x7f0bf7a9c0d0) 0 + vptr=((& QHistoryState::_ZTV13QHistoryState) + 16u) + QAbstractState (0x0x7f0bf7a9c138) 0 + primary-for QHistoryState (0x0x7f0bf7a9c0d0) + QObject (0x0x7f0bf7dbef00) 0 + primary-for QAbstractState (0x0x7f0bf7a9c138) + +Class QIdentityProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIdentityProxyModel::QPrivateSignal (0x0x7f0bf7ab4060) 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 (0x0x7f0bf7a9c1a0) 0 + vptr=((& QIdentityProxyModel::_ZTV19QIdentityProxyModel) + 16u) + QAbstractProxyModel (0x0x7f0bf7a9c208) 0 + primary-for QIdentityProxyModel (0x0x7f0bf7a9c1a0) + QAbstractItemModel (0x0x7f0bf7a9c270) 0 + primary-for QAbstractProxyModel (0x0x7f0bf7a9c208) + QObject (0x0x7f0bf7ab4000) 0 + primary-for QAbstractItemModel (0x0x7f0bf7a9c270) + +Class QItemSelectionRange + size=16 align=8 + base size=16 base align=8 +QItemSelectionRange (0x0x7f0bf7ab40c0) 0 + +Class QItemSelectionModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QItemSelectionModel::QPrivateSignal (0x0x7f0bf7ab4780) 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 (0x0x7f0bf7a9ca90) 0 + vptr=((& QItemSelectionModel::_ZTV19QItemSelectionModel) + 16u) + QObject (0x0x7f0bf7ab4720) 0 + primary-for QItemSelectionModel (0x0x7f0bf7a9ca90) + +Class QItemSelection + size=8 align=8 + base size=8 base align=8 +QItemSelection (0x0x7f0bf7a9cc98) 0 + QList (0x0x7f0bf7a9cd00) 0 + QListSpecialMethods (0x0x7f0bf7ab4a80) 0 empty + +Class QJsonValue + size=24 align=8 + base size=20 base align=8 +QJsonValue (0x0x7f0bf7ab4f60) 0 + +Class QJsonValueRef + size=16 align=8 + base size=12 base align=8 +QJsonValueRef (0x0x7f0bf79056c0) 0 + +Class QJsonValuePtr + size=24 align=8 + base size=24 base align=8 +QJsonValuePtr (0x0x7f0bf7905c00) 0 + +Class QJsonValueRefPtr + size=16 align=8 + base size=16 base align=8 +QJsonValueRefPtr (0x0x7f0bf7905c60) 0 + +Class QJsonArray::iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::iterator (0x0x7f0bf7905e40) 0 + +Class QJsonArray::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::const_iterator (0x0x7f0bf7905ea0) 0 + +Class QJsonArray + size=16 align=8 + base size=16 base align=8 +QJsonArray (0x0x7f0bf7905de0) 0 + +Class QJsonParseError + size=8 align=4 + base size=8 base align=4 +QJsonParseError (0x0x7f0bf7651120) 0 + +Class QJsonDocument + size=8 align=8 + base size=8 base align=8 +QJsonDocument (0x0x7f0bf7651180) 0 + +Class QJsonObject::iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::iterator (0x0x7f0bf76517e0) 0 + +Class QJsonObject::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::const_iterator (0x0x7f0bf7651840) 0 + +Class QJsonObject + size=16 align=8 + base size=16 base align=8 +QJsonObject (0x0x7f0bf7651780) 0 + +Class QLibrary::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLibrary::QPrivateSignal (0x0x7f0bf7728ae0) 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 (0x0x7f0bf7765068) 0 + vptr=((& QLibrary::_ZTV8QLibrary) + 16u) + QObject (0x0x7f0bf7728a80) 0 + primary-for QLibrary (0x0x7f0bf7765068) + +Class QVersionNumber::SegmentStorage + size=8 align=8 + base size=8 base align=8 +QVersionNumber::SegmentStorage (0x0x7f0bf77b31e0) 0 + +Class QVersionNumber + size=8 align=8 + base size=8 base align=8 +QVersionNumber (0x0x7f0bf7728cc0) 0 + +Class QLibraryInfo + size=1 align=1 + base size=0 base align=1 +QLibraryInfo (0x0x7f0bf77b36c0) 0 empty + +Class QPoint + size=8 align=4 + base size=8 base align=4 +QPoint (0x0x7f0bf77b3720) 0 + +Class QPointF + size=16 align=8 + base size=16 base align=8 +QPointF (0x0x7f0bf77b39c0) 0 + +Class QLine + size=16 align=4 + base size=16 base align=4 +QLine (0x0x7f0bf77b3c60) 0 + +Class QLineF + size=32 align=8 + base size=32 base align=8 +QLineF (0x0x7f0bf74a5600) 0 + +Class QLinkedListData + size=32 align=8 + base size=25 base align=8 +QLinkedListData (0x0x7f0bf74a5f60) 0 + +Class QLockFile + size=8 align=8 + base size=8 base align=8 +QLockFile (0x0x7f0bf753d300) 0 + +Class QLoggingCategory::AtomicBools + size=4 align=1 + base size=4 base align=1 +QLoggingCategory::AtomicBools (0x0x7f0bf753d480) 0 + +Class QLoggingCategory + size=24 align=8 + base size=24 base align=8 +QLoggingCategory (0x0x7f0bf753d420) 0 + +Class QMargins + size=16 align=4 + base size=16 base align=4 +QMargins (0x0x7f0bf753d600) 0 + +Class QMarginsF + size=32 align=8 + base size=32 base align=8 +QMarginsF (0x0x7f0bf753d8a0) 0 + +Class QMessageAuthenticationCode + size=8 align=8 + base size=8 base align=8 +QMessageAuthenticationCode (0x0x7f0bf753df00) 0 + +Class QMetaMethod + size=16 align=8 + base size=12 base align=8 +QMetaMethod (0x0x7f0bf753df60) 0 + +Class QMetaEnum + size=16 align=8 + base size=12 base align=8 +QMetaEnum (0x0x7f0bf730b5a0) 0 + +Class QMetaProperty + size=32 align=8 + base size=32 base align=8 +QMetaProperty (0x0x7f0bf730b8a0) 0 + +Class QMetaClassInfo + size=16 align=8 + base size=12 base align=8 +QMetaClassInfo (0x0x7f0bf730b900) 0 + +Class QMimeData::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QMimeData::QPrivateSignal (0x0x7f0bf730bc00) 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 (0x0x7f0bf73272d8) 0 + vptr=((& QMimeData::_ZTV9QMimeData) + 16u) + QObject (0x0x7f0bf730bba0) 0 + primary-for QMimeData (0x0x7f0bf73272d8) + +Class QMimeType + size=8 align=8 + base size=8 base align=8 +QMimeType (0x0x7f0bf730bc60) 0 + +Class QMimeDatabase + size=8 align=8 + base size=8 base align=8 +QMimeDatabase (0x0x7f0bf730bf60) 0 + +Class QObjectCleanupHandler::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObjectCleanupHandler::QPrivateSignal (0x0x7f0bf7377060) 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 (0x0x7f0bf73274e0) 0 + vptr=((& QObjectCleanupHandler::_ZTV21QObjectCleanupHandler) + 16u) + QObject (0x0x7f0bf7377000) 0 + primary-for QObjectCleanupHandler (0x0x7f0bf73274e0) + +Class QOperatingSystemVersion + size=16 align=4 + base size=16 base align=4 +QOperatingSystemVersion (0x0x7f0bf73770c0) 0 + +Class QParallelAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QParallelAnimationGroup::QPrivateSignal (0x0x7f0bf7377840) 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 (0x0x7f0bf7327c30) 0 + vptr=((& QParallelAnimationGroup::_ZTV23QParallelAnimationGroup) + 16u) + QAnimationGroup (0x0x7f0bf7327c98) 0 + primary-for QParallelAnimationGroup (0x0x7f0bf7327c30) + QAbstractAnimation (0x0x7f0bf7327d00) 0 + primary-for QAnimationGroup (0x0x7f0bf7327c98) + QObject (0x0x7f0bf73777e0) 0 + primary-for QAbstractAnimation (0x0x7f0bf7327d00) + +Class QPauseAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPauseAnimation::QPrivateSignal (0x0x7f0bf7377900) 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 (0x0x7f0bf7327d68) 0 + vptr=((& QPauseAnimation::_ZTV15QPauseAnimation) + 16u) + QAbstractAnimation (0x0x7f0bf7327dd0) 0 + primary-for QPauseAnimation (0x0x7f0bf7327d68) + QObject (0x0x7f0bf73778a0) 0 + primary-for QAbstractAnimation (0x0x7f0bf7327dd0) + +Class QStaticPlugin + size=16 align=8 + base size=16 base align=8 +QStaticPlugin (0x0x7f0bf7377ae0) 0 + +Class QPluginLoader::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPluginLoader::QPrivateSignal (0x0x7f0bf7377de0) 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 (0x0x7f0bf7327548) 0 + vptr=((& QPluginLoader::_ZTV13QPluginLoader) + 16u) + QObject (0x0x7f0bf7377d80) 0 + primary-for QPluginLoader (0x0x7f0bf7327548) + +Class QProcessEnvironment + size=8 align=8 + base size=8 base align=8 +QProcessEnvironment (0x0x7f0bf7377e40) 0 + +Class QProcess::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QProcess::QPrivateSignal (0x0x7f0bf7419540) 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 (0x0x7f0bf741a618) 0 + vptr=((& QProcess::_ZTV8QProcess) + 16u) + QIODevice (0x0x7f0bf741a680) 0 + primary-for QProcess (0x0x7f0bf741a618) + QObject (0x0x7f0bf74194e0) 0 + primary-for QIODevice (0x0x7f0bf741a680) + +Class QVariantAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QVariantAnimation::QPrivateSignal (0x0x7f0bf7419600) 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 (0x0x7f0bf741a6e8) 0 + vptr=((& QVariantAnimation::_ZTV17QVariantAnimation) + 16u) + QAbstractAnimation (0x0x7f0bf741a750) 0 + primary-for QVariantAnimation (0x0x7f0bf741a6e8) + QObject (0x0x7f0bf74195a0) 0 + primary-for QAbstractAnimation (0x0x7f0bf741a750) + +Class QPropertyAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPropertyAnimation::QPrivateSignal (0x0x7f0bf74196c0) 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 (0x0x7f0bf741a820) 0 + vptr=((& QPropertyAnimation::_ZTV18QPropertyAnimation) + 16u) + QVariantAnimation (0x0x7f0bf741a888) 0 + primary-for QPropertyAnimation (0x0x7f0bf741a820) + QAbstractAnimation (0x0x7f0bf741a8f0) 0 + primary-for QVariantAnimation (0x0x7f0bf741a888) + QObject (0x0x7f0bf7419660) 0 + primary-for QAbstractAnimation (0x0x7f0bf741a8f0) + +Class QRandomGenerator::Storage + size=2504 align=8 + base size=2504 base align=8 +QRandomGenerator::Storage (0x0x7f0bf74197e0) 0 + +Class QRandomGenerator + size=2512 align=8 + base size=2512 base align=8 +QRandomGenerator (0x0x7f0bf7419780) 0 + +Class QRandomGenerator64 + size=2512 align=8 + base size=2512 base align=8 +QRandomGenerator64 (0x0x7f0bf70f8bc8) 0 + QRandomGenerator (0x0x7f0bf7102780) 0 + +Class QReadWriteLock + size=8 align=8 + base size=8 base align=8 +QReadWriteLock (0x0x7f0bf7102840) 0 + +Class QReadLocker + size=8 align=8 + base size=8 base align=8 +QReadLocker (0x0x7f0bf7102ae0) 0 + +Class QWriteLocker + size=8 align=8 + base size=8 base align=8 +QWriteLocker (0x0x7f0bf7102ba0) 0 + +Class QSize + size=8 align=4 + base size=8 base align=4 +QSize (0x0x7f0bf7102c60) 0 + +Class QSizeF + size=16 align=8 + base size=16 base align=8 +QSizeF (0x0x7f0bf7102f00) 0 + +Class QRect + size=16 align=4 + base size=16 base align=4 +QRect (0x0x7f0bf721c1e0) 0 + +Class QRectF + size=32 align=8 + base size=32 base align=8 +QRectF (0x0x7f0bf721c480) 0 + +Class QRegularExpression + size=8 align=8 + base size=8 base align=8 +QRegularExpression (0x0x7f0bf721c720) 0 + +Class QRegularExpressionMatch + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatch (0x0x7f0bf721cd20) 0 + +Class QRegularExpressionMatchIterator + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatchIterator (0x0x7f0bf7003060) 0 + +Class QResource + size=8 align=8 + base size=8 base align=8 +QResource (0x0x7f0bf7003360) 0 + +Class QSaveFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSaveFile::QPrivateSignal (0x0x7f0bf70034e0) 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 (0x0x7f0bf7206dd0) 0 + vptr=((& QSaveFile::_ZTV9QSaveFile) + 16u) + QFileDevice (0x0x7f0bf7206e38) 0 + primary-for QSaveFile (0x0x7f0bf7206dd0) + QIODevice (0x0x7f0bf7206ea0) 0 + primary-for QFileDevice (0x0x7f0bf7206e38) + QObject (0x0x7f0bf7003480) 0 + primary-for QIODevice (0x0x7f0bf7206ea0) + +Class QSemaphore + size=8 align=8 + base size=8 base align=8 +QSemaphore (0x0x7f0bf70035a0) 0 + +Class QSemaphoreReleaser + size=16 align=8 + base size=12 base align=8 +QSemaphoreReleaser (0x0x7f0bf7003600) 0 + +Class QSequentialAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSequentialAnimationGroup::QPrivateSignal (0x0x7f0bf6d1cc00) 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 (0x0x7f0bf6d336e8) 0 + vptr=((& QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup) + 16u) + QAnimationGroup (0x0x7f0bf6d33750) 0 + primary-for QSequentialAnimationGroup (0x0x7f0bf6d336e8) + QAbstractAnimation (0x0x7f0bf6d337b8) 0 + primary-for QAnimationGroup (0x0x7f0bf6d33750) + QObject (0x0x7f0bf6d1cba0) 0 + primary-for QAbstractAnimation (0x0x7f0bf6d337b8) + +Class QSettings::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSettings::QPrivateSignal (0x0x7f0bf6d1ccc0) 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 (0x0x7f0bf6d33820) 0 + vptr=((& QSettings::_ZTV9QSettings) + 16u) + QObject (0x0x7f0bf6d1cc60) 0 + primary-for QSettings (0x0x7f0bf6d33820) + +Class QSharedMemory::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSharedMemory::QPrivateSignal (0x0x7f0bf6d1cd80) 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 (0x0x7f0bf6d33888) 0 + vptr=((& QSharedMemory::_ZTV13QSharedMemory) + 16u) + QObject (0x0x7f0bf6d1cd20) 0 + primary-for QSharedMemory (0x0x7f0bf6d33888) + +Class QSignalMapper::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalMapper::QPrivateSignal (0x0x7f0bf6d1ce40) 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 (0x0x7f0bf6d338f0) 0 + vptr=((& QSignalMapper::_ZTV13QSignalMapper) + 16u) + QObject (0x0x7f0bf6d1cde0) 0 + primary-for QSignalMapper (0x0x7f0bf6d338f0) + +Class QSignalTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalTransition::QPrivateSignal (0x0x7f0bf6d1cf00) 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 (0x0x7f0bf6d33958) 0 + vptr=((& QSignalTransition::_ZTV17QSignalTransition) + 16u) + QAbstractTransition (0x0x7f0bf6d339c0) 0 + primary-for QSignalTransition (0x0x7f0bf6d33958) + QObject (0x0x7f0bf6d1cea0) 0 + primary-for QAbstractTransition (0x0x7f0bf6d339c0) + +Class QSocketNotifier::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSocketNotifier::QPrivateSignal (0x0x7f0bf6dac000) 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 (0x0x7f0bf6d33a28) 0 + vptr=((& QSocketNotifier::_ZTV15QSocketNotifier) + 16u) + QObject (0x0x7f0bf6d1cf60) 0 + primary-for QSocketNotifier (0x0x7f0bf6d33a28) + +Class QSortFilterProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSortFilterProxyModel::QPrivateSignal (0x0x7f0bf6dac0c0) 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 (0x0x7f0bf6d33a90) 0 + vptr=((& QSortFilterProxyModel::_ZTV21QSortFilterProxyModel) + 16u) + QAbstractProxyModel (0x0x7f0bf6d33af8) 0 + primary-for QSortFilterProxyModel (0x0x7f0bf6d33a90) + QAbstractItemModel (0x0x7f0bf6d33b60) 0 + primary-for QAbstractProxyModel (0x0x7f0bf6d33af8) + QObject (0x0x7f0bf6dac060) 0 + primary-for QAbstractItemModel (0x0x7f0bf6d33b60) + +Class QStandardPaths + size=1 align=1 + base size=0 base align=1 +QStandardPaths (0x0x7f0bf6dac180) 0 empty + +Class QState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QState::QPrivateSignal (0x0x7f0bf6dac3c0) 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 (0x0x7f0bf6d33d00) 0 + vptr=((& QState::_ZTV6QState) + 16u) + QAbstractState (0x0x7f0bf6d33d68) 0 + primary-for QState (0x0x7f0bf6d33d00) + QObject (0x0x7f0bf6dac360) 0 + primary-for QAbstractState (0x0x7f0bf6d33d68) + +Class QStateMachine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStateMachine::QPrivateSignal (0x0x7f0bf6dac4e0) 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 (0x0x7f0bf6d33f08) 0 + vptr=((& QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE) + 16u) + QEvent (0x0x7f0bf6dac540) 0 + primary-for QStateMachine::SignalEvent (0x0x7f0bf6d33f08) + +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 (0x0x7f0bf6d33f70) 0 + vptr=((& QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE) + 16u) + QEvent (0x0x7f0bf6dac5a0) 0 + primary-for QStateMachine::WrappedEvent (0x0x7f0bf6d33f70) + +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 (0x0x7f0bf6d33dd0) 0 + vptr=((& QStateMachine::_ZTV13QStateMachine) + 16u) + QState (0x0x7f0bf6d33e38) 0 + primary-for QStateMachine (0x0x7f0bf6d33dd0) + QAbstractState (0x0x7f0bf6d33ea0) 0 + primary-for QState (0x0x7f0bf6d33e38) + QObject (0x0x7f0bf6dac480) 0 + primary-for QAbstractState (0x0x7f0bf6d33ea0) + +Class QStorageInfo + size=8 align=8 + base size=8 base align=8 +QStorageInfo (0x0x7f0bf6dac600) 0 + +Class QAbstractConcatenable + size=1 align=1 + base size=0 base align=1 +QAbstractConcatenable (0x0x7f0bf6a9e540) 0 empty + +Class QStringListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStringListModel::QPrivateSignal (0x0x7f0bf6b2e060) 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 (0x0x7f0bf6b02478) 0 + vptr=((& QStringListModel::_ZTV16QStringListModel) + 16u) + QAbstractListModel (0x0x7f0bf6b024e0) 0 + primary-for QStringListModel (0x0x7f0bf6b02478) + QAbstractItemModel (0x0x7f0bf6b02548) 0 + primary-for QAbstractListModel (0x0x7f0bf6b024e0) + QObject (0x0x7f0bf6b2e000) 0 + primary-for QAbstractItemModel (0x0x7f0bf6b02548) + +Class QSystemSemaphore + size=8 align=8 + base size=8 base align=8 +QSystemSemaphore (0x0x7f0bf6b2e0c0) 0 + +Class QTemporaryDir + size=8 align=8 + base size=8 base align=8 +QTemporaryDir (0x0x7f0bf6b2e180) 0 + +Class QTemporaryFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTemporaryFile::QPrivateSignal (0x0x7f0bf6b2e2a0) 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 (0x0x7f0bf6b025b0) 0 + vptr=((& QTemporaryFile::_ZTV14QTemporaryFile) + 16u) + QFile (0x0x7f0bf6b02618) 0 + primary-for QTemporaryFile (0x0x7f0bf6b025b0) + QFileDevice (0x0x7f0bf6b02680) 0 + primary-for QFile (0x0x7f0bf6b02618) + QIODevice (0x0x7f0bf6b026e8) 0 + primary-for QFileDevice (0x0x7f0bf6b02680) + QObject (0x0x7f0bf6b2e240) 0 + primary-for QIODevice (0x0x7f0bf6b026e8) + +Class QTextBoundaryFinder + size=48 align=8 + base size=48 base align=8 +QTextBoundaryFinder (0x0x7f0bf6b2e300) 0 + +Class QTextCodec::ConverterState + size=32 align=8 + base size=32 base align=8 +QTextCodec::ConverterState (0x0x7f0bf6b2e540) 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 (0x0x7f0bf6b2e4e0) 0 nearly-empty + vptr=((& QTextCodec::_ZTV10QTextCodec) + 16u) + +Class QTextEncoder + size=40 align=8 + base size=40 base align=8 +QTextEncoder (0x0x7f0bf6b2e720) 0 + +Class QTextDecoder + size=40 align=8 + base size=40 base align=8 +QTextDecoder (0x0x7f0bf6b2e780) 0 + +Class std::__mutex_base + size=40 align=8 + base size=40 base align=8 +std::__mutex_base (0x0x7f0bf6b2e7e0) 0 + +Class std::__recursive_mutex_base + size=40 align=8 + base size=40 base align=8 +std::__recursive_mutex_base (0x0x7f0bf6b2e840) 0 + +Class std::mutex + size=40 align=8 + base size=40 base align=8 +std::mutex (0x0x7f0bf6b028f0) 0 + std::__mutex_base (0x0x7f0bf6b2e8a0) 0 + +Class std::recursive_mutex + size=40 align=8 + base size=40 base align=8 +std::recursive_mutex (0x0x7f0bf6b02958) 0 + std::__recursive_mutex_base (0x0x7f0bf6b2e900) 0 + +Class std::timed_mutex + size=40 align=8 + base size=40 base align=8 +std::timed_mutex (0x0x7f0bf6c13700) 0 + std::__mutex_base (0x0x7f0bf6b2ea20) 0 + std::__timed_mutex_impl (0x0x7f0bf6b2ea80) 0 empty + +Class std::recursive_timed_mutex + size=40 align=8 + base size=40 base align=8 +std::recursive_timed_mutex (0x0x7f0bf6c2d380) 0 + std::__recursive_mutex_base (0x0x7f0bf6b2eb40) 0 + std::__timed_mutex_impl (0x0x7f0bf6b2eba0) 0 empty + +Class std::defer_lock_t + size=1 align=1 + base size=0 base align=1 +std::defer_lock_t (0x0x7f0bf6b2ec00) 0 empty + +Class std::try_to_lock_t + size=1 align=1 + base size=0 base align=1 +std::try_to_lock_t (0x0x7f0bf6b2ec60) 0 empty + +Class std::adopt_lock_t + size=1 align=1 + base size=0 base align=1 +std::adopt_lock_t (0x0x7f0bf6b2ecc0) 0 empty + +Class std::once_flag + size=4 align=4 + base size=4 base align=4 +std::once_flag (0x0x7f0bf6b2ef00) 0 + +Vtable for __gnu_cxx::__concurrence_lock_error +__gnu_cxx::__concurrence_lock_error::_ZTVN9__gnu_cxx24__concurrence_lock_errorE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx24__concurrence_lock_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_lock_error::~__concurrence_lock_error +24 (int (*)(...))__gnu_cxx::__concurrence_lock_error::~__concurrence_lock_error +32 (int (*)(...))__gnu_cxx::__concurrence_lock_error::what + +Class __gnu_cxx::__concurrence_lock_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_lock_error (0x0x7f0bf6b02a90) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_lock_error::_ZTVN9__gnu_cxx24__concurrence_lock_errorE) + 16u) + std::exception (0x0x7f0bf6881000) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_lock_error (0x0x7f0bf6b02a90) + +Vtable for __gnu_cxx::__concurrence_unlock_error +__gnu_cxx::__concurrence_unlock_error::_ZTVN9__gnu_cxx26__concurrence_unlock_errorE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx26__concurrence_unlock_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::~__concurrence_unlock_error +24 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::~__concurrence_unlock_error +32 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::what + +Class __gnu_cxx::__concurrence_unlock_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_unlock_error (0x0x7f0bf6b02af8) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_unlock_error::_ZTVN9__gnu_cxx26__concurrence_unlock_errorE) + 16u) + std::exception (0x0x7f0bf68810c0) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_unlock_error (0x0x7f0bf6b02af8) + +Vtable for __gnu_cxx::__concurrence_broadcast_error +__gnu_cxx::__concurrence_broadcast_error::_ZTVN9__gnu_cxx29__concurrence_broadcast_errorE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx29__concurrence_broadcast_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::~__concurrence_broadcast_error +24 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::~__concurrence_broadcast_error +32 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::what + +Class __gnu_cxx::__concurrence_broadcast_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_broadcast_error (0x0x7f0bf6b02b60) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_broadcast_error::_ZTVN9__gnu_cxx29__concurrence_broadcast_errorE) + 16u) + std::exception (0x0x7f0bf6881180) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_broadcast_error (0x0x7f0bf6b02b60) + +Vtable for __gnu_cxx::__concurrence_wait_error +__gnu_cxx::__concurrence_wait_error::_ZTVN9__gnu_cxx24__concurrence_wait_errorE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx24__concurrence_wait_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_wait_error::~__concurrence_wait_error +24 (int (*)(...))__gnu_cxx::__concurrence_wait_error::~__concurrence_wait_error +32 (int (*)(...))__gnu_cxx::__concurrence_wait_error::what + +Class __gnu_cxx::__concurrence_wait_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_wait_error (0x0x7f0bf6b02c30) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_wait_error::_ZTVN9__gnu_cxx24__concurrence_wait_errorE) + 16u) + std::exception (0x0x7f0bf6881240) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_wait_error (0x0x7f0bf6b02c30) + +Class __gnu_cxx::__mutex + size=40 align=8 + base size=40 base align=8 +__gnu_cxx::__mutex (0x0x7f0bf6881300) 0 + +Class __gnu_cxx::__recursive_mutex + size=40 align=8 + base size=40 base align=8 +__gnu_cxx::__recursive_mutex (0x0x7f0bf6881360) 0 + +Class __gnu_cxx::__scoped_lock + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__scoped_lock (0x0x7f0bf68813c0) 0 + +Class __gnu_cxx::__cond + size=48 align=8 + base size=48 base align=8 +__gnu_cxx::__cond (0x0x7f0bf6881420) 0 + +Vtable for std::bad_weak_ptr +std::bad_weak_ptr::_ZTVSt12bad_weak_ptr: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt12bad_weak_ptr) +16 (int (*)(...))std::bad_weak_ptr::~bad_weak_ptr +24 (int (*)(...))std::bad_weak_ptr::~bad_weak_ptr +32 (int (*)(...))std::bad_weak_ptr::what + +Class std::bad_weak_ptr + size=8 align=8 + base size=8 base align=8 +std::bad_weak_ptr (0x0x7f0bf6b02f08) 0 nearly-empty + vptr=((& std::bad_weak_ptr::_ZTVSt12bad_weak_ptr) + 16u) + std::exception (0x0x7f0bf6881780) 0 nearly-empty + primary-for std::bad_weak_ptr (0x0x7f0bf6b02f08) + +Class std::_Sp_make_shared_tag + size=1 align=1 + base size=0 base align=1 +std::_Sp_make_shared_tag (0x0x7f0bf69b8000) 0 empty + +Class std::_Sp_locker + size=2 align=1 + base size=2 base align=1 +std::_Sp_locker (0x0x7f0bf69b87e0) 0 + +Class std::thread::id + size=8 align=8 + base size=8 base align=8 +std::thread::id (0x0x7f0bf69b89c0) 0 + +Vtable for std::thread::_Impl_base +std::thread::_Impl_base::_ZTVNSt6thread10_Impl_baseE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt6thread10_Impl_baseE) +16 0u +24 0u +32 (int (*)(...))__cxa_pure_virtual + +Class std::thread::_Impl_base + size=24 align=8 + base size=24 base align=8 +std::thread::_Impl_base (0x0x7f0bf69b8a20) 0 + vptr=((& std::thread::_Impl_base::_ZTVNSt6thread10_Impl_baseE) + 16u) + +Class std::thread + size=8 align=8 + base size=8 base align=8 +std::thread (0x0x7f0bf69b8960) 0 + +Class std::condition_variable + size=48 align=8 + base size=48 base align=8 +std::condition_variable (0x0x7f0bf6733660) 0 + +Class std::__at_thread_exit_elt + size=16 align=8 + base size=16 base align=8 +std::__at_thread_exit_elt (0x0x7f0bf6733720) 0 + +Class std::_V2::condition_variable_any + size=64 align=8 + base size=64 base align=8 +std::_V2::condition_variable_any (0x0x7f0bf6733780) 0 + +Class std::__atomic_futex_unsigned_base + size=1 align=1 + base size=0 base align=1 +std::__atomic_futex_unsigned_base (0x0x7f0bf63bede0) 0 empty + +Vtable for std::future_error +std::future_error::_ZTVSt12future_error: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt12future_error) +16 (int (*)(...))std::future_error::~future_error +24 (int (*)(...))std::future_error::~future_error +32 (int (*)(...))std::future_error::what + +Class std::future_error + size=32 align=8 + base size=32 base align=8 +std::future_error (0x0x7f0bf6439270) 0 + vptr=((& std::future_error::_ZTVSt12future_error) + 16u) + std::logic_error (0x0x7f0bf64392d8) 0 + primary-for std::future_error (0x0x7f0bf6439270) + std::exception (0x0x7f0bf63bef00) 0 nearly-empty + primary-for std::logic_error (0x0x7f0bf64392d8) + +Class std::__future_base::_Result_base::_Deleter + size=1 align=1 + base size=0 base align=1 +std::__future_base::_Result_base::_Deleter (0x0x7f0bf6474060) 0 empty + +Vtable for std::__future_base::_Result_base +std::__future_base::_Result_base::_ZTVNSt13__future_base12_Result_baseE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt13__future_base12_Result_baseE) +16 (int (*)(...))__cxa_pure_virtual +24 0u +32 0u + +Class std::__future_base::_Result_base + size=16 align=8 + base size=16 base align=8 +std::__future_base::_Result_base (0x0x7f0bf6474000) 0 + vptr=((& std::__future_base::_Result_base::_ZTVNSt13__future_base12_Result_baseE) + 16u) + +Class std::__future_base::_State_baseV2::__exception_ptr_tag + size=1 align=1 + base size=0 base align=1 +std::__future_base::_State_baseV2::__exception_ptr_tag (0x0x7f0bf61705a0) 0 empty + +Class std::__future_base::_State_baseV2::_Make_ready + size=32 align=8 + base size=32 base align=8 +std::__future_base::_State_baseV2::_Make_ready (0x0x7f0bf6167888) 0 + std::__at_thread_exit_elt (0x0x7f0bf6170660) 0 + +Vtable for std::__future_base::_State_baseV2 +std::__future_base::_State_baseV2::_ZTVNSt13__future_base13_State_baseV2E: 6u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt13__future_base13_State_baseV2E) +16 (int (*)(...))std::__future_base::_State_baseV2::~_State_baseV2 +24 (int (*)(...))std::__future_base::_State_baseV2::~_State_baseV2 +32 (int (*)(...))std::__future_base::_State_baseV2::_M_complete_async +40 (int (*)(...))std::__future_base::_State_baseV2::_M_is_deferred_future + +Class std::__future_base::_State_baseV2 + size=32 align=8 + base size=28 base align=8 +std::__future_base::_State_baseV2 (0x0x7f0bf64741e0) 0 + vptr=((& std::__future_base::_State_baseV2::_ZTVNSt13__future_base13_State_baseV2E) + 16u) + +Class std::__future_base + size=1 align=1 + base size=0 base align=1 +std::__future_base (0x0x7f0bf63bef60) 0 empty + +Vtable for std::__future_base::_Async_state_commonV2 +std::__future_base::_Async_state_commonV2::_ZTVNSt13__future_base21_Async_state_commonV2E: 6u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt13__future_base21_Async_state_commonV2E) +16 (int (*)(...))std::__future_base::_Async_state_commonV2::~_Async_state_commonV2 +24 (int (*)(...))std::__future_base::_Async_state_commonV2::~_Async_state_commonV2 +32 (int (*)(...))std::__future_base::_Async_state_commonV2::_M_complete_async +40 (int (*)(...))std::__future_base::_State_baseV2::_M_is_deferred_future + +Class std::__future_base::_Async_state_commonV2 + size=48 align=8 + base size=44 base align=8 +std::__future_base::_Async_state_commonV2 (0x0x7f0bf5ed0478) 0 + vptr=((& std::__future_base::_Async_state_commonV2::_ZTVNSt13__future_base21_Async_state_commonV2E) + 16u) + std::__future_base::_State_baseV2 (0x0x7f0bf5ec9540) 0 + primary-for std::__future_base::_Async_state_commonV2 (0x0x7f0bf5ed0478) + +Class QThread::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThread::QPrivateSignal (0x0x7f0bf5ec9c60) 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 (0x0x7f0bf5ed0f08) 0 + vptr=((& QThread::_ZTV7QThread) + 16u) + QObject (0x0x7f0bf5ec9c00) 0 + primary-for QThread (0x0x7f0bf5ed0f08) + +Class QThreadPool::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThreadPool::QPrivateSignal (0x0x7f0bf5ec9d80) 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 (0x0x7f0bf5ed0f70) 0 + vptr=((& QThreadPool::_ZTV11QThreadPool) + 16u) + QObject (0x0x7f0bf5ec9d20) 0 + primary-for QThreadPool (0x0x7f0bf5ed0f70) + +Class QThreadStorageData + size=4 align=4 + base size=4 base align=4 +QThreadStorageData (0x0x7f0bf5ec9de0) 0 + +Class QTimeLine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimeLine::QPrivateSignal (0x0x7f0bf5ec9f00) 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 (0x0x7f0bf5b87000) 0 + vptr=((& QTimeLine::_ZTV9QTimeLine) + 16u) + QObject (0x0x7f0bf5ec9ea0) 0 + primary-for QTimeLine (0x0x7f0bf5b87000) + +Class QTimer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimer::QPrivateSignal (0x0x7f0bf5ba3000) 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 (0x0x7f0bf5b87068) 0 + vptr=((& QTimer::_ZTV6QTimer) + 16u) + QObject (0x0x7f0bf5ec9f60) 0 + primary-for QTimer (0x0x7f0bf5b87068) + +Class QTimeZone::OffsetData + size=32 align=8 + base size=28 base align=8 +QTimeZone::OffsetData (0x0x7f0bf5ba36c0) 0 + +Class QTimeZone + size=8 align=8 + base size=8 base align=8 +QTimeZone (0x0x7f0bf5ba3660) 0 + +Class QTranslator::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTranslator::QPrivateSignal (0x0x7f0bf5ba3c60) 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 (0x0x7f0bf5b87af8) 0 + vptr=((& QTranslator::_ZTV11QTranslator) + 16u) + QObject (0x0x7f0bf5ba3c00) 0 + primary-for QTranslator (0x0x7f0bf5b87af8) + +Class QUrl + size=8 align=8 + base size=8 base align=8 +QUrl (0x0x7f0bf5ba3d80) 0 + +Class QUrlQuery + size=8 align=8 + base size=8 base align=8 +QUrlQuery (0x0x7f0bf5d2a480) 0 + +Class QUuid + size=16 align=4 + base size=16 base align=4 +QUuid (0x0x7f0bf5d2aae0) 0 + +Class QWaitCondition + size=8 align=8 + base size=8 base align=8 +QWaitCondition (0x0x7f0bf59e8120) 0 + +Class QXmlStreamStringRef + size=16 align=8 + base size=16 base align=8 +QXmlStreamStringRef (0x0x7f0bf59e8180) 0 + +Class QXmlStreamAttribute + size=80 align=8 + base size=73 base align=8 +QXmlStreamAttribute (0x0x7f0bf59e8480) 0 + +Class QXmlStreamAttributes + size=8 align=8 + base size=8 base align=8 +QXmlStreamAttributes (0x0x7f0bf5a295b0) 0 + QVector (0x0x7f0bf59e8840) 0 + +Class QXmlStreamNamespaceDeclaration + size=40 align=8 + base size=40 base align=8 +QXmlStreamNamespaceDeclaration (0x0x7f0bf59e88a0) 0 + +Class QXmlStreamNotationDeclaration + size=56 align=8 + base size=56 base align=8 +QXmlStreamNotationDeclaration (0x0x7f0bf59e8b40) 0 + +Class QXmlStreamEntityDeclaration + size=88 align=8 + base size=88 base align=8 +QXmlStreamEntityDeclaration (0x0x7f0bf59e8de0) 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 (0x0x7f0bf5b010c0) 0 nearly-empty + vptr=((& QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver) + 16u) + +Class QXmlStreamReader + size=8 align=8 + base size=8 base align=8 +QXmlStreamReader (0x0x7f0bf5b01120) 0 + +Class QXmlStreamWriter + size=8 align=8 + base size=8 base align=8 +QXmlStreamWriter (0x0x7f0bf5b01b40) 0 + +Class QBluetoothAddress + size=8 align=8 + base size=8 base align=8 +QBluetoothAddress (0x0x7f0bf5b01f60) 0 + +Class QBluetoothDeviceInfo + size=8 align=8 + base size=8 base align=8 +QBluetoothDeviceInfo (0x0x7f0bf57df120) 0 + +Class QBluetoothDeviceDiscoveryAgent::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothDeviceDiscoveryAgent::QPrivateSignal (0x0x7f0bf57df600) 0 empty + +Vtable for QBluetoothDeviceDiscoveryAgent +QBluetoothDeviceDiscoveryAgent::_ZTV30QBluetoothDeviceDiscoveryAgent: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI30QBluetoothDeviceDiscoveryAgent) +16 (int (*)(...))QBluetoothDeviceDiscoveryAgent::metaObject +24 (int (*)(...))QBluetoothDeviceDiscoveryAgent::qt_metacast +32 (int (*)(...))QBluetoothDeviceDiscoveryAgent::qt_metacall +40 (int (*)(...))QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent +48 (int (*)(...))QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent +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 QBluetoothDeviceDiscoveryAgent + size=24 align=8 + base size=24 base align=8 +QBluetoothDeviceDiscoveryAgent (0x0x7f0bf572e9c0) 0 + vptr=((& QBluetoothDeviceDiscoveryAgent::_ZTV30QBluetoothDeviceDiscoveryAgent) + 16u) + QObject (0x0x7f0bf57df5a0) 0 + primary-for QBluetoothDeviceDiscoveryAgent (0x0x7f0bf572e9c0) + +Class QBluetoothHostInfo + size=8 align=8 + base size=8 base align=8 +QBluetoothHostInfo (0x0x7f0bf57df7e0) 0 + +Class QBluetoothLocalDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothLocalDevice::QPrivateSignal (0x0x7f0bf57df9c0) 0 empty + +Vtable for QBluetoothLocalDevice +QBluetoothLocalDevice::_ZTV21QBluetoothLocalDevice: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QBluetoothLocalDevice) +16 (int (*)(...))QBluetoothLocalDevice::metaObject +24 (int (*)(...))QBluetoothLocalDevice::qt_metacast +32 (int (*)(...))QBluetoothLocalDevice::qt_metacall +40 (int (*)(...))QBluetoothLocalDevice::~QBluetoothLocalDevice +48 (int (*)(...))QBluetoothLocalDevice::~QBluetoothLocalDevice +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 QBluetoothLocalDevice + size=24 align=8 + base size=24 base align=8 +QBluetoothLocalDevice (0x0x7f0bf572eaf8) 0 + vptr=((& QBluetoothLocalDevice::_ZTV21QBluetoothLocalDevice) + 16u) + QObject (0x0x7f0bf57df960) 0 + primary-for QBluetoothLocalDevice (0x0x7f0bf572eaf8) + +Class quint128 + size=16 align=1 + base size=16 base align=1 +quint128 (0x0x7f0bf57dfd80) 0 + +Class QBluetoothUuid + size=16 align=4 + base size=16 base align=4 +QBluetoothUuid (0x0x7f0bf572eb60) 0 + QUuid (0x0x7f0bf57dfde0) 0 + +Class QBluetoothServiceInfo::Sequence + size=8 align=8 + base size=8 base align=8 +QBluetoothServiceInfo::Sequence (0x0x7f0bf572ebc8) 0 + QList (0x0x7f0bf572ec30) 0 + QListSpecialMethods (0x0x7f0bf59220c0) 0 empty + +Class QBluetoothServiceInfo::Alternative + size=8 align=8 + base size=8 base align=8 +QBluetoothServiceInfo::Alternative (0x0x7f0bf572ec98) 0 + QList (0x0x7f0bf572ed00) 0 + QListSpecialMethods (0x0x7f0bf5922120) 0 empty + +Class QBluetoothServiceInfo + size=16 align=8 + base size=16 base align=8 +QBluetoothServiceInfo (0x0x7f0bf5922060) 0 + +Class QAbstractSocket::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractSocket::QPrivateSignal (0x0x7f0bf59225a0) 0 empty + +Vtable for QAbstractSocket +QAbstractSocket::_ZTV15QAbstractSocket: 41u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QAbstractSocket) +16 (int (*)(...))QAbstractSocket::metaObject +24 (int (*)(...))QAbstractSocket::qt_metacast +32 (int (*)(...))QAbstractSocket::qt_metacall +40 (int (*)(...))QAbstractSocket::~QAbstractSocket +48 (int (*)(...))QAbstractSocket::~QAbstractSocket +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 (*)(...))QAbstractSocket::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QAbstractSocket::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QAbstractSocket::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QAbstractSocket::bytesAvailable +184 (int (*)(...))QAbstractSocket::bytesToWrite +192 (int (*)(...))QAbstractSocket::canReadLine +200 (int (*)(...))QAbstractSocket::waitForReadyRead +208 (int (*)(...))QAbstractSocket::waitForBytesWritten +216 (int (*)(...))QAbstractSocket::readData +224 (int (*)(...))QAbstractSocket::readLineData +232 (int (*)(...))QAbstractSocket::writeData +240 (int (*)(...))QAbstractSocket::resume +248 (int (*)(...))QAbstractSocket::connectToHost +256 (int (*)(...))QAbstractSocket::connectToHost +264 (int (*)(...))QAbstractSocket::disconnectFromHost +272 (int (*)(...))QAbstractSocket::setReadBufferSize +280 (int (*)(...))QAbstractSocket::socketDescriptor +288 (int (*)(...))QAbstractSocket::setSocketDescriptor +296 (int (*)(...))QAbstractSocket::setSocketOption +304 (int (*)(...))QAbstractSocket::socketOption +312 (int (*)(...))QAbstractSocket::waitForConnected +320 (int (*)(...))QAbstractSocket::waitForDisconnected + +Class QAbstractSocket + size=16 align=8 + base size=16 base align=8 +QAbstractSocket (0x0x7f0bf572ef70) 0 + vptr=((& QAbstractSocket::_ZTV15QAbstractSocket) + 16u) + QIODevice (0x0x7f0bf5598000) 0 + primary-for QAbstractSocket (0x0x7f0bf572ef70) + QObject (0x0x7f0bf5922540) 0 + primary-for QIODevice (0x0x7f0bf5598000) + +Class QBluetoothSocket::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothSocket::QPrivateSignal (0x0x7f0bf5922ba0) 0 empty + +Vtable for QBluetoothSocket +QBluetoothSocket::_ZTV16QBluetoothSocket: 30u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QBluetoothSocket) +16 (int (*)(...))QBluetoothSocket::metaObject +24 (int (*)(...))QBluetoothSocket::qt_metacast +32 (int (*)(...))QBluetoothSocket::qt_metacall +40 (int (*)(...))QBluetoothSocket::~QBluetoothSocket +48 (int (*)(...))QBluetoothSocket::~QBluetoothSocket +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 (*)(...))QBluetoothSocket::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QBluetoothSocket::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QIODevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QBluetoothSocket::bytesAvailable +184 (int (*)(...))QBluetoothSocket::bytesToWrite +192 (int (*)(...))QBluetoothSocket::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QBluetoothSocket::readData +224 (int (*)(...))QIODevice::readLineData +232 (int (*)(...))QBluetoothSocket::writeData + +Class QBluetoothSocket + size=24 align=8 + base size=24 base align=8 +QBluetoothSocket (0x0x7f0bf5598208) 0 + vptr=((& QBluetoothSocket::_ZTV16QBluetoothSocket) + 16u) + QIODevice (0x0x7f0bf5598270) 0 + primary-for QBluetoothSocket (0x0x7f0bf5598208) + QObject (0x0x7f0bf5922b40) 0 + primary-for QIODevice (0x0x7f0bf5598270) + +Class QBluetoothServer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothServer::QPrivateSignal (0x0x7f0bf5922c60) 0 empty + +Vtable for QBluetoothServer +QBluetoothServer::_ZTV16QBluetoothServer: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QBluetoothServer) +16 (int (*)(...))QBluetoothServer::metaObject +24 (int (*)(...))QBluetoothServer::qt_metacast +32 (int (*)(...))QBluetoothServer::qt_metacall +40 (int (*)(...))QBluetoothServer::~QBluetoothServer +48 (int (*)(...))QBluetoothServer::~QBluetoothServer +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 QBluetoothServer + size=24 align=8 + base size=24 base align=8 +QBluetoothServer (0x0x7f0bf55982d8) 0 + vptr=((& QBluetoothServer::_ZTV16QBluetoothServer) + 16u) + QObject (0x0x7f0bf5922c00) 0 + primary-for QBluetoothServer (0x0x7f0bf55982d8) + +Class QBluetoothServiceDiscoveryAgent::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothServiceDiscoveryAgent::QPrivateSignal (0x0x7f0bf5922d20) 0 empty + +Vtable for QBluetoothServiceDiscoveryAgent +QBluetoothServiceDiscoveryAgent::_ZTV31QBluetoothServiceDiscoveryAgent: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI31QBluetoothServiceDiscoveryAgent) +16 (int (*)(...))QBluetoothServiceDiscoveryAgent::metaObject +24 (int (*)(...))QBluetoothServiceDiscoveryAgent::qt_metacast +32 (int (*)(...))QBluetoothServiceDiscoveryAgent::qt_metacall +40 (int (*)(...))QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent +48 (int (*)(...))QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent +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 QBluetoothServiceDiscoveryAgent + size=24 align=8 + base size=24 base align=8 +QBluetoothServiceDiscoveryAgent (0x0x7f0bf5598340) 0 + vptr=((& QBluetoothServiceDiscoveryAgent::_ZTV31QBluetoothServiceDiscoveryAgent) + 16u) + QObject (0x0x7f0bf5922cc0) 0 + primary-for QBluetoothServiceDiscoveryAgent (0x0x7f0bf5598340) + +Class QBluetoothTransferManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothTransferManager::QPrivateSignal (0x0x7f0bf5922de0) 0 empty + +Vtable for QBluetoothTransferManager +QBluetoothTransferManager::_ZTV25QBluetoothTransferManager: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI25QBluetoothTransferManager) +16 (int (*)(...))QBluetoothTransferManager::metaObject +24 (int (*)(...))QBluetoothTransferManager::qt_metacast +32 (int (*)(...))QBluetoothTransferManager::qt_metacall +40 (int (*)(...))QBluetoothTransferManager::~QBluetoothTransferManager +48 (int (*)(...))QBluetoothTransferManager::~QBluetoothTransferManager +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 QBluetoothTransferManager + size=16 align=8 + base size=16 base align=8 +QBluetoothTransferManager (0x0x7f0bf55983a8) 0 + vptr=((& QBluetoothTransferManager::_ZTV25QBluetoothTransferManager) + 16u) + QObject (0x0x7f0bf5922d80) 0 + primary-for QBluetoothTransferManager (0x0x7f0bf55983a8) + +Class QBluetoothTransferRequest + size=8 align=8 + base size=8 base align=8 +QBluetoothTransferRequest (0x0x7f0bf5922e40) 0 + +Class QBluetoothTransferReply::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothTransferReply::QPrivateSignal (0x0x7f0bf5922f00) 0 empty + +Vtable for QBluetoothTransferReply +QBluetoothTransferReply::_ZTV23QBluetoothTransferReply: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI23QBluetoothTransferReply) +16 (int (*)(...))QBluetoothTransferReply::metaObject +24 (int (*)(...))QBluetoothTransferReply::qt_metacast +32 (int (*)(...))QBluetoothTransferReply::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 + +Class QBluetoothTransferReply + size=24 align=8 + base size=24 base align=8 +QBluetoothTransferReply (0x0x7f0bf5598410) 0 + vptr=((& QBluetoothTransferReply::_ZTV23QBluetoothTransferReply) + 16u) + QObject (0x0x7f0bf5922ea0) 0 + primary-for QBluetoothTransferReply (0x0x7f0bf5598410) + +Class QLowEnergyAdvertisingData + size=8 align=8 + base size=8 base align=8 +QLowEnergyAdvertisingData (0x0x7f0bf56b60c0) 0 + +Class QLowEnergyDescriptor + size=24 align=8 + base size=24 base align=8 +QLowEnergyDescriptor (0x0x7f0bf56b6720) 0 + +Class QLowEnergyCharacteristic + size=24 align=8 + base size=24 base align=8 +QLowEnergyCharacteristic (0x0x7f0bf56b6900) 0 + +Class QLowEnergyService::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLowEnergyService::QPrivateSignal (0x0x7f0bf56b6c60) 0 empty + +Vtable for QLowEnergyService +QLowEnergyService::_ZTV17QLowEnergyService: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QLowEnergyService) +16 (int (*)(...))QLowEnergyService::metaObject +24 (int (*)(...))QLowEnergyService::qt_metacast +32 (int (*)(...))QLowEnergyService::qt_metacall +40 (int (*)(...))QLowEnergyService::~QLowEnergyService +48 (int (*)(...))QLowEnergyService::~QLowEnergyService +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 QLowEnergyService + size=32 align=8 + base size=32 base align=8 +QLowEnergyService (0x0x7f0bf5598b60) 0 + vptr=((& QLowEnergyService::_ZTV17QLowEnergyService) + 16u) + QObject (0x0x7f0bf56b6c00) 0 + primary-for QLowEnergyService (0x0x7f0bf5598b60) + +Class QLowEnergyController::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLowEnergyController::QPrivateSignal (0x0x7f0bf53af360) 0 empty + +Vtable for QLowEnergyController +QLowEnergyController::_ZTV20QLowEnergyController: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI20QLowEnergyController) +16 (int (*)(...))QLowEnergyController::metaObject +24 (int (*)(...))QLowEnergyController::qt_metacast +32 (int (*)(...))QLowEnergyController::qt_metacall +40 (int (*)(...))QLowEnergyController::~QLowEnergyController +48 (int (*)(...))QLowEnergyController::~QLowEnergyController +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 QLowEnergyController + size=24 align=8 + base size=24 base align=8 +QLowEnergyController (0x0x7f0bf5598c98) 0 + vptr=((& QLowEnergyController::_ZTV20QLowEnergyController) + 16u) + QObject (0x0x7f0bf53af300) 0 + primary-for QLowEnergyController (0x0x7f0bf5598c98) + +Class QLowEnergyAdvertisingParameters::AddressInfo + size=16 align=8 + base size=12 base align=8 +QLowEnergyAdvertisingParameters::AddressInfo (0x0x7f0bf53af8a0) 0 + +Class QLowEnergyAdvertisingParameters + size=8 align=8 + base size=8 base align=8 +QLowEnergyAdvertisingParameters (0x0x7f0bf53af840) 0 + +Class QLowEnergyCharacteristicData + size=8 align=8 + base size=8 base align=8 +QLowEnergyCharacteristicData (0x0x7f0bf543d840) 0 + +Class QLowEnergyConnectionParameters + size=8 align=8 + base size=8 base align=8 +QLowEnergyConnectionParameters (0x0x7f0bf543dea0) 0 + +Class QLowEnergyDescriptorData + size=8 align=8 + base size=8 base align=8 +QLowEnergyDescriptorData (0x0x7f0bf5492660) 0 + +Class QLowEnergyServiceData + size=8 align=8 + base size=8 base align=8 +QLowEnergyServiceData (0x0x7f0bf5492cc0) 0 + diff --git a/tests/auto/bic/data/QtBluetooth.5.11.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtBluetooth.5.11.0.linux-gcc-amd64.txt new file mode 100644 index 0000000..ed8c8d2 --- /dev/null +++ b/tests/auto/bic/data/QtBluetooth.5.11.0.linux-gcc-amd64.txt @@ -0,0 +1,4988 @@ +Class std::__failure_type + size=1 align=1 + base size=0 base align=1 +std::__failure_type (0x0x7f441c92a780) 0 empty + +Class std::__do_is_destructible_impl + size=1 align=1 + base size=0 base align=1 +std::__do_is_destructible_impl (0x0x7f441c97ff00) 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 (0x0x7f441a52b180) 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 (0x0x7f441a52b3c0) 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 (0x0x7f441a52b600) 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 (0x0x7f441a52b780) 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 (0x0x7f441a52bb40) 0 empty + +Class std::__do_common_type_impl + size=1 align=1 + base size=0 base align=1 +std::__do_common_type_impl (0x0x7f441a5e4300) 0 empty + +Class std::__do_member_type_wrapper + size=1 align=1 + base size=0 base align=1 +std::__do_member_type_wrapper (0x0x7f441a5e43c0) 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 (0x0x7f441a5e4720) 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 (0x0x7f441a5e47e0) 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 (0x0x7f441a5e48a0) 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 (0x0x7f441a5e4960) 0 empty + +Class std::__result_of_other_impl + size=1 align=1 + base size=0 base align=1 +std::__result_of_other_impl (0x0x7f441a5e4c00) 0 empty + +Class std::piecewise_construct_t + size=1 align=1 + base size=0 base align=1 +std::piecewise_construct_t (0x0x7f441a5e4de0) 0 empty + +Class std::__true_type + size=1 align=1 + base size=0 base align=1 +std::__true_type (0x0x7f441a6612a0) 0 empty + +Class std::__false_type + size=1 align=1 + base size=0 base align=1 +std::__false_type (0x0x7f441a661300) 0 empty + +Class std::input_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::input_iterator_tag (0x0x7f441a69ff60) 0 empty + +Class std::output_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::output_iterator_tag (0x0x7f441a6cf000) 0 empty + +Class std::forward_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::forward_iterator_tag (0x0x7f441a59eb60) 0 empty + std::input_iterator_tag (0x0x7f441a6cf060) 0 empty + +Class std::bidirectional_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::bidirectional_iterator_tag (0x0x7f441a59ebc8) 0 empty + std::forward_iterator_tag (0x0x7f441a59ec30) 0 empty + std::input_iterator_tag (0x0x7f441a6cf0c0) 0 empty + +Class std::random_access_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::random_access_iterator_tag (0x0x7f441a59ec98) 0 empty + std::bidirectional_iterator_tag (0x0x7f441a59ed00) 0 empty + std::forward_iterator_tag (0x0x7f441a59ed68) 0 empty + std::input_iterator_tag (0x0x7f441a6cf120) 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 (0x0x7f441a6cfd80) 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 (0x0x7f441a6cfde0) 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 (0x0x7f441a6cfe40) 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 (0x0x7f441a6cfea0) 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 (0x0x7f441a6cff00) 0 empty + +Class wait + size=4 align=4 + base size=4 base align=4 +wait (0x0x7f441a395a20) 0 + +Class __locale_struct + size=232 align=8 + base size=232 base align=8 +__locale_struct (0x0x7f441a395c60) 0 + +Class timespec + size=16 align=8 + base size=16 base align=8 +timespec (0x0x7f441a395d20) 0 + +Class timeval + size=16 align=8 + base size=16 base align=8 +timeval (0x0x7f441a395d80) 0 + +Class pthread_attr_t + size=56 align=8 + base size=56 base align=8 +pthread_attr_t (0x0x7f441a395e40) 0 + +Class __pthread_internal_list + size=16 align=8 + base size=16 base align=8 +__pthread_internal_list (0x0x7f441a395ea0) 0 + +Class random_data + size=48 align=8 + base size=48 base align=8 +random_data (0x0x7f441a447360) 0 + +Class drand48_data + size=24 align=8 + base size=24 base align=8 +drand48_data (0x0x7f441a4473c0) 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 (0x0x7f441a447420) 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 (0x0x7f441a6ff2d8) 0 nearly-empty + vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16u) + std::exception (0x0x7f441a447480) 0 nearly-empty + primary-for std::bad_exception (0x0x7f441a6ff2d8) + +Class std::__exception_ptr::exception_ptr + size=8 align=8 + base size=8 base align=8 +std::__exception_ptr::exception_ptr (0x0x7f441a4474e0) 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 (0x0x7f441a447540) 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 (0x0x7f441a6ff4e0) 0 nearly-empty + vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16u) + std::exception (0x0x7f441a447960) 0 nearly-empty + primary-for std::bad_alloc (0x0x7f441a6ff4e0) + +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 (0x0x7f441a6ff548) 0 nearly-empty + vptr=((& std::bad_array_new_length::_ZTVSt20bad_array_new_length) + 16u) + std::bad_alloc (0x0x7f441a6ff5b0) 0 nearly-empty + primary-for std::bad_array_new_length (0x0x7f441a6ff548) + std::exception (0x0x7f441a4479c0) 0 nearly-empty + primary-for std::bad_alloc (0x0x7f441a6ff5b0) + +Class std::nothrow_t + size=1 align=1 + base size=0 base align=1 +std::nothrow_t (0x0x7f441a447a20) 0 empty + +Class __exception + size=40 align=8 + base size=40 base align=8 +__exception (0x0x7f441a1c1660) 0 + +Class lconv + size=96 align=8 + base size=96 base align=8 +lconv (0x0x7f4419fdb360) 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 (0x0x7f4419fdb3c0) 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 (0x0x7f441a07d2a0) 0 + +Class __sched_param + size=4 align=4 + base size=4 base align=4 +__sched_param (0x0x7f441a07d300) 0 + +Class timex + size=208 align=8 + base size=208 base align=8 +timex (0x0x7f441a07d3c0) 0 + +Class tm + size=56 align=8 + base size=56 base align=8 +tm (0x0x7f441a07d420) 0 + +Class itimerspec + size=32 align=8 + base size=32 base align=8 +itimerspec (0x0x7f441a07d480) 0 + +Class _pthread_cleanup_buffer + size=32 align=8 + base size=32 base align=8 +_pthread_cleanup_buffer (0x0x7f441a07d4e0) 0 + +Class __pthread_cleanup_frame + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_frame (0x0x7f441a07d600) 0 + +Class __pthread_cleanup_class + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_class (0x0x7f441a07d660) 0 + +Class _IO_marker + size=24 align=8 + base size=24 base align=8 +_IO_marker (0x0x7f441a07da80) 0 + +Class _IO_FILE + size=216 align=8 + base size=216 base align=8 +_IO_FILE (0x0x7f441a07dae0) 0 + +Class std::_Hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Hash_impl (0x0x7f4419bb7300) 0 empty + +Class std::_Fnv_hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Fnv_hash_impl (0x0x7f4419bb7360) 0 empty + +Class std::__numeric_limits_base + size=1 align=1 + base size=0 base align=1 +std::__numeric_limits_base (0x0x7f4419c83300) 0 empty + +Class std::_Bit_reference + size=16 align=8 + base size=16 base align=8 +std::_Bit_reference (0x0x7f4419a3d120) 0 + +Class std::_Bit_iterator_base + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator_base (0x0x7f441996d1a0) 0 + std::iterator (0x0x7f4419a3d1e0) 0 empty + +Class std::_Bit_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator (0x0x7f441996d208) 0 + std::_Bit_iterator_base (0x0x7f441996d270) 0 + std::iterator (0x0x7f4419a3d240) 0 empty + +Class std::_Bit_const_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_const_iterator (0x0x7f441996d2d8) 0 + std::_Bit_iterator_base (0x0x7f441996d340) 0 + std::iterator (0x0x7f4419a3d2a0) 0 empty + +Class std::random_device + size=5000 align=8 + base size=5000 base align=8 +std::random_device (0x0x7f44198650c0) 0 + +Class std::bernoulli_distribution::param_type + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution::param_type (0x0x7f4419865e40) 0 + +Class std::bernoulli_distribution + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution (0x0x7f4419865de0) 0 + +Class std::seed_seq + size=24 align=8 + base size=24 base align=8 +std::seed_seq (0x0x7f44195c3de0) 0 + +Class qIsNull(double)::U + size=8 align=8 + base size=8 base align=8 +qIsNull(double)::U (0x0x7f4418249900) 0 + +Class qIsNull(float)::U + size=4 align=4 + base size=4 base align=4 +qIsNull(float)::U (0x0x7f4418249960) 0 + +Class QSysInfo + size=1 align=1 + base size=0 base align=1 +QSysInfo (0x0x7f4417f33420) 0 empty + +Class QMessageLogContext + size=32 align=8 + base size=32 base align=8 +QMessageLogContext (0x0x7f4417f33480) 0 + +Class QMessageLogger + size=32 align=8 + base size=32 base align=8 +QMessageLogger (0x0x7f4417f334e0) 0 + +Class QFlag + size=4 align=4 + base size=4 base align=4 +QFlag (0x0x7f4417f33540) 0 + +Class QIncompatibleFlag + size=4 align=4 + base size=4 base align=4 +QIncompatibleFlag (0x0x7f4417f337e0) 0 + +Class std::__atomic_flag_base + size=1 align=1 + base size=1 base align=1 +std::__atomic_flag_base (0x0x7f4417f33d20) 0 + +Class std::atomic_flag + size=1 align=1 + base size=1 base align=1 +std::atomic_flag (0x0x7f4417f8e208) 0 + std::__atomic_flag_base (0x0x7f4417f33d80) 0 + +Class QAtomicInt + size=4 align=4 + base size=4 base align=4 +QAtomicInt (0x0x7f4417f8e958) 0 + QAtomicInteger (0x0x7f4417f8e9c0) 0 + QBasicAtomicInteger (0x0x7f4417eee4e0) 0 + +Class QInternal + size=1 align=1 + base size=0 base align=1 +QInternal (0x0x7f44179afa80) 0 empty + +Class QtPrivate::QSlotObjectBase + size=16 align=8 + base size=16 base align=8 +QtPrivate::QSlotObjectBase (0x0x7f44177caae0) 0 + +Class QGenericArgument + size=16 align=8 + base size=16 base align=8 +QGenericArgument (0x0x7f44177cac00) 0 + +Class QGenericReturnArgument + size=16 align=8 + base size=16 base align=8 +QGenericReturnArgument (0x0x7f44177eb410) 0 + QGenericArgument (0x0x7f44177cac60) 0 + +Class QMetaObject + size=48 align=8 + base size=48 base align=8 +QMetaObject (0x0x7f44177cade0) 0 + +Class QMetaObject::Connection + size=8 align=8 + base size=8 base align=8 +QMetaObject::Connection (0x0x7f44177caea0) 0 + +Class QLatin1Char + size=1 align=1 + base size=1 base align=1 +QLatin1Char (0x0x7f44178c2f00) 0 + +Class QChar + size=2 align=2 + base size=2 base align=2 +QChar (0x0x7f44178c2f60) 0 + +Class QtPrivate::RefCount + size=4 align=4 + base size=4 base align=4 +QtPrivate::RefCount (0x0x7f4417572240) 0 + +Class QArrayData + size=24 align=8 + base size=24 base align=8 +QArrayData (0x0x7f44175722a0) 0 + +Class QtPrivate::QContainerImplHelper + size=1 align=1 + base size=0 base align=1 +QtPrivate::QContainerImplHelper (0x0x7f4417572600) 0 empty + +Class std::locale + size=8 align=8 + base size=8 base align=8 +std::locale (0x0x7f4417572660) 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 (0x0x7f44175726c0) 0 + vptr=((& std::locale::facet::_ZTVNSt6locale5facetE) + 16u) + +Class std::locale::id + size=8 align=8 + base size=8 base align=8 +std::locale::id (0x0x7f4417572720) 0 + +Class std::locale::_Impl + size=40 align=8 + base size=40 base align=8 +std::locale::_Impl (0x0x7f4417572780) 0 + +Class std::__cow_string + size=8 align=8 + base size=8 base align=8 +std::__cow_string (0x0x7f4417572b40) 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 (0x0x7f44175f2a28) 0 + vptr=((& std::logic_error::_ZTVSt11logic_error) + 16u) + std::exception (0x0x7f4417572c00) 0 nearly-empty + primary-for std::logic_error (0x0x7f44175f2a28) + +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 (0x0x7f44175f2a90) 0 + vptr=((& std::domain_error::_ZTVSt12domain_error) + 16u) + std::logic_error (0x0x7f44175f2af8) 0 + primary-for std::domain_error (0x0x7f44175f2a90) + std::exception (0x0x7f4417572c60) 0 nearly-empty + primary-for std::logic_error (0x0x7f44175f2af8) + +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 (0x0x7f44175f2b60) 0 + vptr=((& std::invalid_argument::_ZTVSt16invalid_argument) + 16u) + std::logic_error (0x0x7f44175f2bc8) 0 + primary-for std::invalid_argument (0x0x7f44175f2b60) + std::exception (0x0x7f4417572cc0) 0 nearly-empty + primary-for std::logic_error (0x0x7f44175f2bc8) + +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 (0x0x7f44175f2c30) 0 + vptr=((& std::length_error::_ZTVSt12length_error) + 16u) + std::logic_error (0x0x7f44175f2c98) 0 + primary-for std::length_error (0x0x7f44175f2c30) + std::exception (0x0x7f4417572d20) 0 nearly-empty + primary-for std::logic_error (0x0x7f44175f2c98) + +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 (0x0x7f44175f2d00) 0 + vptr=((& std::out_of_range::_ZTVSt12out_of_range) + 16u) + std::logic_error (0x0x7f44175f2d68) 0 + primary-for std::out_of_range (0x0x7f44175f2d00) + std::exception (0x0x7f4417572d80) 0 nearly-empty + primary-for std::logic_error (0x0x7f44175f2d68) + +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 (0x0x7f44175f2dd0) 0 + vptr=((& std::runtime_error::_ZTVSt13runtime_error) + 16u) + std::exception (0x0x7f4417572de0) 0 nearly-empty + primary-for std::runtime_error (0x0x7f44175f2dd0) + +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 (0x0x7f44175f2e38) 0 + vptr=((& std::range_error::_ZTVSt11range_error) + 16u) + std::runtime_error (0x0x7f44175f2ea0) 0 + primary-for std::range_error (0x0x7f44175f2e38) + std::exception (0x0x7f4417572e40) 0 nearly-empty + primary-for std::runtime_error (0x0x7f44175f2ea0) + +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 (0x0x7f44175f2f08) 0 + vptr=((& std::overflow_error::_ZTVSt14overflow_error) + 16u) + std::runtime_error (0x0x7f44175f2f70) 0 + primary-for std::overflow_error (0x0x7f44175f2f08) + std::exception (0x0x7f4417572ea0) 0 nearly-empty + primary-for std::runtime_error (0x0x7f44175f2f70) + +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 (0x0x7f44175f2750) 0 + vptr=((& std::underflow_error::_ZTVSt15underflow_error) + 16u) + std::runtime_error (0x0x7f44175f2820) 0 + primary-for std::underflow_error (0x0x7f44175f2750) + std::exception (0x0x7f4417572f00) 0 nearly-empty + primary-for std::runtime_error (0x0x7f44175f2820) + +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 (0x0x7f44176bc0c0) 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 (0x0x7f44176bc300) 0 + +Class std::error_condition + size=16 align=8 + base size=16 base align=8 +std::error_condition (0x0x7f44176bc480) 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 (0x0x7f44176b9478) 0 + vptr=((& std::system_error::_ZTVSt12system_error) + 16u) + std::runtime_error (0x0x7f44176b94e0) 0 + primary-for std::system_error (0x0x7f44176b9478) + std::exception (0x0x7f44176bc6c0) 0 nearly-empty + primary-for std::runtime_error (0x0x7f44176b94e0) + +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 (0x0x7f44173310d0) 0 + vptr=((& std::ios_base::failure::_ZTVNSt8ios_base7failureB5cxx11E) + 16u) + std::system_error (0x0x7f4417331138) 0 + primary-for std::ios_base::failure (0x0x7f44173310d0) + std::runtime_error (0x0x7f44173311a0) 0 + primary-for std::system_error (0x0x7f4417331138) + std::exception (0x0x7f44176bc9c0) 0 nearly-empty + primary-for std::runtime_error (0x0x7f44173311a0) + +Class std::ios_base::_Callback_list + size=24 align=8 + base size=24 base align=8 +std::ios_base::_Callback_list (0x0x7f44176bca20) 0 + +Class std::ios_base::_Words + size=16 align=8 + base size=16 base align=8 +std::ios_base::_Words (0x0x7f44176bca80) 0 + +Class std::ios_base::Init + size=1 align=1 + base size=0 base align=1 +std::ios_base::Init (0x0x7f44176bcae0) 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 (0x0x7f44176bc960) 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 (0x0x7f44173f62a0) 0 empty + +Class std::__num_base + size=1 align=1 + base size=0 base align=1 +std::__num_base (0x0x7f44173f6960) 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 (0x0x7f4416fa1c30 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 (0x0x7f4416fa1d00 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 (0x0x7f4416fa11a0 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 (0x0x7f4416fa12d8 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 (0x0x7f44170231e0) 0 + +Class QByteArray + size=8 align=8 + base size=8 base align=8 +QByteArray (0x0x7f4417023240) 0 + +Class QByteRef + size=16 align=8 + base size=12 base align=8 +QByteRef (0x0x7f4416d365a0) 0 + +Class QStringDataPtr + size=8 align=8 + base size=8 base align=8 +QStringDataPtr (0x0x7f4416d36900) 0 + +Class QStringView + size=16 align=8 + base size=16 base align=8 +QStringView (0x0x7f4416d36d80) 0 + +Class QLatin1String + size=16 align=8 + base size=16 base align=8 +QLatin1String (0x0x7f4416e6cc00) 0 + +Class QString::Null + size=1 align=1 + base size=0 base align=1 +QString::Null (0x0x7f4416efc2a0) 0 empty + +Class QString + size=8 align=8 + base size=8 base align=8 +QString (0x0x7f4416efc240) 0 + +Class QCharRef + size=16 align=8 + base size=12 base align=8 +QCharRef (0x0x7f4416ca6360) 0 + +Class QStringRef + size=16 align=8 + base size=16 base align=8 +QStringRef (0x0x7f4416ca6f60) 0 + +Class QtPrivate::QHashCombine + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombine (0x0x7f4416a9bc00) 0 empty + +Class QtPrivate::QHashCombineCommutative + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombineCommutative (0x0x7f4416a9bc60) 0 empty + +Class std::__detail::_List_node_base + size=16 align=8 + base size=16 base align=8 +std::__detail::_List_node_base (0x0x7f4416a9bcc0) 0 + +Class QListData::NotArrayCompatibleLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotArrayCompatibleLayout (0x0x7f44169040c0) 0 empty + +Class QListData::NotIndirectLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotIndirectLayout (0x0x7f4416904120) 0 empty + +Class QListData::ArrayCompatibleLayout + size=1 align=1 + base size=1 base align=1 +QListData::ArrayCompatibleLayout (0x0x7f4416ab6a28) 0 empty + QListData::NotIndirectLayout (0x0x7f4416904180) 0 empty + +Class QListData::InlineWithPaddingLayout + size=1 align=1 + base size=1 base align=1 +QListData::InlineWithPaddingLayout (0x0x7f44168fecb0) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7f44169041e0) 0 empty + QListData::NotIndirectLayout (0x0x7f4416904240) 0 empty + +Class QListData::IndirectLayout + size=1 align=1 + base size=1 base align=1 +QListData::IndirectLayout (0x0x7f4416ab6a90) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7f44169042a0) 0 empty + +Class QListData::Data + size=24 align=8 + base size=24 base align=8 +QListData::Data (0x0x7f4416904300) 0 + +Class QListData + size=8 align=8 + base size=8 base align=8 +QListData (0x0x7f4416904060) 0 + +Class QRegExp + size=8 align=8 + base size=8 base align=8 +QRegExp (0x0x7f4416904780) 0 + +Class QStringMatcher::Data + size=272 align=8 + base size=272 base align=8 +QStringMatcher::Data (0x0x7f44166b49c0) 0 + +Class QStringMatcher + size=1048 align=8 + base size=1048 base align=8 +QStringMatcher (0x0x7f44166b4960) 0 + +Class QStringList + size=8 align=8 + base size=8 base align=8 +QStringList (0x0x7f44166be4e0) 0 + QList (0x0x7f44166be548) 0 + QListSpecialMethods (0x0x7f44166b4ba0) 0 empty + +Class QScopedPointerPodDeleter + size=1 align=1 + base size=0 base align=1 +QScopedPointerPodDeleter (0x0x7f4416355000) 0 empty + +Class std::_Rb_tree_node_base + size=32 align=8 + base size=32 base align=8 +std::_Rb_tree_node_base (0x0x7f4416355ba0) 0 + +Class std::allocator_arg_t + size=1 align=1 + base size=0 base align=1 +std::allocator_arg_t (0x0x7f4416144240) 0 empty + +Class std::__uses_alloc_base + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc_base (0x0x7f44161443c0) 0 empty + +Class std::__uses_alloc0::_Sink + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc0::_Sink (0x0x7f4416144480) 0 empty + +Class std::__uses_alloc0 + size=1 align=1 + base size=1 base align=1 +std::__uses_alloc0 (0x0x7f44166bee38) 0 + std::__uses_alloc_base (0x0x7f4416144420) 0 empty + +Class std::_Swallow_assign + size=1 align=1 + base size=0 base align=1 +std::_Swallow_assign (0x0x7f441625f4e0) 0 empty + +Class QtPrivate::AbstractDebugStreamFunction + size=16 align=8 + base size=16 base align=8 +QtPrivate::AbstractDebugStreamFunction (0x0x7f441625f720) 0 + +Class QtPrivate::AbstractComparatorFunction + size=24 align=8 + base size=24 base align=8 +QtPrivate::AbstractComparatorFunction (0x0x7f441625f7e0) 0 + +Class QtPrivate::AbstractConverterFunction + size=8 align=8 + base size=8 base align=8 +QtPrivate::AbstractConverterFunction (0x0x7f441625f900) 0 + +Class QMetaType + size=80 align=8 + base size=80 base align=8 +QMetaType (0x0x7f441625fa80) 0 + +Class QtMetaTypePrivate::VariantData + size=24 align=8 + base size=20 base align=8 +QtMetaTypePrivate::VariantData (0x0x7f441625fea0) 0 + +Class QtMetaTypePrivate::VectorBoolElements + size=1 align=1 + base size=0 base align=1 +QtMetaTypePrivate::VectorBoolElements (0x0x7f4415fbd000) 0 empty + +Class QtMetaTypePrivate::QSequentialIterableImpl + size=104 align=8 + base size=104 base align=8 +QtMetaTypePrivate::QSequentialIterableImpl (0x0x7f4415fbd960) 0 + +Class QtMetaTypePrivate::QAssociativeIterableImpl + size=112 align=8 + base size=112 base align=8 +QtMetaTypePrivate::QAssociativeIterableImpl (0x0x7f4415fbdd80) 0 + +Class QtMetaTypePrivate::QPairVariantInterfaceImpl + size=40 align=8 + base size=40 base align=8 +QtMetaTypePrivate::QPairVariantInterfaceImpl (0x0x7f44160ac0c0) 0 + +Class std::chrono::_V2::system_clock + size=1 align=1 + base size=0 base align=1 +std::chrono::_V2::system_clock (0x0x7f4415ecf900) 0 empty + +Class std::chrono::_V2::steady_clock + size=1 align=1 + base size=0 base align=1 +std::chrono::_V2::steady_clock (0x0x7f4415c36780) 0 empty + +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 (0x0x7f4415c367e0) 0 + vptr=((& QObjectData::_ZTV11QObjectData) + 16u) + +Class QObject::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObject::QPrivateSignal (0x0x7f4415c369c0) 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 (0x0x7f4415c36960) 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 (0x0x7f4415cfec60) 0 nearly-empty + vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16u) + +Class QSignalBlocker + size=16 align=8 + base size=10 base align=8 +QSignalBlocker (0x0x7f4415cfecc0) 0 + +Class QAbstractAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractAnimation::QPrivateSignal (0x0x7f4415cfed80) 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 (0x0x7f441592d068) 0 + vptr=((& QAbstractAnimation::_ZTV18QAbstractAnimation) + 16u) + QObject (0x0x7f4415cfed20) 0 + primary-for QAbstractAnimation (0x0x7f441592d068) + +Class QAnimationDriver::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationDriver::QPrivateSignal (0x0x7f4415cfee40) 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 (0x0x7f441592d0d0) 0 + vptr=((& QAnimationDriver::_ZTV16QAnimationDriver) + 16u) + QObject (0x0x7f4415cfede0) 0 + primary-for QAnimationDriver (0x0x7f441592d0d0) + +Class QEventLoop::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventLoop::QPrivateSignal (0x0x7f4415cfef00) 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 (0x0x7f441592d138) 0 + vptr=((& QEventLoop::_ZTV10QEventLoop) + 16u) + QObject (0x0x7f4415cfeea0) 0 + primary-for QEventLoop (0x0x7f441592d138) + +Class QEventLoopLocker + size=8 align=8 + base size=8 base align=8 +QEventLoopLocker (0x0x7f4415987120) 0 + +Class QAbstractEventDispatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractEventDispatcher::QPrivateSignal (0x0x7f44159871e0) 0 empty + +Class QAbstractEventDispatcher::TimerInfo + size=12 align=4 + base size=12 base align=4 +QAbstractEventDispatcher::TimerInfo (0x0x7f4415987240) 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 (0x0x7f441592d270) 0 + vptr=((& QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher) + 16u) + QObject (0x0x7f4415987180) 0 + primary-for QAbstractEventDispatcher (0x0x7f441592d270) + +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 (0x0x7f44159874e0) 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 (0x0x7f441592d478) 0 nearly-empty + vptr=((& std::bad_cast::_ZTVSt8bad_cast) + 16u) + std::exception (0x0x7f4415987540) 0 nearly-empty + primary-for std::bad_cast (0x0x7f441592d478) + +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 (0x0x7f441592d4e0) 0 nearly-empty + vptr=((& std::bad_typeid::_ZTVSt10bad_typeid) + 16u) + std::exception (0x0x7f44159875a0) 0 nearly-empty + primary-for std::bad_typeid (0x0x7f441592d4e0) + +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 (0x0x7f4415ae9750) 0 nearly-empty + vptr=((& std::bad_function_call::_ZTVSt17bad_function_call) + 16u) + std::exception (0x0x7f441574c660) 0 nearly-empty + primary-for std::bad_function_call (0x0x7f4415ae9750) + +Class std::_Nocopy_types + size=16 align=8 + base size=16 base align=8 +std::_Nocopy_types (0x0x7f441574c720) 0 + +Class std::_Any_data + size=16 align=8 + base size=16 base align=8 +std::_Any_data (0x0x7f441574c780) 0 + +Class std::_Function_base + size=24 align=8 + base size=24 base align=8 +std::_Function_base (0x0x7f441574c8a0) 0 + +Class QMapNodeBase + size=24 align=8 + base size=24 base align=8 +QMapNodeBase (0x0x7f441574cd80) 0 + +Class QMapDataBase + size=40 align=8 + base size=40 base align=8 +QMapDataBase (0x0x7f4415805300) 0 + +Class QHashData::Node + size=16 align=8 + base size=16 base align=8 +QHashData::Node (0x0x7f44158056c0) 0 + +Class QHashData + size=48 align=8 + base size=44 base align=8 +QHashData (0x0x7f4415805660) 0 + +Class QHashDummyValue + size=1 align=1 + base size=0 base align=1 +QHashDummyValue (0x0x7f4415805720) 0 empty + +Class QVariant::PrivateShared + size=16 align=8 + base size=12 base align=8 +QVariant::PrivateShared (0x0x7f4415644000) 0 + +Class QVariant::Private::Data + size=8 align=8 + base size=8 base align=8 +QVariant::Private::Data (0x0x7f44156440c0) 0 + +Class QVariant::Private + size=16 align=8 + base size=12 base align=8 +QVariant::Private (0x0x7f4415644060) 0 + +Class QVariant::Handler + size=72 align=8 + base size=72 base align=8 +QVariant::Handler (0x0x7f4415644120) 0 + +Class QVariant + size=16 align=8 + base size=16 base align=8 +QVariant (0x0x7f4415805f60) 0 + +Class QVariantComparisonHelper + size=8 align=8 + base size=8 base align=8 +QVariantComparisonHelper (0x0x7f44156edc00) 0 + +Class QSequentialIterable::const_iterator + size=112 align=8 + base size=112 base align=8 +QSequentialIterable::const_iterator (0x0x7f441538f2a0) 0 + +Class QSequentialIterable + size=104 align=8 + base size=104 base align=8 +QSequentialIterable (0x0x7f441538f240) 0 + +Class QAssociativeIterable::const_iterator + size=120 align=8 + base size=120 base align=8 +QAssociativeIterable::const_iterator (0x0x7f441538f360) 0 + +Class QAssociativeIterable + size=112 align=8 + base size=112 base align=8 +QAssociativeIterable (0x0x7f441538f300) 0 + +Class QModelIndex + size=24 align=8 + base size=24 base align=8 +QModelIndex (0x0x7f44154b0660) 0 + +Class QPersistentModelIndex + size=8 align=8 + base size=8 base align=8 +QPersistentModelIndex (0x0x7f44154b0d20) 0 + +Class QAbstractItemModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractItemModel::QPrivateSignal (0x0x7f4415299480) 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 (0x0x7f441529c4e0) 0 + vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16u) + QObject (0x0x7f4415299420) 0 + primary-for QAbstractItemModel (0x0x7f441529c4e0) + +Class QAbstractTableModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTableModel::QPrivateSignal (0x0x7f4415299d20) 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 (0x0x7f441529cbc8) 0 + vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16u) + QAbstractItemModel (0x0x7f441529cc30) 0 + primary-for QAbstractTableModel (0x0x7f441529cbc8) + QObject (0x0x7f4415299cc0) 0 + primary-for QAbstractItemModel (0x0x7f441529cc30) + +Class QAbstractListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractListModel::QPrivateSignal (0x0x7f4415299de0) 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 (0x0x7f441529cc98) 0 + vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16u) + QAbstractItemModel (0x0x7f441529cd00) 0 + primary-for QAbstractListModel (0x0x7f441529cc98) + QObject (0x0x7f4415299d80) 0 + primary-for QAbstractItemModel (0x0x7f441529cd00) + +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 (0x0x7f4414fd30c0) 0 + vptr=((& QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter) + 16u) + +Class QAbstractProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractProxyModel::QPrivateSignal (0x0x7f4414fd3180) 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 (0x0x7f441529ce38) 0 + vptr=((& QAbstractProxyModel::_ZTV19QAbstractProxyModel) + 16u) + QAbstractItemModel (0x0x7f441529cea0) 0 + primary-for QAbstractProxyModel (0x0x7f441529ce38) + QObject (0x0x7f4414fd3120) 0 + primary-for QAbstractItemModel (0x0x7f441529cea0) + +Class QAbstractState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractState::QPrivateSignal (0x0x7f4414fd3240) 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 (0x0x7f441529cf08) 0 + vptr=((& QAbstractState::_ZTV14QAbstractState) + 16u) + QObject (0x0x7f4414fd31e0) 0 + primary-for QAbstractState (0x0x7f441529cf08) + +Class QAbstractTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTransition::QPrivateSignal (0x0x7f4414fd3300) 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 (0x0x7f441529cf70) 0 + vptr=((& QAbstractTransition::_ZTV19QAbstractTransition) + 16u) + QObject (0x0x7f4414fd32a0) 0 + primary-for QAbstractTransition (0x0x7f441529cf70) + +Class QAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationGroup::QPrivateSignal (0x0x7f4414fd33c0) 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 (0x0x7f4415020000) 0 + vptr=((& QAnimationGroup::_ZTV15QAnimationGroup) + 16u) + QAbstractAnimation (0x0x7f4415020068) 0 + primary-for QAnimationGroup (0x0x7f4415020000) + QObject (0x0x7f4414fd3360) 0 + primary-for QAbstractAnimation (0x0x7f4415020068) + +Class QBasicTimer + size=4 align=4 + base size=4 base align=4 +QBasicTimer (0x0x7f441506d120) 0 + +Class QBitArray + size=8 align=8 + base size=8 base align=8 +QBitArray (0x0x7f441506d3c0) 0 + +Class QBitRef + size=16 align=8 + base size=12 base align=8 +QBitRef (0x0x7f441506d480) 0 + +Class QIODevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIODevice::QPrivateSignal (0x0x7f441506d780) 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 (0x0x7f44150206e8) 0 + vptr=((& QIODevice::_ZTV9QIODevice) + 16u) + QObject (0x0x7f441506d720) 0 + primary-for QIODevice (0x0x7f44150206e8) + +Class QBuffer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBuffer::QPrivateSignal (0x0x7f441506d9c0) 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 (0x0x7f4415020820) 0 + vptr=((& QBuffer::_ZTV7QBuffer) + 16u) + QIODevice (0x0x7f4415020888) 0 + primary-for QBuffer (0x0x7f4415020820) + QObject (0x0x7f441506d960) 0 + primary-for QIODevice (0x0x7f4415020888) + +Class QByteArrayMatcher::Data + size=272 align=8 + base size=272 base align=8 +QByteArrayMatcher::Data (0x0x7f441506da80) 0 + +Class QByteArrayMatcher + size=1040 align=8 + base size=1040 base align=8 +QByteArrayMatcher (0x0x7f441506da20) 0 + +Class QStaticByteArrayMatcherBase::Skiptable + size=256 align=1 + base size=256 base align=1 +QStaticByteArrayMatcherBase::Skiptable (0x0x7f441506dba0) 0 + +Class QStaticByteArrayMatcherBase + size=256 align=16 + base size=256 base align=16 +QStaticByteArrayMatcherBase (0x0x7f441506db40) 0 + +Class QSharedData + size=4 align=4 + base size=4 base align=4 +QSharedData (0x0x7f441506dd80) 0 + +Class QLocale + size=8 align=8 + base size=8 base align=8 +QLocale (0x0x7f441506df60) 0 + +Class QCollatorSortKey + size=8 align=8 + base size=8 base align=8 +QCollatorSortKey (0x0x7f4414e405a0) 0 + +Class QCollator + size=8 align=8 + base size=8 base align=8 +QCollator (0x0x7f4414e40660) 0 + +Class QCommandLineOption + size=8 align=8 + base size=8 base align=8 +QCommandLineOption (0x0x7f4414b3d660) 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 (0x0x7f4414b3dae0) 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 (0x0x7f4414b36d68) 0 + vptr=((& QTimerEvent::_ZTV11QTimerEvent) + 16u) + QEvent (0x0x7f4414b3db40) 0 + primary-for QTimerEvent (0x0x7f4414b36d68) + +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 (0x0x7f4414b36dd0) 0 + vptr=((& QChildEvent::_ZTV11QChildEvent) + 16u) + QEvent (0x0x7f4414b3dba0) 0 + primary-for QChildEvent (0x0x7f4414b36dd0) + +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 (0x0x7f4414bbf340) 0 + vptr=((& QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent) + 16u) + QEvent (0x0x7f4414bc20c0) 0 + primary-for QDynamicPropertyChangeEvent (0x0x7f4414bbf340) + +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 (0x0x7f4414bbf3a8) 0 + vptr=((& QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent) + 16u) + QEvent (0x0x7f4414bc2120) 0 + primary-for QDeferredDeleteEvent (0x0x7f4414bbf3a8) + +Class QCoreApplication::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QCoreApplication::QPrivateSignal (0x0x7f4414bc21e0) 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 (0x0x7f4414bbf410) 0 + vptr=((& QCoreApplication::_ZTV16QCoreApplication) + 16u) + QObject (0x0x7f4414bc2180) 0 + primary-for QCoreApplication (0x0x7f4414bbf410) + +Class QCommandLineParser + size=8 align=8 + base size=8 base align=8 +QCommandLineParser (0x0x7f4414bc2240) 0 + +Class QContiguousCacheData + size=24 align=4 + base size=24 base align=4 +QContiguousCacheData (0x0x7f4414bc22a0) 0 + +Class QCryptographicHash + size=8 align=8 + base size=8 base align=8 +QCryptographicHash (0x0x7f4414bc28a0) 0 + +Class QDataStream + size=32 align=8 + base size=32 base align=8 +QDataStream (0x0x7f4414bc2900) 0 + +Class QtPrivate::StreamStateSaver + size=16 align=8 + base size=12 base align=8 +QtPrivate::StreamStateSaver (0x0x7f4414bc29c0) 0 + +Class QDate + size=8 align=8 + base size=8 base align=8 +QDate (0x0x7f4414bc2ea0) 0 + +Class QTime + size=4 align=4 + base size=4 base align=4 +QTime (0x0x7f4414cef180) 0 + +Class QDateTime::ShortData + size=8 align=8 + base size=8 base align=8 +QDateTime::ShortData (0x0x7f4414cef900) 0 + +Class QDateTime::Data + size=8 align=8 + base size=8 base align=8 +QDateTime::Data (0x0x7f4414cef960) 0 + +Class QDateTime + size=8 align=8 + base size=8 base align=8 +QDateTime (0x0x7f4414cef8a0) 0 + +Class QElapsedTimer + size=16 align=8 + base size=16 base align=8 +QElapsedTimer (0x0x7f44149b4a80) 0 + +Class QDeadlineTimer + size=16 align=8 + base size=16 base align=8 +QDeadlineTimer (0x0x7f44149b4f60) 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 (0x0x7f4414ad5f00) 0 + vptr=((& QTextStream::_ZTV11QTextStream) + 16u) + +Class QTextStreamManipulator + size=40 align=8 + base size=38 base align=8 +QTextStreamManipulator (0x0x7f441475b1e0) 0 + +Class QtSharedPointer::NormalDeleter + size=1 align=1 + base size=0 base align=1 +QtSharedPointer::NormalDeleter (0x0x7f441475b420) 0 empty + +Class QtSharedPointer::ExternalRefCountData + size=16 align=8 + base size=16 base align=8 +QtSharedPointer::ExternalRefCountData (0x0x7f441475b5a0) 0 + +Class QDebug::Stream + size=80 align=8 + base size=76 base align=8 +QDebug::Stream (0x0x7f441475bae0) 0 + +Class QDebug + size=8 align=8 + base size=8 base align=8 +QDebug (0x0x7f441475ba80) 0 + +Class QDebugStateSaver + size=8 align=8 + base size=8 base align=8 +QDebugStateSaver (0x0x7f44145d6000) 0 + +Class QNoDebug + size=1 align=1 + base size=0 base align=1 +QNoDebug (0x0x7f44145d60c0) 0 empty + +Class QFileDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileDevice::QPrivateSignal (0x0x7f441467a240) 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 (0x0x7f441467d270) 0 + vptr=((& QFileDevice::_ZTV11QFileDevice) + 16u) + QIODevice (0x0x7f441467d2d8) 0 + primary-for QFileDevice (0x0x7f441467d270) + QObject (0x0x7f441467a1e0) 0 + primary-for QIODevice (0x0x7f441467d2d8) + +Class QFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFile::QPrivateSignal (0x0x7f441467a480) 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 (0x0x7f441467d410) 0 + vptr=((& QFile::_ZTV5QFile) + 16u) + QFileDevice (0x0x7f441467d478) 0 + primary-for QFile (0x0x7f441467d410) + QIODevice (0x0x7f441467d4e0) 0 + primary-for QFileDevice (0x0x7f441467d478) + QObject (0x0x7f441467a420) 0 + primary-for QIODevice (0x0x7f441467d4e0) + +Class QFileInfo + size=8 align=8 + base size=8 base align=8 +QFileInfo (0x0x7f441467a660) 0 + +Class QDir + size=8 align=8 + base size=8 base align=8 +QDir (0x0x7f441467aa80) 0 + +Class QDirIterator + size=8 align=8 + base size=8 base align=8 +QDirIterator (0x0x7f441439e0c0) 0 + +Class QEasingCurve + size=8 align=8 + base size=8 base align=8 +QEasingCurve (0x0x7f441439e300) 0 + +Class QEventTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventTransition::QPrivateSignal (0x0x7f4414489720) 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 (0x0x7f441448e410) 0 + vptr=((& QEventTransition::_ZTV16QEventTransition) + 16u) + QAbstractTransition (0x0x7f441448e478) 0 + primary-for QEventTransition (0x0x7f441448e410) + QObject (0x0x7f44144896c0) 0 + primary-for QAbstractTransition (0x0x7f441448e478) + +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 (0x0x7f441448e4e0) 0 nearly-empty + vptr=((& QException::_ZTV10QException) + 16u) + std::exception (0x0x7f4414489780) 0 nearly-empty + primary-for QException (0x0x7f441448e4e0) + +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 (0x0x7f441448e548) 0 nearly-empty + vptr=((& QUnhandledException::_ZTV19QUnhandledException) + 16u) + QException (0x0x7f441448e5b0) 0 nearly-empty + primary-for QUnhandledException (0x0x7f441448e548) + std::exception (0x0x7f44144897e0) 0 nearly-empty + primary-for QException (0x0x7f441448e5b0) + +Class QtPrivate::ExceptionHolder + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionHolder (0x0x7f4414489840) 0 + +Class QtPrivate::ExceptionStore + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionStore (0x0x7f4414489900) 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 (0x0x7f4414489960) 0 nearly-empty + vptr=((& QFactoryInterface::_ZTV17QFactoryInterface) + 16u) + +Class QFileSelector::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSelector::QPrivateSignal (0x0x7f4414489a80) 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 (0x0x7f441448e618) 0 + vptr=((& QFileSelector::_ZTV13QFileSelector) + 16u) + QObject (0x0x7f4414489a20) 0 + primary-for QFileSelector (0x0x7f441448e618) + +Class QFileSystemWatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSystemWatcher::QPrivateSignal (0x0x7f4414489b40) 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 (0x0x7f441448e680) 0 + vptr=((& QFileSystemWatcher::_ZTV18QFileSystemWatcher) + 16u) + QObject (0x0x7f4414489ae0) 0 + primary-for QFileSystemWatcher (0x0x7f441448e680) + +Class QFinalState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFinalState::QPrivateSignal (0x0x7f4414489c00) 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 (0x0x7f441448e6e8) 0 + vptr=((& QFinalState::_ZTV11QFinalState) + 16u) + QAbstractState (0x0x7f441448e750) 0 + primary-for QFinalState (0x0x7f441448e6e8) + QObject (0x0x7f4414489ba0) 0 + primary-for QAbstractState (0x0x7f441448e750) + +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 (0x0x7f4414489c60) 0 + vptr=((& QRunnable::_ZTV9QRunnable) + 16u) + +Class QBasicMutex + size=8 align=8 + base size=8 base align=8 +QBasicMutex (0x0x7f4414489cc0) 0 + +Class QMutex + size=8 align=8 + base size=8 base align=8 +QMutex (0x0x7f441448e888) 0 + QBasicMutex (0x0x7f4414489ea0) 0 + +Class QMutexLocker + size=8 align=8 + base size=8 base align=8 +QMutexLocker (0x0x7f4414489f00) 0 + +Class QtPrivate::ResultItem + size=16 align=8 + base size=16 base align=8 +QtPrivate::ResultItem (0x0x7f4414489f60) 0 + +Class QtPrivate::ResultIteratorBase + size=16 align=8 + base size=12 base align=8 +QtPrivate::ResultIteratorBase (0x0x7f44141d2000) 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 (0x0x7f44141d2120) 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 (0x0x7f44141d2960) 0 + vptr=((& QFutureInterfaceBase::_ZTV20QFutureInterfaceBase) + 16u) + +Class QFutureWatcherBase::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFutureWatcherBase::QPrivateSignal (0x0x7f44142a7180) 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 (0x0x7f44142219c0) 0 + vptr=((& QFutureWatcherBase::_ZTV18QFutureWatcherBase) + 16u) + QObject (0x0x7f44142a7120) 0 + primary-for QFutureWatcherBase (0x0x7f44142219c0) + +Class QHistoryState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QHistoryState::QPrivateSignal (0x0x7f44142a7780) 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 (0x0x7f44142fd2d8) 0 + vptr=((& QHistoryState::_ZTV13QHistoryState) + 16u) + QAbstractState (0x0x7f44142fd340) 0 + primary-for QHistoryState (0x0x7f44142fd2d8) + QObject (0x0x7f44142a7720) 0 + primary-for QAbstractState (0x0x7f44142fd340) + +Class QIdentityProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIdentityProxyModel::QPrivateSignal (0x0x7f44142a7840) 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 (0x0x7f44142fd3a8) 0 + vptr=((& QIdentityProxyModel::_ZTV19QIdentityProxyModel) + 16u) + QAbstractProxyModel (0x0x7f44142fd410) 0 + primary-for QIdentityProxyModel (0x0x7f44142fd3a8) + QAbstractItemModel (0x0x7f44142fd478) 0 + primary-for QAbstractProxyModel (0x0x7f44142fd410) + QObject (0x0x7f44142a77e0) 0 + primary-for QAbstractItemModel (0x0x7f44142fd478) + +Class QItemSelectionRange + size=16 align=8 + base size=16 base align=8 +QItemSelectionRange (0x0x7f44142a78a0) 0 + +Class QItemSelectionModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QItemSelectionModel::QPrivateSignal (0x0x7f44142a7f60) 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 (0x0x7f44142fdc98) 0 + vptr=((& QItemSelectionModel::_ZTV19QItemSelectionModel) + 16u) + QObject (0x0x7f44142a7f00) 0 + primary-for QItemSelectionModel (0x0x7f44142fdc98) + +Class QItemSelection + size=8 align=8 + base size=8 base align=8 +QItemSelection (0x0x7f44142fdea0) 0 + QList (0x0x7f44142fdf08) 0 + QListSpecialMethods (0x0x7f4413f9a2a0) 0 empty + +Class QJsonValue + size=24 align=8 + base size=20 base align=8 +QJsonValue (0x0x7f4413f9a780) 0 + +Class QJsonValueRef + size=16 align=8 + base size=12 base align=8 +QJsonValueRef (0x0x7f4413d59ea0) 0 + +Class QJsonValuePtr + size=24 align=8 + base size=24 base align=8 +QJsonValuePtr (0x0x7f4413dce420) 0 + +Class QJsonValueRefPtr + size=16 align=8 + base size=16 base align=8 +QJsonValueRefPtr (0x0x7f4413dce480) 0 + +Class QJsonArray::iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::iterator (0x0x7f4413dce660) 0 + +Class QJsonArray::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::const_iterator (0x0x7f4413dce6c0) 0 + +Class QJsonArray + size=16 align=8 + base size=16 base align=8 +QJsonArray (0x0x7f4413dce600) 0 + +Class QJsonParseError + size=8 align=4 + base size=8 base align=4 +QJsonParseError (0x0x7f4413e90900) 0 + +Class QJsonDocument + size=8 align=8 + base size=8 base align=8 +QJsonDocument (0x0x7f4413e90960) 0 + +Class QJsonObject::iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::iterator (0x0x7f4413f19000) 0 + +Class QJsonObject::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::const_iterator (0x0x7f4413f19060) 0 + +Class QJsonObject + size=16 align=8 + base size=16 base align=8 +QJsonObject (0x0x7f4413e90f60) 0 + +Class QLibrary::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLibrary::QPrivateSignal (0x0x7f4413ba2300) 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 (0x0x7f4413ba1270) 0 + vptr=((& QLibrary::_ZTV8QLibrary) + 16u) + QObject (0x0x7f4413ba22a0) 0 + primary-for QLibrary (0x0x7f4413ba1270) + +Class QVersionNumber::SegmentStorage + size=8 align=8 + base size=8 base align=8 +QVersionNumber::SegmentStorage (0x0x7f4413ba29c0) 0 + +Class QVersionNumber + size=8 align=8 + base size=8 base align=8 +QVersionNumber (0x0x7f4413ba24e0) 0 + +Class QLibraryInfo + size=1 align=1 + base size=0 base align=1 +QLibraryInfo (0x0x7f4413ba2ea0) 0 empty + +Class QPoint + size=8 align=4 + base size=8 base align=4 +QPoint (0x0x7f4413ba2f00) 0 + +Class QPointF + size=16 align=8 + base size=16 base align=8 +QPointF (0x0x7f4413caf1e0) 0 + +Class QLine + size=16 align=4 + base size=16 base align=4 +QLine (0x0x7f4413caf480) 0 + +Class QLineF + size=32 align=8 + base size=32 base align=8 +QLineF (0x0x7f4413cafde0) 0 + +Class QLinkedListData + size=32 align=8 + base size=25 base align=8 +QLinkedListData (0x0x7f441396f780) 0 + +Class QLockFile + size=8 align=8 + base size=8 base align=8 +QLockFile (0x0x7f441396fae0) 0 + +Class QLoggingCategory::AtomicBools + size=4 align=1 + base size=4 base align=1 +QLoggingCategory::AtomicBools (0x0x7f441396fc60) 0 + +Class QLoggingCategory + size=24 align=8 + base size=24 base align=8 +QLoggingCategory (0x0x7f441396fc00) 0 + +Class QMargins + size=16 align=4 + base size=16 base align=4 +QMargins (0x0x7f441396fde0) 0 + +Class QMarginsF + size=32 align=8 + base size=32 base align=8 +QMarginsF (0x0x7f4413ac00c0) 0 + +Class QMessageAuthenticationCode + size=8 align=8 + base size=8 base align=8 +QMessageAuthenticationCode (0x0x7f4413ac0720) 0 + +Class QMetaMethod + size=16 align=8 + base size=12 base align=8 +QMetaMethod (0x0x7f4413ac0780) 0 + +Class QMetaEnum + size=16 align=8 + base size=12 base align=8 +QMetaEnum (0x0x7f4413ac0d80) 0 + +Class QMetaProperty + size=32 align=8 + base size=32 base align=8 +QMetaProperty (0x0x7f44137a90c0) 0 + +Class QMetaClassInfo + size=16 align=8 + base size=12 base align=8 +QMetaClassInfo (0x0x7f44137a9120) 0 + +Class QMimeData::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QMimeData::QPrivateSignal (0x0x7f44137a9420) 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 (0x0x7f44137984e0) 0 + vptr=((& QMimeData::_ZTV9QMimeData) + 16u) + QObject (0x0x7f44137a93c0) 0 + primary-for QMimeData (0x0x7f44137984e0) + +Class QMimeType + size=8 align=8 + base size=8 base align=8 +QMimeType (0x0x7f44137a9480) 0 + +Class QMimeDatabase + size=8 align=8 + base size=8 base align=8 +QMimeDatabase (0x0x7f44137a9780) 0 + +Class QObjectCleanupHandler::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObjectCleanupHandler::QPrivateSignal (0x0x7f44137a9840) 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 (0x0x7f44137986e8) 0 + vptr=((& QObjectCleanupHandler::_ZTV21QObjectCleanupHandler) + 16u) + QObject (0x0x7f44137a97e0) 0 + primary-for QObjectCleanupHandler (0x0x7f44137986e8) + +Class QOperatingSystemVersion + size=16 align=4 + base size=16 base align=4 +QOperatingSystemVersion (0x0x7f44137a98a0) 0 + +Class QParallelAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QParallelAnimationGroup::QPrivateSignal (0x0x7f441383a060) 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 (0x0x7f4413798e38) 0 + vptr=((& QParallelAnimationGroup::_ZTV23QParallelAnimationGroup) + 16u) + QAnimationGroup (0x0x7f4413798ea0) 0 + primary-for QParallelAnimationGroup (0x0x7f4413798e38) + QAbstractAnimation (0x0x7f4413798f08) 0 + primary-for QAnimationGroup (0x0x7f4413798ea0) + QObject (0x0x7f441383a000) 0 + primary-for QAbstractAnimation (0x0x7f4413798f08) + +Class QPauseAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPauseAnimation::QPrivateSignal (0x0x7f441383a120) 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 (0x0x7f4413798f70) 0 + vptr=((& QPauseAnimation::_ZTV15QPauseAnimation) + 16u) + QAbstractAnimation (0x0x7f4413798750) 0 + primary-for QPauseAnimation (0x0x7f4413798f70) + QObject (0x0x7f441383a0c0) 0 + primary-for QAbstractAnimation (0x0x7f4413798750) + +Class QStaticPlugin + size=16 align=8 + base size=16 base align=8 +QStaticPlugin (0x0x7f441383a300) 0 + +Class QPluginLoader::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPluginLoader::QPrivateSignal (0x0x7f441383a600) 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 (0x0x7f44138741a0) 0 + vptr=((& QPluginLoader::_ZTV13QPluginLoader) + 16u) + QObject (0x0x7f441383a5a0) 0 + primary-for QPluginLoader (0x0x7f44138741a0) + +Class QProcessEnvironment + size=8 align=8 + base size=8 base align=8 +QProcessEnvironment (0x0x7f441383a660) 0 + +Class QProcess::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QProcess::QPrivateSignal (0x0x7f441383ad20) 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 (0x0x7f4413874820) 0 + vptr=((& QProcess::_ZTV8QProcess) + 16u) + QIODevice (0x0x7f4413874888) 0 + primary-for QProcess (0x0x7f4413874820) + QObject (0x0x7f441383acc0) 0 + primary-for QIODevice (0x0x7f4413874888) + +Class QVariantAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QVariantAnimation::QPrivateSignal (0x0x7f441383ade0) 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 (0x0x7f44138748f0) 0 + vptr=((& QVariantAnimation::_ZTV17QVariantAnimation) + 16u) + QAbstractAnimation (0x0x7f4413874958) 0 + primary-for QVariantAnimation (0x0x7f44138748f0) + QObject (0x0x7f441383ad80) 0 + primary-for QAbstractAnimation (0x0x7f4413874958) + +Class QPropertyAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPropertyAnimation::QPrivateSignal (0x0x7f441383aea0) 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 (0x0x7f4413874a28) 0 + vptr=((& QPropertyAnimation::_ZTV18QPropertyAnimation) + 16u) + QVariantAnimation (0x0x7f4413874a90) 0 + primary-for QPropertyAnimation (0x0x7f4413874a28) + QAbstractAnimation (0x0x7f4413874af8) 0 + primary-for QVariantAnimation (0x0x7f4413874a90) + QObject (0x0x7f441383ae40) 0 + primary-for QAbstractAnimation (0x0x7f4413874af8) + +Class QRandomGenerator::Storage + size=2504 align=8 + base size=2504 base align=8 +QRandomGenerator::Storage (0x0x7f441351f000) 0 + +Class QRandomGenerator + size=2512 align=8 + base size=2512 base align=8 +QRandomGenerator (0x0x7f441383af60) 0 + +Class QRandomGenerator64 + size=2512 align=8 + base size=2512 base align=8 +QRandomGenerator64 (0x0x7f4413574dd0) 0 + QRandomGenerator (0x0x7f441356df60) 0 + +Class QReadWriteLock + size=8 align=8 + base size=8 base align=8 +QReadWriteLock (0x0x7f44135c3060) 0 + +Class QReadLocker + size=8 align=8 + base size=8 base align=8 +QReadLocker (0x0x7f44135c3300) 0 + +Class QWriteLocker + size=8 align=8 + base size=8 base align=8 +QWriteLocker (0x0x7f44135c33c0) 0 + +Class QSize + size=8 align=4 + base size=8 base align=4 +QSize (0x0x7f44135c3480) 0 + +Class QSizeF + size=16 align=8 + base size=16 base align=8 +QSizeF (0x0x7f44135c3720) 0 + +Class QRect + size=16 align=4 + base size=16 base align=4 +QRect (0x0x7f44135c39c0) 0 + +Class QRectF + size=32 align=8 + base size=32 base align=8 +QRectF (0x0x7f44135c3c60) 0 + +Class QRegularExpression + size=8 align=8 + base size=8 base align=8 +QRegularExpression (0x0x7f44135c3f00) 0 + +Class QRegularExpressionMatch + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatch (0x0x7f4413417540) 0 + +Class QRegularExpressionMatchIterator + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatchIterator (0x0x7f4413417840) 0 + +Class QResource + size=8 align=8 + base size=8 base align=8 +QResource (0x0x7f4413417b40) 0 + +Class QSaveFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSaveFile::QPrivateSignal (0x0x7f4413417cc0) 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 (0x0x7f44134c3000) 0 + vptr=((& QSaveFile::_ZTV9QSaveFile) + 16u) + QFileDevice (0x0x7f44134c3068) 0 + primary-for QSaveFile (0x0x7f44134c3000) + QIODevice (0x0x7f44134c30d0) 0 + primary-for QFileDevice (0x0x7f44134c3068) + QObject (0x0x7f4413417c60) 0 + primary-for QIODevice (0x0x7f44134c30d0) + +Class QSemaphore + size=8 align=8 + base size=8 base align=8 +QSemaphore (0x0x7f4413417d80) 0 + +Class QSemaphoreReleaser + size=16 align=8 + base size=12 base align=8 +QSemaphoreReleaser (0x0x7f4413417f00) 0 + +Class QSequentialAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSequentialAnimationGroup::QPrivateSignal (0x0x7f4413203540) 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 (0x0x7f4413201958) 0 + vptr=((& QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup) + 16u) + QAnimationGroup (0x0x7f44132019c0) 0 + primary-for QSequentialAnimationGroup (0x0x7f4413201958) + QAbstractAnimation (0x0x7f4413201a28) 0 + primary-for QAnimationGroup (0x0x7f44132019c0) + QObject (0x0x7f44132034e0) 0 + primary-for QAbstractAnimation (0x0x7f4413201a28) + +Class QSettings::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSettings::QPrivateSignal (0x0x7f4413203600) 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 (0x0x7f4413201a90) 0 + vptr=((& QSettings::_ZTV9QSettings) + 16u) + QObject (0x0x7f44132035a0) 0 + primary-for QSettings (0x0x7f4413201a90) + +Class QSharedMemory::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSharedMemory::QPrivateSignal (0x0x7f44132036c0) 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 (0x0x7f4413201af8) 0 + vptr=((& QSharedMemory::_ZTV13QSharedMemory) + 16u) + QObject (0x0x7f4413203660) 0 + primary-for QSharedMemory (0x0x7f4413201af8) + +Class QSignalMapper::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalMapper::QPrivateSignal (0x0x7f4413203780) 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 (0x0x7f4413201b60) 0 + vptr=((& QSignalMapper::_ZTV13QSignalMapper) + 16u) + QObject (0x0x7f4413203720) 0 + primary-for QSignalMapper (0x0x7f4413201b60) + +Class QSignalTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalTransition::QPrivateSignal (0x0x7f4413203840) 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 (0x0x7f4413201bc8) 0 + vptr=((& QSignalTransition::_ZTV17QSignalTransition) + 16u) + QAbstractTransition (0x0x7f4413201c30) 0 + primary-for QSignalTransition (0x0x7f4413201bc8) + QObject (0x0x7f44132037e0) 0 + primary-for QAbstractTransition (0x0x7f4413201c30) + +Class QSocketNotifier::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSocketNotifier::QPrivateSignal (0x0x7f4413203900) 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 (0x0x7f4413201c98) 0 + vptr=((& QSocketNotifier::_ZTV15QSocketNotifier) + 16u) + QObject (0x0x7f44132038a0) 0 + primary-for QSocketNotifier (0x0x7f4413201c98) + +Class QSortFilterProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSortFilterProxyModel::QPrivateSignal (0x0x7f44132039c0) 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 (0x0x7f4413201d00) 0 + vptr=((& QSortFilterProxyModel::_ZTV21QSortFilterProxyModel) + 16u) + QAbstractProxyModel (0x0x7f4413201d68) 0 + primary-for QSortFilterProxyModel (0x0x7f4413201d00) + QAbstractItemModel (0x0x7f4413201dd0) 0 + primary-for QAbstractProxyModel (0x0x7f4413201d68) + QObject (0x0x7f4413203960) 0 + primary-for QAbstractItemModel (0x0x7f4413201dd0) + +Class QStandardPaths + size=1 align=1 + base size=0 base align=1 +QStandardPaths (0x0x7f4413203a80) 0 empty + +Class QState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QState::QPrivateSignal (0x0x7f4413203cc0) 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 (0x0x7f4413201f70) 0 + vptr=((& QState::_ZTV6QState) + 16u) + QAbstractState (0x0x7f44132f1000) 0 + primary-for QState (0x0x7f4413201f70) + QObject (0x0x7f4413203c60) 0 + primary-for QAbstractState (0x0x7f44132f1000) + +Class QStateMachine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStateMachine::QPrivateSignal (0x0x7f4413203de0) 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 (0x0x7f44132f11a0) 0 + vptr=((& QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE) + 16u) + QEvent (0x0x7f4413203e40) 0 + primary-for QStateMachine::SignalEvent (0x0x7f44132f11a0) + +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 (0x0x7f44132f1208) 0 + vptr=((& QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE) + 16u) + QEvent (0x0x7f4413203ea0) 0 + primary-for QStateMachine::WrappedEvent (0x0x7f44132f1208) + +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 (0x0x7f44132f1068) 0 + vptr=((& QStateMachine::_ZTV13QStateMachine) + 16u) + QState (0x0x7f44132f10d0) 0 + primary-for QStateMachine (0x0x7f44132f1068) + QAbstractState (0x0x7f44132f1138) 0 + primary-for QState (0x0x7f44132f10d0) + QObject (0x0x7f4413203d80) 0 + primary-for QAbstractState (0x0x7f44132f1138) + +Class QStorageInfo + size=8 align=8 + base size=8 base align=8 +QStorageInfo (0x0x7f4413203f00) 0 + +Class QAbstractConcatenable + size=1 align=1 + base size=0 base align=1 +QAbstractConcatenable (0x0x7f4412f54e40) 0 empty + +Class QStringListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStringListModel::QPrivateSignal (0x0x7f4413009240) 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 (0x0x7f441300a208) 0 + vptr=((& QStringListModel::_ZTV16QStringListModel) + 16u) + QAbstractListModel (0x0x7f441300a270) 0 + primary-for QStringListModel (0x0x7f441300a208) + QAbstractItemModel (0x0x7f441300a2d8) 0 + primary-for QAbstractListModel (0x0x7f441300a270) + QObject (0x0x7f44130091e0) 0 + primary-for QAbstractItemModel (0x0x7f441300a2d8) + +Class QSystemSemaphore + size=8 align=8 + base size=8 base align=8 +QSystemSemaphore (0x0x7f44130092a0) 0 + +Class QTemporaryDir + size=8 align=8 + base size=8 base align=8 +QTemporaryDir (0x0x7f4413009360) 0 + +Class QTemporaryFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTemporaryFile::QPrivateSignal (0x0x7f4413009480) 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 (0x0x7f441300a340) 0 + vptr=((& QTemporaryFile::_ZTV14QTemporaryFile) + 16u) + QFile (0x0x7f441300a3a8) 0 + primary-for QTemporaryFile (0x0x7f441300a340) + QFileDevice (0x0x7f441300a410) 0 + primary-for QFile (0x0x7f441300a3a8) + QIODevice (0x0x7f441300a478) 0 + primary-for QFileDevice (0x0x7f441300a410) + QObject (0x0x7f4413009420) 0 + primary-for QIODevice (0x0x7f441300a478) + +Class QTextBoundaryFinder + size=48 align=8 + base size=48 base align=8 +QTextBoundaryFinder (0x0x7f44130094e0) 0 + +Class QTextCodec::ConverterState + size=32 align=8 + base size=32 base align=8 +QTextCodec::ConverterState (0x0x7f4413009720) 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 (0x0x7f44130096c0) 0 nearly-empty + vptr=((& QTextCodec::_ZTV10QTextCodec) + 16u) + +Class QTextEncoder + size=40 align=8 + base size=40 base align=8 +QTextEncoder (0x0x7f4413009900) 0 + +Class QTextDecoder + size=40 align=8 + base size=40 base align=8 +QTextDecoder (0x0x7f4413009960) 0 + +Class std::__mutex_base + size=40 align=8 + base size=40 base align=8 +std::__mutex_base (0x0x7f44130099c0) 0 + +Class std::__recursive_mutex_base + size=40 align=8 + base size=40 base align=8 +std::__recursive_mutex_base (0x0x7f4413009a20) 0 + +Class std::mutex + size=40 align=8 + base size=40 base align=8 +std::mutex (0x0x7f441300a680) 0 + std::__mutex_base (0x0x7f4413009a80) 0 + +Class std::recursive_mutex + size=40 align=8 + base size=40 base align=8 +std::recursive_mutex (0x0x7f441300a6e8) 0 + std::__recursive_mutex_base (0x0x7f4413009ae0) 0 + +Class std::timed_mutex + size=40 align=8 + base size=40 base align=8 +std::timed_mutex (0x0x7f4412c00e00) 0 + std::__mutex_base (0x0x7f4413009c00) 0 + std::__timed_mutex_impl (0x0x7f4413009c60) 0 empty + +Class std::recursive_timed_mutex + size=40 align=8 + base size=40 base align=8 +std::recursive_timed_mutex (0x0x7f4412c1c7e0) 0 + std::__recursive_mutex_base (0x0x7f4413009d20) 0 + std::__timed_mutex_impl (0x0x7f4413009d80) 0 empty + +Class std::defer_lock_t + size=1 align=1 + base size=0 base align=1 +std::defer_lock_t (0x0x7f4413009de0) 0 empty + +Class std::try_to_lock_t + size=1 align=1 + base size=0 base align=1 +std::try_to_lock_t (0x0x7f4413009e40) 0 empty + +Class std::adopt_lock_t + size=1 align=1 + base size=0 base align=1 +std::adopt_lock_t (0x0x7f4413009ea0) 0 empty + +Class std::once_flag + size=4 align=4 + base size=4 base align=4 +std::once_flag (0x0x7f4412c5e120) 0 + +Vtable for __gnu_cxx::__concurrence_lock_error +__gnu_cxx::__concurrence_lock_error::_ZTVN9__gnu_cxx24__concurrence_lock_errorE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx24__concurrence_lock_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_lock_error::~__concurrence_lock_error +24 (int (*)(...))__gnu_cxx::__concurrence_lock_error::~__concurrence_lock_error +32 (int (*)(...))__gnu_cxx::__concurrence_lock_error::what + +Class __gnu_cxx::__concurrence_lock_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_lock_error (0x0x7f441300a820) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_lock_error::_ZTVN9__gnu_cxx24__concurrence_lock_errorE) + 16u) + std::exception (0x0x7f4412c5e1e0) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_lock_error (0x0x7f441300a820) + +Vtable for __gnu_cxx::__concurrence_unlock_error +__gnu_cxx::__concurrence_unlock_error::_ZTVN9__gnu_cxx26__concurrence_unlock_errorE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx26__concurrence_unlock_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::~__concurrence_unlock_error +24 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::~__concurrence_unlock_error +32 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::what + +Class __gnu_cxx::__concurrence_unlock_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_unlock_error (0x0x7f441300a888) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_unlock_error::_ZTVN9__gnu_cxx26__concurrence_unlock_errorE) + 16u) + std::exception (0x0x7f4412c5e2a0) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_unlock_error (0x0x7f441300a888) + +Vtable for __gnu_cxx::__concurrence_broadcast_error +__gnu_cxx::__concurrence_broadcast_error::_ZTVN9__gnu_cxx29__concurrence_broadcast_errorE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx29__concurrence_broadcast_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::~__concurrence_broadcast_error +24 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::~__concurrence_broadcast_error +32 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::what + +Class __gnu_cxx::__concurrence_broadcast_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_broadcast_error (0x0x7f441300a8f0) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_broadcast_error::_ZTVN9__gnu_cxx29__concurrence_broadcast_errorE) + 16u) + std::exception (0x0x7f4412c5e360) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_broadcast_error (0x0x7f441300a8f0) + +Vtable for __gnu_cxx::__concurrence_wait_error +__gnu_cxx::__concurrence_wait_error::_ZTVN9__gnu_cxx24__concurrence_wait_errorE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx24__concurrence_wait_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_wait_error::~__concurrence_wait_error +24 (int (*)(...))__gnu_cxx::__concurrence_wait_error::~__concurrence_wait_error +32 (int (*)(...))__gnu_cxx::__concurrence_wait_error::what + +Class __gnu_cxx::__concurrence_wait_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_wait_error (0x0x7f441300a9c0) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_wait_error::_ZTVN9__gnu_cxx24__concurrence_wait_errorE) + 16u) + std::exception (0x0x7f4412c5e420) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_wait_error (0x0x7f441300a9c0) + +Class __gnu_cxx::__mutex + size=40 align=8 + base size=40 base align=8 +__gnu_cxx::__mutex (0x0x7f4412c5e4e0) 0 + +Class __gnu_cxx::__recursive_mutex + size=40 align=8 + base size=40 base align=8 +__gnu_cxx::__recursive_mutex (0x0x7f4412c5e540) 0 + +Class __gnu_cxx::__scoped_lock + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__scoped_lock (0x0x7f4412c5e5a0) 0 + +Class __gnu_cxx::__cond + size=48 align=8 + base size=48 base align=8 +__gnu_cxx::__cond (0x0x7f4412c5e600) 0 + +Vtable for std::bad_weak_ptr +std::bad_weak_ptr::_ZTVSt12bad_weak_ptr: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt12bad_weak_ptr) +16 (int (*)(...))std::bad_weak_ptr::~bad_weak_ptr +24 (int (*)(...))std::bad_weak_ptr::~bad_weak_ptr +32 (int (*)(...))std::bad_weak_ptr::what + +Class std::bad_weak_ptr + size=8 align=8 + base size=8 base align=8 +std::bad_weak_ptr (0x0x7f441300ac98) 0 nearly-empty + vptr=((& std::bad_weak_ptr::_ZTVSt12bad_weak_ptr) + 16u) + std::exception (0x0x7f4412c5e960) 0 nearly-empty + primary-for std::bad_weak_ptr (0x0x7f441300ac98) + +Class std::_Sp_make_shared_tag + size=1 align=1 + base size=0 base align=1 +std::_Sp_make_shared_tag (0x0x7f4412da11e0) 0 empty + +Class std::_Sp_locker + size=2 align=1 + base size=2 base align=1 +std::_Sp_locker (0x0x7f4412da19c0) 0 + +Class std::thread::id + size=8 align=8 + base size=8 base align=8 +std::thread::id (0x0x7f4412da1ba0) 0 + +Vtable for std::thread::_Impl_base +std::thread::_Impl_base::_ZTVNSt6thread10_Impl_baseE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt6thread10_Impl_baseE) +16 0u +24 0u +32 (int (*)(...))__cxa_pure_virtual + +Class std::thread::_Impl_base + size=24 align=8 + base size=24 base align=8 +std::thread::_Impl_base (0x0x7f4412da1c00) 0 + vptr=((& std::thread::_Impl_base::_ZTVNSt6thread10_Impl_baseE) + 16u) + +Class std::thread + size=8 align=8 + base size=8 base align=8 +std::thread (0x0x7f4412da1b40) 0 + +Class std::condition_variable + size=48 align=8 + base size=48 base align=8 +std::condition_variable (0x0x7f4412834840) 0 + +Class std::__at_thread_exit_elt + size=16 align=8 + base size=16 base align=8 +std::__at_thread_exit_elt (0x0x7f4412834900) 0 + +Class std::_V2::condition_variable_any + size=64 align=8 + base size=64 base align=8 +std::_V2::condition_variable_any (0x0x7f4412834960) 0 + +Class std::__atomic_futex_unsigned_base + size=1 align=1 + base size=0 base align=1 +std::__atomic_futex_unsigned_base (0x0x7f4412954000) 0 empty + +Vtable for std::future_error +std::future_error::_ZTVSt12future_error: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt12future_error) +16 (int (*)(...))std::future_error::~future_error +24 (int (*)(...))std::future_error::~future_error +32 (int (*)(...))std::future_error::what + +Class std::future_error + size=32 align=8 + base size=32 base align=8 +std::future_error (0x0x7f4412969000) 0 + vptr=((& std::future_error::_ZTVSt12future_error) + 16u) + std::logic_error (0x0x7f4412969068) 0 + primary-for std::future_error (0x0x7f4412969000) + std::exception (0x0x7f4412954120) 0 nearly-empty + primary-for std::logic_error (0x0x7f4412969068) + +Class std::__future_base::_Result_base::_Deleter + size=1 align=1 + base size=0 base align=1 +std::__future_base::_Result_base::_Deleter (0x0x7f4412954240) 0 empty + +Vtable for std::__future_base::_Result_base +std::__future_base::_Result_base::_ZTVNSt13__future_base12_Result_baseE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt13__future_base12_Result_baseE) +16 (int (*)(...))__cxa_pure_virtual +24 0u +32 0u + +Class std::__future_base::_Result_base + size=16 align=8 + base size=16 base align=8 +std::__future_base::_Result_base (0x0x7f44129541e0) 0 + vptr=((& std::__future_base::_Result_base::_ZTVNSt13__future_base12_Result_baseE) + 16u) + +Class std::__future_base::_State_baseV2::__exception_ptr_tag + size=1 align=1 + base size=0 base align=1 +std::__future_base::_State_baseV2::__exception_ptr_tag (0x0x7f4412671780) 0 empty + +Class std::__future_base::_State_baseV2::_Make_ready + size=32 align=8 + base size=32 base align=8 +std::__future_base::_State_baseV2::_Make_ready (0x0x7f4412673618) 0 + std::__at_thread_exit_elt (0x0x7f4412671840) 0 + +Vtable for std::__future_base::_State_baseV2 +std::__future_base::_State_baseV2::_ZTVNSt13__future_base13_State_baseV2E: 6u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt13__future_base13_State_baseV2E) +16 (int (*)(...))std::__future_base::_State_baseV2::~_State_baseV2 +24 (int (*)(...))std::__future_base::_State_baseV2::~_State_baseV2 +32 (int (*)(...))std::__future_base::_State_baseV2::_M_complete_async +40 (int (*)(...))std::__future_base::_State_baseV2::_M_is_deferred_future + +Class std::__future_base::_State_baseV2 + size=32 align=8 + base size=28 base align=8 +std::__future_base::_State_baseV2 (0x0x7f44129543c0) 0 + vptr=((& std::__future_base::_State_baseV2::_ZTVNSt13__future_base13_State_baseV2E) + 16u) + +Class std::__future_base + size=1 align=1 + base size=0 base align=1 +std::__future_base (0x0x7f4412954180) 0 empty + +Vtable for std::__future_base::_Async_state_commonV2 +std::__future_base::_Async_state_commonV2::_ZTVNSt13__future_base21_Async_state_commonV2E: 6u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt13__future_base21_Async_state_commonV2E) +16 (int (*)(...))std::__future_base::_Async_state_commonV2::~_Async_state_commonV2 +24 (int (*)(...))std::__future_base::_Async_state_commonV2::~_Async_state_commonV2 +32 (int (*)(...))std::__future_base::_Async_state_commonV2::_M_complete_async +40 (int (*)(...))std::__future_base::_State_baseV2::_M_is_deferred_future + +Class std::__future_base::_Async_state_commonV2 + size=48 align=8 + base size=44 base align=8 +std::__future_base::_Async_state_commonV2 (0x0x7f4412018208) 0 + vptr=((& std::__future_base::_Async_state_commonV2::_ZTVNSt13__future_base21_Async_state_commonV2E) + 16u) + std::__future_base::_State_baseV2 (0x0x7f44123d3720) 0 + primary-for std::__future_base::_Async_state_commonV2 (0x0x7f4412018208) + +Class QThread::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThread::QPrivateSignal (0x0x7f44123d3e40) 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 (0x0x7f4412018c98) 0 + vptr=((& QThread::_ZTV7QThread) + 16u) + QObject (0x0x7f44123d3de0) 0 + primary-for QThread (0x0x7f4412018c98) + +Class QThreadPool::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThreadPool::QPrivateSignal (0x0x7f44123d3f60) 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 (0x0x7f4412018d00) 0 + vptr=((& QThreadPool::_ZTV11QThreadPool) + 16u) + QObject (0x0x7f44123d3f00) 0 + primary-for QThreadPool (0x0x7f4412018d00) + +Class QThreadStorageData + size=4 align=4 + base size=4 base align=4 +QThreadStorageData (0x0x7f4412086000) 0 + +Class QTimeLine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimeLine::QPrivateSignal (0x0x7f4412086120) 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 (0x0x7f4412018d68) 0 + vptr=((& QTimeLine::_ZTV9QTimeLine) + 16u) + QObject (0x0x7f44120860c0) 0 + primary-for QTimeLine (0x0x7f4412018d68) + +Class QTimer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimer::QPrivateSignal (0x0x7f44120861e0) 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 (0x0x7f4412018dd0) 0 + vptr=((& QTimer::_ZTV6QTimer) + 16u) + QObject (0x0x7f4412086180) 0 + primary-for QTimer (0x0x7f4412018dd0) + +Class QTimeZone::OffsetData + size=32 align=8 + base size=28 base align=8 +QTimeZone::OffsetData (0x0x7f44120868a0) 0 + +Class QTimeZone + size=8 align=8 + base size=8 base align=8 +QTimeZone (0x0x7f4412086840) 0 + +Class QTranslator::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTranslator::QPrivateSignal (0x0x7f4412086e40) 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 (0x0x7f44120dc820) 0 + vptr=((& QTranslator::_ZTV11QTranslator) + 16u) + QObject (0x0x7f4412086de0) 0 + primary-for QTranslator (0x0x7f44120dc820) + +Class QUrl + size=8 align=8 + base size=8 base align=8 +QUrl (0x0x7f4412086f60) 0 + +Class QUrlQuery + size=8 align=8 + base size=8 base align=8 +QUrlQuery (0x0x7f4411e3a660) 0 + +Class QUuid + size=16 align=4 + base size=16 base align=4 +QUuid (0x0x7f4411e3acc0) 0 + +Class QWaitCondition + size=8 align=8 + base size=8 base align=8 +QWaitCondition (0x0x7f4411efb300) 0 + +Class QXmlStreamStringRef + size=16 align=8 + base size=16 base align=8 +QXmlStreamStringRef (0x0x7f4411efb360) 0 + +Class QXmlStreamAttribute + size=80 align=8 + base size=73 base align=8 +QXmlStreamAttribute (0x0x7f4411efb600) 0 + +Class QXmlStreamAttributes + size=8 align=8 + base size=8 base align=8 +QXmlStreamAttributes (0x0x7f4411f73208) 0 + QVector (0x0x7f4411efb9c0) 0 + +Class QXmlStreamNamespaceDeclaration + size=40 align=8 + base size=40 base align=8 +QXmlStreamNamespaceDeclaration (0x0x7f4411efba20) 0 + +Class QXmlStreamNotationDeclaration + size=56 align=8 + base size=56 base align=8 +QXmlStreamNotationDeclaration (0x0x7f4411efbcc0) 0 + +Class QXmlStreamEntityDeclaration + size=88 align=8 + base size=88 base align=8 +QXmlStreamEntityDeclaration (0x0x7f4411efbf60) 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 (0x0x7f4411c18240) 0 nearly-empty + vptr=((& QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver) + 16u) + +Class QXmlStreamReader + size=8 align=8 + base size=8 base align=8 +QXmlStreamReader (0x0x7f4411c182a0) 0 + +Class QXmlStreamWriter + size=8 align=8 + base size=8 base align=8 +QXmlStreamWriter (0x0x7f4411c18cc0) 0 + +Class QBluetoothAddress + size=8 align=8 + base size=8 base align=8 +QBluetoothAddress (0x0x7f4411cc2120) 0 + +Class QBluetoothDeviceInfo + size=8 align=8 + base size=8 base align=8 +QBluetoothDeviceInfo (0x0x7f4411cc22a0) 0 + +Class QBluetoothDeviceDiscoveryAgent::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothDeviceDiscoveryAgent::QPrivateSignal (0x0x7f4411cc2780) 0 empty + +Vtable for QBluetoothDeviceDiscoveryAgent +QBluetoothDeviceDiscoveryAgent::_ZTV30QBluetoothDeviceDiscoveryAgent: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI30QBluetoothDeviceDiscoveryAgent) +16 (int (*)(...))QBluetoothDeviceDiscoveryAgent::metaObject +24 (int (*)(...))QBluetoothDeviceDiscoveryAgent::qt_metacast +32 (int (*)(...))QBluetoothDeviceDiscoveryAgent::qt_metacall +40 (int (*)(...))QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent +48 (int (*)(...))QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent +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 QBluetoothDeviceDiscoveryAgent + size=24 align=8 + base size=24 base align=8 +QBluetoothDeviceDiscoveryAgent (0x0x7f4411c706e8) 0 + vptr=((& QBluetoothDeviceDiscoveryAgent::_ZTV30QBluetoothDeviceDiscoveryAgent) + 16u) + QObject (0x0x7f4411cc2720) 0 + primary-for QBluetoothDeviceDiscoveryAgent (0x0x7f4411c706e8) + +Class QBluetoothHostInfo + size=8 align=8 + base size=8 base align=8 +QBluetoothHostInfo (0x0x7f4411cc2960) 0 + +Class QBluetoothLocalDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothLocalDevice::QPrivateSignal (0x0x7f4411cc2b40) 0 empty + +Vtable for QBluetoothLocalDevice +QBluetoothLocalDevice::_ZTV21QBluetoothLocalDevice: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QBluetoothLocalDevice) +16 (int (*)(...))QBluetoothLocalDevice::metaObject +24 (int (*)(...))QBluetoothLocalDevice::qt_metacast +32 (int (*)(...))QBluetoothLocalDevice::qt_metacall +40 (int (*)(...))QBluetoothLocalDevice::~QBluetoothLocalDevice +48 (int (*)(...))QBluetoothLocalDevice::~QBluetoothLocalDevice +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 QBluetoothLocalDevice + size=24 align=8 + base size=24 base align=8 +QBluetoothLocalDevice (0x0x7f4411c70820) 0 + vptr=((& QBluetoothLocalDevice::_ZTV21QBluetoothLocalDevice) + 16u) + QObject (0x0x7f4411cc2ae0) 0 + primary-for QBluetoothLocalDevice (0x0x7f4411c70820) + +Class quint128 + size=16 align=1 + base size=16 base align=1 +quint128 (0x0x7f4411cc2f00) 0 + +Class QBluetoothUuid + size=16 align=4 + base size=16 base align=4 +QBluetoothUuid (0x0x7f4411c70888) 0 + QUuid (0x0x7f4411cc2f60) 0 + +Class QBluetoothServiceInfo::Sequence + size=8 align=8 + base size=8 base align=8 +QBluetoothServiceInfo::Sequence (0x0x7f4411c708f0) 0 + QList (0x0x7f4411c70958) 0 + QListSpecialMethods (0x0x7f4411a36240) 0 empty + +Class QBluetoothServiceInfo::Alternative + size=8 align=8 + base size=8 base align=8 +QBluetoothServiceInfo::Alternative (0x0x7f4411c709c0) 0 + QList (0x0x7f4411c70a28) 0 + QListSpecialMethods (0x0x7f4411a362a0) 0 empty + +Class QBluetoothServiceInfo + size=16 align=8 + base size=16 base align=8 +QBluetoothServiceInfo (0x0x7f4411a361e0) 0 + +Class QAbstractSocket::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractSocket::QPrivateSignal (0x0x7f4411a36720) 0 empty + +Vtable for QAbstractSocket +QAbstractSocket::_ZTV15QAbstractSocket: 41u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QAbstractSocket) +16 (int (*)(...))QAbstractSocket::metaObject +24 (int (*)(...))QAbstractSocket::qt_metacast +32 (int (*)(...))QAbstractSocket::qt_metacall +40 (int (*)(...))QAbstractSocket::~QAbstractSocket +48 (int (*)(...))QAbstractSocket::~QAbstractSocket +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 (*)(...))QAbstractSocket::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QAbstractSocket::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QAbstractSocket::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QAbstractSocket::bytesAvailable +184 (int (*)(...))QAbstractSocket::bytesToWrite +192 (int (*)(...))QAbstractSocket::canReadLine +200 (int (*)(...))QAbstractSocket::waitForReadyRead +208 (int (*)(...))QAbstractSocket::waitForBytesWritten +216 (int (*)(...))QAbstractSocket::readData +224 (int (*)(...))QAbstractSocket::readLineData +232 (int (*)(...))QAbstractSocket::writeData +240 (int (*)(...))QAbstractSocket::resume +248 (int (*)(...))QAbstractSocket::connectToHost +256 (int (*)(...))QAbstractSocket::connectToHost +264 (int (*)(...))QAbstractSocket::disconnectFromHost +272 (int (*)(...))QAbstractSocket::setReadBufferSize +280 (int (*)(...))QAbstractSocket::socketDescriptor +288 (int (*)(...))QAbstractSocket::setSocketDescriptor +296 (int (*)(...))QAbstractSocket::setSocketOption +304 (int (*)(...))QAbstractSocket::socketOption +312 (int (*)(...))QAbstractSocket::waitForConnected +320 (int (*)(...))QAbstractSocket::waitForDisconnected + +Class QAbstractSocket + size=16 align=8 + base size=16 base align=8 +QAbstractSocket (0x0x7f4411c70c98) 0 + vptr=((& QAbstractSocket::_ZTV15QAbstractSocket) + 16u) + QIODevice (0x0x7f4411c70d00) 0 + primary-for QAbstractSocket (0x0x7f4411c70c98) + QObject (0x0x7f4411a366c0) 0 + primary-for QIODevice (0x0x7f4411c70d00) + +Class QBluetoothSocket::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothSocket::QPrivateSignal (0x0x7f4411a36d20) 0 empty + +Vtable for QBluetoothSocket +QBluetoothSocket::_ZTV16QBluetoothSocket: 30u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QBluetoothSocket) +16 (int (*)(...))QBluetoothSocket::metaObject +24 (int (*)(...))QBluetoothSocket::qt_metacast +32 (int (*)(...))QBluetoothSocket::qt_metacall +40 (int (*)(...))QBluetoothSocket::~QBluetoothSocket +48 (int (*)(...))QBluetoothSocket::~QBluetoothSocket +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 (*)(...))QBluetoothSocket::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QBluetoothSocket::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QIODevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QBluetoothSocket::bytesAvailable +184 (int (*)(...))QBluetoothSocket::bytesToWrite +192 (int (*)(...))QBluetoothSocket::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QBluetoothSocket::readData +224 (int (*)(...))QIODevice::readLineData +232 (int (*)(...))QBluetoothSocket::writeData + +Class QBluetoothSocket + size=24 align=8 + base size=24 base align=8 +QBluetoothSocket (0x0x7f4411c70f08) 0 + vptr=((& QBluetoothSocket::_ZTV16QBluetoothSocket) + 16u) + QIODevice (0x0x7f4411c70f70) 0 + primary-for QBluetoothSocket (0x0x7f4411c70f08) + QObject (0x0x7f4411a36cc0) 0 + primary-for QIODevice (0x0x7f4411c70f70) + +Class QBluetoothServer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothServer::QPrivateSignal (0x0x7f4411a36de0) 0 empty + +Vtable for QBluetoothServer +QBluetoothServer::_ZTV16QBluetoothServer: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QBluetoothServer) +16 (int (*)(...))QBluetoothServer::metaObject +24 (int (*)(...))QBluetoothServer::qt_metacast +32 (int (*)(...))QBluetoothServer::qt_metacall +40 (int (*)(...))QBluetoothServer::~QBluetoothServer +48 (int (*)(...))QBluetoothServer::~QBluetoothServer +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 QBluetoothServer + size=24 align=8 + base size=24 base align=8 +QBluetoothServer (0x0x7f4411b85000) 0 + vptr=((& QBluetoothServer::_ZTV16QBluetoothServer) + 16u) + QObject (0x0x7f4411a36d80) 0 + primary-for QBluetoothServer (0x0x7f4411b85000) + +Class QBluetoothServiceDiscoveryAgent::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothServiceDiscoveryAgent::QPrivateSignal (0x0x7f4411a36ea0) 0 empty + +Vtable for QBluetoothServiceDiscoveryAgent +QBluetoothServiceDiscoveryAgent::_ZTV31QBluetoothServiceDiscoveryAgent: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI31QBluetoothServiceDiscoveryAgent) +16 (int (*)(...))QBluetoothServiceDiscoveryAgent::metaObject +24 (int (*)(...))QBluetoothServiceDiscoveryAgent::qt_metacast +32 (int (*)(...))QBluetoothServiceDiscoveryAgent::qt_metacall +40 (int (*)(...))QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent +48 (int (*)(...))QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent +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 QBluetoothServiceDiscoveryAgent + size=24 align=8 + base size=24 base align=8 +QBluetoothServiceDiscoveryAgent (0x0x7f4411b85068) 0 + vptr=((& QBluetoothServiceDiscoveryAgent::_ZTV31QBluetoothServiceDiscoveryAgent) + 16u) + QObject (0x0x7f4411a36e40) 0 + primary-for QBluetoothServiceDiscoveryAgent (0x0x7f4411b85068) + +Class QBluetoothTransferManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothTransferManager::QPrivateSignal (0x0x7f4411a36f60) 0 empty + +Vtable for QBluetoothTransferManager +QBluetoothTransferManager::_ZTV25QBluetoothTransferManager: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI25QBluetoothTransferManager) +16 (int (*)(...))QBluetoothTransferManager::metaObject +24 (int (*)(...))QBluetoothTransferManager::qt_metacast +32 (int (*)(...))QBluetoothTransferManager::qt_metacall +40 (int (*)(...))QBluetoothTransferManager::~QBluetoothTransferManager +48 (int (*)(...))QBluetoothTransferManager::~QBluetoothTransferManager +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 QBluetoothTransferManager + size=16 align=8 + base size=16 base align=8 +QBluetoothTransferManager (0x0x7f4411b850d0) 0 + vptr=((& QBluetoothTransferManager::_ZTV25QBluetoothTransferManager) + 16u) + QObject (0x0x7f4411a36f00) 0 + primary-for QBluetoothTransferManager (0x0x7f4411b850d0) + +Class QBluetoothTransferRequest + size=8 align=8 + base size=8 base align=8 +QBluetoothTransferRequest (0x0x7f4411bba000) 0 + +Class QBluetoothTransferReply::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothTransferReply::QPrivateSignal (0x0x7f4411bba0c0) 0 empty + +Vtable for QBluetoothTransferReply +QBluetoothTransferReply::_ZTV23QBluetoothTransferReply: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI23QBluetoothTransferReply) +16 (int (*)(...))QBluetoothTransferReply::metaObject +24 (int (*)(...))QBluetoothTransferReply::qt_metacast +32 (int (*)(...))QBluetoothTransferReply::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 + +Class QBluetoothTransferReply + size=24 align=8 + base size=24 base align=8 +QBluetoothTransferReply (0x0x7f4411b85138) 0 + vptr=((& QBluetoothTransferReply::_ZTV23QBluetoothTransferReply) + 16u) + QObject (0x0x7f4411bba060) 0 + primary-for QBluetoothTransferReply (0x0x7f4411b85138) + +Class QLowEnergyAdvertisingData + size=8 align=8 + base size=8 base align=8 +QLowEnergyAdvertisingData (0x0x7f4411bba240) 0 + +Class QLowEnergyDescriptor + size=24 align=8 + base size=24 base align=8 +QLowEnergyDescriptor (0x0x7f4411bba8a0) 0 + +Class QLowEnergyCharacteristic + size=24 align=8 + base size=24 base align=8 +QLowEnergyCharacteristic (0x0x7f4411bbaa80) 0 + +Class QLowEnergyService::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLowEnergyService::QPrivateSignal (0x0x7f4411bbade0) 0 empty + +Vtable for QLowEnergyService +QLowEnergyService::_ZTV17QLowEnergyService: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QLowEnergyService) +16 (int (*)(...))QLowEnergyService::metaObject +24 (int (*)(...))QLowEnergyService::qt_metacast +32 (int (*)(...))QLowEnergyService::qt_metacall +40 (int (*)(...))QLowEnergyService::~QLowEnergyService +48 (int (*)(...))QLowEnergyService::~QLowEnergyService +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 QLowEnergyService + size=32 align=8 + base size=32 base align=8 +QLowEnergyService (0x0x7f4411b85888) 0 + vptr=((& QLowEnergyService::_ZTV17QLowEnergyService) + 16u) + QObject (0x0x7f4411bbad80) 0 + primary-for QLowEnergyService (0x0x7f4411b85888) + +Class QLowEnergyController::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLowEnergyController::QPrivateSignal (0x0x7f44118c94e0) 0 empty + +Vtable for QLowEnergyController +QLowEnergyController::_ZTV20QLowEnergyController: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI20QLowEnergyController) +16 (int (*)(...))QLowEnergyController::metaObject +24 (int (*)(...))QLowEnergyController::qt_metacast +32 (int (*)(...))QLowEnergyController::qt_metacall +40 (int (*)(...))QLowEnergyController::~QLowEnergyController +48 (int (*)(...))QLowEnergyController::~QLowEnergyController +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 QLowEnergyController + size=24 align=8 + base size=24 base align=8 +QLowEnergyController (0x0x7f4411b859c0) 0 + vptr=((& QLowEnergyController::_ZTV20QLowEnergyController) + 16u) + QObject (0x0x7f44118c9480) 0 + primary-for QLowEnergyController (0x0x7f4411b859c0) + +Class QLowEnergyAdvertisingParameters::AddressInfo + size=16 align=8 + base size=12 base align=8 +QLowEnergyAdvertisingParameters::AddressInfo (0x0x7f44118c9a20) 0 + +Class QLowEnergyAdvertisingParameters + size=8 align=8 + base size=8 base align=8 +QLowEnergyAdvertisingParameters (0x0x7f44118c99c0) 0 + +Class QLowEnergyCharacteristicData + size=8 align=8 + base size=8 base align=8 +QLowEnergyCharacteristicData (0x0x7f44119669c0) 0 + +Class QLowEnergyConnectionParameters + size=8 align=8 + base size=8 base align=8 +QLowEnergyConnectionParameters (0x0x7f44119a3060) 0 + +Class QLowEnergyDescriptorData + size=8 align=8 + base size=8 base align=8 +QLowEnergyDescriptorData (0x0x7f44119a37e0) 0 + +Class QLowEnergyServiceData + size=8 align=8 + base size=8 base align=8 +QLowEnergyServiceData (0x0x7f44119a3e40) 0 + diff --git a/tests/auto/bic/data/QtBluetooth.5.12.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtBluetooth.5.12.0.linux-gcc-amd64.txt new file mode 100644 index 0000000..98f1c8c --- /dev/null +++ b/tests/auto/bic/data/QtBluetooth.5.12.0.linux-gcc-amd64.txt @@ -0,0 +1,5053 @@ +Class std::__failure_type + size=1 align=1 + base size=0 base align=1 +std::__failure_type (0x0x7f88a7cb9c00) 0 empty + +Class std::__do_is_destructible_impl + size=1 align=1 + base size=0 base align=1 +std::__do_is_destructible_impl (0x0x7f88a58bd3c0) 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 (0x0x7f88a58bd600) 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 (0x0x7f88a58bd840) 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 (0x0x7f88a58bda80) 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 (0x0x7f88a58bdc00) 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 (0x0x7f88a58f6000) 0 empty + +Class std::__do_common_type_impl + size=1 align=1 + base size=0 base align=1 +std::__do_common_type_impl (0x0x7f88a5978780) 0 empty + +Class std::__do_member_type_wrapper + size=1 align=1 + base size=0 base align=1 +std::__do_member_type_wrapper (0x0x7f88a5978840) 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 (0x0x7f88a5978ba0) 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 (0x0x7f88a5978c60) 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 (0x0x7f88a5978d20) 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 (0x0x7f88a5978de0) 0 empty + +Class std::__result_of_other_impl + size=1 align=1 + base size=0 base align=1 +std::__result_of_other_impl (0x0x7f88a59b60c0) 0 empty + +Class std::piecewise_construct_t + size=1 align=1 + base size=0 base align=1 +std::piecewise_construct_t (0x0x7f88a59b62a0) 0 empty + +Class std::__true_type + size=1 align=1 + base size=0 base align=1 +std::__true_type (0x0x7f88a59b6720) 0 empty + +Class std::__false_type + size=1 align=1 + base size=0 base align=1 +std::__false_type (0x0x7f88a59b6780) 0 empty + +Class std::input_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::input_iterator_tag (0x0x7f88a5a5b420) 0 empty + +Class std::output_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::output_iterator_tag (0x0x7f88a5a5b480) 0 empty + +Class std::forward_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::forward_iterator_tag (0x0x7f88a5934e38) 0 empty + std::input_iterator_tag (0x0x7f88a5a5b4e0) 0 empty + +Class std::bidirectional_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::bidirectional_iterator_tag (0x0x7f88a5934ea0) 0 empty + std::forward_iterator_tag (0x0x7f88a5934f08) 0 empty + std::input_iterator_tag (0x0x7f88a5a5b540) 0 empty + +Class std::random_access_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::random_access_iterator_tag (0x0x7f88a5934f70) 0 empty + std::bidirectional_iterator_tag (0x0x7f88a5a6f000) 0 empty + std::forward_iterator_tag (0x0x7f88a5a6f068) 0 empty + std::input_iterator_tag (0x0x7f88a5a5b5a0) 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 (0x0x7f88a56c2240) 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 (0x0x7f88a56c22a0) 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 (0x0x7f88a56c2300) 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 (0x0x7f88a56c2360) 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 (0x0x7f88a56c23c0) 0 empty + +Class wait + size=4 align=4 + base size=4 base align=4 +wait (0x0x7f88a56c2ea0) 0 + +Class __locale_struct + size=232 align=8 + base size=232 base align=8 +__locale_struct (0x0x7f88a57d1120) 0 + +Class timespec + size=16 align=8 + base size=16 base align=8 +timespec (0x0x7f88a57d11e0) 0 + +Class timeval + size=16 align=8 + base size=16 base align=8 +timeval (0x0x7f88a57d1240) 0 + +Class pthread_attr_t + size=56 align=8 + base size=56 base align=8 +pthread_attr_t (0x0x7f88a57d1300) 0 + +Class __pthread_internal_list + size=16 align=8 + base size=16 base align=8 +__pthread_internal_list (0x0x7f88a57d1360) 0 + +Class random_data + size=48 align=8 + base size=48 base align=8 +random_data (0x0x7f88a57d17e0) 0 + +Class drand48_data + size=24 align=8 + base size=24 base align=8 +drand48_data (0x0x7f88a57d1840) 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 (0x0x7f88a57d18a0) 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 (0x0x7f88a5a6f5b0) 0 nearly-empty + vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16u) + std::exception (0x0x7f88a57d1900) 0 nearly-empty + primary-for std::bad_exception (0x0x7f88a5a6f5b0) + +Class std::__exception_ptr::exception_ptr + size=8 align=8 + base size=8 base align=8 +std::__exception_ptr::exception_ptr (0x0x7f88a57d1960) 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 (0x0x7f88a57d19c0) 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 (0x0x7f88a5a6f7b8) 0 nearly-empty + vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16u) + std::exception (0x0x7f88a57d1de0) 0 nearly-empty + primary-for std::bad_alloc (0x0x7f88a5a6f7b8) + +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 (0x0x7f88a5a6f820) 0 nearly-empty + vptr=((& std::bad_array_new_length::_ZTVSt20bad_array_new_length) + 16u) + std::bad_alloc (0x0x7f88a5a6f888) 0 nearly-empty + primary-for std::bad_array_new_length (0x0x7f88a5a6f820) + std::exception (0x0x7f88a57d1e40) 0 nearly-empty + primary-for std::bad_alloc (0x0x7f88a5a6f888) + +Class std::nothrow_t + size=1 align=1 + base size=0 base align=1 +std::nothrow_t (0x0x7f88a57d1ea0) 0 empty + +Class __exception + size=40 align=8 + base size=40 base align=8 +__exception (0x0x7f88a54f9ae0) 0 + +Class lconv + size=96 align=8 + base size=96 base align=8 +lconv (0x0x7f88a532d7e0) 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 (0x0x7f88a532d840) 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 (0x0x7f88a53f3720) 0 + +Class __sched_param + size=4 align=4 + base size=4 base align=4 +__sched_param (0x0x7f88a53f3780) 0 + +Class timex + size=208 align=8 + base size=208 base align=8 +timex (0x0x7f88a53f3840) 0 + +Class tm + size=56 align=8 + base size=56 base align=8 +tm (0x0x7f88a53f38a0) 0 + +Class itimerspec + size=32 align=8 + base size=32 base align=8 +itimerspec (0x0x7f88a53f3900) 0 + +Class _pthread_cleanup_buffer + size=32 align=8 + base size=32 base align=8 +_pthread_cleanup_buffer (0x0x7f88a53f3960) 0 + +Class __pthread_cleanup_frame + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_frame (0x0x7f88a53f3a80) 0 + +Class __pthread_cleanup_class + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_class (0x0x7f88a53f3ae0) 0 + +Class _IO_marker + size=24 align=8 + base size=24 base align=8 +_IO_marker (0x0x7f88a53f3f00) 0 + +Class _IO_FILE + size=216 align=8 + base size=216 base align=8 +_IO_FILE (0x0x7f88a53f3f60) 0 + +Class std::_Hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Hash_impl (0x0x7f88a4f4c780) 0 empty + +Class std::_Fnv_hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Fnv_hash_impl (0x0x7f88a4f4c7e0) 0 empty + +Class std::__numeric_limits_base + size=1 align=1 + base size=0 base align=1 +std::__numeric_limits_base (0x0x7f88a4f99780) 0 empty + +Class std::_Bit_reference + size=16 align=8 + base size=16 base align=8 +std::_Bit_reference (0x0x7f88a4d955a0) 0 + +Class std::_Bit_iterator_base + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator_base (0x0x7f88a501b548) 0 + std::iterator (0x0x7f88a4d95660) 0 empty + +Class std::_Bit_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator (0x0x7f88a501b5b0) 0 + std::_Bit_iterator_base (0x0x7f88a501b618) 0 + std::iterator (0x0x7f88a4d956c0) 0 empty + +Class std::_Bit_const_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_const_iterator (0x0x7f88a501b680) 0 + std::_Bit_iterator_base (0x0x7f88a501b6e8) 0 + std::iterator (0x0x7f88a4d95720) 0 empty + +Class std::random_device + size=5000 align=8 + base size=5000 base align=8 +std::random_device (0x0x7f88a4bb5540) 0 + +Class std::bernoulli_distribution::param_type + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution::param_type (0x0x7f88a48cf300) 0 + +Class std::bernoulli_distribution + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution (0x0x7f88a48cf2a0) 0 + +Class std::seed_seq + size=24 align=8 + base size=24 base align=8 +std::seed_seq (0x0x7f88a4a602a0) 0 + +Class qIsNull(double)::U + size=8 align=8 + base size=8 base align=8 +qIsNull(double)::U (0x0x7f88a3547d80) 0 + +Class qIsNull(float)::U + size=4 align=4 + base size=4 base align=4 +qIsNull(float)::U (0x0x7f88a3547de0) 0 + +Class QSysInfo + size=1 align=1 + base size=0 base align=1 +QSysInfo (0x0x7f88a32c98a0) 0 empty + +Class QMessageLogContext + size=32 align=8 + base size=32 base align=8 +QMessageLogContext (0x0x7f88a32c9900) 0 + +Class QMessageLogger + size=32 align=8 + base size=32 base align=8 +QMessageLogger (0x0x7f88a32c9960) 0 + +Class QFlag + size=4 align=4 + base size=4 base align=4 +QFlag (0x0x7f88a32c99c0) 0 + +Class QIncompatibleFlag + size=4 align=4 + base size=4 base align=4 +QIncompatibleFlag (0x0x7f88a32c9c60) 0 + +Class std::__atomic_flag_base + size=1 align=1 + base size=1 base align=1 +std::__atomic_flag_base (0x0x7f88a334f1e0) 0 + +Class std::atomic_flag + size=1 align=1 + base size=1 base align=1 +std::atomic_flag (0x0x7f88a32e24e0) 0 + std::__atomic_flag_base (0x0x7f88a334f240) 0 + +Class QAtomicInt + size=4 align=4 + base size=4 base align=4 +QAtomicInt (0x0x7f88a32e2c30) 0 + QAtomicInteger (0x0x7f88a32e2c98) 0 + QBasicAtomicInteger (0x0x7f88a31bc960) 0 + +Class QInternal + size=1 align=1 + base size=0 base align=1 +QInternal (0x0x7f88a2d36f00) 0 empty + +Class QtPrivate::QSlotObjectBase + size=16 align=8 + base size=16 base align=8 +QtPrivate::QSlotObjectBase (0x0x7f88a2bb0120) 0 + +Class QGenericArgument + size=16 align=8 + base size=16 base align=8 +QGenericArgument (0x0x7f88a2bb0240) 0 + +Class QGenericReturnArgument + size=16 align=8 + base size=16 base align=8 +QGenericReturnArgument (0x0x7f88a2e59888) 0 + QGenericArgument (0x0x7f88a2bb02a0) 0 + +Class QMetaObject + size=48 align=8 + base size=48 base align=8 +QMetaObject (0x0x7f88a2bb0420) 0 + +Class QMetaObject::Connection + size=8 align=8 + base size=8 base align=8 +QMetaObject::Connection (0x0x7f88a2bb04e0) 0 + +Class QLatin1Char + size=1 align=1 + base size=1 base align=1 +QLatin1Char (0x0x7f88a2c8a540) 0 + +Class QChar + size=2 align=2 + base size=2 base align=2 +QChar (0x0x7f88a2c8a5a0) 0 + +Class QtPrivate::RefCount + size=4 align=4 + base size=4 base align=4 +QtPrivate::RefCount (0x0x7f88a2c8a840) 0 + +Class QArrayData + size=24 align=8 + base size=24 base align=8 +QArrayData (0x0x7f88a2c8a8a0) 0 + +Class QtPrivate::QContainerImplHelper + size=1 align=1 + base size=0 base align=1 +QtPrivate::QContainerImplHelper (0x0x7f88a2c8ac00) 0 empty + +Class std::locale + size=8 align=8 + base size=8 base align=8 +std::locale (0x0x7f88a2c8ac60) 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 (0x0x7f88a2c8acc0) 0 + vptr=((& std::locale::facet::_ZTVNSt6locale5facetE) + 16u) + +Class std::locale::id + size=8 align=8 + base size=8 base align=8 +std::locale::id (0x0x7f88a2c8ad20) 0 + +Class std::locale::_Impl + size=40 align=8 + base size=40 base align=8 +std::locale::_Impl (0x0x7f88a2c8ad80) 0 + +Class std::__cow_string + size=8 align=8 + base size=8 base align=8 +std::__cow_string (0x0x7f88a2a22180) 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 (0x0x7f88a2c94ea0) 0 + vptr=((& std::logic_error::_ZTVSt11logic_error) + 16u) + std::exception (0x0x7f88a2a22240) 0 nearly-empty + primary-for std::logic_error (0x0x7f88a2c94ea0) + +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 (0x0x7f88a2c94f08) 0 + vptr=((& std::domain_error::_ZTVSt12domain_error) + 16u) + std::logic_error (0x0x7f88a2c94f70) 0 + primary-for std::domain_error (0x0x7f88a2c94f08) + std::exception (0x0x7f88a2a222a0) 0 nearly-empty + primary-for std::logic_error (0x0x7f88a2c94f70) + +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 (0x0x7f88a2c94bc8) 0 + vptr=((& std::invalid_argument::_ZTVSt16invalid_argument) + 16u) + std::logic_error (0x0x7f88a2c94c98) 0 + primary-for std::invalid_argument (0x0x7f88a2c94bc8) + std::exception (0x0x7f88a2a22300) 0 nearly-empty + primary-for std::logic_error (0x0x7f88a2c94c98) + +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 (0x0x7f88a2a49000) 0 + vptr=((& std::length_error::_ZTVSt12length_error) + 16u) + std::logic_error (0x0x7f88a2a49068) 0 + primary-for std::length_error (0x0x7f88a2a49000) + std::exception (0x0x7f88a2a22360) 0 nearly-empty + primary-for std::logic_error (0x0x7f88a2a49068) + +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 (0x0x7f88a2a490d0) 0 + vptr=((& std::out_of_range::_ZTVSt12out_of_range) + 16u) + std::logic_error (0x0x7f88a2a49138) 0 + primary-for std::out_of_range (0x0x7f88a2a490d0) + std::exception (0x0x7f88a2a223c0) 0 nearly-empty + primary-for std::logic_error (0x0x7f88a2a49138) + +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 (0x0x7f88a2a491a0) 0 + vptr=((& std::runtime_error::_ZTVSt13runtime_error) + 16u) + std::exception (0x0x7f88a2a22420) 0 nearly-empty + primary-for std::runtime_error (0x0x7f88a2a491a0) + +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 (0x0x7f88a2a49208) 0 + vptr=((& std::range_error::_ZTVSt11range_error) + 16u) + std::runtime_error (0x0x7f88a2a49270) 0 + primary-for std::range_error (0x0x7f88a2a49208) + std::exception (0x0x7f88a2a22480) 0 nearly-empty + primary-for std::runtime_error (0x0x7f88a2a49270) + +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 (0x0x7f88a2a492d8) 0 + vptr=((& std::overflow_error::_ZTVSt14overflow_error) + 16u) + std::runtime_error (0x0x7f88a2a49340) 0 + primary-for std::overflow_error (0x0x7f88a2a492d8) + std::exception (0x0x7f88a2a224e0) 0 nearly-empty + primary-for std::runtime_error (0x0x7f88a2a49340) + +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 (0x0x7f88a2a493a8) 0 + vptr=((& std::underflow_error::_ZTVSt15underflow_error) + 16u) + std::runtime_error (0x0x7f88a2a49410) 0 + primary-for std::underflow_error (0x0x7f88a2a493a8) + std::exception (0x0x7f88a2a22540) 0 nearly-empty + primary-for std::runtime_error (0x0x7f88a2a49410) + +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 (0x0x7f88a2a226c0) 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 (0x0x7f88a2a22900) 0 + +Class std::error_condition + size=16 align=8 + base size=16 base align=8 +std::error_condition (0x0x7f88a2a22a80) 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 (0x0x7f88a2a498f0) 0 + vptr=((& std::system_error::_ZTVSt12system_error) + 16u) + std::runtime_error (0x0x7f88a2a49958) 0 + primary-for std::system_error (0x0x7f88a2a498f0) + std::exception (0x0x7f88a2a22cc0) 0 nearly-empty + primary-for std::runtime_error (0x0x7f88a2a49958) + +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 (0x0x7f88a26c3548) 0 + vptr=((& std::ios_base::failure::_ZTVNSt8ios_base7failureB5cxx11E) + 16u) + std::system_error (0x0x7f88a26c35b0) 0 + primary-for std::ios_base::failure (0x0x7f88a26c3548) + std::runtime_error (0x0x7f88a26c3618) 0 + primary-for std::system_error (0x0x7f88a26c35b0) + std::exception (0x0x7f88a26f2000) 0 nearly-empty + primary-for std::runtime_error (0x0x7f88a26c3618) + +Class std::ios_base::_Callback_list + size=24 align=8 + base size=24 base align=8 +std::ios_base::_Callback_list (0x0x7f88a26f2060) 0 + +Class std::ios_base::_Words + size=16 align=8 + base size=16 base align=8 +std::ios_base::_Words (0x0x7f88a26f20c0) 0 + +Class std::ios_base::Init + size=1 align=1 + base size=0 base align=1 +std::ios_base::Init (0x0x7f88a26f2120) 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 (0x0x7f88a2a22f60) 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 (0x0x7f88a26f28a0) 0 empty + +Class std::__num_base + size=1 align=1 + base size=0 base align=1 +std::__num_base (0x0x7f88a26f2f60) 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 (0x0x7f88a2309820 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 (0x0x7f88a2309e38 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 (0x0x7f88a23bc340 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 (0x0x7f88a23bc410 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 (0x0x7f88a26867e0) 0 + +Class QByteArray + size=8 align=8 + base size=8 base align=8 +QByteArray (0x0x7f88a2686840) 0 + +Class QByteRef + size=16 align=8 + base size=12 base align=8 +QByteRef (0x0x7f88a20d0ba0) 0 + +Class QStringDataPtr + size=8 align=8 + base size=8 base align=8 +QStringDataPtr (0x0x7f88a20d0f00) 0 + +Class QStringView + size=16 align=8 + base size=16 base align=8 +QStringView (0x0x7f88a21c93c0) 0 + +Class QLatin1String + size=16 align=8 + base size=16 base align=8 +QLatin1String (0x0x7f88a2252240) 0 + +Class QString::Null + size=1 align=1 + base size=0 base align=1 +QString::Null (0x0x7f88a22528a0) 0 empty + +Class QString + size=8 align=8 + base size=8 base align=8 +QString (0x0x7f88a2252840) 0 + +Class QCharRef + size=16 align=8 + base size=12 base align=8 +QCharRef (0x0x7f88a2034960) 0 + +Class QStringRef + size=16 align=8 + base size=16 base align=8 +QStringRef (0x0x7f88a1dd35a0) 0 + +Class QtPrivate::QHashCombine + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombine (0x0x7f88a1be2240) 0 empty + +Class QtPrivate::QHashCombineCommutative + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombineCommutative (0x0x7f88a1be22a0) 0 empty + +Class std::__detail::_List_node_base + size=16 align=8 + base size=16 base align=8 +std::__detail::_List_node_base (0x0x7f88a1be2300) 0 + +Class QListData::NotArrayCompatibleLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotArrayCompatibleLayout (0x0x7f88a1be26c0) 0 empty + +Class QListData::NotIndirectLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotIndirectLayout (0x0x7f88a1be2720) 0 empty + +Class QListData::ArrayCompatibleLayout + size=1 align=1 + base size=1 base align=1 +QListData::ArrayCompatibleLayout (0x0x7f88a1e02ea0) 0 empty + QListData::NotIndirectLayout (0x0x7f88a1be2780) 0 empty + +Class QListData::InlineWithPaddingLayout + size=1 align=1 + base size=1 base align=1 +QListData::InlineWithPaddingLayout (0x0x7f88a18ad690) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7f88a1be27e0) 0 empty + QListData::NotIndirectLayout (0x0x7f88a1be2840) 0 empty + +Class QListData::IndirectLayout + size=1 align=1 + base size=1 base align=1 +QListData::IndirectLayout (0x0x7f88a1e02f08) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7f88a1be28a0) 0 empty + +Class QListData::Data + size=24 align=8 + base size=24 base align=8 +QListData::Data (0x0x7f88a1be2900) 0 + +Class QListData + size=8 align=8 + base size=8 base align=8 +QListData (0x0x7f88a1be2660) 0 + +Class QRegExp + size=8 align=8 + base size=8 base align=8 +QRegExp (0x0x7f88a1be2d80) 0 + +Class QStringMatcher::Data + size=272 align=8 + base size=272 base align=8 +QStringMatcher::Data (0x0x7f88a1a7a000) 0 + +Class QStringMatcher + size=1048 align=8 + base size=1048 base align=8 +QStringMatcher (0x0x7f88a1a4cf60) 0 + +Class QStringList + size=8 align=8 + base size=8 base align=8 +QStringList (0x0x7f88a1a64958) 0 + QList (0x0x7f88a1a649c0) 0 + QListSpecialMethods (0x0x7f88a1a7a1e0) 0 empty + +Class QScopedPointerPodDeleter + size=1 align=1 + base size=0 base align=1 +QScopedPointerPodDeleter (0x0x7f88a1a7a600) 0 empty + +Class std::_Rb_tree_node_base + size=32 align=8 + base size=32 base align=8 +std::_Rb_tree_node_base (0x0x7f88a179b1e0) 0 + +Class std::allocator_arg_t + size=1 align=1 + base size=0 base align=1 +std::allocator_arg_t (0x0x7f88a179b840) 0 empty + +Class std::__uses_alloc_base + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc_base (0x0x7f88a179b9c0) 0 empty + +Class std::__uses_alloc0::_Sink + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc0::_Sink (0x0x7f88a179ba80) 0 empty + +Class std::__uses_alloc0 + size=1 align=1 + base size=1 base align=1 +std::__uses_alloc0 (0x0x7f88a15211a0) 0 + std::__uses_alloc_base (0x0x7f88a179ba20) 0 empty + +Class std::_Swallow_assign + size=1 align=1 + base size=0 base align=1 +std::_Swallow_assign (0x0x7f88a15c0ae0) 0 empty + +Class QtPrivate::AbstractDebugStreamFunction + size=16 align=8 + base size=16 base align=8 +QtPrivate::AbstractDebugStreamFunction (0x0x7f88a15c0d20) 0 + +Class QtPrivate::AbstractComparatorFunction + size=24 align=8 + base size=24 base align=8 +QtPrivate::AbstractComparatorFunction (0x0x7f88a15c0de0) 0 + +Class QtPrivate::AbstractConverterFunction + size=8 align=8 + base size=8 base align=8 +QtPrivate::AbstractConverterFunction (0x0x7f88a15c0f00) 0 + +Class QMetaType + size=80 align=8 + base size=80 base align=8 +QMetaType (0x0x7f88a12ed0c0) 0 + +Class QtMetaTypePrivate::VariantData + size=24 align=8 + base size=20 base align=8 +QtMetaTypePrivate::VariantData (0x0x7f88a12ed4e0) 0 + +Class QtMetaTypePrivate::VectorBoolElements + size=1 align=1 + base size=0 base align=1 +QtMetaTypePrivate::VectorBoolElements (0x0x7f88a12ed600) 0 empty + +Class QtMetaTypePrivate::QSequentialIterableImpl + size=104 align=8 + base size=104 base align=8 +QtMetaTypePrivate::QSequentialIterableImpl (0x0x7f88a12edf60) 0 + +Class QtMetaTypePrivate::QAssociativeIterableImpl + size=112 align=8 + base size=112 base align=8 +QtMetaTypePrivate::QAssociativeIterableImpl (0x0x7f88a14223c0) 0 + +Class QtMetaTypePrivate::QPairVariantInterfaceImpl + size=40 align=8 + base size=40 base align=8 +QtMetaTypePrivate::QPairVariantInterfaceImpl (0x0x7f88a14226c0) 0 + +Class std::chrono::_V2::system_clock + size=1 align=1 + base size=0 base align=1 +std::chrono::_V2::system_clock (0x0x7f88a0ed50c0) 0 empty + +Class std::chrono::_V2::steady_clock + size=1 align=1 + base size=0 base align=1 +std::chrono::_V2::steady_clock (0x0x7f88a0fd4f00) 0 empty + +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 (0x0x7f88a0fd4f60) 0 + vptr=((& QObjectData::_ZTV11QObjectData) + 16u) + +Class QObject::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObject::QPrivateSignal (0x0x7f88a101b180) 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 (0x0x7f88a101b120) 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 (0x0x7f88a0cdc420) 0 nearly-empty + vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16u) + +Class QSignalBlocker + size=16 align=8 + base size=10 base align=8 +QSignalBlocker (0x0x7f88a0cdc480) 0 + +Class QAbstractAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractAnimation::QPrivateSignal (0x0x7f88a0cdc540) 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 (0x0x7f88a0cdf4e0) 0 + vptr=((& QAbstractAnimation::_ZTV18QAbstractAnimation) + 16u) + QObject (0x0x7f88a0cdc4e0) 0 + primary-for QAbstractAnimation (0x0x7f88a0cdf4e0) + +Class QAnimationDriver::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationDriver::QPrivateSignal (0x0x7f88a0cdc600) 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 (0x0x7f88a0cdf548) 0 + vptr=((& QAnimationDriver::_ZTV16QAnimationDriver) + 16u) + QObject (0x0x7f88a0cdc5a0) 0 + primary-for QAnimationDriver (0x0x7f88a0cdf548) + +Class QEventLoop::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventLoop::QPrivateSignal (0x0x7f88a0cdc6c0) 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 (0x0x7f88a0cdf5b0) 0 + vptr=((& QEventLoop::_ZTV10QEventLoop) + 16u) + QObject (0x0x7f88a0cdc660) 0 + primary-for QEventLoop (0x0x7f88a0cdf5b0) + +Class QEventLoopLocker + size=8 align=8 + base size=8 base align=8 +QEventLoopLocker (0x0x7f88a0cdc8a0) 0 + +Class QAbstractEventDispatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractEventDispatcher::QPrivateSignal (0x0x7f88a0cdc960) 0 empty + +Class QAbstractEventDispatcher::TimerInfo + size=12 align=4 + base size=12 base align=4 +QAbstractEventDispatcher::TimerInfo (0x0x7f88a0cdc9c0) 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 (0x0x7f88a0cdf6e8) 0 + vptr=((& QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher) + 16u) + QObject (0x0x7f88a0cdc900) 0 + primary-for QAbstractEventDispatcher (0x0x7f88a0cdf6e8) + +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 (0x0x7f88a0cdcc60) 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 (0x0x7f88a0cdf8f0) 0 nearly-empty + vptr=((& std::bad_cast::_ZTVSt8bad_cast) + 16u) + std::exception (0x0x7f88a0cdccc0) 0 nearly-empty + primary-for std::bad_cast (0x0x7f88a0cdf8f0) + +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 (0x0x7f88a0cdf958) 0 nearly-empty + vptr=((& std::bad_typeid::_ZTVSt10bad_typeid) + 16u) + std::exception (0x0x7f88a0cdcd20) 0 nearly-empty + primary-for std::bad_typeid (0x0x7f88a0cdf958) + +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 (0x0x7f88a0e45bc8) 0 nearly-empty + vptr=((& std::bad_function_call::_ZTVSt17bad_function_call) + 16u) + std::exception (0x0x7f88a0e93de0) 0 nearly-empty + primary-for std::bad_function_call (0x0x7f88a0e45bc8) + +Class std::_Nocopy_types + size=16 align=8 + base size=16 base align=8 +std::_Nocopy_types (0x0x7f88a0e93ea0) 0 + +Class std::_Any_data + size=16 align=8 + base size=16 base align=8 +std::_Any_data (0x0x7f88a0e93f00) 0 + +Class std::_Function_base + size=24 align=8 + base size=24 base align=8 +std::_Function_base (0x0x7f88a0b38060) 0 + +Class QMapNodeBase + size=24 align=8 + base size=24 base align=8 +QMapNodeBase (0x0x7f88a0b38540) 0 + +Class QMapDataBase + size=40 align=8 + base size=40 base align=8 +QMapDataBase (0x0x7f88a0b38a80) 0 + +Class QHashData::Node + size=16 align=8 + base size=16 base align=8 +QHashData::Node (0x0x7f88a0b38e40) 0 + +Class QHashData + size=48 align=8 + base size=44 base align=8 +QHashData (0x0x7f88a0b38de0) 0 + +Class QHashDummyValue + size=1 align=1 + base size=0 base align=1 +QHashDummyValue (0x0x7f88a0b38ea0) 0 empty + +Class QVariant::PrivateShared + size=16 align=8 + base size=12 base align=8 +QVariant::PrivateShared (0x0x7f88a08d8780) 0 + +Class QVariant::Private::Data + size=8 align=8 + base size=8 base align=8 +QVariant::Private::Data (0x0x7f88a08d8840) 0 + +Class QVariant::Private + size=16 align=8 + base size=12 base align=8 +QVariant::Private (0x0x7f88a08d87e0) 0 + +Class QVariant::Handler + size=72 align=8 + base size=72 base align=8 +QVariant::Handler (0x0x7f88a08d88a0) 0 + +Class QVariant + size=16 align=8 + base size=16 base align=8 +QVariant (0x0x7f88a08d8720) 0 + +Class QVariantComparisonHelper + size=8 align=8 + base size=8 base align=8 +QVariantComparisonHelper (0x0x7f88a072e3c0) 0 + +Class QSequentialIterable::const_iterator + size=112 align=8 + base size=112 base align=8 +QSequentialIterable::const_iterator (0x0x7f88a072ea20) 0 + +Class QSequentialIterable + size=104 align=8 + base size=104 base align=8 +QSequentialIterable (0x0x7f88a072e9c0) 0 + +Class QAssociativeIterable::const_iterator + size=120 align=8 + base size=120 base align=8 +QAssociativeIterable::const_iterator (0x0x7f88a072eae0) 0 + +Class QAssociativeIterable + size=112 align=8 + base size=112 base align=8 +QAssociativeIterable (0x0x7f88a072ea80) 0 + +Class QModelIndex + size=24 align=8 + base size=24 base align=8 +QModelIndex (0x0x7f88a085ade0) 0 + +Class QPersistentModelIndex + size=8 align=8 + base size=8 base align=8 +QPersistentModelIndex (0x0x7f88a05a34e0) 0 + +Class QAbstractItemModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractItemModel::QPrivateSignal (0x0x7f88a063fc00) 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 (0x0x7f88a0651958) 0 + vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16u) + QObject (0x0x7f88a063fba0) 0 + primary-for QAbstractItemModel (0x0x7f88a0651958) + +Class QAbstractTableModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTableModel::QPrivateSignal (0x0x7f88a02a44e0) 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 (0x0x7f88a02ea068) 0 + vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16u) + QAbstractItemModel (0x0x7f88a02ea0d0) 0 + primary-for QAbstractTableModel (0x0x7f88a02ea068) + QObject (0x0x7f88a02a4480) 0 + primary-for QAbstractItemModel (0x0x7f88a02ea0d0) + +Class QAbstractListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractListModel::QPrivateSignal (0x0x7f88a02a45a0) 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 (0x0x7f88a02ea138) 0 + vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16u) + QAbstractItemModel (0x0x7f88a02ea1a0) 0 + primary-for QAbstractListModel (0x0x7f88a02ea138) + QObject (0x0x7f88a02a4540) 0 + primary-for QAbstractItemModel (0x0x7f88a02ea1a0) + +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 (0x0x7f88a02a4840) 0 + vptr=((& QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter) + 16u) + +Class QAbstractProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractProxyModel::QPrivateSignal (0x0x7f88a02a4900) 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 (0x0x7f88a02ea2d8) 0 + vptr=((& QAbstractProxyModel::_ZTV19QAbstractProxyModel) + 16u) + QAbstractItemModel (0x0x7f88a02ea340) 0 + primary-for QAbstractProxyModel (0x0x7f88a02ea2d8) + QObject (0x0x7f88a02a48a0) 0 + primary-for QAbstractItemModel (0x0x7f88a02ea340) + +Class QAbstractState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractState::QPrivateSignal (0x0x7f88a02a49c0) 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 (0x0x7f88a02ea3a8) 0 + vptr=((& QAbstractState::_ZTV14QAbstractState) + 16u) + QObject (0x0x7f88a02a4960) 0 + primary-for QAbstractState (0x0x7f88a02ea3a8) + +Class QAbstractTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTransition::QPrivateSignal (0x0x7f88a02a4a80) 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 (0x0x7f88a02ea410) 0 + vptr=((& QAbstractTransition::_ZTV19QAbstractTransition) + 16u) + QObject (0x0x7f88a02a4a20) 0 + primary-for QAbstractTransition (0x0x7f88a02ea410) + +Class QAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationGroup::QPrivateSignal (0x0x7f88a02a4b40) 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 (0x0x7f88a02ea478) 0 + vptr=((& QAnimationGroup::_ZTV15QAnimationGroup) + 16u) + QAbstractAnimation (0x0x7f88a02ea4e0) 0 + primary-for QAnimationGroup (0x0x7f88a02ea478) + QObject (0x0x7f88a02a4ae0) 0 + primary-for QAbstractAnimation (0x0x7f88a02ea4e0) + +Class QBasicTimer + size=4 align=4 + base size=4 base align=4 +QBasicTimer (0x0x7f88a040d8a0) 0 + +Class QBitArray + size=8 align=8 + base size=8 base align=8 +QBitArray (0x0x7f88a040db40) 0 + +Class QBitRef + size=16 align=8 + base size=12 base align=8 +QBitRef (0x0x7f88a040dc00) 0 + +Class QIODevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIODevice::QPrivateSignal (0x0x7f88a040df00) 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 (0x0x7f88a02eab60) 0 + vptr=((& QIODevice::_ZTV9QIODevice) + 16u) + QObject (0x0x7f88a040dea0) 0 + primary-for QIODevice (0x0x7f88a02eab60) + +Class QBuffer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBuffer::QPrivateSignal (0x0x7f88a00c5180) 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 (0x0x7f88a02eac98) 0 + vptr=((& QBuffer::_ZTV7QBuffer) + 16u) + QIODevice (0x0x7f88a02ead00) 0 + primary-for QBuffer (0x0x7f88a02eac98) + QObject (0x0x7f88a00c5120) 0 + primary-for QIODevice (0x0x7f88a02ead00) + +Class QByteArrayMatcher::Data + size=272 align=8 + base size=272 base align=8 +QByteArrayMatcher::Data (0x0x7f88a00c5240) 0 + +Class QByteArrayMatcher + size=1040 align=8 + base size=1040 base align=8 +QByteArrayMatcher (0x0x7f88a00c51e0) 0 + +Class QStaticByteArrayMatcherBase::Skiptable + size=256 align=1 + base size=256 base align=1 +QStaticByteArrayMatcherBase::Skiptable (0x0x7f88a00c5360) 0 + +Class QStaticByteArrayMatcherBase + size=256 align=16 + base size=256 base align=16 +QStaticByteArrayMatcherBase (0x0x7f88a00c5300) 0 + +Class QSharedData + size=4 align=4 + base size=4 base align=4 +QSharedData (0x0x7f88a00c5540) 0 + +Class QDate + size=8 align=8 + base size=8 base align=8 +QDate (0x0x7f88a00c5720) 0 + +Class QTime + size=4 align=4 + base size=4 base align=4 +QTime (0x0x7f88a00c59c0) 0 + +Class QDateTime::ShortData + size=8 align=8 + base size=8 base align=8 +QDateTime::ShortData (0x0x7f88a01e2180) 0 + +Class QDateTime::Data + size=8 align=8 + base size=8 base align=8 +QDateTime::Data (0x0x7f88a01e21e0) 0 + +Class QDateTime + size=8 align=8 + base size=8 base align=8 +QDateTime (0x0x7f88a01e2120) 0 + +Class QLocale + size=8 align=8 + base size=8 base align=8 +QLocale (0x0x7f88a0289300) 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 (0x0x7f88a0289900) 0 + vptr=((& QTextStream::_ZTV11QTextStream) + 16u) + +Class QTextStreamManipulator + size=40 align=8 + base size=38 base align=8 +QTextStreamManipulator (0x0x7f88a0289ba0) 0 + +Class QContiguousCacheData + size=24 align=4 + base size=24 base align=4 +QContiguousCacheData (0x0x7f88a0289de0) 0 + +Class QtSharedPointer::NormalDeleter + size=1 align=1 + base size=0 base align=1 +QtSharedPointer::NormalDeleter (0x0x7f88a007c4e0) 0 empty + +Class QtSharedPointer::ExternalRefCountData + size=16 align=8 + base size=16 base align=8 +QtSharedPointer::ExternalRefCountData (0x0x7f88a007c660) 0 + +Class QDebug::Stream + size=80 align=8 + base size=76 base align=8 +QDebug::Stream (0x0x7f88a007cba0) 0 + +Class QDebug + size=8 align=8 + base size=8 base align=8 +QDebug (0x0x7f88a007cb40) 0 + +Class QDebugStateSaver + size=8 align=8 + base size=8 base align=8 +QDebugStateSaver (0x0x7f889faa8ea0) 0 + +Class QNoDebug + size=1 align=1 + base size=0 base align=1 +QNoDebug (0x0x7f889faa8f60) 0 empty + +Class QCborError + size=4 align=4 + base size=4 base align=4 +QCborError (0x0x7f889fb50300) 0 + +Class QRegularExpression + size=8 align=8 + base size=8 base align=8 +QRegularExpression (0x0x7f889fb50480) 0 + +Class QRegularExpressionMatch + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatch (0x0x7f889fb50a80) 0 + +Class QRegularExpressionMatchIterator + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatchIterator (0x0x7f889fb50d80) 0 + +Class QUrl + size=8 align=8 + base size=8 base align=8 +QUrl (0x0x7f889fc22180) 0 + +Class QUuid + size=16 align=4 + base size=16 base align=4 +QUuid (0x0x7f889f929840) 0 + +Class QCborParserError + size=16 align=8 + base size=12 base align=8 +QCborParserError (0x0x7f889f929e40) 0 + +Class QCborValue + size=24 align=8 + base size=20 base align=8 +QCborValue (0x0x7f889f929ea0) 0 + +Class QCborValueRef + size=16 align=8 + base size=16 base align=8 +QCborValueRef (0x0x7f889f7e2ea0) 0 + +Class QCborArray::Iterator + size=16 align=8 + base size=16 base align=8 +QCborArray::Iterator (0x0x7f889f4be480) 0 + +Class QCborArray::ConstIterator + size=16 align=8 + base size=16 base align=8 +QCborArray::ConstIterator (0x0x7f889f4be4e0) 0 + +Class QCborArray + size=8 align=8 + base size=8 base align=8 +QCborArray (0x0x7f889f4be420) 0 + +Class QCborMap::Iterator + size=16 align=8 + base size=16 base align=8 +QCborMap::Iterator (0x0x7f889f586540) 0 + +Class QCborMap::ConstIterator + size=16 align=8 + base size=16 base align=8 +QCborMap::ConstIterator (0x0x7f889f5865a0) 0 + +Class QCborMap + size=8 align=8 + base size=8 base align=8 +QCborMap (0x0x7f889f5864e0) 0 + +Class qfloat16 + size=2 align=2 + base size=2 base align=2 +qfloat16 (0x0x7f889f39d120) 0 + +Class QCborStreamWriter + size=8 align=8 + base size=8 base align=8 +QCborStreamWriter (0x0x7f889f39d4e0) 0 + +Class QCborStreamReader + size=24 align=8 + base size=20 base align=8 +QCborStreamReader (0x0x7f889f39dea0) 0 + +Class QCollatorSortKey + size=8 align=8 + base size=8 base align=8 +QCollatorSortKey (0x0x7f889f47a540) 0 + +Class QCollator + size=8 align=8 + base size=8 base align=8 +QCollator (0x0x7f889f47a600) 0 + +Class QCommandLineOption + size=8 align=8 + base size=8 base align=8 +QCommandLineOption (0x0x7f889f14c600) 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 (0x0x7f889f14ca80) 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 (0x0x7f889f15d2d8) 0 + vptr=((& QTimerEvent::_ZTV11QTimerEvent) + 16u) + QEvent (0x0x7f889f14cae0) 0 + primary-for QTimerEvent (0x0x7f889f15d2d8) + +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 (0x0x7f889f15d340) 0 + vptr=((& QChildEvent::_ZTV11QChildEvent) + 16u) + QEvent (0x0x7f889f14cb40) 0 + primary-for QChildEvent (0x0x7f889f15d340) + +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 (0x0x7f889f15d888) 0 + vptr=((& QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent) + 16u) + QEvent (0x0x7f889f1cf060) 0 + primary-for QDynamicPropertyChangeEvent (0x0x7f889f15d888) + +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 (0x0x7f889f15d8f0) 0 + vptr=((& QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent) + 16u) + QEvent (0x0x7f889f1cf0c0) 0 + primary-for QDeferredDeleteEvent (0x0x7f889f15d8f0) + +Class QCoreApplication::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QCoreApplication::QPrivateSignal (0x0x7f889f1cf180) 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 (0x0x7f889f15d958) 0 + vptr=((& QCoreApplication::_ZTV16QCoreApplication) + 16u) + QObject (0x0x7f889f1cf120) 0 + primary-for QCoreApplication (0x0x7f889f15d958) + +Class QCommandLineParser + size=8 align=8 + base size=8 base align=8 +QCommandLineParser (0x0x7f889f1cf1e0) 0 + +Class QCryptographicHash + size=8 align=8 + base size=8 base align=8 +QCryptographicHash (0x0x7f889f1cf240) 0 + +Class QDataStream + size=32 align=8 + base size=32 base align=8 +QDataStream (0x0x7f889f1cf2a0) 0 + +Class QtPrivate::StreamStateSaver + size=16 align=8 + base size=12 base align=8 +QtPrivate::StreamStateSaver (0x0x7f889f1cf360) 0 + +Class QElapsedTimer + size=16 align=8 + base size=16 base align=8 +QElapsedTimer (0x0x7f889f1cf840) 0 + +Class QDeadlineTimer + size=16 align=8 + base size=16 base align=8 +QDeadlineTimer (0x0x7f889f1cfd20) 0 + +Class QFileDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileDevice::QPrivateSignal (0x0x7f889efaeba0) 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 (0x0x7f889efb0dd0) 0 + vptr=((& QFileDevice::_ZTV11QFileDevice) + 16u) + QIODevice (0x0x7f889efb0e38) 0 + primary-for QFileDevice (0x0x7f889efb0dd0) + QObject (0x0x7f889efaeb40) 0 + primary-for QIODevice (0x0x7f889efb0e38) + +Class QFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFile::QPrivateSignal (0x0x7f889efaede0) 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 (0x0x7f889efb0f70) 0 + vptr=((& QFile::_ZTV5QFile) + 16u) + QFileDevice (0x0x7f889f016000) 0 + primary-for QFile (0x0x7f889efb0f70) + QIODevice (0x0x7f889f016068) 0 + primary-for QFileDevice (0x0x7f889f016000) + QObject (0x0x7f889efaed80) 0 + primary-for QIODevice (0x0x7f889f016068) + +Class QFileInfo + size=8 align=8 + base size=8 base align=8 +QFileInfo (0x0x7f889f04b000) 0 + +Class QDir + size=8 align=8 + base size=8 base align=8 +QDir (0x0x7f889f04b420) 0 + +Class QDirIterator + size=8 align=8 + base size=8 base align=8 +QDirIterator (0x0x7f889f04ba20) 0 + +Class QEasingCurve + size=8 align=8 + base size=8 base align=8 +QEasingCurve (0x0x7f889f04bc60) 0 + +Class QEventTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventTransition::QPrivateSignal (0x0x7f889ee1a0c0) 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 (0x0x7f889ee19068) 0 + vptr=((& QEventTransition::_ZTV16QEventTransition) + 16u) + QAbstractTransition (0x0x7f889ee190d0) 0 + primary-for QEventTransition (0x0x7f889ee19068) + QObject (0x0x7f889ee1a060) 0 + primary-for QAbstractTransition (0x0x7f889ee190d0) + +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 (0x0x7f889ee19138) 0 nearly-empty + vptr=((& QException::_ZTV10QException) + 16u) + std::exception (0x0x7f889ee1a120) 0 nearly-empty + primary-for QException (0x0x7f889ee19138) + +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 (0x0x7f889ee191a0) 0 nearly-empty + vptr=((& QUnhandledException::_ZTV19QUnhandledException) + 16u) + QException (0x0x7f889ee19208) 0 nearly-empty + primary-for QUnhandledException (0x0x7f889ee191a0) + std::exception (0x0x7f889ee1a180) 0 nearly-empty + primary-for QException (0x0x7f889ee19208) + +Class QtPrivate::ExceptionHolder + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionHolder (0x0x7f889ee1a1e0) 0 + +Class QtPrivate::ExceptionStore + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionStore (0x0x7f889ee1a2a0) 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 (0x0x7f889ee1a300) 0 nearly-empty + vptr=((& QFactoryInterface::_ZTV17QFactoryInterface) + 16u) + +Class QFileSelector::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSelector::QPrivateSignal (0x0x7f889ee1a420) 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 (0x0x7f889ee19270) 0 + vptr=((& QFileSelector::_ZTV13QFileSelector) + 16u) + QObject (0x0x7f889ee1a3c0) 0 + primary-for QFileSelector (0x0x7f889ee19270) + +Class QFileSystemWatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSystemWatcher::QPrivateSignal (0x0x7f889ee1a4e0) 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 (0x0x7f889ee192d8) 0 + vptr=((& QFileSystemWatcher::_ZTV18QFileSystemWatcher) + 16u) + QObject (0x0x7f889ee1a480) 0 + primary-for QFileSystemWatcher (0x0x7f889ee192d8) + +Class QFinalState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFinalState::QPrivateSignal (0x0x7f889ee1a5a0) 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 (0x0x7f889ee19340) 0 + vptr=((& QFinalState::_ZTV11QFinalState) + 16u) + QAbstractState (0x0x7f889ee193a8) 0 + primary-for QFinalState (0x0x7f889ee19340) + QObject (0x0x7f889ee1a540) 0 + primary-for QAbstractState (0x0x7f889ee193a8) + +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 (0x0x7f889ee1a600) 0 + vptr=((& QRunnable::_ZTV9QRunnable) + 16u) + +Class QBasicMutex + size=8 align=8 + base size=8 base align=8 +QBasicMutex (0x0x7f889ee1a660) 0 + +Class QMutex + size=8 align=8 + base size=8 base align=8 +QMutex (0x0x7f889ee194e0) 0 + QBasicMutex (0x0x7f889ee1a840) 0 + +Class QMutexLocker + size=8 align=8 + base size=8 base align=8 +QMutexLocker (0x0x7f889ee1a8a0) 0 + +Class QtPrivate::ResultItem + size=16 align=8 + base size=16 base align=8 +QtPrivate::ResultItem (0x0x7f889ee1a900) 0 + +Class QtPrivate::ResultIteratorBase + size=16 align=8 + base size=12 base align=8 +QtPrivate::ResultIteratorBase (0x0x7f889ee1a960) 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 (0x0x7f889ee1aa80) 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 (0x0x7f889eb6f300) 0 + vptr=((& QFutureInterfaceBase::_ZTV20QFutureInterfaceBase) + 16u) + +Class QFutureWatcherBase::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFutureWatcherBase::QPrivateSignal (0x0x7f889eb6fae0) 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 (0x0x7f889eb9d618) 0 + vptr=((& QFutureWatcherBase::_ZTV18QFutureWatcherBase) + 16u) + QObject (0x0x7f889eb6fa80) 0 + primary-for QFutureWatcherBase (0x0x7f889eb9d618) + +Class QHistoryState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QHistoryState::QPrivateSignal (0x0x7f889ec54120) 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 (0x0x7f889eb9df08) 0 + vptr=((& QHistoryState::_ZTV13QHistoryState) + 16u) + QAbstractState (0x0x7f889eb9df70) 0 + primary-for QHistoryState (0x0x7f889eb9df08) + QObject (0x0x7f889ec540c0) 0 + primary-for QAbstractState (0x0x7f889eb9df70) + +Class QIdentityProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIdentityProxyModel::QPrivateSignal (0x0x7f889ec541e0) 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 (0x0x7f889e86e000) 0 + vptr=((& QIdentityProxyModel::_ZTV19QIdentityProxyModel) + 16u) + QAbstractProxyModel (0x0x7f889e86e068) 0 + primary-for QIdentityProxyModel (0x0x7f889e86e000) + QAbstractItemModel (0x0x7f889e86e0d0) 0 + primary-for QAbstractProxyModel (0x0x7f889e86e068) + QObject (0x0x7f889ec54180) 0 + primary-for QAbstractItemModel (0x0x7f889e86e0d0) + +Class QItemSelectionRange + size=16 align=8 + base size=16 base align=8 +QItemSelectionRange (0x0x7f889ec54240) 0 + +Class QItemSelectionModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QItemSelectionModel::QPrivateSignal (0x0x7f889ec54900) 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 (0x0x7f889e86e8f0) 0 + vptr=((& QItemSelectionModel::_ZTV19QItemSelectionModel) + 16u) + QObject (0x0x7f889ec548a0) 0 + primary-for QItemSelectionModel (0x0x7f889e86e8f0) + +Class QItemSelection + size=8 align=8 + base size=8 base align=8 +QItemSelection (0x0x7f889e86eaf8) 0 + QList (0x0x7f889e86eb60) 0 + QListSpecialMethods (0x0x7f889ec54c00) 0 empty + +Class QJsonValue + size=24 align=8 + base size=20 base align=8 +QJsonValue (0x0x7f889e95a120) 0 + +Class QJsonValueRef + size=16 align=8 + base size=12 base align=8 +QJsonValueRef (0x0x7f889e6c9840) 0 + +Class QJsonValuePtr + size=24 align=8 + base size=24 base align=8 +QJsonValuePtr (0x0x7f889e6c9d80) 0 + +Class QJsonValueRefPtr + size=16 align=8 + base size=16 base align=8 +QJsonValueRefPtr (0x0x7f889e6c9de0) 0 + +Class QJsonArray::iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::iterator (0x0x7f889e752000) 0 + +Class QJsonArray::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::const_iterator (0x0x7f889e752060) 0 + +Class QJsonArray + size=16 align=8 + base size=16 base align=8 +QJsonArray (0x0x7f889e6c9f60) 0 + +Class QJsonParseError + size=8 align=4 + base size=8 base align=4 +QJsonParseError (0x0x7f889e7f52a0) 0 + +Class QJsonDocument + size=8 align=8 + base size=8 base align=8 +QJsonDocument (0x0x7f889e7f5300) 0 + +Class QJsonObject::iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::iterator (0x0x7f889e7f5960) 0 + +Class QJsonObject::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::const_iterator (0x0x7f889e7f59c0) 0 + +Class QJsonObject + size=16 align=8 + base size=16 base align=8 +QJsonObject (0x0x7f889e7f5900) 0 + +Class QLibrary::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLibrary::QPrivateSignal (0x0x7f889e512c60) 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 (0x0x7f889e500ea0) 0 + vptr=((& QLibrary::_ZTV8QLibrary) + 16u) + QObject (0x0x7f889e512c00) 0 + primary-for QLibrary (0x0x7f889e500ea0) + +Class QVersionNumber::SegmentStorage + size=8 align=8 + base size=8 base align=8 +QVersionNumber::SegmentStorage (0x0x7f889e5a0360) 0 + +Class QVersionNumber + size=8 align=8 + base size=8 base align=8 +QVersionNumber (0x0x7f889e512e40) 0 + +Class QLibraryInfo + size=1 align=1 + base size=0 base align=1 +QLibraryInfo (0x0x7f889e5a0840) 0 empty + +Class QPoint + size=8 align=4 + base size=8 base align=4 +QPoint (0x0x7f889e5a08a0) 0 + +Class QPointF + size=16 align=8 + base size=16 base align=8 +QPointF (0x0x7f889e5a0b40) 0 + +Class QLine + size=16 align=4 + base size=16 base align=4 +QLine (0x0x7f889e286180) 0 + +Class QLineF + size=32 align=8 + base size=32 base align=8 +QLineF (0x0x7f889e286ae0) 0 + +Class QLinkedListData + size=32 align=8 + base size=25 base align=8 +QLinkedListData (0x0x7f889e2fd120) 0 + +Class QLockFile + size=8 align=8 + base size=8 base align=8 +QLockFile (0x0x7f889e2fd480) 0 + +Class QLoggingCategory::AtomicBools + size=4 align=1 + base size=4 base align=1 +QLoggingCategory::AtomicBools (0x0x7f889e2fd600) 0 + +Class QLoggingCategory + size=24 align=8 + base size=24 base align=8 +QLoggingCategory (0x0x7f889e2fd5a0) 0 + +Class QMargins + size=16 align=4 + base size=16 base align=4 +QMargins (0x0x7f889e2fd780) 0 + +Class QMarginsF + size=32 align=8 + base size=32 base align=8 +QMarginsF (0x0x7f889e2fda20) 0 + +Class QMessageAuthenticationCode + size=8 align=8 + base size=8 base align=8 +QMessageAuthenticationCode (0x0x7f889dfa90c0) 0 + +Class QMetaMethod + size=16 align=8 + base size=12 base align=8 +QMetaMethod (0x0x7f889dfa9120) 0 + +Class QMetaEnum + size=16 align=8 + base size=12 base align=8 +QMetaEnum (0x0x7f889dfa9720) 0 + +Class QMetaProperty + size=32 align=8 + base size=32 base align=8 +QMetaProperty (0x0x7f889dfa9a20) 0 + +Class QMetaClassInfo + size=16 align=8 + base size=12 base align=8 +QMetaClassInfo (0x0x7f889dfa9a80) 0 + +Class QMimeData::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QMimeData::QPrivateSignal (0x0x7f889dfa9d80) 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 (0x0x7f889e043138) 0 + vptr=((& QMimeData::_ZTV9QMimeData) + 16u) + QObject (0x0x7f889dfa9d20) 0 + primary-for QMimeData (0x0x7f889e043138) + +Class QMimeType + size=8 align=8 + base size=8 base align=8 +QMimeType (0x0x7f889dfa9de0) 0 + +Class QMimeDatabase + size=8 align=8 + base size=8 base align=8 +QMimeDatabase (0x0x7f889e072120) 0 + +Class QObjectCleanupHandler::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObjectCleanupHandler::QPrivateSignal (0x0x7f889e0721e0) 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 (0x0x7f889e043340) 0 + vptr=((& QObjectCleanupHandler::_ZTV21QObjectCleanupHandler) + 16u) + QObject (0x0x7f889e072180) 0 + primary-for QObjectCleanupHandler (0x0x7f889e043340) + +Class QOperatingSystemVersion + size=16 align=4 + base size=16 base align=4 +QOperatingSystemVersion (0x0x7f889e072240) 0 + +Class QParallelAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QParallelAnimationGroup::QPrivateSignal (0x0x7f889e0729c0) 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 (0x0x7f889e043a90) 0 + vptr=((& QParallelAnimationGroup::_ZTV23QParallelAnimationGroup) + 16u) + QAnimationGroup (0x0x7f889e043af8) 0 + primary-for QParallelAnimationGroup (0x0x7f889e043a90) + QAbstractAnimation (0x0x7f889e043b60) 0 + primary-for QAnimationGroup (0x0x7f889e043af8) + QObject (0x0x7f889e072960) 0 + primary-for QAbstractAnimation (0x0x7f889e043b60) + +Class QPauseAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPauseAnimation::QPrivateSignal (0x0x7f889e072a80) 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 (0x0x7f889e043bc8) 0 + vptr=((& QPauseAnimation::_ZTV15QPauseAnimation) + 16u) + QAbstractAnimation (0x0x7f889e043c30) 0 + primary-for QPauseAnimation (0x0x7f889e043bc8) + QObject (0x0x7f889e072a20) 0 + primary-for QAbstractAnimation (0x0x7f889e043c30) + +Class QStaticPlugin + size=16 align=8 + base size=16 base align=8 +QStaticPlugin (0x0x7f889e072c60) 0 + +Class QPluginLoader::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPluginLoader::QPrivateSignal (0x0x7f889e072f60) 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 (0x0x7f889e043e38) 0 + vptr=((& QPluginLoader::_ZTV13QPluginLoader) + 16u) + QObject (0x0x7f889e072f00) 0 + primary-for QPluginLoader (0x0x7f889e043e38) + +Class QProcessEnvironment + size=8 align=8 + base size=8 base align=8 +QProcessEnvironment (0x0x7f889e10d000) 0 + +Class QProcess::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QProcess::QPrivateSignal (0x0x7f889e10d6c0) 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 (0x0x7f889e128478) 0 + vptr=((& QProcess::_ZTV8QProcess) + 16u) + QIODevice (0x0x7f889e1284e0) 0 + primary-for QProcess (0x0x7f889e128478) + QObject (0x0x7f889e10d660) 0 + primary-for QIODevice (0x0x7f889e1284e0) + +Class QVariantAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QVariantAnimation::QPrivateSignal (0x0x7f889e10d780) 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 (0x0x7f889e128548) 0 + vptr=((& QVariantAnimation::_ZTV17QVariantAnimation) + 16u) + QAbstractAnimation (0x0x7f889e1285b0) 0 + primary-for QVariantAnimation (0x0x7f889e128548) + QObject (0x0x7f889e10d720) 0 + primary-for QAbstractAnimation (0x0x7f889e1285b0) + +Class QPropertyAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPropertyAnimation::QPrivateSignal (0x0x7f889e10d840) 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 (0x0x7f889e128680) 0 + vptr=((& QPropertyAnimation::_ZTV18QPropertyAnimation) + 16u) + QVariantAnimation (0x0x7f889e1286e8) 0 + primary-for QPropertyAnimation (0x0x7f889e128680) + QAbstractAnimation (0x0x7f889e128750) 0 + primary-for QVariantAnimation (0x0x7f889e1286e8) + QObject (0x0x7f889e10d7e0) 0 + primary-for QAbstractAnimation (0x0x7f889e128750) + +Class QRandomGenerator::Storage + size=2504 align=8 + base size=2504 base align=8 +QRandomGenerator::Storage (0x0x7f889e10d960) 0 + +Class QRandomGenerator + size=2512 align=8 + base size=2512 base align=8 +QRandomGenerator (0x0x7f889e10d900) 0 + +Class QRandomGenerator64 + size=2512 align=8 + base size=2512 base align=8 +QRandomGenerator64 (0x0x7f889de09a28) 0 + QRandomGenerator (0x0x7f889de0d900) 0 + +Class QReadWriteLock + size=8 align=8 + base size=8 base align=8 +QReadWriteLock (0x0x7f889de0d9c0) 0 + +Class QReadLocker + size=8 align=8 + base size=8 base align=8 +QReadLocker (0x0x7f889de0dc60) 0 + +Class QWriteLocker + size=8 align=8 + base size=8 base align=8 +QWriteLocker (0x0x7f889de0dd20) 0 + +Class QSize + size=8 align=4 + base size=8 base align=4 +QSize (0x0x7f889de0dde0) 0 + +Class QSizeF + size=16 align=8 + base size=16 base align=8 +QSizeF (0x0x7f889def10c0) 0 + +Class QRect + size=16 align=4 + base size=16 base align=4 +QRect (0x0x7f889def1360) 0 + +Class QRectF + size=32 align=8 + base size=32 base align=8 +QRectF (0x0x7f889def1600) 0 + +Class QResource + size=8 align=8 + base size=8 base align=8 +QResource (0x0x7f889def18a0) 0 + +Class QSaveFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSaveFile::QPrivateSignal (0x0x7f889def1a20) 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 (0x0x7f889df355b0) 0 + vptr=((& QSaveFile::_ZTV9QSaveFile) + 16u) + QFileDevice (0x0x7f889df35618) 0 + primary-for QSaveFile (0x0x7f889df355b0) + QIODevice (0x0x7f889df35680) 0 + primary-for QFileDevice (0x0x7f889df35618) + QObject (0x0x7f889def19c0) 0 + primary-for QIODevice (0x0x7f889df35680) + +Class QSemaphore + size=8 align=8 + base size=8 base align=8 +QSemaphore (0x0x7f889def1b40) 0 + +Class QSemaphoreReleaser + size=16 align=8 + base size=12 base align=8 +QSemaphoreReleaser (0x0x7f889def1cc0) 0 + +Class QSequentialAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSequentialAnimationGroup::QPrivateSignal (0x0x7f889d9e5300) 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 (0x0x7f889d9cbf08) 0 + vptr=((& QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup) + 16u) + QAnimationGroup (0x0x7f889d9cbf70) 0 + primary-for QSequentialAnimationGroup (0x0x7f889d9cbf08) + QAbstractAnimation (0x0x7f889d9eb000) 0 + primary-for QAnimationGroup (0x0x7f889d9cbf70) + QObject (0x0x7f889d9e52a0) 0 + primary-for QAbstractAnimation (0x0x7f889d9eb000) + +Class QSettings::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSettings::QPrivateSignal (0x0x7f889d9e53c0) 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 (0x0x7f889d9eb068) 0 + vptr=((& QSettings::_ZTV9QSettings) + 16u) + QObject (0x0x7f889d9e5360) 0 + primary-for QSettings (0x0x7f889d9eb068) + +Class QSharedMemory::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSharedMemory::QPrivateSignal (0x0x7f889d9e5480) 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 (0x0x7f889d9eb0d0) 0 + vptr=((& QSharedMemory::_ZTV13QSharedMemory) + 16u) + QObject (0x0x7f889d9e5420) 0 + primary-for QSharedMemory (0x0x7f889d9eb0d0) + +Class QSignalMapper::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalMapper::QPrivateSignal (0x0x7f889d9e5540) 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 (0x0x7f889d9eb138) 0 + vptr=((& QSignalMapper::_ZTV13QSignalMapper) + 16u) + QObject (0x0x7f889d9e54e0) 0 + primary-for QSignalMapper (0x0x7f889d9eb138) + +Class QSignalTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalTransition::QPrivateSignal (0x0x7f889d9e5600) 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 (0x0x7f889d9eb1a0) 0 + vptr=((& QSignalTransition::_ZTV17QSignalTransition) + 16u) + QAbstractTransition (0x0x7f889d9eb208) 0 + primary-for QSignalTransition (0x0x7f889d9eb1a0) + QObject (0x0x7f889d9e55a0) 0 + primary-for QAbstractTransition (0x0x7f889d9eb208) + +Class QSocketNotifier::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSocketNotifier::QPrivateSignal (0x0x7f889d9e56c0) 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 (0x0x7f889d9eb270) 0 + vptr=((& QSocketNotifier::_ZTV15QSocketNotifier) + 16u) + QObject (0x0x7f889d9e5660) 0 + primary-for QSocketNotifier (0x0x7f889d9eb270) + +Class QSortFilterProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSortFilterProxyModel::QPrivateSignal (0x0x7f889d9e5780) 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 (0x0x7f889d9eb2d8) 0 + vptr=((& QSortFilterProxyModel::_ZTV21QSortFilterProxyModel) + 16u) + QAbstractProxyModel (0x0x7f889d9eb340) 0 + primary-for QSortFilterProxyModel (0x0x7f889d9eb2d8) + QAbstractItemModel (0x0x7f889d9eb3a8) 0 + primary-for QAbstractProxyModel (0x0x7f889d9eb340) + QObject (0x0x7f889d9e5720) 0 + primary-for QAbstractItemModel (0x0x7f889d9eb3a8) + +Class QStandardPaths + size=1 align=1 + base size=0 base align=1 +QStandardPaths (0x0x7f889d9e5840) 0 empty + +Class QState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QState::QPrivateSignal (0x0x7f889d9e5a80) 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 (0x0x7f889d9eb548) 0 + vptr=((& QState::_ZTV6QState) + 16u) + QAbstractState (0x0x7f889d9eb5b0) 0 + primary-for QState (0x0x7f889d9eb548) + QObject (0x0x7f889d9e5a20) 0 + primary-for QAbstractState (0x0x7f889d9eb5b0) + +Class QStateMachine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStateMachine::QPrivateSignal (0x0x7f889d9e5ba0) 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 (0x0x7f889d9eb750) 0 + vptr=((& QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE) + 16u) + QEvent (0x0x7f889d9e5c00) 0 + primary-for QStateMachine::SignalEvent (0x0x7f889d9eb750) + +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 (0x0x7f889d9eb7b8) 0 + vptr=((& QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE) + 16u) + QEvent (0x0x7f889d9e5c60) 0 + primary-for QStateMachine::WrappedEvent (0x0x7f889d9eb7b8) + +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 (0x0x7f889d9eb618) 0 + vptr=((& QStateMachine::_ZTV13QStateMachine) + 16u) + QState (0x0x7f889d9eb680) 0 + primary-for QStateMachine (0x0x7f889d9eb618) + QAbstractState (0x0x7f889d9eb6e8) 0 + primary-for QState (0x0x7f889d9eb680) + QObject (0x0x7f889d9e5b40) 0 + primary-for QAbstractState (0x0x7f889d9eb6e8) + +Class QStorageInfo + size=8 align=8 + base size=8 base align=8 +QStorageInfo (0x0x7f889d9e5cc0) 0 + +Class QAbstractConcatenable + size=1 align=1 + base size=0 base align=1 +QAbstractConcatenable (0x0x7f889db2fc00) 0 empty + +Class QStringListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStringListModel::QPrivateSignal (0x0x7f889d806000) 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 (0x0x7f889d7e47b8) 0 + vptr=((& QStringListModel::_ZTV16QStringListModel) + 16u) + QAbstractListModel (0x0x7f889d7e4820) 0 + primary-for QStringListModel (0x0x7f889d7e47b8) + QAbstractItemModel (0x0x7f889d7e4888) 0 + primary-for QAbstractListModel (0x0x7f889d7e4820) + QObject (0x0x7f889d77ff60) 0 + primary-for QAbstractItemModel (0x0x7f889d7e4888) + +Class QSystemSemaphore + size=8 align=8 + base size=8 base align=8 +QSystemSemaphore (0x0x7f889d806060) 0 + +Class QTemporaryDir + size=8 align=8 + base size=8 base align=8 +QTemporaryDir (0x0x7f889d806120) 0 + +Class QTemporaryFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTemporaryFile::QPrivateSignal (0x0x7f889d806240) 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 (0x0x7f889d7e48f0) 0 + vptr=((& QTemporaryFile::_ZTV14QTemporaryFile) + 16u) + QFile (0x0x7f889d7e4958) 0 + primary-for QTemporaryFile (0x0x7f889d7e48f0) + QFileDevice (0x0x7f889d7e49c0) 0 + primary-for QFile (0x0x7f889d7e4958) + QIODevice (0x0x7f889d7e4a28) 0 + primary-for QFileDevice (0x0x7f889d7e49c0) + QObject (0x0x7f889d8061e0) 0 + primary-for QIODevice (0x0x7f889d7e4a28) + +Class QTextBoundaryFinder + size=48 align=8 + base size=48 base align=8 +QTextBoundaryFinder (0x0x7f889d8062a0) 0 + +Class QTextCodec::ConverterState + size=32 align=8 + base size=32 base align=8 +QTextCodec::ConverterState (0x0x7f889d8064e0) 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 (0x0x7f889d806480) 0 nearly-empty + vptr=((& QTextCodec::_ZTV10QTextCodec) + 16u) + +Class QTextEncoder + size=40 align=8 + base size=40 base align=8 +QTextEncoder (0x0x7f889d8066c0) 0 + +Class QTextDecoder + size=40 align=8 + base size=40 base align=8 +QTextDecoder (0x0x7f889d806720) 0 + +Class std::__mutex_base + size=40 align=8 + base size=40 base align=8 +std::__mutex_base (0x0x7f889d806780) 0 + +Class std::__recursive_mutex_base + size=40 align=8 + base size=40 base align=8 +std::__recursive_mutex_base (0x0x7f889d8067e0) 0 + +Class std::mutex + size=40 align=8 + base size=40 base align=8 +std::mutex (0x0x7f889d7e4c30) 0 + std::__mutex_base (0x0x7f889d806840) 0 + +Class std::recursive_mutex + size=40 align=8 + base size=40 base align=8 +std::recursive_mutex (0x0x7f889d7e4c98) 0 + std::__recursive_mutex_base (0x0x7f889d8068a0) 0 + +Class std::timed_mutex + size=40 align=8 + base size=40 base align=8 +std::timed_mutex (0x0x7f889d8e6770) 0 + std::__mutex_base (0x0x7f889d8069c0) 0 + std::__timed_mutex_impl (0x0x7f889d806a20) 0 empty + +Class std::recursive_timed_mutex + size=40 align=8 + base size=40 base align=8 +std::recursive_timed_mutex (0x0x7f889d900150) 0 + std::__recursive_mutex_base (0x0x7f889d806ae0) 0 + std::__timed_mutex_impl (0x0x7f889d806b40) 0 empty + +Class std::defer_lock_t + size=1 align=1 + base size=0 base align=1 +std::defer_lock_t (0x0x7f889d806ba0) 0 empty + +Class std::try_to_lock_t + size=1 align=1 + base size=0 base align=1 +std::try_to_lock_t (0x0x7f889d806c00) 0 empty + +Class std::adopt_lock_t + size=1 align=1 + base size=0 base align=1 +std::adopt_lock_t (0x0x7f889d806c60) 0 empty + +Class std::once_flag + size=4 align=4 + base size=4 base align=4 +std::once_flag (0x0x7f889d806ea0) 0 + +Vtable for __gnu_cxx::__concurrence_lock_error +__gnu_cxx::__concurrence_lock_error::_ZTVN9__gnu_cxx24__concurrence_lock_errorE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx24__concurrence_lock_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_lock_error::~__concurrence_lock_error +24 (int (*)(...))__gnu_cxx::__concurrence_lock_error::~__concurrence_lock_error +32 (int (*)(...))__gnu_cxx::__concurrence_lock_error::what + +Class __gnu_cxx::__concurrence_lock_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_lock_error (0x0x7f889d7e4dd0) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_lock_error::_ZTVN9__gnu_cxx24__concurrence_lock_errorE) + 16u) + std::exception (0x0x7f889d806f60) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_lock_error (0x0x7f889d7e4dd0) + +Vtable for __gnu_cxx::__concurrence_unlock_error +__gnu_cxx::__concurrence_unlock_error::_ZTVN9__gnu_cxx26__concurrence_unlock_errorE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx26__concurrence_unlock_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::~__concurrence_unlock_error +24 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::~__concurrence_unlock_error +32 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::what + +Class __gnu_cxx::__concurrence_unlock_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_unlock_error (0x0x7f889d7e4e38) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_unlock_error::_ZTVN9__gnu_cxx26__concurrence_unlock_errorE) + 16u) + std::exception (0x0x7f889d959060) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_unlock_error (0x0x7f889d7e4e38) + +Vtable for __gnu_cxx::__concurrence_broadcast_error +__gnu_cxx::__concurrence_broadcast_error::_ZTVN9__gnu_cxx29__concurrence_broadcast_errorE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx29__concurrence_broadcast_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::~__concurrence_broadcast_error +24 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::~__concurrence_broadcast_error +32 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::what + +Class __gnu_cxx::__concurrence_broadcast_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_broadcast_error (0x0x7f889d7e4ea0) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_broadcast_error::_ZTVN9__gnu_cxx29__concurrence_broadcast_errorE) + 16u) + std::exception (0x0x7f889d959120) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_broadcast_error (0x0x7f889d7e4ea0) + +Vtable for __gnu_cxx::__concurrence_wait_error +__gnu_cxx::__concurrence_wait_error::_ZTVN9__gnu_cxx24__concurrence_wait_errorE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx24__concurrence_wait_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_wait_error::~__concurrence_wait_error +24 (int (*)(...))__gnu_cxx::__concurrence_wait_error::~__concurrence_wait_error +32 (int (*)(...))__gnu_cxx::__concurrence_wait_error::what + +Class __gnu_cxx::__concurrence_wait_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_wait_error (0x0x7f889d7e4f70) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_wait_error::_ZTVN9__gnu_cxx24__concurrence_wait_errorE) + 16u) + std::exception (0x0x7f889d9591e0) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_wait_error (0x0x7f889d7e4f70) + +Class __gnu_cxx::__mutex + size=40 align=8 + base size=40 base align=8 +__gnu_cxx::__mutex (0x0x7f889d9592a0) 0 + +Class __gnu_cxx::__recursive_mutex + size=40 align=8 + base size=40 base align=8 +__gnu_cxx::__recursive_mutex (0x0x7f889d959300) 0 + +Class __gnu_cxx::__scoped_lock + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__scoped_lock (0x0x7f889d959360) 0 + +Class __gnu_cxx::__cond + size=48 align=8 + base size=48 base align=8 +__gnu_cxx::__cond (0x0x7f889d9593c0) 0 + +Vtable for std::bad_weak_ptr +std::bad_weak_ptr::_ZTVSt12bad_weak_ptr: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt12bad_weak_ptr) +16 (int (*)(...))std::bad_weak_ptr::~bad_weak_ptr +24 (int (*)(...))std::bad_weak_ptr::~bad_weak_ptr +32 (int (*)(...))std::bad_weak_ptr::what + +Class std::bad_weak_ptr + size=8 align=8 + base size=8 base align=8 +std::bad_weak_ptr (0x0x7f889d5ab270) 0 nearly-empty + vptr=((& std::bad_weak_ptr::_ZTVSt12bad_weak_ptr) + 16u) + std::exception (0x0x7f889d959720) 0 nearly-empty + primary-for std::bad_weak_ptr (0x0x7f889d5ab270) + +Class std::_Sp_make_shared_tag + size=1 align=1 + base size=0 base align=1 +std::_Sp_make_shared_tag (0x0x7f889d959f60) 0 empty + +Class std::_Sp_locker + size=2 align=1 + base size=2 base align=1 +std::_Sp_locker (0x0x7f889d690780) 0 + +Class std::thread::id + size=8 align=8 + base size=8 base align=8 +std::thread::id (0x0x7f889d690960) 0 + +Vtable for std::thread::_Impl_base +std::thread::_Impl_base::_ZTVNSt6thread10_Impl_baseE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt6thread10_Impl_baseE) +16 0u +24 0u +32 (int (*)(...))__cxa_pure_virtual + +Class std::thread::_Impl_base + size=24 align=8 + base size=24 base align=8 +std::thread::_Impl_base (0x0x7f889d6909c0) 0 + vptr=((& std::thread::_Impl_base::_ZTVNSt6thread10_Impl_baseE) + 16u) + +Class std::thread + size=8 align=8 + base size=8 base align=8 +std::thread (0x0x7f889d690900) 0 + +Class std::condition_variable + size=48 align=8 + base size=48 base align=8 +std::condition_variable (0x0x7f889d518600) 0 + +Class std::__at_thread_exit_elt + size=16 align=8 + base size=16 base align=8 +std::__at_thread_exit_elt (0x0x7f889d5186c0) 0 + +Class std::_V2::condition_variable_any + size=64 align=8 + base size=64 base align=8 +std::_V2::condition_variable_any (0x0x7f889d518720) 0 + +Class std::__atomic_futex_unsigned_base + size=1 align=1 + base size=0 base align=1 +std::__atomic_futex_unsigned_base (0x0x7f889d184d80) 0 empty + +Vtable for std::future_error +std::future_error::_ZTVSt12future_error: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt12future_error) +16 (int (*)(...))std::future_error::~future_error +24 (int (*)(...))std::future_error::~future_error +32 (int (*)(...))std::future_error::what + +Class std::future_error + size=32 align=8 + base size=32 base align=8 +std::future_error (0x0x7f889d1d65b0) 0 + vptr=((& std::future_error::_ZTVSt12future_error) + 16u) + std::logic_error (0x0x7f889d1d6618) 0 + primary-for std::future_error (0x0x7f889d1d65b0) + std::exception (0x0x7f889d184ea0) 0 nearly-empty + primary-for std::logic_error (0x0x7f889d1d6618) + +Class std::__future_base::_Result_base::_Deleter + size=1 align=1 + base size=0 base align=1 +std::__future_base::_Result_base::_Deleter (0x0x7f889d239000) 0 empty + +Vtable for std::__future_base::_Result_base +std::__future_base::_Result_base::_ZTVNSt13__future_base12_Result_baseE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt13__future_base12_Result_baseE) +16 (int (*)(...))__cxa_pure_virtual +24 0u +32 0u + +Class std::__future_base::_Result_base + size=16 align=8 + base size=16 base align=8 +std::__future_base::_Result_base (0x0x7f889d184f60) 0 + vptr=((& std::__future_base::_Result_base::_ZTVNSt13__future_base12_Result_baseE) + 16u) + +Class std::__future_base::_State_baseV2::__exception_ptr_tag + size=1 align=1 + base size=0 base align=1 +std::__future_base::_State_baseV2::__exception_ptr_tag (0x0x7f889cf52540) 0 empty + +Class std::__future_base::_State_baseV2::_Make_ready + size=32 align=8 + base size=32 base align=8 +std::__future_base::_State_baseV2::_Make_ready (0x0x7f889d321bc8) 0 + std::__at_thread_exit_elt (0x0x7f889cf52600) 0 + +Vtable for std::__future_base::_State_baseV2 +std::__future_base::_State_baseV2::_ZTVNSt13__future_base13_State_baseV2E: 6u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt13__future_base13_State_baseV2E) +16 (int (*)(...))std::__future_base::_State_baseV2::~_State_baseV2 +24 (int (*)(...))std::__future_base::_State_baseV2::~_State_baseV2 +32 (int (*)(...))std::__future_base::_State_baseV2::_M_complete_async +40 (int (*)(...))std::__future_base::_State_baseV2::_M_is_deferred_future + +Class std::__future_base::_State_baseV2 + size=32 align=8 + base size=28 base align=8 +std::__future_base::_State_baseV2 (0x0x7f889d239180) 0 + vptr=((& std::__future_base::_State_baseV2::_ZTVNSt13__future_base13_State_baseV2E) + 16u) + +Class std::__future_base + size=1 align=1 + base size=0 base align=1 +std::__future_base (0x0x7f889d184f00) 0 empty + +Vtable for std::__future_base::_Async_state_commonV2 +std::__future_base::_Async_state_commonV2::_ZTVNSt13__future_base21_Async_state_commonV2E: 6u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt13__future_base21_Async_state_commonV2E) +16 (int (*)(...))std::__future_base::_Async_state_commonV2::~_Async_state_commonV2 +24 (int (*)(...))std::__future_base::_Async_state_commonV2::~_Async_state_commonV2 +32 (int (*)(...))std::__future_base::_Async_state_commonV2::_M_complete_async +40 (int (*)(...))std::__future_base::_State_baseV2::_M_is_deferred_future + +Class std::__future_base::_Async_state_commonV2 + size=48 align=8 + base size=44 base align=8 +std::__future_base::_Async_state_commonV2 (0x0x7f889ccac7b8) 0 + vptr=((& std::__future_base::_Async_state_commonV2::_ZTVNSt13__future_base21_Async_state_commonV2E) + 16u) + std::__future_base::_State_baseV2 (0x0x7f889ccb14e0) 0 + primary-for std::__future_base::_Async_state_commonV2 (0x0x7f889ccac7b8) + +Class QThread::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThread::QPrivateSignal (0x0x7f889ccb1c00) 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 (0x0x7f889cd0c270) 0 + vptr=((& QThread::_ZTV7QThread) + 16u) + QObject (0x0x7f889ccb1ba0) 0 + primary-for QThread (0x0x7f889cd0c270) + +Class QThreadPool::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThreadPool::QPrivateSignal (0x0x7f889ccb1d20) 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 (0x0x7f889cd0c2d8) 0 + vptr=((& QThreadPool::_ZTV11QThreadPool) + 16u) + QObject (0x0x7f889ccb1cc0) 0 + primary-for QThreadPool (0x0x7f889cd0c2d8) + +Class QThreadStorageData + size=4 align=4 + base size=4 base align=4 +QThreadStorageData (0x0x7f889ccb1d80) 0 + +Class QTimeLine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimeLine::QPrivateSignal (0x0x7f889ccb1ea0) 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 (0x0x7f889cd0c340) 0 + vptr=((& QTimeLine::_ZTV9QTimeLine) + 16u) + QObject (0x0x7f889ccb1e40) 0 + primary-for QTimeLine (0x0x7f889cd0c340) + +Class QTimer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimer::QPrivateSignal (0x0x7f889ccb1f60) 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 (0x0x7f889cd0c3a8) 0 + vptr=((& QTimer::_ZTV6QTimer) + 16u) + QObject (0x0x7f889ccb1f00) 0 + primary-for QTimer (0x0x7f889cd0c3a8) + +Class QTimeZone::OffsetData + size=32 align=8 + base size=28 base align=8 +QTimeZone::OffsetData (0x0x7f889c9a36c0) 0 + +Class QTimeZone + size=8 align=8 + base size=8 base align=8 +QTimeZone (0x0x7f889c9a3660) 0 + +Class QTranslator::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTranslator::QPrivateSignal (0x0x7f889c9a3c60) 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 (0x0x7f889cd0cf70) 0 + vptr=((& QTranslator::_ZTV11QTranslator) + 16u) + QObject (0x0x7f889c9a3c00) 0 + primary-for QTranslator (0x0x7f889cd0cf70) + +Class QUrlQuery + size=8 align=8 + base size=8 base align=8 +QUrlQuery (0x0x7f889c9a3cc0) 0 + +Class QWaitCondition + size=8 align=8 + base size=8 base align=8 +QWaitCondition (0x0x7f889ca35360) 0 + +Class QXmlStreamStringRef + size=16 align=8 + base size=16 base align=8 +QXmlStreamStringRef (0x0x7f889ca353c0) 0 + +Class QXmlStreamAttribute + size=80 align=8 + base size=73 base align=8 +QXmlStreamAttribute (0x0x7f889ca35660) 0 + +Class QXmlStreamAttributes + size=8 align=8 + base size=8 base align=8 +QXmlStreamAttributes (0x0x7f889ca33c30) 0 + QVector (0x0x7f889ca35a20) 0 + +Class QXmlStreamNamespaceDeclaration + size=40 align=8 + base size=40 base align=8 +QXmlStreamNamespaceDeclaration (0x0x7f889ca35a80) 0 + +Class QXmlStreamNotationDeclaration + size=56 align=8 + base size=56 base align=8 +QXmlStreamNotationDeclaration (0x0x7f889ca35d20) 0 + +Class QXmlStreamEntityDeclaration + size=88 align=8 + base size=88 base align=8 +QXmlStreamEntityDeclaration (0x0x7f889cb24000) 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 (0x0x7f889cb242a0) 0 nearly-empty + vptr=((& QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver) + 16u) + +Class QXmlStreamReader + size=8 align=8 + base size=8 base align=8 +QXmlStreamReader (0x0x7f889cb24300) 0 + +Class QXmlStreamWriter + size=8 align=8 + base size=8 base align=8 +QXmlStreamWriter (0x0x7f889cb24d20) 0 + +Class QBluetoothAddress + size=8 align=8 + base size=8 base align=8 +QBluetoothAddress (0x0x7f889c7fe180) 0 + +Class QBluetoothDeviceInfo + size=8 align=8 + base size=8 base align=8 +QBluetoothDeviceInfo (0x0x7f889c7fe300) 0 + +Class QBluetoothDeviceDiscoveryAgent::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothDeviceDiscoveryAgent::QPrivateSignal (0x0x7f889c7fe7e0) 0 empty + +Vtable for QBluetoothDeviceDiscoveryAgent +QBluetoothDeviceDiscoveryAgent::_ZTV30QBluetoothDeviceDiscoveryAgent: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI30QBluetoothDeviceDiscoveryAgent) +16 (int (*)(...))QBluetoothDeviceDiscoveryAgent::metaObject +24 (int (*)(...))QBluetoothDeviceDiscoveryAgent::qt_metacast +32 (int (*)(...))QBluetoothDeviceDiscoveryAgent::qt_metacall +40 (int (*)(...))QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent +48 (int (*)(...))QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent +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 QBluetoothDeviceDiscoveryAgent + size=24 align=8 + base size=24 base align=8 +QBluetoothDeviceDiscoveryAgent (0x0x7f889c887068) 0 + vptr=((& QBluetoothDeviceDiscoveryAgent::_ZTV30QBluetoothDeviceDiscoveryAgent) + 16u) + QObject (0x0x7f889c7fe780) 0 + primary-for QBluetoothDeviceDiscoveryAgent (0x0x7f889c887068) + +Class QBluetoothHostInfo + size=8 align=8 + base size=8 base align=8 +QBluetoothHostInfo (0x0x7f889c7fe9c0) 0 + +Class QBluetoothLocalDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothLocalDevice::QPrivateSignal (0x0x7f889c7feba0) 0 empty + +Vtable for QBluetoothLocalDevice +QBluetoothLocalDevice::_ZTV21QBluetoothLocalDevice: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QBluetoothLocalDevice) +16 (int (*)(...))QBluetoothLocalDevice::metaObject +24 (int (*)(...))QBluetoothLocalDevice::qt_metacast +32 (int (*)(...))QBluetoothLocalDevice::qt_metacall +40 (int (*)(...))QBluetoothLocalDevice::~QBluetoothLocalDevice +48 (int (*)(...))QBluetoothLocalDevice::~QBluetoothLocalDevice +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 QBluetoothLocalDevice + size=24 align=8 + base size=24 base align=8 +QBluetoothLocalDevice (0x0x7f889c8871a0) 0 + vptr=((& QBluetoothLocalDevice::_ZTV21QBluetoothLocalDevice) + 16u) + QObject (0x0x7f889c7feb40) 0 + primary-for QBluetoothLocalDevice (0x0x7f889c8871a0) + +Class quint128 + size=16 align=1 + base size=16 base align=1 +quint128 (0x0x7f889c7fef60) 0 + +Class QBluetoothUuid + size=16 align=4 + base size=16 base align=4 +QBluetoothUuid (0x0x7f889c887208) 0 + QUuid (0x0x7f889c541000) 0 + +Class QBluetoothServiceInfo::Sequence + size=8 align=8 + base size=8 base align=8 +QBluetoothServiceInfo::Sequence (0x0x7f889c8872d8) 0 + QList (0x0x7f889c887340) 0 + QListSpecialMethods (0x0x7f889c541300) 0 empty + +Class QBluetoothServiceInfo::Alternative + size=8 align=8 + base size=8 base align=8 +QBluetoothServiceInfo::Alternative (0x0x7f889c8873a8) 0 + QList (0x0x7f889c887410) 0 + QListSpecialMethods (0x0x7f889c541360) 0 empty + +Class QBluetoothServiceInfo + size=16 align=8 + base size=16 base align=8 +QBluetoothServiceInfo (0x0x7f889c5412a0) 0 + +Class QAbstractSocket::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractSocket::QPrivateSignal (0x0x7f889c5417e0) 0 empty + +Vtable for QAbstractSocket +QAbstractSocket::_ZTV15QAbstractSocket: 41u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QAbstractSocket) +16 (int (*)(...))QAbstractSocket::metaObject +24 (int (*)(...))QAbstractSocket::qt_metacast +32 (int (*)(...))QAbstractSocket::qt_metacall +40 (int (*)(...))QAbstractSocket::~QAbstractSocket +48 (int (*)(...))QAbstractSocket::~QAbstractSocket +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 (*)(...))QAbstractSocket::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QAbstractSocket::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QAbstractSocket::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QAbstractSocket::bytesAvailable +184 (int (*)(...))QAbstractSocket::bytesToWrite +192 (int (*)(...))QAbstractSocket::canReadLine +200 (int (*)(...))QAbstractSocket::waitForReadyRead +208 (int (*)(...))QAbstractSocket::waitForBytesWritten +216 (int (*)(...))QAbstractSocket::readData +224 (int (*)(...))QAbstractSocket::readLineData +232 (int (*)(...))QAbstractSocket::writeData +240 (int (*)(...))QAbstractSocket::resume +248 (int (*)(...))QAbstractSocket::connectToHost +256 (int (*)(...))QAbstractSocket::connectToHost +264 (int (*)(...))QAbstractSocket::disconnectFromHost +272 (int (*)(...))QAbstractSocket::setReadBufferSize +280 (int (*)(...))QAbstractSocket::socketDescriptor +288 (int (*)(...))QAbstractSocket::setSocketDescriptor +296 (int (*)(...))QAbstractSocket::setSocketOption +304 (int (*)(...))QAbstractSocket::socketOption +312 (int (*)(...))QAbstractSocket::waitForConnected +320 (int (*)(...))QAbstractSocket::waitForDisconnected + +Class QAbstractSocket + size=16 align=8 + base size=16 base align=8 +QAbstractSocket (0x0x7f889c887680) 0 + vptr=((& QAbstractSocket::_ZTV15QAbstractSocket) + 16u) + QIODevice (0x0x7f889c8876e8) 0 + primary-for QAbstractSocket (0x0x7f889c887680) + QObject (0x0x7f889c541780) 0 + primary-for QIODevice (0x0x7f889c8876e8) + +Class QBluetoothSocket::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothSocket::QPrivateSignal (0x0x7f889c541de0) 0 empty + +Vtable for QBluetoothSocket +QBluetoothSocket::_ZTV16QBluetoothSocket: 30u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QBluetoothSocket) +16 (int (*)(...))QBluetoothSocket::metaObject +24 (int (*)(...))QBluetoothSocket::qt_metacast +32 (int (*)(...))QBluetoothSocket::qt_metacall +40 (int (*)(...))QBluetoothSocket::~QBluetoothSocket +48 (int (*)(...))QBluetoothSocket::~QBluetoothSocket +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 (*)(...))QBluetoothSocket::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QBluetoothSocket::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QIODevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QBluetoothSocket::bytesAvailable +184 (int (*)(...))QBluetoothSocket::bytesToWrite +192 (int (*)(...))QBluetoothSocket::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QBluetoothSocket::readData +224 (int (*)(...))QIODevice::readLineData +232 (int (*)(...))QBluetoothSocket::writeData + +Class QBluetoothSocket + size=24 align=8 + base size=24 base align=8 +QBluetoothSocket (0x0x7f889c8878f0) 0 + vptr=((& QBluetoothSocket::_ZTV16QBluetoothSocket) + 16u) + QIODevice (0x0x7f889c887958) 0 + primary-for QBluetoothSocket (0x0x7f889c8878f0) + QObject (0x0x7f889c541d80) 0 + primary-for QIODevice (0x0x7f889c887958) + +Class QBluetoothServer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothServer::QPrivateSignal (0x0x7f889c541ea0) 0 empty + +Vtable for QBluetoothServer +QBluetoothServer::_ZTV16QBluetoothServer: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QBluetoothServer) +16 (int (*)(...))QBluetoothServer::metaObject +24 (int (*)(...))QBluetoothServer::qt_metacast +32 (int (*)(...))QBluetoothServer::qt_metacall +40 (int (*)(...))QBluetoothServer::~QBluetoothServer +48 (int (*)(...))QBluetoothServer::~QBluetoothServer +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 QBluetoothServer + size=24 align=8 + base size=24 base align=8 +QBluetoothServer (0x0x7f889c8879c0) 0 + vptr=((& QBluetoothServer::_ZTV16QBluetoothServer) + 16u) + QObject (0x0x7f889c541e40) 0 + primary-for QBluetoothServer (0x0x7f889c8879c0) + +Class QBluetoothServiceDiscoveryAgent::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothServiceDiscoveryAgent::QPrivateSignal (0x0x7f889c541f60) 0 empty + +Vtable for QBluetoothServiceDiscoveryAgent +QBluetoothServiceDiscoveryAgent::_ZTV31QBluetoothServiceDiscoveryAgent: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI31QBluetoothServiceDiscoveryAgent) +16 (int (*)(...))QBluetoothServiceDiscoveryAgent::metaObject +24 (int (*)(...))QBluetoothServiceDiscoveryAgent::qt_metacast +32 (int (*)(...))QBluetoothServiceDiscoveryAgent::qt_metacall +40 (int (*)(...))QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent +48 (int (*)(...))QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent +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 QBluetoothServiceDiscoveryAgent + size=24 align=8 + base size=24 base align=8 +QBluetoothServiceDiscoveryAgent (0x0x7f889c887a28) 0 + vptr=((& QBluetoothServiceDiscoveryAgent::_ZTV31QBluetoothServiceDiscoveryAgent) + 16u) + QObject (0x0x7f889c541f00) 0 + primary-for QBluetoothServiceDiscoveryAgent (0x0x7f889c887a28) + +Class QBluetoothTransferManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothTransferManager::QPrivateSignal (0x0x7f889c6df060) 0 empty + +Vtable for QBluetoothTransferManager +QBluetoothTransferManager::_ZTV25QBluetoothTransferManager: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI25QBluetoothTransferManager) +16 (int (*)(...))QBluetoothTransferManager::metaObject +24 (int (*)(...))QBluetoothTransferManager::qt_metacast +32 (int (*)(...))QBluetoothTransferManager::qt_metacall +40 (int (*)(...))QBluetoothTransferManager::~QBluetoothTransferManager +48 (int (*)(...))QBluetoothTransferManager::~QBluetoothTransferManager +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 QBluetoothTransferManager + size=16 align=8 + base size=16 base align=8 +QBluetoothTransferManager (0x0x7f889c887a90) 0 + vptr=((& QBluetoothTransferManager::_ZTV25QBluetoothTransferManager) + 16u) + QObject (0x0x7f889c6df000) 0 + primary-for QBluetoothTransferManager (0x0x7f889c887a90) + +Class QBluetoothTransferRequest + size=8 align=8 + base size=8 base align=8 +QBluetoothTransferRequest (0x0x7f889c6df0c0) 0 + +Class QBluetoothTransferReply::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothTransferReply::QPrivateSignal (0x0x7f889c6df180) 0 empty + +Vtable for QBluetoothTransferReply +QBluetoothTransferReply::_ZTV23QBluetoothTransferReply: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI23QBluetoothTransferReply) +16 (int (*)(...))QBluetoothTransferReply::metaObject +24 (int (*)(...))QBluetoothTransferReply::qt_metacast +32 (int (*)(...))QBluetoothTransferReply::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 + +Class QBluetoothTransferReply + size=24 align=8 + base size=24 base align=8 +QBluetoothTransferReply (0x0x7f889c887af8) 0 + vptr=((& QBluetoothTransferReply::_ZTV23QBluetoothTransferReply) + 16u) + QObject (0x0x7f889c6df120) 0 + primary-for QBluetoothTransferReply (0x0x7f889c887af8) + +Class QLowEnergyAdvertisingData + size=8 align=8 + base size=8 base align=8 +QLowEnergyAdvertisingData (0x0x7f889c6df300) 0 + +Class QLowEnergyDescriptor + size=24 align=8 + base size=24 base align=8 +QLowEnergyDescriptor (0x0x7f889c6df960) 0 + +Class QLowEnergyCharacteristic + size=24 align=8 + base size=24 base align=8 +QLowEnergyCharacteristic (0x0x7f889c6dfb40) 0 + +Class QLowEnergyService::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLowEnergyService::QPrivateSignal (0x0x7f889c6dfea0) 0 empty + +Vtable for QLowEnergyService +QLowEnergyService::_ZTV17QLowEnergyService: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QLowEnergyService) +16 (int (*)(...))QLowEnergyService::metaObject +24 (int (*)(...))QLowEnergyService::qt_metacast +32 (int (*)(...))QLowEnergyService::qt_metacall +40 (int (*)(...))QLowEnergyService::~QLowEnergyService +48 (int (*)(...))QLowEnergyService::~QLowEnergyService +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 QLowEnergyService + size=32 align=8 + base size=32 base align=8 +QLowEnergyService (0x0x7f889c72c270) 0 + vptr=((& QLowEnergyService::_ZTV17QLowEnergyService) + 16u) + QObject (0x0x7f889c6dfe40) 0 + primary-for QLowEnergyService (0x0x7f889c72c270) + +Class QLowEnergyController::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLowEnergyController::QPrivateSignal (0x0x7f889c3c95a0) 0 empty + +Vtable for QLowEnergyController +QLowEnergyController::_ZTV20QLowEnergyController: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI20QLowEnergyController) +16 (int (*)(...))QLowEnergyController::metaObject +24 (int (*)(...))QLowEnergyController::qt_metacast +32 (int (*)(...))QLowEnergyController::qt_metacall +40 (int (*)(...))QLowEnergyController::~QLowEnergyController +48 (int (*)(...))QLowEnergyController::~QLowEnergyController +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 QLowEnergyController + size=24 align=8 + base size=24 base align=8 +QLowEnergyController (0x0x7f889c72c3a8) 0 + vptr=((& QLowEnergyController::_ZTV20QLowEnergyController) + 16u) + QObject (0x0x7f889c3c9540) 0 + primary-for QLowEnergyController (0x0x7f889c72c3a8) + +Class QLowEnergyAdvertisingParameters::AddressInfo + size=16 align=8 + base size=12 base align=8 +QLowEnergyAdvertisingParameters::AddressInfo (0x0x7f889c3c9ae0) 0 + +Class QLowEnergyAdvertisingParameters + size=8 align=8 + base size=8 base align=8 +QLowEnergyAdvertisingParameters (0x0x7f889c3c9a80) 0 + +Class QLowEnergyCharacteristicData + size=8 align=8 + base size=8 base align=8 +QLowEnergyCharacteristicData (0x0x7f889c481a80) 0 + +Class QLowEnergyConnectionParameters + size=8 align=8 + base size=8 base align=8 +QLowEnergyConnectionParameters (0x0x7f889c4c9120) 0 + +Class QLowEnergyDescriptorData + size=8 align=8 + base size=8 base align=8 +QLowEnergyDescriptorData (0x0x7f889c4c98a0) 0 + +Class QLowEnergyServiceData + size=8 align=8 + base size=8 base align=8 +QLowEnergyServiceData (0x0x7f889c4c9f00) 0 + diff --git a/tests/auto/bic/data/QtBluetooth.5.13.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtBluetooth.5.13.0.linux-gcc-amd64.txt new file mode 100644 index 0000000..ef61ed6 --- /dev/null +++ b/tests/auto/bic/data/QtBluetooth.5.13.0.linux-gcc-amd64.txt @@ -0,0 +1,5423 @@ +Class std::__failure_type + size=1 align=1 + base size=0 base align=1 +std::__failure_type (0x0x7f5ec289f600) 0 empty + +Class std::__do_is_destructible_impl + size=1 align=1 + base size=0 base align=1 +std::__do_is_destructible_impl (0x0x7f5ec28f7d80) 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 (0x0x7f5ec2922000) 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 (0x0x7f5ec2922240) 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 (0x0x7f5ec2922480) 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 (0x0x7f5ec2922600) 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 (0x0x7f5ec29229c0) 0 empty + +Class std::__do_is_implicitly_default_constructible_impl + size=1 align=1 + base size=0 base align=1 +std::__do_is_implicitly_default_constructible_impl (0x0x7f5ec2960ae0) 0 empty + +Class std::__do_common_type_impl + size=1 align=1 + base size=0 base align=1 +std::__do_common_type_impl (0x0x7f5ec29e41e0) 0 empty + +Class std::__do_member_type_wrapper + size=1 align=1 + base size=0 base align=1 +std::__do_member_type_wrapper (0x0x7f5ec29e42a0) 0 empty + +Class std::__invoke_memfun_ref + size=1 align=1 + base size=0 base align=1 +std::__invoke_memfun_ref (0x0x7f5ec29e4660) 0 empty + +Class std::__invoke_memfun_deref + size=1 align=1 + base size=0 base align=1 +std::__invoke_memfun_deref (0x0x7f5ec29e46c0) 0 empty + +Class std::__invoke_memobj_ref + size=1 align=1 + base size=0 base align=1 +std::__invoke_memobj_ref (0x0x7f5ec29e4720) 0 empty + +Class std::__invoke_memobj_deref + size=1 align=1 + base size=0 base align=1 +std::__invoke_memobj_deref (0x0x7f5ec29e4780) 0 empty + +Class std::__invoke_other + size=1 align=1 + base size=0 base align=1 +std::__invoke_other (0x0x7f5ec29e47e0) 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 (0x0x7f5ec29e48a0) 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 (0x0x7f5ec29e4960) 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 (0x0x7f5ec29e4a20) 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 (0x0x7f5ec29e4ae0) 0 empty + +Class std::__result_of_other_impl + size=1 align=1 + base size=0 base align=1 +std::__result_of_other_impl (0x0x7f5ec29e4e40) 0 empty + +Class std::__swappable_details::__do_is_swappable_impl + size=1 align=1 + base size=0 base align=1 +std::__swappable_details::__do_is_swappable_impl (0x0x7f5ec26211e0) 0 empty + +Class std::__swappable_details::__do_is_nothrow_swappable_impl + size=1 align=1 + base size=0 base align=1 +std::__swappable_details::__do_is_nothrow_swappable_impl (0x0x7f5ec2621240) 0 empty + +Class std::__nonesuch + size=1 align=1 + base size=0 base align=1 +std::__nonesuch (0x0x7f5ec26217e0) 0 empty + +Class std::piecewise_construct_t + size=1 align=1 + base size=0 base align=1 +std::piecewise_construct_t (0x0x7f5ec2621e40) 0 empty + +Class std::__nonesuch_no_braces + size=1 align=1 + base size=1 base align=1 +std::__nonesuch_no_braces (0x0x7f5ec261c680) 0 empty + std::__nonesuch (0x0x7f5ec2667360) 0 empty + +Class std::__true_type + size=1 align=1 + base size=0 base align=1 +std::__true_type (0x0x7f5ec26b4cc0) 0 empty + +Class std::__false_type + size=1 align=1 + base size=0 base align=1 +std::__false_type (0x0x7f5ec26b4d20) 0 empty + +Class std::input_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::input_iterator_tag (0x0x7f5ec2712a20) 0 empty + +Class std::output_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::output_iterator_tag (0x0x7f5ec2712a80) 0 empty + +Class std::forward_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::forward_iterator_tag (0x0x7f5ec261cb60) 0 empty + std::input_iterator_tag (0x0x7f5ec2712ae0) 0 empty + +Class std::bidirectional_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::bidirectional_iterator_tag (0x0x7f5ec261cbc8) 0 empty + std::forward_iterator_tag (0x0x7f5ec261cc30) 0 empty + std::input_iterator_tag (0x0x7f5ec2712b40) 0 empty + +Class std::random_access_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::random_access_iterator_tag (0x0x7f5ec261cc98) 0 empty + std::bidirectional_iterator_tag (0x0x7f5ec261cd00) 0 empty + std::forward_iterator_tag (0x0x7f5ec261cd68) 0 empty + std::input_iterator_tag (0x0x7f5ec2712ba0) 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 (0x0x7f5ec27c56c0) 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 (0x0x7f5ec27c57e0) 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 (0x0x7f5ec27c5ae0) 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 (0x0x7f5ec27c5de0) 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 (0x0x7f5ec27c5f00) 0 empty + +Class __locale_struct + size=232 align=8 + base size=232 base align=8 +__locale_struct (0x0x7f5ec247f240) 0 + +Class timeval + size=16 align=8 + base size=16 base align=8 +timeval (0x0x7f5ec247f540) 0 + +Class timespec + size=16 align=8 + base size=16 base align=8 +timespec (0x0x7f5ec247f5a0) 0 + +Class __pthread_rwlock_arch_t + size=56 align=8 + base size=56 base align=8 +__pthread_rwlock_arch_t (0x0x7f5ec247f660) 0 + +Class __pthread_internal_list + size=16 align=8 + base size=16 base align=8 +__pthread_internal_list (0x0x7f5ec247f6c0) 0 + +Class __pthread_mutex_s + size=40 align=8 + base size=40 base align=8 +__pthread_mutex_s (0x0x7f5ec247f720) 0 + +Class __pthread_cond_s + size=48 align=8 + base size=48 base align=8 +__pthread_cond_s (0x0x7f5ec247f780) 0 + +Class pthread_attr_t + size=56 align=8 + base size=56 base align=8 +pthread_attr_t (0x0x7f5ec247fa20) 0 + +Class random_data + size=48 align=8 + base size=48 base align=8 +random_data (0x0x7f5ec247fcc0) 0 + +Class drand48_data + size=24 align=8 + base size=24 base align=8 +drand48_data (0x0x7f5ec247fd20) 0 + +Vtable for std::exception +std::exception::_ZTVSt9exception: 5 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 (0x0x7f5ec24e1ae0) 0 nearly-empty + vptr=((& std::exception::_ZTVSt9exception) + 16) + +Vtable for std::bad_exception +std::bad_exception::_ZTVSt13bad_exception: 5 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 (0x0x7f5ec27870d0) 0 nearly-empty + vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16) + std::exception (0x0x7f5ec24e1cc0) 0 nearly-empty + primary-for std::bad_exception (0x0x7f5ec27870d0) + +Vtable for std::type_info +std::type_info::_ZTVSt9type_info: 8 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 (0x0x7f5ec24e1ea0) 0 + vptr=((& std::type_info::_ZTVSt9type_info) + 16) + +Vtable for std::bad_cast +std::bad_cast::_ZTVSt8bad_cast: 5 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 (0x0x7f5ec2787138) 0 nearly-empty + vptr=((& std::bad_cast::_ZTVSt8bad_cast) + 16) + std::exception (0x0x7f5ec257e2a0) 0 nearly-empty + primary-for std::bad_cast (0x0x7f5ec2787138) + +Vtable for std::bad_typeid +std::bad_typeid::_ZTVSt10bad_typeid: 5 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 (0x0x7f5ec27871a0) 0 nearly-empty + vptr=((& std::bad_typeid::_ZTVSt10bad_typeid) + 16) + std::exception (0x0x7f5ec257e480) 0 nearly-empty + primary-for std::bad_typeid (0x0x7f5ec27871a0) + +Class std::__exception_ptr::exception_ptr + size=8 align=8 + base size=8 base align=8 +std::__exception_ptr::exception_ptr (0x0x7f5ec257e660) 0 + +Vtable for std::nested_exception +std::nested_exception::_ZTVSt16nested_exception: 4 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 (0x0x7f5ec257ec00) 0 + vptr=((& std::nested_exception::_ZTVSt16nested_exception) + 16) + +Vtable for std::bad_alloc +std::bad_alloc::_ZTVSt9bad_alloc: 5 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 (0x0x7f5ec2787208) 0 nearly-empty + vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16) + std::exception (0x0x7f5ec25b1300) 0 nearly-empty + primary-for std::bad_alloc (0x0x7f5ec2787208) + +Vtable for std::bad_array_new_length +std::bad_array_new_length::_ZTVSt20bad_array_new_length: 5 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 (0x0x7f5ec2787270) 0 nearly-empty + vptr=((& std::bad_array_new_length::_ZTVSt20bad_array_new_length) + 16) + std::bad_alloc (0x0x7f5ec27872d8) 0 nearly-empty + primary-for std::bad_array_new_length (0x0x7f5ec2787270) + std::exception (0x0x7f5ec25b14e0) 0 nearly-empty + primary-for std::bad_alloc (0x0x7f5ec27872d8) + +Class std::nothrow_t + size=1 align=1 + base size=0 base align=1 +std::nothrow_t (0x0x7f5ec25b16c0) 0 empty + +Class std::__allocator_traits_base + size=1 align=1 + base size=0 base align=1 +std::__allocator_traits_base (0x0x7f5ec25b18a0) 0 empty + +Class std::__numeric_limits_base + size=1 align=1 + base size=0 base align=1 +std::__numeric_limits_base (0x0x7f5ec222fd80) 0 empty + +Class qIsNull(double)::U + size=8 align=8 + base size=8 base align=8 +qIsNull(double)::U (0x0x7f5ec2408840) 0 + +Class qIsNull(float)::U + size=4 align=4 + base size=4 base align=4 +qIsNull(float)::U (0x0x7f5ec2408900) 0 + +Class QSysInfo + size=1 align=1 + base size=0 base align=1 +QSysInfo (0x0x7f5ec1ec92a0) 0 empty + +Class QMessageLogContext + size=32 align=8 + base size=32 base align=8 +QMessageLogContext (0x0x7f5ec1ec93c0) 0 + +Class QMessageLogger + size=32 align=8 + base size=32 base align=8 +QMessageLogger (0x0x7f5ec1ec9720) 0 + +Class QFlag + size=4 align=4 + base size=4 base align=4 +QFlag (0x0x7f5ec1ec9c60) 0 + +Class QIncompatibleFlag + size=4 align=4 + base size=4 base align=4 +QIncompatibleFlag (0x0x7f5ec1f42420) 0 + +Class std::__atomic_flag_base + size=1 align=1 + base size=1 base align=1 +std::__atomic_flag_base (0x0x7f5ec1fd8840) 0 + +Class std::atomic_flag + size=1 align=1 + base size=1 base align=1 +std::atomic_flag (0x0x7f5ec1f86138) 0 + std::__atomic_flag_base (0x0x7f5ec1fd88a0) 0 + +Class QAtomicInt + size=4 align=4 + base size=4 base align=4 +QAtomicInt (0x0x7f5ec1f86888) 0 + QAtomicInteger (0x0x7f5ec1f868f0) 0 + QBasicAtomicInteger (0x0x7f5ec1b0b840) 0 + +Class QInternal + size=1 align=1 + base size=0 base align=1 +QInternal (0x0x7f5ec1729b40) 0 empty + +Class QtPrivate::QSlotObjectBase + size=16 align=8 + base size=16 base align=8 +QtPrivate::QSlotObjectBase (0x0x7f5ec1796120) 0 + +Class QGenericArgument + size=16 align=8 + base size=16 base align=8 +QGenericArgument (0x0x7f5ec1796840) 0 + +Class QGenericReturnArgument + size=16 align=8 + base size=16 base align=8 +QGenericReturnArgument (0x0x7f5ec177c478) 0 + QGenericArgument (0x0x7f5ec1796ae0) 0 + +Class QMetaObject + size=48 align=8 + base size=48 base align=8 +QMetaObject (0x0x7f5ec1796f00) 0 + +Class QMetaObject::Connection + size=8 align=8 + base size=8 base align=8 +QMetaObject::Connection (0x0x7f5ec17f1360) 0 + +Class QLatin1Char + size=1 align=1 + base size=1 base align=1 +QLatin1Char (0x0x7f5ec145ae40) 0 + +Class QChar + size=2 align=2 + base size=2 base align=2 +QChar (0x0x7f5ec147c120) 0 + +Class QtPrivate::RefCount + size=4 align=4 + base size=4 base align=4 +QtPrivate::RefCount (0x0x7f5ec1528f00) 0 + +Class QArrayData + size=24 align=8 + base size=24 base align=8 +QArrayData (0x0x7f5ec154b2a0) 0 + +Class QtPrivate::QContainerImplHelper + size=1 align=1 + base size=0 base align=1 +QtPrivate::QContainerImplHelper (0x0x7f5ec15ac5a0) 0 empty + +Class lconv + size=96 align=8 + base size=96 base align=8 +lconv (0x0x7f5ec125bde0) 0 + +Vtable for __cxxabiv1::__forced_unwind +__cxxabiv1::__forced_unwind::_ZTVN10__cxxabiv115__forced_unwindE: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN10__cxxabiv115__forced_unwindE) +16 0 +24 0 +32 (int (*)(...))__cxa_pure_virtual + +Class __cxxabiv1::__forced_unwind + size=8 align=8 + base size=8 base align=8 +__cxxabiv1::__forced_unwind (0x0x7f5ec125bea0) 0 nearly-empty + vptr=((& __cxxabiv1::__forced_unwind::_ZTVN10__cxxabiv115__forced_unwindE) + 16) + +Class sched_param + size=4 align=4 + base size=4 base align=4 +sched_param (0x0x7f5ec1353000) 0 + +Class timex + size=208 align=8 + base size=208 base align=8 +timex (0x0x7f5ec13530c0) 0 + +Class tm + size=56 align=8 + base size=56 base align=8 +tm (0x0x7f5ec1353120) 0 + +Class itimerspec + size=32 align=8 + base size=32 base align=8 +itimerspec (0x0x7f5ec1353180) 0 + +Class _pthread_cleanup_buffer + size=32 align=8 + base size=32 base align=8 +_pthread_cleanup_buffer (0x0x7f5ec13531e0) 0 + +Class __pthread_cleanup_frame + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_frame (0x0x7f5ec1353300) 0 + +Class __pthread_cleanup_class + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_class (0x0x7f5ec1353360) 0 + +Class _IO_marker + size=24 align=8 + base size=24 base align=8 +_IO_marker (0x0x7f5ec1097300) 0 + +Class _IO_FILE + size=216 align=8 + base size=216 base align=8 +_IO_FILE (0x0x7f5ec1097360) 0 + +Class std::_Hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Hash_impl (0x0x7f5ec0e493c0) 0 empty + +Class std::_Fnv_hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Fnv_hash_impl (0x0x7f5ec0e49540) 0 empty + +Class std::locale + size=8 align=8 + base size=8 base align=8 +std::locale (0x0x7f5ec0fc36c0) 0 + +Vtable for std::locale::facet +std::locale::facet::_ZTVNSt6locale5facetE: 4 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 (0x0x7f5ec0fc3a80) 0 + vptr=((& std::locale::facet::_ZTVNSt6locale5facetE) + 16) + +Class std::locale::id + size=8 align=8 + base size=8 base align=8 +std::locale::id (0x0x7f5ec0fc3d20) 0 + +Class std::locale::_Impl + size=40 align=8 + base size=40 base align=8 +std::locale::_Impl (0x0x7f5ec0fc3f00) 0 + +Class std::__cow_string + size=8 align=8 + base size=8 base align=8 +std::__cow_string (0x0x7f5ec0c1ff00) 0 + +Vtable for std::logic_error +std::logic_error::_ZTVSt11logic_error: 5 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 (0x0x7f5ec0c29410) 0 + vptr=((& std::logic_error::_ZTVSt11logic_error) + 16) + std::exception (0x0x7f5ec0c67000) 0 nearly-empty + primary-for std::logic_error (0x0x7f5ec0c29410) + +Vtable for std::domain_error +std::domain_error::_ZTVSt12domain_error: 5 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 (0x0x7f5ec0c29478) 0 + vptr=((& std::domain_error::_ZTVSt12domain_error) + 16) + std::logic_error (0x0x7f5ec0c294e0) 0 + primary-for std::domain_error (0x0x7f5ec0c29478) + std::exception (0x0x7f5ec0c67060) 0 nearly-empty + primary-for std::logic_error (0x0x7f5ec0c294e0) + +Vtable for std::invalid_argument +std::invalid_argument::_ZTVSt16invalid_argument: 5 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 (0x0x7f5ec0c29548) 0 + vptr=((& std::invalid_argument::_ZTVSt16invalid_argument) + 16) + std::logic_error (0x0x7f5ec0c295b0) 0 + primary-for std::invalid_argument (0x0x7f5ec0c29548) + std::exception (0x0x7f5ec0c670c0) 0 nearly-empty + primary-for std::logic_error (0x0x7f5ec0c295b0) + +Vtable for std::length_error +std::length_error::_ZTVSt12length_error: 5 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 (0x0x7f5ec0c29618) 0 + vptr=((& std::length_error::_ZTVSt12length_error) + 16) + std::logic_error (0x0x7f5ec0c29680) 0 + primary-for std::length_error (0x0x7f5ec0c29618) + std::exception (0x0x7f5ec0c67120) 0 nearly-empty + primary-for std::logic_error (0x0x7f5ec0c29680) + +Vtable for std::out_of_range +std::out_of_range::_ZTVSt12out_of_range: 5 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 (0x0x7f5ec0c296e8) 0 + vptr=((& std::out_of_range::_ZTVSt12out_of_range) + 16) + std::logic_error (0x0x7f5ec0c29750) 0 + primary-for std::out_of_range (0x0x7f5ec0c296e8) + std::exception (0x0x7f5ec0c67180) 0 nearly-empty + primary-for std::logic_error (0x0x7f5ec0c29750) + +Vtable for std::runtime_error +std::runtime_error::_ZTVSt13runtime_error: 5 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 (0x0x7f5ec0c297b8) 0 + vptr=((& std::runtime_error::_ZTVSt13runtime_error) + 16) + std::exception (0x0x7f5ec0c671e0) 0 nearly-empty + primary-for std::runtime_error (0x0x7f5ec0c297b8) + +Vtable for std::range_error +std::range_error::_ZTVSt11range_error: 5 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 (0x0x7f5ec0c29820) 0 + vptr=((& std::range_error::_ZTVSt11range_error) + 16) + std::runtime_error (0x0x7f5ec0c29888) 0 + primary-for std::range_error (0x0x7f5ec0c29820) + std::exception (0x0x7f5ec0c67240) 0 nearly-empty + primary-for std::runtime_error (0x0x7f5ec0c29888) + +Vtable for std::overflow_error +std::overflow_error::_ZTVSt14overflow_error: 5 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 (0x0x7f5ec0c298f0) 0 + vptr=((& std::overflow_error::_ZTVSt14overflow_error) + 16) + std::runtime_error (0x0x7f5ec0c29958) 0 + primary-for std::overflow_error (0x0x7f5ec0c298f0) + std::exception (0x0x7f5ec0c672a0) 0 nearly-empty + primary-for std::runtime_error (0x0x7f5ec0c29958) + +Vtable for std::underflow_error +std::underflow_error::_ZTVSt15underflow_error: 5 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 (0x0x7f5ec0c299c0) 0 + vptr=((& std::underflow_error::_ZTVSt15underflow_error) + 16) + std::runtime_error (0x0x7f5ec0c29a28) 0 + primary-for std::underflow_error (0x0x7f5ec0c299c0) + std::exception (0x0x7f5ec0c67300) 0 nearly-empty + primary-for std::runtime_error (0x0x7f5ec0c29a28) + +Vtable for std::_V2::error_category +std::_V2::error_category::_ZTVNSt3_V214error_categoryE: 10 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt3_V214error_categoryE) +16 0 +24 0 +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 (0x0x7f5ec0c67480) 0 nearly-empty + vptr=((& std::_V2::error_category::_ZTVNSt3_V214error_categoryE) + 16) + +Class std::error_code + size=16 align=8 + base size=16 base align=8 +std::error_code (0x0x7f5ec0c677e0) 0 + +Class std::error_condition + size=16 align=8 + base size=16 base align=8 +std::error_condition (0x0x7f5ec0cb6060) 0 + +Vtable for std::system_error +std::system_error::_ZTVSt12system_error: 5 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 (0x0x7f5ec0c29e38) 0 + vptr=((& std::system_error::_ZTVSt12system_error) + 16) + std::runtime_error (0x0x7f5ec0c29ea0) 0 + primary-for std::system_error (0x0x7f5ec0c29e38) + std::exception (0x0x7f5ec0cb6c00) 0 nearly-empty + primary-for std::runtime_error (0x0x7f5ec0c29ea0) + +Vtable for std::ios_base::failure +std::ios_base::failure::_ZTVNSt8ios_base7failureB5cxx11E: 5 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 (0x0x7f5ec0cf9138) 0 + vptr=((& std::ios_base::failure::_ZTVNSt8ios_base7failureB5cxx11E) + 16) + std::system_error (0x0x7f5ec0cf91a0) 0 + primary-for std::ios_base::failure (0x0x7f5ec0cf9138) + std::runtime_error (0x0x7f5ec0cf9208) 0 + primary-for std::system_error (0x0x7f5ec0cf91a0) + std::exception (0x0x7f5ec0d121e0) 0 nearly-empty + primary-for std::runtime_error (0x0x7f5ec0cf9208) + +Class std::ios_base::_Callback_list + size=24 align=8 + base size=24 base align=8 +std::ios_base::_Callback_list (0x0x7f5ec0d12240) 0 + +Class std::ios_base::_Words + size=16 align=8 + base size=16 base align=8 +std::ios_base::_Words (0x0x7f5ec0d122a0) 0 + +Class std::ios_base::Init + size=1 align=1 + base size=0 base align=1 +std::ios_base::Init (0x0x7f5ec0d12300) 0 empty + +Vtable for std::ios_base +std::ios_base::_ZTVSt8ios_base: 4 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 (0x0x7f5ec0d12180) 0 + vptr=((& std::ios_base::_ZTVSt8ios_base) + 16) + +Class std::ctype_base + size=1 align=1 + base size=0 base align=1 +std::ctype_base (0x0x7f5ec0ddfc00) 0 empty + +Class std::__num_base + size=1 align=1 + base size=0 base align=1 +std::__num_base (0x0x7f5ec0a88de0) 0 empty + +VTT for std::basic_ostream +std::basic_ostream::_ZTTSo: 2 entries +0 ((& std::basic_ostream::_ZTVSo) + 24) +8 ((& std::basic_ostream::_ZTVSo) + 64) + +VTT for std::basic_ostream +std::basic_ostream::_ZTTSt13basic_ostreamIwSt11char_traitsIwEE: 2 entries +0 ((& std::basic_ostream::_ZTVSt13basic_ostreamIwSt11char_traitsIwEE) + 24) +8 ((& std::basic_ostream::_ZTVSt13basic_ostreamIwSt11char_traitsIwEE) + 64) + +VTT for std::basic_istream +std::basic_istream::_ZTTSi: 2 entries +0 ((& std::basic_istream::_ZTVSi) + 24) +8 ((& std::basic_istream::_ZTVSi) + 64) + +VTT for std::basic_istream +std::basic_istream::_ZTTSt13basic_istreamIwSt11char_traitsIwEE: 2 entries +0 ((& std::basic_istream::_ZTVSt13basic_istreamIwSt11char_traitsIwEE) + 24) +8 ((& std::basic_istream::_ZTVSt13basic_istreamIwSt11char_traitsIwEE) + 64) + +Construction vtable for std::basic_istream (0x0x7f5ec06178f0 instance) in std::basic_iostream +std::basic_iostream::_ZTCSd0_Si: 10 entries +0 24 +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISi) +24 0 +32 0 +40 18446744073709551592 +48 (int (*)(...))-24 +56 (int (*)(...))(& _ZTISi) +64 0 +72 0 + +Construction vtable for std::basic_ostream (0x0x7f5ec06179c0 instance) in std::basic_iostream +std::basic_iostream::_ZTCSd16_So: 10 entries +0 8 +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISo) +24 0 +32 0 +40 18446744073709551608 +48 (int (*)(...))-8 +56 (int (*)(...))(& _ZTISo) +64 0 +72 0 + +VTT for std::basic_iostream +std::basic_iostream::_ZTTSd: 7 entries +0 ((& std::basic_iostream::_ZTVSd) + 24) +8 ((& std::basic_iostream::_ZTCSd0_Si) + 24) +16 ((& std::basic_iostream::_ZTCSd0_Si) + 64) +24 ((& std::basic_iostream::_ZTCSd16_So) + 24) +32 ((& std::basic_iostream::_ZTCSd16_So) + 64) +40 ((& std::basic_iostream::_ZTVSd) + 104) +48 ((& std::basic_iostream::_ZTVSd) + 64) + +Construction vtable for std::basic_istream (0x0x7f5ec0654680 instance) in std::basic_iostream +std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE0_St13basic_istreamIwS1_E: 10 entries +0 24 +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISt13basic_istreamIwSt11char_traitsIwEE) +24 0 +32 0 +40 18446744073709551592 +48 (int (*)(...))-24 +56 (int (*)(...))(& _ZTISt13basic_istreamIwSt11char_traitsIwEE) +64 0 +72 0 + +Construction vtable for std::basic_ostream (0x0x7f5ec0654750 instance) in std::basic_iostream +std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE16_St13basic_ostreamIwS1_E: 10 entries +0 8 +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISt13basic_ostreamIwSt11char_traitsIwEE) +24 0 +32 0 +40 18446744073709551608 +48 (int (*)(...))-8 +56 (int (*)(...))(& _ZTISt13basic_ostreamIwSt11char_traitsIwEE) +64 0 +72 0 + +VTT for std::basic_iostream +std::basic_iostream::_ZTTSt14basic_iostreamIwSt11char_traitsIwEE: 7 entries +0 ((& std::basic_iostream::_ZTVSt14basic_iostreamIwSt11char_traitsIwEE) + 24) +8 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE0_St13basic_istreamIwS1_E) + 24) +16 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE0_St13basic_istreamIwS1_E) + 64) +24 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE16_St13basic_ostreamIwS1_E) + 24) +32 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE16_St13basic_ostreamIwS1_E) + 64) +40 ((& std::basic_iostream::_ZTVSt14basic_iostreamIwSt11char_traitsIwEE) + 104) +48 ((& std::basic_iostream::_ZTVSt14basic_iostreamIwSt11char_traitsIwEE) + 64) + +Class QByteArrayDataPtr + size=8 align=8 + base size=8 base align=8 +QByteArrayDataPtr (0x0x7f5ec067f780) 0 + +Class QByteArray + size=8 align=8 + base size=8 base align=8 +QByteArray (0x0x7f5ec067f7e0) 0 + +Class QByteRef + size=16 align=8 + base size=12 base align=8 +QByteRef (0x0x7f5ec07adba0) 0 + +Class QStringDataPtr + size=8 align=8 + base size=8 base align=8 +QStringDataPtr (0x0x7f5ec0451a20) 0 + +Class QStringView + size=16 align=8 + base size=16 base align=8 +QStringView (0x0x7f5ec0451ea0) 0 + +Class QLatin1String + size=16 align=8 + base size=16 base align=8 +QLatin1String (0x0x7f5ec0521c60) 0 + +Class QString::Null + size=1 align=1 + base size=0 base align=1 +QString::Null (0x0x7f5ec05c26c0) 0 empty + +Class QString + size=8 align=8 + base size=8 base align=8 +QString (0x0x7f5ec05c2660) 0 + +Class QCharRef + size=16 align=8 + base size=12 base align=8 +QCharRef (0x0x7f5ec03a5840) 0 + +Class QStringRef + size=16 align=8 + base size=16 base align=8 +QStringRef (0x0x7f5ec01430c0) 0 + +Class QtPrivate::QHashCombine + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombine (0x0x7f5ebff5e3c0) 0 empty + +Class QtPrivate::QHashCombineCommutative + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombineCommutative (0x0x7f5ebff5e480) 0 empty + +Class std::_Bit_reference + size=16 align=8 + base size=16 base align=8 +std::_Bit_reference (0x0x7f5ebfc1e960) 0 + +Class std::_Bit_iterator_base + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator_base (0x0x7f5ebfdd1a90) 0 + std::iterator (0x0x7f5ebfc400c0) 0 empty + +Class std::_Bit_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator (0x0x7f5ebfdd1bc8) 0 + std::_Bit_iterator_base (0x0x7f5ebfdd1c30) 0 + std::iterator (0x0x7f5ebfc40720) 0 empty + +Class std::_Bit_const_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_const_iterator (0x0x7f5ebfdd1c98) 0 + std::_Bit_iterator_base (0x0x7f5ebfdd1d00) 0 + std::iterator (0x0x7f5ebfc40f00) 0 empty + +Class std::__detail::_List_node_base + size=16 align=8 + base size=16 base align=8 +std::__detail::_List_node_base (0x0x7f5ebfa595a0) 0 + +Class QListData::NotArrayCompatibleLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotArrayCompatibleLayout (0x0x7f5ebfb21360) 0 empty + +Class QListData::NotIndirectLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotIndirectLayout (0x0x7f5ebfb213c0) 0 empty + +Class QListData::ArrayCompatibleLayout + size=1 align=1 + base size=1 base align=1 +QListData::ArrayCompatibleLayout (0x0x7f5ebfce77b8) 0 empty + QListData::NotIndirectLayout (0x0x7f5ebfb21420) 0 empty + +Class QListData::InlineWithPaddingLayout + size=1 align=1 + base size=1 base align=1 +QListData::InlineWithPaddingLayout (0x0x7f5ebfa9a380) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7f5ebfb21480) 0 empty + QListData::NotIndirectLayout (0x0x7f5ebfb214e0) 0 empty + +Class QListData::IndirectLayout + size=1 align=1 + base size=1 base align=1 +QListData::IndirectLayout (0x0x7f5ebfce7820) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7f5ebfb21540) 0 empty + +Class QListData::Data + size=24 align=8 + base size=24 base align=8 +QListData::Data (0x0x7f5ebfb215a0) 0 + +Class QListData + size=8 align=8 + base size=8 base align=8 +QListData (0x0x7f5ebfb21300) 0 + +Class QRegExp + size=8 align=8 + base size=8 base align=8 +QRegExp (0x0x7f5ebf814780) 0 + +Class QStringMatcher::Data + size=272 align=8 + base size=272 base align=8 +QStringMatcher::Data (0x0x7f5ebf8efde0) 0 + +Class QStringMatcher + size=1048 align=8 + base size=1048 base align=8 +QStringMatcher (0x0x7f5ebf8efd80) 0 + +Class QStringList + size=8 align=8 + base size=8 base align=8 +QStringList (0x0x7f5ebf9014e0) 0 + QList (0x0x7f5ebf901548) 0 + QListSpecialMethods (0x0x7f5ebf91b060) 0 empty + +Class QScopedPointerPodDeleter + size=1 align=1 + base size=0 base align=1 +QScopedPointerPodDeleter (0x0x7f5ebf9acba0) 0 empty + +Class std::_Rb_tree_node_base + size=32 align=8 + base size=32 base align=8 +std::_Rb_tree_node_base (0x0x7f5ebf642cc0) 0 + +Class std::_Rb_tree_header + size=40 align=8 + base size=40 base align=8 +std::_Rb_tree_header (0x0x7f5ebf665060) 0 + +Class std::__erased_type + size=1 align=1 + base size=0 base align=1 +std::__erased_type (0x0x7f5ebf43c600) 0 empty + +Class std::allocator_arg_t + size=1 align=1 + base size=0 base align=1 +std::allocator_arg_t (0x0x7f5ebf43c660) 0 empty + +Class std::__uses_alloc_base + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc_base (0x0x7f5ebf43c7e0) 0 empty + +Class std::__uses_alloc0::_Sink + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc0::_Sink (0x0x7f5ebf43c8a0) 0 empty + +Class std::__uses_alloc0 + size=1 align=1 + base size=1 base align=1 +std::__uses_alloc0 (0x0x7f5ebf7c9888) 0 + std::__uses_alloc_base (0x0x7f5ebf43c840) 0 empty + +Class std::_Swallow_assign + size=1 align=1 + base size=0 base align=1 +std::_Swallow_assign (0x0x7f5ebf59dc00) 0 empty + +Class QtPrivate::AbstractDebugStreamFunction + size=16 align=8 + base size=16 base align=8 +QtPrivate::AbstractDebugStreamFunction (0x0x7f5ebf1e50c0) 0 + +Class QtPrivate::AbstractComparatorFunction + size=24 align=8 + base size=24 base align=8 +QtPrivate::AbstractComparatorFunction (0x0x7f5ebf1e5420) 0 + +Class QtPrivate::AbstractConverterFunction + size=8 align=8 + base size=8 base align=8 +QtPrivate::AbstractConverterFunction (0x0x7f5ebf1e5960) 0 + +Class QMetaType + size=80 align=8 + base size=80 base align=8 +QMetaType (0x0x7f5ebf1e5ea0) 0 + +Class QtMetaTypePrivate::VariantData + size=24 align=8 + base size=20 base align=8 +QtMetaTypePrivate::VariantData (0x0x7f5ebf2710c0) 0 + +Class QtMetaTypePrivate::VectorBoolElements + size=1 align=1 + base size=0 base align=1 +QtMetaTypePrivate::VectorBoolElements (0x0x7f5ebf271780) 0 empty + +Class QtMetaTypePrivate::QSequentialIterableImpl + size=104 align=8 + base size=104 base align=8 +QtMetaTypePrivate::QSequentialIterableImpl (0x0x7f5ebf307600) 0 + +Class QtMetaTypePrivate::QAssociativeIterableImpl + size=112 align=8 + base size=112 base align=8 +QtMetaTypePrivate::QAssociativeIterableImpl (0x0x7f5ebef60cc0) 0 + +Class QtMetaTypePrivate::QPairVariantInterfaceImpl + size=40 align=8 + base size=40 base align=8 +QtMetaTypePrivate::QPairVariantInterfaceImpl (0x0x7f5ebefdd240) 0 + +Class std::chrono::_V2::system_clock + size=1 align=1 + base size=0 base align=1 +std::chrono::_V2::system_clock (0x0x7f5ebee2a060) 0 empty + +Class std::chrono::_V2::steady_clock + size=1 align=1 + base size=0 base align=1 +std::chrono::_V2::steady_clock (0x0x7f5ebeb21ae0) 0 empty + +Vtable for QObjectData +QObjectData::_ZTV11QObjectData: 4 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 (0x0x7f5ebeb21b40) 0 + vptr=((& QObjectData::_ZTV11QObjectData) + 16) + +Class QObject::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObject::QPrivateSignal (0x0x7f5ebeb21d20) 0 empty + +Vtable for QObject +QObject::_ZTV7QObject: 14 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 (0x0x7f5ebeb21cc0) 0 + vptr=((& QObject::_ZTV7QObject) + 16) + +Vtable for QObjectUserData +QObjectUserData::_ZTV15QObjectUserData: 4 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 (0x0x7f5ebebfcb40) 0 nearly-empty + vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16) + +Class QSignalBlocker + size=16 align=8 + base size=10 base align=8 +QSignalBlocker (0x0x7f5ebebfccc0) 0 + +Class QAbstractAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractAnimation::QPrivateSignal (0x0x7f5ebec1d5a0) 0 empty + +Vtable for QAbstractAnimation +QAbstractAnimation::_ZTV18QAbstractAnimation: 18 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QAbstractAnimation) +16 (int (*)(...))QAbstractAnimation::metaObject +24 (int (*)(...))QAbstractAnimation::qt_metacast +32 (int (*)(...))QAbstractAnimation::qt_metacall +40 0 +48 0 +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 (0x0x7f5ebebdda90) 0 + vptr=((& QAbstractAnimation::_ZTV18QAbstractAnimation) + 16) + QObject (0x0x7f5ebec1d540) 0 + primary-for QAbstractAnimation (0x0x7f5ebebdda90) + +Class QAnimationDriver::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationDriver::QPrivateSignal (0x0x7f5ebec1d960) 0 empty + +Vtable for QAnimationDriver +QAnimationDriver::_ZTV16QAnimationDriver: 18 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 (0x0x7f5ebebddaf8) 0 + vptr=((& QAnimationDriver::_ZTV16QAnimationDriver) + 16) + QObject (0x0x7f5ebec1d900) 0 + primary-for QAnimationDriver (0x0x7f5ebebddaf8) + +Class QEventLoop::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventLoop::QPrivateSignal (0x0x7f5ebec1dba0) 0 empty + +Vtable for QEventLoop +QEventLoop::_ZTV10QEventLoop: 14 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 (0x0x7f5ebebddb60) 0 + vptr=((& QEventLoop::_ZTV10QEventLoop) + 16) + QObject (0x0x7f5ebec1db40) 0 + primary-for QEventLoop (0x0x7f5ebebddb60) + +Class QEventLoopLocker + size=8 align=8 + base size=8 base align=8 +QEventLoopLocker (0x0x7f5ebec73480) 0 + +Class QAbstractEventDispatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractEventDispatcher::QPrivateSignal (0x0x7f5ebec73540) 0 empty + +Class QAbstractEventDispatcher::TimerInfo + size=12 align=4 + base size=12 base align=4 +QAbstractEventDispatcher::TimerInfo (0x0x7f5ebec735a0) 0 + +Vtable for QAbstractEventDispatcher +QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher: 28 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI24QAbstractEventDispatcher) +16 (int (*)(...))QAbstractEventDispatcher::metaObject +24 (int (*)(...))QAbstractEventDispatcher::qt_metacast +32 (int (*)(...))QAbstractEventDispatcher::qt_metacall +40 0 +48 0 +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 (0x0x7f5ebebddc98) 0 + vptr=((& QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher) + 16) + QObject (0x0x7f5ebec734e0) 0 + primary-for QAbstractEventDispatcher (0x0x7f5ebebddc98) + +Vtable for std::bad_function_call +std::bad_function_call::_ZTVSt17bad_function_call: 5 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 (0x0x7f5ebe90d618) 0 nearly-empty + vptr=((& std::bad_function_call::_ZTVSt17bad_function_call) + 16) + std::exception (0x0x7f5ebe905c00) 0 nearly-empty + primary-for std::bad_function_call (0x0x7f5ebe90d618) + +Class std::_Nocopy_types + size=16 align=8 + base size=16 base align=8 +std::_Nocopy_types (0x0x7f5ebe905cc0) 0 + +Class std::_Any_data + size=16 align=8 + base size=16 base align=8 +std::_Any_data (0x0x7f5ebe905d20) 0 + +Class std::_Function_base + size=24 align=8 + base size=24 base align=8 +std::_Function_base (0x0x7f5ebe937060) 0 + +Class QMapNodeBase + size=24 align=8 + base size=24 base align=8 +QMapNodeBase (0x0x7f5ebe732000) 0 + +Class QMapDataBase + size=40 align=8 + base size=40 base align=8 +QMapDataBase (0x0x7f5ebe732c60) 0 + +Class QHashData::Node + size=16 align=8 + base size=16 base align=8 +QHashData::Node (0x0x7f5ebe830600) 0 + +Class QHashData + size=48 align=8 + base size=44 base align=8 +QHashData (0x0x7f5ebe8305a0) 0 + +Class QHashDummyValue + size=1 align=1 + base size=0 base align=1 +QHashDummyValue (0x0x7f5ebe8308a0) 0 empty + +Class QVariant::PrivateShared + size=16 align=8 + base size=12 base align=8 +QVariant::PrivateShared (0x0x7f5ebe532e40) 0 + +Class QVariant::Private::Data + size=8 align=8 + base size=8 base align=8 +QVariant::Private::Data (0x0x7f5ebe532f00) 0 + +Class QVariant::Private + size=16 align=8 + base size=12 base align=8 +QVariant::Private (0x0x7f5ebe532ea0) 0 + +Class QVariant::Handler + size=72 align=8 + base size=72 base align=8 +QVariant::Handler (0x0x7f5ebe532f60) 0 + +Class QVariant + size=16 align=8 + base size=16 base align=8 +QVariant (0x0x7f5ebe532de0) 0 + +Class QVariantComparisonHelper + size=8 align=8 + base size=8 base align=8 +QVariantComparisonHelper (0x0x7f5ebe6ab240) 0 + +Class QSequentialIterable::const_iterator + size=112 align=8 + base size=112 base align=8 +QSequentialIterable::const_iterator (0x0x7f5ebe2f48a0) 0 + +Class QSequentialIterable + size=104 align=8 + base size=104 base align=8 +QSequentialIterable (0x0x7f5ebe2f4840) 0 + +Class QAssociativeIterable::const_iterator + size=120 align=8 + base size=120 base align=8 +QAssociativeIterable::const_iterator (0x0x7f5ebe2f49c0) 0 + +Class QAssociativeIterable + size=112 align=8 + base size=112 base align=8 +QAssociativeIterable (0x0x7f5ebe2f4960) 0 + +Class QModelIndex + size=24 align=8 + base size=24 base align=8 +QModelIndex (0x0x7f5ebe3bdb40) 0 + +Class QPersistentModelIndex + size=8 align=8 + base size=8 base align=8 +QPersistentModelIndex (0x0x7f5ebe42e780) 0 + +Class QAbstractItemModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractItemModel::QPrivateSignal (0x0x7f5ebe0ff5a0) 0 empty + +Vtable for QAbstractItemModel +QAbstractItemModel::_ZTV18QAbstractItemModel: 48 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QAbstractItemModel) +16 (int (*)(...))QAbstractItemModel::metaObject +24 (int (*)(...))QAbstractItemModel::qt_metacast +32 (int (*)(...))QAbstractItemModel::qt_metacall +40 0 +48 0 +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 (0x0x7f5ebe103208) 0 + vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16) + QObject (0x0x7f5ebe0ff540) 0 + primary-for QAbstractItemModel (0x0x7f5ebe103208) + +Class QAbstractTableModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTableModel::QPrivateSignal (0x0x7f5ebe1b6960) 0 empty + +Vtable for QAbstractTableModel +QAbstractTableModel::_ZTV19QAbstractTableModel: 48 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QAbstractTableModel) +16 (int (*)(...))QAbstractTableModel::metaObject +24 (int (*)(...))QAbstractTableModel::qt_metacast +32 (int (*)(...))QAbstractTableModel::qt_metacall +40 0 +48 0 +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 (0x0x7f5ebe103820) 0 + vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16) + QAbstractItemModel (0x0x7f5ebe103888) 0 + primary-for QAbstractTableModel (0x0x7f5ebe103820) + QObject (0x0x7f5ebe1b6900) 0 + primary-for QAbstractItemModel (0x0x7f5ebe103888) + +Class QAbstractListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractListModel::QPrivateSignal (0x0x7f5ebe1b6ae0) 0 empty + +Vtable for QAbstractListModel +QAbstractListModel::_ZTV18QAbstractListModel: 48 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QAbstractListModel) +16 (int (*)(...))QAbstractListModel::metaObject +24 (int (*)(...))QAbstractListModel::qt_metacast +32 (int (*)(...))QAbstractListModel::qt_metacall +40 0 +48 0 +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 (0x0x7f5ebe1038f0) 0 + vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16) + QAbstractItemModel (0x0x7f5ebe103958) 0 + primary-for QAbstractListModel (0x0x7f5ebe1038f0) + QObject (0x0x7f5ebe1b6a80) 0 + primary-for QAbstractItemModel (0x0x7f5ebe103958) + +Vtable for QAbstractNativeEventFilter +QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI26QAbstractNativeEventFilter) +16 0 +24 0 +32 (int (*)(...))__cxa_pure_virtual + +Class QAbstractNativeEventFilter + size=16 align=8 + base size=16 base align=8 +QAbstractNativeEventFilter (0x0x7f5ebe1fc240) 0 + vptr=((& QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter) + 16) + +Class QAbstractProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractProxyModel::QPrivateSignal (0x0x7f5ebe1fc300) 0 empty + +Vtable for QAbstractProxyModel +QAbstractProxyModel::_ZTV19QAbstractProxyModel: 53 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QAbstractProxyModel) +16 (int (*)(...))QAbstractProxyModel::metaObject +24 (int (*)(...))QAbstractProxyModel::qt_metacast +32 (int (*)(...))QAbstractProxyModel::qt_metacall +40 0 +48 0 +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 (0x0x7f5ebe103a28) 0 + vptr=((& QAbstractProxyModel::_ZTV19QAbstractProxyModel) + 16) + QAbstractItemModel (0x0x7f5ebe103a90) 0 + primary-for QAbstractProxyModel (0x0x7f5ebe103a28) + QObject (0x0x7f5ebe1fc2a0) 0 + primary-for QAbstractItemModel (0x0x7f5ebe103a90) + +Class QAbstractState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractState::QPrivateSignal (0x0x7f5ebe1fc540) 0 empty + +Vtable for QAbstractState +QAbstractState::_ZTV14QAbstractState: 16 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI14QAbstractState) +16 (int (*)(...))QAbstractState::metaObject +24 (int (*)(...))QAbstractState::qt_metacast +32 (int (*)(...))QAbstractState::qt_metacall +40 0 +48 0 +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 (0x0x7f5ebe103af8) 0 + vptr=((& QAbstractState::_ZTV14QAbstractState) + 16) + QObject (0x0x7f5ebe1fc4e0) 0 + primary-for QAbstractState (0x0x7f5ebe103af8) + +Class QAbstractTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTransition::QPrivateSignal (0x0x7f5ebe1fc780) 0 empty + +Vtable for QAbstractTransition +QAbstractTransition::_ZTV19QAbstractTransition: 16 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QAbstractTransition) +16 (int (*)(...))QAbstractTransition::metaObject +24 (int (*)(...))QAbstractTransition::qt_metacast +32 (int (*)(...))QAbstractTransition::qt_metacall +40 0 +48 0 +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 (0x0x7f5ebe103b60) 0 + vptr=((& QAbstractTransition::_ZTV19QAbstractTransition) + 16) + QObject (0x0x7f5ebe1fc720) 0 + primary-for QAbstractTransition (0x0x7f5ebe103b60) + +Class QAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationGroup::QPrivateSignal (0x0x7f5ebe1fca80) 0 empty + +Vtable for QAnimationGroup +QAnimationGroup::_ZTV15QAnimationGroup: 18 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QAnimationGroup) +16 (int (*)(...))QAnimationGroup::metaObject +24 (int (*)(...))QAnimationGroup::qt_metacast +32 (int (*)(...))QAnimationGroup::qt_metacall +40 0 +48 0 +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 (0x0x7f5ebe103bc8) 0 + vptr=((& QAnimationGroup::_ZTV15QAnimationGroup) + 16) + QAbstractAnimation (0x0x7f5ebe103c30) 0 + primary-for QAnimationGroup (0x0x7f5ebe103bc8) + QObject (0x0x7f5ebe1fca20) 0 + primary-for QAbstractAnimation (0x0x7f5ebe103c30) + +Class QBasicTimer + size=4 align=4 + base size=4 base align=4 +QBasicTimer (0x0x7f5ebe2a6de0) 0 + +Class QBitArray + size=8 align=8 + base size=8 base align=8 +QBitArray (0x0x7f5ebdf021e0) 0 + +Class QBitRef + size=16 align=8 + base size=12 base align=8 +QBitRef (0x0x7f5ebdf61660) 0 + +Class QIODevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIODevice::QPrivateSignal (0x0x7f5ebdfada20) 0 empty + +Vtable for QIODevice +QIODevice::_ZTV9QIODevice: 30 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QIODevice) +16 (int (*)(...))QIODevice::metaObject +24 (int (*)(...))QIODevice::qt_metacast +32 (int (*)(...))QIODevice::qt_metacall +40 0 +48 0 +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 (0x0x7f5ebdfba1a0) 0 + vptr=((& QIODevice::_ZTV9QIODevice) + 16) + QObject (0x0x7f5ebdfad9c0) 0 + primary-for QIODevice (0x0x7f5ebdfba1a0) + +Class QBuffer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBuffer::QPrivateSignal (0x0x7f5ebdffa3c0) 0 empty + +Vtable for QBuffer +QBuffer::_ZTV7QBuffer: 30 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 (0x0x7f5ebdfba2d8) 0 + vptr=((& QBuffer::_ZTV7QBuffer) + 16) + QIODevice (0x0x7f5ebdfba340) 0 + primary-for QBuffer (0x0x7f5ebdfba2d8) + QObject (0x0x7f5ebdffa360) 0 + primary-for QIODevice (0x0x7f5ebdfba340) + +Class QByteArrayMatcher::Data + size=272 align=8 + base size=272 base align=8 +QByteArrayMatcher::Data (0x0x7f5ebdffa660) 0 + +Class QByteArrayMatcher + size=1040 align=8 + base size=1040 base align=8 +QByteArrayMatcher (0x0x7f5ebdffa600) 0 + +Class QStaticByteArrayMatcherBase::Skiptable + size=256 align=1 + base size=256 base align=1 +QStaticByteArrayMatcherBase::Skiptable (0x0x7f5ebdffa7e0) 0 + +Class QStaticByteArrayMatcherBase + size=256 align=16 + base size=256 base align=16 +QStaticByteArrayMatcherBase (0x0x7f5ebdffa780) 0 + +Class QSharedData + size=4 align=4 + base size=4 base align=4 +QSharedData (0x0x7f5ebe0466c0) 0 + +Class QDate + size=8 align=8 + base size=8 base align=8 +QDate (0x0x7f5ebe087660) 0 + +Class QTime + size=4 align=4 + base size=4 base align=4 +QTime (0x0x7f5ebdcdbf00) 0 + +Class QDateTime::ShortData + size=8 align=8 + base size=8 base align=8 +QDateTime::ShortData (0x0x7f5ebdd45ba0) 0 + +Class QDateTime::Data + size=8 align=8 + base size=8 base align=8 +QDateTime::Data (0x0x7f5ebdd45c00) 0 + +Class QDateTime + size=8 align=8 + base size=8 base align=8 +QDateTime (0x0x7f5ebdd45b40) 0 + +Class QLocale + size=8 align=8 + base size=8 base align=8 +QLocale (0x0x7f5ebde36300) 0 + +Vtable for QTextStream +QTextStream::_ZTV11QTextStream: 4 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 (0x0x7f5ebdb338a0) 0 + vptr=((& QTextStream::_ZTV11QTextStream) + 16) + +Class QTextStreamManipulator + size=40 align=8 + base size=38 base align=8 +QTextStreamManipulator (0x0x7f5ebdb99180) 0 + +Class QContiguousCacheData + size=24 align=4 + base size=24 base align=4 +QContiguousCacheData (0x0x7f5ebdc0bc60) 0 + +Class QtSharedPointer::NormalDeleter + size=1 align=1 + base size=0 base align=1 +QtSharedPointer::NormalDeleter (0x0x7f5ebdc54900) 0 empty + +Class QtSharedPointer::ExternalRefCountData + size=16 align=8 + base size=16 base align=8 +QtSharedPointer::ExternalRefCountData (0x0x7f5ebdc54a80) 0 + +Class QDebug::Stream + size=80 align=8 + base size=76 base align=8 +QDebug::Stream (0x0x7f5ebd90d6c0) 0 + +Class QDebug + size=8 align=8 + base size=8 base align=8 +QDebug (0x0x7f5ebd90d660) 0 + +Class QDebugStateSaver + size=8 align=8 + base size=8 base align=8 +QDebugStateSaver (0x0x7f5ebdaaf720) 0 + +Class QNoDebug + size=1 align=1 + base size=0 base align=1 +QNoDebug (0x0x7f5ebdaaf7e0) 0 empty + +Class QCborError + size=4 align=4 + base size=4 base align=4 +QCborError (0x0x7f5ebd72fae0) 0 + +Class QRegularExpression + size=8 align=8 + base size=8 base align=8 +QRegularExpression (0x0x7f5ebd7632a0) 0 + +Class QRegularExpressionMatch + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatch (0x0x7f5ebd816180) 0 + +Class QRegularExpressionMatchIterator + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatchIterator (0x0x7f5ebd853f00) 0 + +Class QUrl + size=8 align=8 + base size=8 base align=8 +QUrl (0x0x7f5ebd4d1960) 0 + +Class QUuid + size=16 align=4 + base size=16 base align=4 +QUuid (0x0x7f5ebd615900) 0 + +Class QCborParserError + size=16 align=8 + base size=12 base align=8 +QCborParserError (0x0x7f5ebd6a0480) 0 + +Class QCborValue + size=24 align=8 + base size=20 base align=8 +QCborValue (0x0x7f5ebd6a0540) 0 + +Class QCborValueRef + size=16 align=8 + base size=16 base align=8 +QCborValueRef (0x0x7f5ebd114540) 0 + +Class QCborArray::Iterator + size=16 align=8 + base size=16 base align=8 +QCborArray::Iterator (0x0x7f5ebd188f60) 0 + +Class QCborArray::ConstIterator + size=16 align=8 + base size=16 base align=8 +QCborArray::ConstIterator (0x0x7f5ebd1bc000) 0 + +Class QCborArray + size=8 align=8 + base size=8 base align=8 +QCborArray (0x0x7f5ebd188f00) 0 + +Class QCborMap::Iterator + size=16 align=8 + base size=16 base align=8 +QCborMap::Iterator (0x0x7f5ebd2a19c0) 0 + +Class QCborMap::ConstIterator + size=16 align=8 + base size=16 base align=8 +QCborMap::ConstIterator (0x0x7f5ebd2a1a20) 0 + +Class QCborMap + size=8 align=8 + base size=8 base align=8 +QCborMap (0x0x7f5ebd2a1960) 0 + +Class qfloat16 + size=2 align=2 + base size=2 base align=2 +qfloat16 (0x0x7f5ebd0b4180) 0 + +Class QCborStreamWriter + size=8 align=8 + base size=8 base align=8 +QCborStreamWriter (0x0x7f5ebcd73120) 0 + +Class QCborStreamReader + size=24 align=8 + base size=20 base align=8 +QCborStreamReader (0x0x7f5ebcd73e40) 0 + +Class QCollatorSortKey + size=8 align=8 + base size=8 base align=8 +QCollatorSortKey (0x0x7f5ebce08f60) 0 + +Class QCollator + size=8 align=8 + base size=8 base align=8 +QCollator (0x0x7f5ebce29180) 0 + +Class QCommandLineOption + size=8 align=8 + base size=8 base align=8 +QCommandLineOption (0x0x7f5ebcb21720) 0 + +Vtable for QEvent +QEvent::_ZTV6QEvent: 4 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 (0x0x7f5ebcb77e40) 0 + vptr=((& QEvent::_ZTV6QEvent) + 16) + +Vtable for QTimerEvent +QTimerEvent::_ZTV11QTimerEvent: 4 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 (0x0x7f5ebcb7b4e0) 0 + vptr=((& QTimerEvent::_ZTV11QTimerEvent) + 16) + QEvent (0x0x7f5ebcbbb240) 0 + primary-for QTimerEvent (0x0x7f5ebcb7b4e0) + +Vtable for QChildEvent +QChildEvent::_ZTV11QChildEvent: 4 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 (0x0x7f5ebcb7b548) 0 + vptr=((& QChildEvent::_ZTV11QChildEvent) + 16) + QEvent (0x0x7f5ebcbbb300) 0 + primary-for QChildEvent (0x0x7f5ebcb7b548) + +Vtable for QDynamicPropertyChangeEvent +QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent: 4 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 (0x0x7f5ebcb7ba90) 0 + vptr=((& QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent) + 16) + QEvent (0x0x7f5ebcbbb960) 0 + primary-for QDynamicPropertyChangeEvent (0x0x7f5ebcb7ba90) + +Vtable for QDeferredDeleteEvent +QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent: 4 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 (0x0x7f5ebcb7baf8) 0 + vptr=((& QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent) + 16) + QEvent (0x0x7f5ebcbbba20) 0 + primary-for QDeferredDeleteEvent (0x0x7f5ebcb7baf8) + +Class QCoreApplication::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QCoreApplication::QPrivateSignal (0x0x7f5ebcbbbb40) 0 empty + +Vtable for QCoreApplication +QCoreApplication::_ZTV16QCoreApplication: 16 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 (0x0x7f5ebcb7bb60) 0 + vptr=((& QCoreApplication::_ZTV16QCoreApplication) + 16) + QObject (0x0x7f5ebcbbbae0) 0 + primary-for QCoreApplication (0x0x7f5ebcb7bb60) + +Class QCommandLineParser + size=8 align=8 + base size=8 base align=8 +QCommandLineParser (0x0x7f5ebcbbbd80) 0 + +Class QConcatenateTablesProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QConcatenateTablesProxyModel::QPrivateSignal (0x0x7f5ebcbbbf00) 0 empty + +Vtable for QConcatenateTablesProxyModel +QConcatenateTablesProxyModel::_ZTV28QConcatenateTablesProxyModel: 48 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI28QConcatenateTablesProxyModel) +16 (int (*)(...))QConcatenateTablesProxyModel::metaObject +24 (int (*)(...))QConcatenateTablesProxyModel::qt_metacast +32 (int (*)(...))QConcatenateTablesProxyModel::qt_metacall +40 (int (*)(...))QConcatenateTablesProxyModel::~QConcatenateTablesProxyModel +48 (int (*)(...))QConcatenateTablesProxyModel::~QConcatenateTablesProxyModel +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 (*)(...))QConcatenateTablesProxyModel::index +120 (int (*)(...))QConcatenateTablesProxyModel::parent +128 (int (*)(...))QAbstractItemModel::sibling +136 (int (*)(...))QConcatenateTablesProxyModel::rowCount +144 (int (*)(...))QConcatenateTablesProxyModel::columnCount +152 (int (*)(...))QAbstractItemModel::hasChildren +160 (int (*)(...))QConcatenateTablesProxyModel::data +168 (int (*)(...))QConcatenateTablesProxyModel::setData +176 (int (*)(...))QConcatenateTablesProxyModel::headerData +184 (int (*)(...))QAbstractItemModel::setHeaderData +192 (int (*)(...))QConcatenateTablesProxyModel::itemData +200 (int (*)(...))QConcatenateTablesProxyModel::setItemData +208 (int (*)(...))QConcatenateTablesProxyModel::mimeTypes +216 (int (*)(...))QConcatenateTablesProxyModel::mimeData +224 (int (*)(...))QConcatenateTablesProxyModel::canDropMimeData +232 (int (*)(...))QConcatenateTablesProxyModel::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 (*)(...))QConcatenateTablesProxyModel::flags +328 (int (*)(...))QAbstractItemModel::sort +336 (int (*)(...))QAbstractItemModel::buddy +344 (int (*)(...))QAbstractItemModel::match +352 (int (*)(...))QConcatenateTablesProxyModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractItemModel::submit +376 (int (*)(...))QAbstractItemModel::revert + +Class QConcatenateTablesProxyModel + size=16 align=8 + base size=16 base align=8 +QConcatenateTablesProxyModel (0x0x7f5ebcb7bbc8) 0 + vptr=((& QConcatenateTablesProxyModel::_ZTV28QConcatenateTablesProxyModel) + 16) + QAbstractItemModel (0x0x7f5ebcb7bc30) 0 + primary-for QConcatenateTablesProxyModel (0x0x7f5ebcb7bbc8) + QObject (0x0x7f5ebcbbbea0) 0 + primary-for QAbstractItemModel (0x0x7f5ebcb7bc30) + +Class QCryptographicHash + size=8 align=8 + base size=8 base align=8 +QCryptographicHash (0x0x7f5ebcc1e120) 0 + +Class QDataStream + size=32 align=8 + base size=32 base align=8 +QDataStream (0x0x7f5ebcc1e240) 0 + +Class QtPrivate::StreamStateSaver + size=16 align=8 + base size=12 base align=8 +QtPrivate::StreamStateSaver (0x0x7f5ebcc1e3c0) 0 + +Class QElapsedTimer + size=16 align=8 + base size=16 base align=8 +QElapsedTimer (0x0x7f5ebcc7cae0) 0 + +Class QDeadlineTimer + size=16 align=8 + base size=16 base align=8 +QDeadlineTimer (0x0x7f5ebccad240) 0 + +Class QFileDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileDevice::QPrivateSignal (0x0x7f5ebc9ccf60) 0 empty + +Vtable for QFileDevice +QFileDevice::_ZTV11QFileDevice: 34 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 (0x0x7f5ebc9cde38) 0 + vptr=((& QFileDevice::_ZTV11QFileDevice) + 16) + QIODevice (0x0x7f5ebc9cdea0) 0 + primary-for QFileDevice (0x0x7f5ebc9cde38) + QObject (0x0x7f5ebc9ccf00) 0 + primary-for QIODevice (0x0x7f5ebc9cdea0) + +Class QFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFile::QPrivateSignal (0x0x7f5ebca048a0) 0 empty + +Vtable for QFile +QFile::_ZTV5QFile: 34 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 (0x0x7f5ebca2d000) 0 + vptr=((& QFile::_ZTV5QFile) + 16) + QFileDevice (0x0x7f5ebca2d068) 0 + primary-for QFile (0x0x7f5ebca2d000) + QIODevice (0x0x7f5ebca2d0d0) 0 + primary-for QFileDevice (0x0x7f5ebca2d068) + QObject (0x0x7f5ebca04840) 0 + primary-for QIODevice (0x0x7f5ebca2d0d0) + +Class QFileInfo + size=8 align=8 + base size=8 base align=8 +QFileInfo (0x0x7f5ebca04f00) 0 + +Class QDir + size=8 align=8 + base size=8 base align=8 +QDir (0x0x7f5ebcab5300) 0 + +Class QDirIterator + size=8 align=8 + base size=8 base align=8 +QDirIterator (0x0x7f5ebc724660) 0 + +Class QEasingCurve + size=8 align=8 + base size=8 base align=8 +QEasingCurve (0x0x7f5ebc724de0) 0 + +Class QEventTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventTransition::QPrivateSignal (0x0x7f5ebc85df00) 0 empty + +Vtable for QEventTransition +QEventTransition::_ZTV16QEventTransition: 16 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 (0x0x7f5ebc83a340) 0 + vptr=((& QEventTransition::_ZTV16QEventTransition) + 16) + QAbstractTransition (0x0x7f5ebc83a3a8) 0 + primary-for QEventTransition (0x0x7f5ebc83a340) + QObject (0x0x7f5ebc85dea0) 0 + primary-for QAbstractTransition (0x0x7f5ebc83a3a8) + +Vtable for QException +QException::_ZTV10QException: 7 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 (0x0x7f5ebc83a410) 0 nearly-empty + vptr=((& QException::_ZTV10QException) + 16) + std::exception (0x0x7f5ebc493120) 0 nearly-empty + primary-for QException (0x0x7f5ebc83a410) + +Vtable for QUnhandledException +QUnhandledException::_ZTV19QUnhandledException: 7 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 (0x0x7f5ebc83a478) 0 nearly-empty + vptr=((& QUnhandledException::_ZTV19QUnhandledException) + 16) + QException (0x0x7f5ebc83a4e0) 0 nearly-empty + primary-for QUnhandledException (0x0x7f5ebc83a478) + std::exception (0x0x7f5ebc493180) 0 nearly-empty + primary-for QException (0x0x7f5ebc83a4e0) + +Class QtPrivate::ExceptionHolder + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionHolder (0x0x7f5ebc4931e0) 0 + +Class QtPrivate::ExceptionStore + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionStore (0x0x7f5ebc4932a0) 0 + +Vtable for QFactoryInterface +QFactoryInterface::_ZTV17QFactoryInterface: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QFactoryInterface) +16 0 +24 0 +32 (int (*)(...))__cxa_pure_virtual + +Class QFactoryInterface + size=8 align=8 + base size=8 base align=8 +QFactoryInterface (0x0x7f5ebc493300) 0 nearly-empty + vptr=((& QFactoryInterface::_ZTV17QFactoryInterface) + 16) + +Class QFileSelector::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSelector::QPrivateSignal (0x0x7f5ebc493540) 0 empty + +Vtable for QFileSelector +QFileSelector::_ZTV13QFileSelector: 14 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 (0x0x7f5ebc83a548) 0 + vptr=((& QFileSelector::_ZTV13QFileSelector) + 16) + QObject (0x0x7f5ebc4934e0) 0 + primary-for QFileSelector (0x0x7f5ebc83a548) + +Class QFileSystemWatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSystemWatcher::QPrivateSignal (0x0x7f5ebc493780) 0 empty + +Vtable for QFileSystemWatcher +QFileSystemWatcher::_ZTV18QFileSystemWatcher: 14 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 (0x0x7f5ebc83a5b0) 0 + vptr=((& QFileSystemWatcher::_ZTV18QFileSystemWatcher) + 16) + QObject (0x0x7f5ebc493720) 0 + primary-for QFileSystemWatcher (0x0x7f5ebc83a5b0) + +Class QFinalState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFinalState::QPrivateSignal (0x0x7f5ebc4939c0) 0 empty + +Vtable for QFinalState +QFinalState::_ZTV11QFinalState: 16 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 (0x0x7f5ebc83a618) 0 + vptr=((& QFinalState::_ZTV11QFinalState) + 16) + QAbstractState (0x0x7f5ebc83a680) 0 + primary-for QFinalState (0x0x7f5ebc83a618) + QObject (0x0x7f5ebc493960) 0 + primary-for QAbstractState (0x0x7f5ebc83a680) + +Vtable for QRunnable +QRunnable::_ZTV9QRunnable: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QRunnable) +16 (int (*)(...))__cxa_pure_virtual +24 0 +32 0 + +Class QRunnable + size=16 align=8 + base size=12 base align=8 +QRunnable (0x0x7f5ebc493ba0) 0 + vptr=((& QRunnable::_ZTV9QRunnable) + 16) + +Class QBasicMutex + size=8 align=8 + base size=8 base align=8 +QBasicMutex (0x0x7f5ebc493e40) 0 + +Class QMutex + size=8 align=8 + base size=8 base align=8 +QMutex (0x0x7f5ebc83a750) 0 + QBasicMutex (0x0x7f5ebc50bae0) 0 + +Class QMutexLocker + size=8 align=8 + base size=8 base align=8 +QMutexLocker (0x0x7f5ebc50bd20) 0 + +Class QtPrivate::ResultItem + size=16 align=8 + base size=16 base align=8 +QtPrivate::ResultItem (0x0x7f5ebc5661e0) 0 + +Class QtPrivate::ResultIteratorBase + size=16 align=8 + base size=12 base align=8 +QtPrivate::ResultIteratorBase (0x0x7f5ebc5667e0) 0 + +Vtable for QtPrivate::ResultStoreBase +QtPrivate::ResultStoreBase::_ZTVN9QtPrivate15ResultStoreBaseE: 4 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 (0x0x7f5ebc5669c0) 0 + vptr=((& QtPrivate::ResultStoreBase::_ZTVN9QtPrivate15ResultStoreBaseE) + 16) + +Vtable for QFutureInterfaceBase +QFutureInterfaceBase::_ZTV20QFutureInterfaceBase: 4 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 (0x0x7f5ebc5f41e0) 0 + vptr=((& QFutureInterfaceBase::_ZTV20QFutureInterfaceBase) + 16) + +Class QFutureWatcherBase::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFutureWatcherBase::QPrivateSignal (0x0x7f5ebc2a14e0) 0 empty + +Vtable for QFutureWatcherBase +QFutureWatcherBase::_ZTV18QFutureWatcherBase: 16 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QFutureWatcherBase) +16 (int (*)(...))QFutureWatcherBase::metaObject +24 (int (*)(...))QFutureWatcherBase::qt_metacast +32 (int (*)(...))QFutureWatcherBase::qt_metacall +40 0 +48 0 +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 (0x0x7f5ebc5f7d68) 0 + vptr=((& QFutureWatcherBase::_ZTV18QFutureWatcherBase) + 16) + QObject (0x0x7f5ebc2a1480) 0 + primary-for QFutureWatcherBase (0x0x7f5ebc5f7d68) + +Class QHistoryState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QHistoryState::QPrivateSignal (0x0x7f5ebc2c8840) 0 empty + +Vtable for QHistoryState +QHistoryState::_ZTV13QHistoryState: 16 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 (0x0x7f5ebc2b85b0) 0 + vptr=((& QHistoryState::_ZTV13QHistoryState) + 16) + QAbstractState (0x0x7f5ebc2b8618) 0 + primary-for QHistoryState (0x0x7f5ebc2b85b0) + QObject (0x0x7f5ebc2c87e0) 0 + primary-for QAbstractState (0x0x7f5ebc2b8618) + +Class QIdentityProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIdentityProxyModel::QPrivateSignal (0x0x7f5ebc2c8b40) 0 empty + +Vtable for QIdentityProxyModel +QIdentityProxyModel::_ZTV19QIdentityProxyModel: 53 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 (0x0x7f5ebc2b8680) 0 + vptr=((& QIdentityProxyModel::_ZTV19QIdentityProxyModel) + 16) + QAbstractProxyModel (0x0x7f5ebc2b86e8) 0 + primary-for QIdentityProxyModel (0x0x7f5ebc2b8680) + QAbstractItemModel (0x0x7f5ebc2b8750) 0 + primary-for QAbstractProxyModel (0x0x7f5ebc2b86e8) + QObject (0x0x7f5ebc2c8ae0) 0 + primary-for QAbstractItemModel (0x0x7f5ebc2b8750) + +Class QItemSelectionRange + size=16 align=8 + base size=16 base align=8 +QItemSelectionRange (0x0x7f5ebc2c8d20) 0 + +Class QItemSelectionModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QItemSelectionModel::QPrivateSignal (0x0x7f5ebc3ac660) 0 empty + +Vtable for QItemSelectionModel +QItemSelectionModel::_ZTV19QItemSelectionModel: 20 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 (0x0x7f5ebc3b40d0) 0 + vptr=((& QItemSelectionModel::_ZTV19QItemSelectionModel) + 16) + QObject (0x0x7f5ebc3ac600) 0 + primary-for QItemSelectionModel (0x0x7f5ebc3b40d0) + +Class QItemSelection + size=8 align=8 + base size=8 base align=8 +QItemSelection (0x0x7f5ebc3b4270) 0 + QList (0x0x7f5ebc3b42d8) 0 + QListSpecialMethods (0x0x7f5ebc3f5180) 0 empty + +Class QJsonValue + size=24 align=8 + base size=20 base align=8 +QJsonValue (0x0x7f5ebc45aa80) 0 + +Class QJsonValueRef + size=16 align=8 + base size=12 base align=8 +QJsonValueRef (0x0x7f5ebc1aac60) 0 + +Class QJsonValuePtr + size=24 align=8 + base size=24 base align=8 +QJsonValuePtr (0x0x7f5ebc1e7c00) 0 + +Class QJsonValueRefPtr + size=16 align=8 + base size=16 base align=8 +QJsonValueRefPtr (0x0x7f5ebc1e7ea0) 0 + +Class QJsonArray::iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::iterator (0x0x7f5ebc261240) 0 + +Class QJsonArray::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::const_iterator (0x0x7f5ebc2612a0) 0 + +Class QJsonArray + size=16 align=8 + base size=16 base align=8 +QJsonArray (0x0x7f5ebc2611e0) 0 + +Class QJsonParseError + size=8 align=4 + base size=8 base align=4 +QJsonParseError (0x0x7f5ebbf8e180) 0 + +Class QJsonDocument + size=8 align=8 + base size=8 base align=8 +QJsonDocument (0x0x7f5ebbf8e1e0) 0 + +Class QJsonObject::iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::iterator (0x0x7f5ebbfe19c0) 0 + +Class QJsonObject::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::const_iterator (0x0x7f5ebbfe1a20) 0 + +Class QJsonObject + size=16 align=8 + base size=16 base align=8 +QJsonObject (0x0x7f5ebbfe1960) 0 + +Class QLibrary::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLibrary::QPrivateSignal (0x0x7f5ebbcefd80) 0 empty + +Vtable for QLibrary +QLibrary::_ZTV8QLibrary: 14 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 (0x0x7f5ebbd02340) 0 + vptr=((& QLibrary::_ZTV8QLibrary) + 16) + QObject (0x0x7f5ebbcefd20) 0 + primary-for QLibrary (0x0x7f5ebbd02340) + +Class QVersionNumber::SegmentStorage + size=8 align=8 + base size=8 base align=8 +QVersionNumber::SegmentStorage (0x0x7f5ebbd1ec00) 0 + +Class QVersionNumber + size=8 align=8 + base size=8 base align=8 +QVersionNumber (0x0x7f5ebbd1e720) 0 + +Class QLibraryInfo + size=1 align=1 + base size=0 base align=1 +QLibraryInfo (0x0x7f5ebbdef360) 0 empty + +Class QPoint + size=8 align=4 + base size=8 base align=4 +QPoint (0x0x7f5ebbdef3c0) 0 + +Class QPointF + size=16 align=8 + base size=16 base align=8 +QPointF (0x0x7f5ebbe6a1e0) 0 + +Class QLine + size=16 align=4 + base size=16 base align=4 +QLine (0x0x7f5ebbad8360) 0 + +Class QLineF + size=32 align=8 + base size=32 base align=8 +QLineF (0x0x7f5ebbb41720) 0 + +Class QLinkedListData + size=32 align=8 + base size=25 base align=8 +QLinkedListData (0x0x7f5ebbbbc9c0) 0 + +Class QLockFile + size=8 align=8 + base size=8 base align=8 +QLockFile (0x0x7f5ebbc63b40) 0 + +Class QLoggingCategory::AtomicBools + size=4 align=1 + base size=4 base align=1 +QLoggingCategory::AtomicBools (0x0x7f5ebbc63d80) 0 + +Class QLoggingCategory + size=24 align=8 + base size=24 base align=8 +QLoggingCategory (0x0x7f5ebbc63d20) 0 + +Class QMargins + size=16 align=4 + base size=16 base align=4 +QMargins (0x0x7f5ebb8cf1e0) 0 + +Class QMarginsF + size=32 align=8 + base size=32 base align=8 +QMarginsF (0x0x7f5ebb94d120) 0 + +Class QMessageAuthenticationCode + size=8 align=8 + base size=8 base align=8 +QMessageAuthenticationCode (0x0x7f5ebb780900) 0 + +Class QMetaMethod + size=16 align=8 + base size=12 base align=8 +QMetaMethod (0x0x7f5ebb780960) 0 + +Class QMetaEnum + size=16 align=8 + base size=12 base align=8 +QMetaEnum (0x0x7f5ebb80c1e0) 0 + +Class QMetaProperty + size=32 align=8 + base size=32 base align=8 +QMetaProperty (0x0x7f5ebb84d420) 0 + +Class QMetaClassInfo + size=16 align=8 + base size=12 base align=8 +QMetaClassInfo (0x0x7f5ebb84d540) 0 + +Class QMimeData::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QMimeData::QPrivateSignal (0x0x7f5ebb489ae0) 0 empty + +Vtable for QMimeData +QMimeData::_ZTV9QMimeData: 17 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 (0x0x7f5ebb886f70) 0 + vptr=((& QMimeData::_ZTV9QMimeData) + 16) + QObject (0x0x7f5ebb489a80) 0 + primary-for QMimeData (0x0x7f5ebb886f70) + +Class QMimeType + size=8 align=8 + base size=8 base align=8 +QMimeType (0x0x7f5ebb489cc0) 0 + +Class QMimeDatabase + size=8 align=8 + base size=8 base align=8 +QMimeDatabase (0x0x7f5ebb4e5de0) 0 + +Class QObjectCleanupHandler::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObjectCleanupHandler::QPrivateSignal (0x0x7f5ebb4e5ea0) 0 empty + +Vtable for QObjectCleanupHandler +QObjectCleanupHandler::_ZTV21QObjectCleanupHandler: 14 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 (0x0x7f5ebb4fe2d8) 0 + vptr=((& QObjectCleanupHandler::_ZTV21QObjectCleanupHandler) + 16) + QObject (0x0x7f5ebb4e5e40) 0 + primary-for QObjectCleanupHandler (0x0x7f5ebb4fe2d8) + +Class QOperatingSystemVersion + size=16 align=4 + base size=16 base align=4 +QOperatingSystemVersion (0x0x7f5ebb517000) 0 + +Class QParallelAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QParallelAnimationGroup::QPrivateSignal (0x0x7f5ebb576780) 0 empty + +Vtable for QParallelAnimationGroup +QParallelAnimationGroup::_ZTV23QParallelAnimationGroup: 18 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 (0x0x7f5ebb572b60) 0 + vptr=((& QParallelAnimationGroup::_ZTV23QParallelAnimationGroup) + 16) + QAnimationGroup (0x0x7f5ebb572bc8) 0 + primary-for QParallelAnimationGroup (0x0x7f5ebb572b60) + QAbstractAnimation (0x0x7f5ebb572c30) 0 + primary-for QAnimationGroup (0x0x7f5ebb572bc8) + QObject (0x0x7f5ebb576720) 0 + primary-for QAbstractAnimation (0x0x7f5ebb572c30) + +Class QPauseAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPauseAnimation::QPrivateSignal (0x0x7f5ebb5769c0) 0 empty + +Vtable for QPauseAnimation +QPauseAnimation::_ZTV15QPauseAnimation: 18 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 (0x0x7f5ebb572c98) 0 + vptr=((& QPauseAnimation::_ZTV15QPauseAnimation) + 16) + QAbstractAnimation (0x0x7f5ebb572d00) 0 + primary-for QPauseAnimation (0x0x7f5ebb572c98) + QObject (0x0x7f5ebb576960) 0 + primary-for QAbstractAnimation (0x0x7f5ebb572d00) + +Class QStaticPlugin + size=16 align=8 + base size=16 base align=8 +QStaticPlugin (0x0x7f5ebb5a8600) 0 + +Class QPluginLoader::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPluginLoader::QPrivateSignal (0x0x7f5ebb5ee780) 0 empty + +Vtable for QPluginLoader +QPluginLoader::_ZTV13QPluginLoader: 14 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 (0x0x7f5ebb5f9068) 0 + vptr=((& QPluginLoader::_ZTV13QPluginLoader) + 16) + QObject (0x0x7f5ebb5ee720) 0 + primary-for QPluginLoader (0x0x7f5ebb5f9068) + +Class QProcessEnvironment + size=8 align=8 + base size=8 base align=8 +QProcessEnvironment (0x0x7f5ebb5ee8a0) 0 + +Class QProcess::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QProcess::QPrivateSignal (0x0x7f5ebb648f00) 0 empty + +Vtable for QProcess +QProcess::_ZTV8QProcess: 31 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 (0x0x7f5ebb64bc98) 0 + vptr=((& QProcess::_ZTV8QProcess) + 16) + QIODevice (0x0x7f5ebb64bd00) 0 + primary-for QProcess (0x0x7f5ebb64bc98) + QObject (0x0x7f5ebb648ea0) 0 + primary-for QIODevice (0x0x7f5ebb64bd00) + +Class QVariantAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QVariantAnimation::QPrivateSignal (0x0x7f5ebb289600) 0 empty + +Vtable for QVariantAnimation +QVariantAnimation::_ZTV17QVariantAnimation: 20 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 (0x0x7f5ebb64bd68) 0 + vptr=((& QVariantAnimation::_ZTV17QVariantAnimation) + 16) + QAbstractAnimation (0x0x7f5ebb64bdd0) 0 + primary-for QVariantAnimation (0x0x7f5ebb64bd68) + QObject (0x0x7f5ebb2895a0) 0 + primary-for QAbstractAnimation (0x0x7f5ebb64bdd0) + +Class QPropertyAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPropertyAnimation::QPrivateSignal (0x0x7f5ebb2898a0) 0 empty + +Vtable for QPropertyAnimation +QPropertyAnimation::_ZTV18QPropertyAnimation: 20 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 (0x0x7f5ebb64bea0) 0 + vptr=((& QPropertyAnimation::_ZTV18QPropertyAnimation) + 16) + QVariantAnimation (0x0x7f5ebb64bf08) 0 + primary-for QPropertyAnimation (0x0x7f5ebb64bea0) + QAbstractAnimation (0x0x7f5ebb64bf70) 0 + primary-for QVariantAnimation (0x0x7f5ebb64bf08) + QObject (0x0x7f5ebb289840) 0 + primary-for QAbstractAnimation (0x0x7f5ebb64bf70) + +Class std::random_device + size=5000 align=8 + base size=5000 base align=8 +std::random_device (0x0x7f5ebb335000) 0 + +Class std::bernoulli_distribution::param_type + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution::param_type (0x0x7f5ebb40ed20) 0 + +Class std::bernoulli_distribution + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution (0x0x7f5ebb40ecc0) 0 + +Class std::seed_seq + size=24 align=8 + base size=24 base align=8 +std::seed_seq (0x0x7f5ebb1f6a80) 0 + +Class QRandomGenerator::Storage + size=2504 align=8 + base size=2504 base align=8 +QRandomGenerator::Storage (0x0x7f5ebb035720) 0 + +Class QRandomGenerator + size=2512 align=8 + base size=2512 base align=8 +QRandomGenerator (0x0x7f5ebb0356c0) 0 + +Class QRandomGenerator64 + size=2512 align=8 + base size=2512 base align=8 +QRandomGenerator64 (0x0x7f5ebac2cc30) 0 + QRandomGenerator (0x0x7f5ebac59240) 0 + +Class QReadWriteLock + size=8 align=8 + base size=8 base align=8 +QReadWriteLock (0x0x7f5ebac59de0) 0 + +Class QReadLocker + size=8 align=8 + base size=8 base align=8 +QReadLocker (0x0x7f5ebacd90c0) 0 + +Class QWriteLocker + size=8 align=8 + base size=8 base align=8 +QWriteLocker (0x0x7f5ebacd95a0) 0 + +Class QSize + size=8 align=4 + base size=8 base align=4 +QSize (0x0x7f5ebacd9a80) 0 + +Class QSizeF + size=16 align=8 + base size=16 base align=8 +QSizeF (0x0x7f5ebad478a0) 0 + +Class QRect + size=16 align=4 + base size=16 base align=4 +QRect (0x0x7f5ebadc3840) 0 + +Class QRectF + size=32 align=8 + base size=32 base align=8 +QRectF (0x0x7f5ebaa778a0) 0 + +Class QResource + size=8 align=8 + base size=8 base align=8 +QResource (0x0x7f5ebab359c0) 0 + +Class QSaveFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSaveFile::QPrivateSignal (0x0x7f5ebab35c60) 0 empty + +Vtable for QSaveFile +QSaveFile::_ZTV9QSaveFile: 34 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 (0x0x7f5ebaafa618) 0 + vptr=((& QSaveFile::_ZTV9QSaveFile) + 16) + QFileDevice (0x0x7f5ebaafa680) 0 + primary-for QSaveFile (0x0x7f5ebaafa618) + QIODevice (0x0x7f5ebaafa6e8) 0 + primary-for QFileDevice (0x0x7f5ebaafa680) + QObject (0x0x7f5ebab35c00) 0 + primary-for QIODevice (0x0x7f5ebaafa6e8) + +Class QSemaphore + size=8 align=8 + base size=8 base align=8 +QSemaphore (0x0x7f5ebab8e2a0) 0 + +Class QSemaphoreReleaser + size=16 align=8 + base size=12 base align=8 +QSemaphoreReleaser (0x0x7f5ebab8e420) 0 + +Class QSequentialAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSequentialAnimationGroup::QPrivateSignal (0x0x7f5eba89c6c0) 0 empty + +Vtable for QSequentialAnimationGroup +QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup: 18 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 (0x0x7f5eba89e410) 0 + vptr=((& QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup) + 16) + QAnimationGroup (0x0x7f5eba89e478) 0 + primary-for QSequentialAnimationGroup (0x0x7f5eba89e410) + QAbstractAnimation (0x0x7f5eba89e4e0) 0 + primary-for QAnimationGroup (0x0x7f5eba89e478) + QObject (0x0x7f5eba89c660) 0 + primary-for QAbstractAnimation (0x0x7f5eba89e4e0) + +Class QSettings::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSettings::QPrivateSignal (0x0x7f5eba89c900) 0 empty + +Vtable for QSettings +QSettings::_ZTV9QSettings: 14 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 (0x0x7f5eba89e548) 0 + vptr=((& QSettings::_ZTV9QSettings) + 16) + QObject (0x0x7f5eba89c8a0) 0 + primary-for QSettings (0x0x7f5eba89e548) + +Class QSharedMemory::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSharedMemory::QPrivateSignal (0x0x7f5eba89cd80) 0 empty + +Vtable for QSharedMemory +QSharedMemory::_ZTV13QSharedMemory: 14 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 (0x0x7f5eba89e5b0) 0 + vptr=((& QSharedMemory::_ZTV13QSharedMemory) + 16) + QObject (0x0x7f5eba89cd20) 0 + primary-for QSharedMemory (0x0x7f5eba89e5b0) + +Class QSignalMapper::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalMapper::QPrivateSignal (0x0x7f5eba8e9000) 0 empty + +Vtable for QSignalMapper +QSignalMapper::_ZTV13QSignalMapper: 14 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 (0x0x7f5eba89e618) 0 + vptr=((& QSignalMapper::_ZTV13QSignalMapper) + 16) + QObject (0x0x7f5eba89cf60) 0 + primary-for QSignalMapper (0x0x7f5eba89e618) + +Class QSignalTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalTransition::QPrivateSignal (0x0x7f5eba8e9240) 0 empty + +Vtable for QSignalTransition +QSignalTransition::_ZTV17QSignalTransition: 16 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 (0x0x7f5eba89e680) 0 + vptr=((& QSignalTransition::_ZTV17QSignalTransition) + 16) + QAbstractTransition (0x0x7f5eba89e6e8) 0 + primary-for QSignalTransition (0x0x7f5eba89e680) + QObject (0x0x7f5eba8e91e0) 0 + primary-for QAbstractTransition (0x0x7f5eba89e6e8) + +Class QSocketNotifier::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSocketNotifier::QPrivateSignal (0x0x7f5eba8e94e0) 0 empty + +Vtable for QSocketNotifier +QSocketNotifier::_ZTV15QSocketNotifier: 14 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 (0x0x7f5eba89e750) 0 + vptr=((& QSocketNotifier::_ZTV15QSocketNotifier) + 16) + QObject (0x0x7f5eba8e9480) 0 + primary-for QSocketNotifier (0x0x7f5eba89e750) + +Class QSortFilterProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSortFilterProxyModel::QPrivateSignal (0x0x7f5eba8e9720) 0 empty + +Vtable for QSortFilterProxyModel +QSortFilterProxyModel::_ZTV21QSortFilterProxyModel: 56 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 (0x0x7f5eba89e7b8) 0 + vptr=((& QSortFilterProxyModel::_ZTV21QSortFilterProxyModel) + 16) + QAbstractProxyModel (0x0x7f5eba89e820) 0 + primary-for QSortFilterProxyModel (0x0x7f5eba89e7b8) + QAbstractItemModel (0x0x7f5eba89e888) 0 + primary-for QAbstractProxyModel (0x0x7f5eba89e820) + QObject (0x0x7f5eba8e96c0) 0 + primary-for QAbstractItemModel (0x0x7f5eba89e888) + +Class QStandardPaths + size=1 align=1 + base size=0 base align=1 +QStandardPaths (0x0x7f5eba8e9b40) 0 empty + +Class QState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QState::QPrivateSignal (0x0x7f5eba962480) 0 empty + +Vtable for QState +QState::_ZTV6QState: 16 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 (0x0x7f5eba89ea28) 0 + vptr=((& QState::_ZTV6QState) + 16) + QAbstractState (0x0x7f5eba89ea90) 0 + primary-for QState (0x0x7f5eba89ea28) + QObject (0x0x7f5eba962420) 0 + primary-for QAbstractState (0x0x7f5eba89ea90) + +Class QStateMachine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStateMachine::QPrivateSignal (0x0x7f5eba962900) 0 empty + +Vtable for QStateMachine::SignalEvent +QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE: 4 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 (0x0x7f5eba89ec30) 0 + vptr=((& QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE) + 16) + QEvent (0x0x7f5eba962960) 0 + primary-for QStateMachine::SignalEvent (0x0x7f5eba89ec30) + +Vtable for QStateMachine::WrappedEvent +QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE: 4 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 (0x0x7f5eba89ec98) 0 + vptr=((& QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE) + 16) + QEvent (0x0x7f5eba9629c0) 0 + primary-for QStateMachine::WrappedEvent (0x0x7f5eba89ec98) + +Vtable for QStateMachine +QStateMachine::_ZTV13QStateMachine: 20 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 (0x0x7f5eba89eaf8) 0 + vptr=((& QStateMachine::_ZTV13QStateMachine) + 16) + QState (0x0x7f5eba89eb60) 0 + primary-for QStateMachine (0x0x7f5eba89eaf8) + QAbstractState (0x0x7f5eba89ebc8) 0 + primary-for QState (0x0x7f5eba89eb60) + QObject (0x0x7f5eba9628a0) 0 + primary-for QAbstractState (0x0x7f5eba89ebc8) + +Class QStorageInfo + size=8 align=8 + base size=8 base align=8 +QStorageInfo (0x0x7f5eba962d80) 0 + +Class QAbstractConcatenable + size=1 align=1 + base size=0 base align=1 +QAbstractConcatenable (0x0x7f5eba61cd80) 0 empty + +Class QStringListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStringListModel::QPrivateSignal (0x0x7f5eba6cb120) 0 empty + +Vtable for QStringListModel +QStringListModel::_ZTV16QStringListModel: 48 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 (*)(...))QStringListModel::itemData +200 (int (*)(...))QStringListModel::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 (*)(...))QStringListModel::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 (0x0x7f5eba690dd0) 0 + vptr=((& QStringListModel::_ZTV16QStringListModel) + 16) + QAbstractListModel (0x0x7f5eba690e38) 0 + primary-for QStringListModel (0x0x7f5eba690dd0) + QAbstractItemModel (0x0x7f5eba690ea0) 0 + primary-for QAbstractListModel (0x0x7f5eba690e38) + QObject (0x0x7f5eba6cb0c0) 0 + primary-for QAbstractItemModel (0x0x7f5eba690ea0) + +Class QSystemSemaphore + size=8 align=8 + base size=8 base align=8 +QSystemSemaphore (0x0x7f5eba6cb240) 0 + +Class QTemporaryDir + size=8 align=8 + base size=8 base align=8 +QTemporaryDir (0x0x7f5eba6cb300) 0 + +Class QTemporaryFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTemporaryFile::QPrivateSignal (0x0x7f5eba6cb420) 0 empty + +Vtable for QTemporaryFile +QTemporaryFile::_ZTV14QTemporaryFile: 34 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 (0x0x7f5eba690f08) 0 + vptr=((& QTemporaryFile::_ZTV14QTemporaryFile) + 16) + QFile (0x0x7f5eba690f70) 0 + primary-for QTemporaryFile (0x0x7f5eba690f08) + QFileDevice (0x0x7f5eba6fc000) 0 + primary-for QFile (0x0x7f5eba690f70) + QIODevice (0x0x7f5eba6fc068) 0 + primary-for QFileDevice (0x0x7f5eba6fc000) + QObject (0x0x7f5eba6cb3c0) 0 + primary-for QIODevice (0x0x7f5eba6fc068) + +Class QTextBoundaryFinder + size=48 align=8 + base size=48 base align=8 +QTextBoundaryFinder (0x0x7f5eba6cb780) 0 + +Class QTextCodec::ConverterState + size=32 align=8 + base size=32 base align=8 +QTextCodec::ConverterState (0x0x7f5eba74d000) 0 + +Vtable for QTextCodec +QTextCodec::_ZTV10QTextCodec: 9 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 0 +64 0 + +Class QTextCodec + size=8 align=8 + base size=8 base align=8 +QTextCodec (0x0x7f5eba6cbf60) 0 nearly-empty + vptr=((& QTextCodec::_ZTV10QTextCodec) + 16) + +Class QTextEncoder + size=40 align=8 + base size=40 base align=8 +QTextEncoder (0x0x7f5eba74d9c0) 0 + +Class QTextDecoder + size=40 align=8 + base size=40 base align=8 +QTextDecoder (0x0x7f5eba74dba0) 0 + +Class std::__mutex_base + size=40 align=8 + base size=40 base align=8 +std::__mutex_base (0x0x7f5eba74dd80) 0 + +Class std::mutex + size=40 align=8 + base size=40 base align=8 +std::mutex (0x0x7f5eba6fc270) 0 + std::__mutex_base (0x0x7f5eba74dde0) 0 + +Class std::defer_lock_t + size=1 align=1 + base size=0 base align=1 +std::defer_lock_t (0x0x7f5eba7a3000) 0 empty + +Class std::try_to_lock_t + size=1 align=1 + base size=0 base align=1 +std::try_to_lock_t (0x0x7f5eba7a3060) 0 empty + +Class std::adopt_lock_t + size=1 align=1 + base size=0 base align=1 +std::adopt_lock_t (0x0x7f5eba7a30c0) 0 empty + +Class std::__recursive_mutex_base + size=40 align=8 + base size=40 base align=8 +std::__recursive_mutex_base (0x0x7f5eba7a3ae0) 0 + +Class std::recursive_mutex + size=40 align=8 + base size=40 base align=8 +std::recursive_mutex (0x0x7f5eba6fc2d8) 0 + std::__recursive_mutex_base (0x0x7f5eba7a3b40) 0 + +Class std::timed_mutex + size=40 align=8 + base size=40 base align=8 +std::timed_mutex (0x0x7f5eba7c61c0) 0 + std::__mutex_base (0x0x7f5eba7a3f00) 0 + std::__timed_mutex_impl (0x0x7f5eba7a3f60) 0 empty + +Class std::recursive_timed_mutex + size=40 align=8 + base size=40 base align=8 +std::recursive_timed_mutex (0x0x7f5eba7c6540) 0 + std::__recursive_mutex_base (0x0x7f5eba7ee300) 0 + std::__timed_mutex_impl (0x0x7f5eba7ee360) 0 empty + +Class std::once_flag + size=4 align=4 + base size=4 base align=4 +std::once_flag (0x0x7f5eba7eea80) 0 + +Vtable for __gnu_cxx::__concurrence_lock_error +__gnu_cxx::__concurrence_lock_error::_ZTVN9__gnu_cxx24__concurrence_lock_errorE: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx24__concurrence_lock_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_lock_error::~__concurrence_lock_error +24 (int (*)(...))__gnu_cxx::__concurrence_lock_error::~__concurrence_lock_error +32 (int (*)(...))__gnu_cxx::__concurrence_lock_error::what + +Class __gnu_cxx::__concurrence_lock_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_lock_error (0x0x7f5eba6fc410) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_lock_error::_ZTVN9__gnu_cxx24__concurrence_lock_errorE) + 16) + std::exception (0x0x7f5eba425000) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_lock_error (0x0x7f5eba6fc410) + +Vtable for __gnu_cxx::__concurrence_unlock_error +__gnu_cxx::__concurrence_unlock_error::_ZTVN9__gnu_cxx26__concurrence_unlock_errorE: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx26__concurrence_unlock_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::~__concurrence_unlock_error +24 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::~__concurrence_unlock_error +32 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::what + +Class __gnu_cxx::__concurrence_unlock_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_unlock_error (0x0x7f5eba6fc478) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_unlock_error::_ZTVN9__gnu_cxx26__concurrence_unlock_errorE) + 16) + std::exception (0x0x7f5eba425120) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_unlock_error (0x0x7f5eba6fc478) + +Vtable for __gnu_cxx::__concurrence_broadcast_error +__gnu_cxx::__concurrence_broadcast_error::_ZTVN9__gnu_cxx29__concurrence_broadcast_errorE: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx29__concurrence_broadcast_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::~__concurrence_broadcast_error +24 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::~__concurrence_broadcast_error +32 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::what + +Class __gnu_cxx::__concurrence_broadcast_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_broadcast_error (0x0x7f5eba6fc4e0) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_broadcast_error::_ZTVN9__gnu_cxx29__concurrence_broadcast_errorE) + 16) + std::exception (0x0x7f5eba425240) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_broadcast_error (0x0x7f5eba6fc4e0) + +Vtable for __gnu_cxx::__concurrence_wait_error +__gnu_cxx::__concurrence_wait_error::_ZTVN9__gnu_cxx24__concurrence_wait_errorE: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx24__concurrence_wait_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_wait_error::~__concurrence_wait_error +24 (int (*)(...))__gnu_cxx::__concurrence_wait_error::~__concurrence_wait_error +32 (int (*)(...))__gnu_cxx::__concurrence_wait_error::what + +Class __gnu_cxx::__concurrence_wait_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_wait_error (0x0x7f5eba6fc5b0) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_wait_error::_ZTVN9__gnu_cxx24__concurrence_wait_errorE) + 16) + std::exception (0x0x7f5eba425360) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_wait_error (0x0x7f5eba6fc5b0) + +Class __gnu_cxx::__mutex + size=40 align=8 + base size=40 base align=8 +__gnu_cxx::__mutex (0x0x7f5eba4473c0) 0 + +Class __gnu_cxx::__recursive_mutex + size=40 align=8 + base size=40 base align=8 +__gnu_cxx::__recursive_mutex (0x0x7f5eba4476c0) 0 + +Class __gnu_cxx::__scoped_lock + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__scoped_lock (0x0x7f5eba4479c0) 0 + +Class __gnu_cxx::__cond + size=48 align=8 + base size=48 base align=8 +__gnu_cxx::__cond (0x0x7f5eba447d20) 0 + +Vtable for std::bad_weak_ptr +std::bad_weak_ptr::_ZTVSt12bad_weak_ptr: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt12bad_weak_ptr) +16 (int (*)(...))std::bad_weak_ptr::~bad_weak_ptr +24 (int (*)(...))std::bad_weak_ptr::~bad_weak_ptr +32 (int (*)(...))std::bad_weak_ptr::what + +Class std::bad_weak_ptr + size=8 align=8 + base size=8 base align=8 +std::bad_weak_ptr (0x0x7f5eba6fc618) 0 nearly-empty + vptr=((& std::bad_weak_ptr::_ZTVSt12bad_weak_ptr) + 16) + std::exception (0x0x7f5eba4c5f00) 0 nearly-empty + primary-for std::bad_weak_ptr (0x0x7f5eba6fc618) + +Class std::_Sp_make_shared_tag + size=1 align=1 + base size=0 base align=1 +std::_Sp_make_shared_tag (0x0x7f5eba527ea0) 0 empty + +Class std::__sp_array_delete + size=1 align=1 + base size=0 base align=1 +std::__sp_array_delete (0x0x7f5eba55a300) 0 empty + +Class std::_Sp_locker + size=2 align=1 + base size=2 base align=1 +std::_Sp_locker (0x0x7f5eba29c180) 0 + +Vtable for std::thread::_State +std::thread::_State::_ZTVNSt6thread6_StateE: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt6thread6_StateE) +16 0 +24 0 +32 (int (*)(...))__cxa_pure_virtual + +Class std::thread::_State + size=8 align=8 + base size=8 base align=8 +std::thread::_State (0x0x7f5eba2c9600) 0 nearly-empty + vptr=((& std::thread::_State::_ZTVNSt6thread6_StateE) + 16) + +Class std::thread::id + size=8 align=8 + base size=8 base align=8 +std::thread::id (0x0x7f5eba2c9660) 0 + +Class std::thread + size=8 align=8 + base size=8 base align=8 +std::thread (0x0x7f5eba2c95a0) 0 + +Class std::condition_variable + size=48 align=8 + base size=48 base align=8 +std::condition_variable (0x0x7f5eba158a20) 0 + +Class std::__at_thread_exit_elt + size=16 align=8 + base size=16 base align=8 +std::__at_thread_exit_elt (0x0x7f5eba158de0) 0 + +Class std::_V2::condition_variable_any + size=64 align=8 + base size=64 base align=8 +std::_V2::condition_variable_any (0x0x7f5eba158e40) 0 + +Class std::__atomic_futex_unsigned_base + size=1 align=1 + base size=0 base align=1 +std::__atomic_futex_unsigned_base (0x0x7f5eb9f11180) 0 empty + +Vtable for std::future_error +std::future_error::_ZTVSt12future_error: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt12future_error) +16 (int (*)(...))std::future_error::~future_error +24 (int (*)(...))std::future_error::~future_error +32 (int (*)(...))std::future_error::what + +Class std::future_error + size=32 align=8 + base size=32 base align=8 +std::future_error (0x0x7f5eb9ef7ea0) 0 + vptr=((& std::future_error::_ZTVSt12future_error) + 16) + std::logic_error (0x0x7f5eb9ef7f08) 0 + primary-for std::future_error (0x0x7f5eb9ef7ea0) + std::exception (0x0x7f5eb9f118a0) 0 nearly-empty + primary-for std::logic_error (0x0x7f5eb9ef7f08) + +Class std::__future_base::_Result_base::_Deleter + size=1 align=1 + base size=0 base align=1 +std::__future_base::_Result_base::_Deleter (0x0x7f5eb9f45000) 0 empty + +Vtable for std::__future_base::_Result_base +std::__future_base::_Result_base::_ZTVNSt13__future_base12_Result_baseE: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt13__future_base12_Result_baseE) +16 (int (*)(...))__cxa_pure_virtual +24 0 +32 0 + +Class std::__future_base::_Result_base + size=16 align=8 + base size=16 base align=8 +std::__future_base::_Result_base (0x0x7f5eb9f11f60) 0 + vptr=((& std::__future_base::_Result_base::_ZTVNSt13__future_base12_Result_baseE) + 16) + +Class std::__future_base::_State_baseV2::__exception_ptr_tag + size=1 align=1 + base size=0 base align=1 +std::__future_base::_State_baseV2::__exception_ptr_tag (0x0x7f5eb9d1f720) 0 empty + +Class std::__future_base::_State_baseV2::_Make_ready + size=32 align=8 + base size=32 base align=8 +std::__future_base::_State_baseV2::_Make_ready (0x0x7f5eb9d1c750) 0 + std::__at_thread_exit_elt (0x0x7f5eb9d1f7e0) 0 + +Vtable for std::__future_base::_State_baseV2 +std::__future_base::_State_baseV2::_ZTVNSt13__future_base13_State_baseV2E: 6 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt13__future_base13_State_baseV2E) +16 (int (*)(...))std::__future_base::_State_baseV2::~_State_baseV2 +24 (int (*)(...))std::__future_base::_State_baseV2::~_State_baseV2 +32 (int (*)(...))std::__future_base::_State_baseV2::_M_complete_async +40 (int (*)(...))std::__future_base::_State_baseV2::_M_is_deferred_future + +Class std::__future_base::_State_baseV2 + size=32 align=8 + base size=28 base align=8 +std::__future_base::_State_baseV2 (0x0x7f5eb9f45180) 0 + vptr=((& std::__future_base::_State_baseV2::_ZTVNSt13__future_base13_State_baseV2E) + 16) + +Class std::__future_base + size=1 align=1 + base size=0 base align=1 +std::__future_base (0x0x7f5eb9f11f00) 0 empty + +Vtable for std::__future_base::_Async_state_commonV2 +std::__future_base::_Async_state_commonV2::_ZTVNSt13__future_base21_Async_state_commonV2E: 6 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt13__future_base21_Async_state_commonV2E) +16 (int (*)(...))std::__future_base::_Async_state_commonV2::~_Async_state_commonV2 +24 (int (*)(...))std::__future_base::_Async_state_commonV2::~_Async_state_commonV2 +32 (int (*)(...))std::__future_base::_Async_state_commonV2::_M_complete_async +40 (int (*)(...))std::__future_base::_State_baseV2::_M_is_deferred_future + +Class std::__future_base::_Async_state_commonV2 + size=48 align=8 + base size=44 base align=8 +std::__future_base::_Async_state_commonV2 (0x0x7f5eb949f478) 0 + vptr=((& std::__future_base::_Async_state_commonV2::_ZTVNSt13__future_base21_Async_state_commonV2E) + 16) + std::__future_base::_State_baseV2 (0x0x7f5eb94c87e0) 0 + primary-for std::__future_base::_Async_state_commonV2 (0x0x7f5eb949f478) + +Class QThread::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThread::QPrivateSignal (0x0x7f5eb94fe0c0) 0 empty + +Vtable for QThread +QThread::_ZTV7QThread: 15 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 (0x0x7f5eb949f7b8) 0 + vptr=((& QThread::_ZTV7QThread) + 16) + QObject (0x0x7f5eb94fe060) 0 + primary-for QThread (0x0x7f5eb949f7b8) + +Class QThreadPool::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThreadPool::QPrivateSignal (0x0x7f5eb94fe480) 0 empty + +Vtable for QThreadPool +QThreadPool::_ZTV11QThreadPool: 14 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 (0x0x7f5eb949f820) 0 + vptr=((& QThreadPool::_ZTV11QThreadPool) + 16) + QObject (0x0x7f5eb94fe420) 0 + primary-for QThreadPool (0x0x7f5eb949f820) + +Class QThreadStorageData + size=4 align=4 + base size=4 base align=4 +QThreadStorageData (0x0x7f5eb94fe660) 0 + +Class QTimeLine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimeLine::QPrivateSignal (0x0x7f5eb94fed20) 0 empty + +Vtable for QTimeLine +QTimeLine::_ZTV9QTimeLine: 15 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 (0x0x7f5eb949f888) 0 + vptr=((& QTimeLine::_ZTV9QTimeLine) + 16) + QObject (0x0x7f5eb94fecc0) 0 + primary-for QTimeLine (0x0x7f5eb949f888) + +Class QTimer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimer::QPrivateSignal (0x0x7f5eb94fef60) 0 empty + +Vtable for QTimer +QTimer::_ZTV6QTimer: 14 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 (0x0x7f5eb949f8f0) 0 + vptr=((& QTimer::_ZTV6QTimer) + 16) + QObject (0x0x7f5eb94fef00) 0 + primary-for QTimer (0x0x7f5eb949f8f0) + +Class QTimeZone::OffsetData + size=32 align=8 + base size=28 base align=8 +QTimeZone::OffsetData (0x0x7f5eb9584900) 0 + +Class QTimeZone + size=8 align=8 + base size=8 base align=8 +QTimeZone (0x0x7f5eb95848a0) 0 + +Class QTranslator::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTranslator::QPrivateSignal (0x0x7f5eb92279c0) 0 empty + +Vtable for QTranslator +QTranslator::_ZTV11QTranslator: 16 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 (0x0x7f5eb9238000) 0 + vptr=((& QTranslator::_ZTV11QTranslator) + 16) + QObject (0x0x7f5eb9227960) 0 + primary-for QTranslator (0x0x7f5eb9238000) + +Class QTransposeProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTransposeProxyModel::QPrivateSignal (0x0x7f5eb9227c00) 0 empty + +Vtable for QTransposeProxyModel +QTransposeProxyModel::_ZTV20QTransposeProxyModel: 53 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI20QTransposeProxyModel) +16 (int (*)(...))QTransposeProxyModel::metaObject +24 (int (*)(...))QTransposeProxyModel::qt_metacast +32 (int (*)(...))QTransposeProxyModel::qt_metacall +40 (int (*)(...))QTransposeProxyModel::~QTransposeProxyModel +48 (int (*)(...))QTransposeProxyModel::~QTransposeProxyModel +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 (*)(...))QTransposeProxyModel::index +120 (int (*)(...))QTransposeProxyModel::parent +128 (int (*)(...))QAbstractProxyModel::sibling +136 (int (*)(...))QTransposeProxyModel::rowCount +144 (int (*)(...))QTransposeProxyModel::columnCount +152 (int (*)(...))QAbstractProxyModel::hasChildren +160 (int (*)(...))QAbstractProxyModel::data +168 (int (*)(...))QAbstractProxyModel::setData +176 (int (*)(...))QTransposeProxyModel::headerData +184 (int (*)(...))QTransposeProxyModel::setHeaderData +192 (int (*)(...))QTransposeProxyModel::itemData +200 (int (*)(...))QTransposeProxyModel::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 (*)(...))QTransposeProxyModel::insertRows +264 (int (*)(...))QTransposeProxyModel::insertColumns +272 (int (*)(...))QTransposeProxyModel::removeRows +280 (int (*)(...))QTransposeProxyModel::removeColumns +288 (int (*)(...))QTransposeProxyModel::moveRows +296 (int (*)(...))QTransposeProxyModel::moveColumns +304 (int (*)(...))QAbstractProxyModel::fetchMore +312 (int (*)(...))QAbstractProxyModel::canFetchMore +320 (int (*)(...))QAbstractProxyModel::flags +328 (int (*)(...))QTransposeProxyModel::sort +336 (int (*)(...))QAbstractProxyModel::buddy +344 (int (*)(...))QAbstractItemModel::match +352 (int (*)(...))QTransposeProxyModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractProxyModel::submit +376 (int (*)(...))QAbstractProxyModel::revert +384 (int (*)(...))QTransposeProxyModel::setSourceModel +392 (int (*)(...))QTransposeProxyModel::mapToSource +400 (int (*)(...))QTransposeProxyModel::mapFromSource +408 (int (*)(...))QAbstractProxyModel::mapSelectionToSource +416 (int (*)(...))QAbstractProxyModel::mapSelectionFromSource + +Class QTransposeProxyModel + size=16 align=8 + base size=16 base align=8 +QTransposeProxyModel (0x0x7f5eb9238068) 0 + vptr=((& QTransposeProxyModel::_ZTV20QTransposeProxyModel) + 16) + QAbstractProxyModel (0x0x7f5eb92380d0) 0 + primary-for QTransposeProxyModel (0x0x7f5eb9238068) + QAbstractItemModel (0x0x7f5eb9238138) 0 + primary-for QAbstractProxyModel (0x0x7f5eb92380d0) + QObject (0x0x7f5eb9227ba0) 0 + primary-for QAbstractItemModel (0x0x7f5eb9238138) + +Class QUrlQuery + size=8 align=8 + base size=8 base align=8 +QUrlQuery (0x0x7f5eb9227de0) 0 + +Class QWaitCondition + size=8 align=8 + base size=8 base align=8 +QWaitCondition (0x0x7f5eb92cb7e0) 0 + +Class QXmlStreamStringRef + size=16 align=8 + base size=16 base align=8 +QXmlStreamStringRef (0x0x7f5eb92cb900) 0 + +Class QXmlStreamAttribute + size=80 align=8 + base size=73 base align=8 +QXmlStreamAttribute (0x0x7f5eb9359cc0) 0 + +Class QXmlStreamAttributes + size=8 align=8 + base size=8 base align=8 +QXmlStreamAttributes (0x0x7f5eb93d47b8) 0 + QVector (0x0x7f5eb93d7420) 0 + +Class QXmlStreamNamespaceDeclaration + size=40 align=8 + base size=40 base align=8 +QXmlStreamNamespaceDeclaration (0x0x7f5eb93d7720) 0 + +Class QXmlStreamNotationDeclaration + size=56 align=8 + base size=56 base align=8 +QXmlStreamNotationDeclaration (0x0x7f5eb8fdd6c0) 0 + +Class QXmlStreamEntityDeclaration + size=88 align=8 + base size=88 base align=8 +QXmlStreamEntityDeclaration (0x0x7f5eb903a6c0) 0 + +Vtable for QXmlStreamEntityResolver +QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver: 6 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 (0x0x7f5eb90a3780) 0 nearly-empty + vptr=((& QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver) + 16) + +Class QXmlStreamReader + size=8 align=8 + base size=8 base align=8 +QXmlStreamReader (0x0x7f5eb90a37e0) 0 + +Class QXmlStreamWriter + size=8 align=8 + base size=8 base align=8 +QXmlStreamWriter (0x0x7f5eb90fa6c0) 0 + +Class QBluetoothAddress + size=8 align=8 + base size=8 base align=8 +QBluetoothAddress (0x0x7f5eb914e660) 0 + +Class QBluetoothDeviceInfo + size=8 align=8 + base size=8 base align=8 +QBluetoothDeviceInfo (0x0x7f5eb914e9c0) 0 + +Class QBluetoothDeviceDiscoveryAgent::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothDeviceDiscoveryAgent::QPrivateSignal (0x0x7f5eb8dccae0) 0 empty + +Vtable for QBluetoothDeviceDiscoveryAgent +QBluetoothDeviceDiscoveryAgent::_ZTV30QBluetoothDeviceDiscoveryAgent: 14 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI30QBluetoothDeviceDiscoveryAgent) +16 (int (*)(...))QBluetoothDeviceDiscoveryAgent::metaObject +24 (int (*)(...))QBluetoothDeviceDiscoveryAgent::qt_metacast +32 (int (*)(...))QBluetoothDeviceDiscoveryAgent::qt_metacall +40 (int (*)(...))QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent +48 (int (*)(...))QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent +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 QBluetoothDeviceDiscoveryAgent + size=24 align=8 + base size=24 base align=8 +QBluetoothDeviceDiscoveryAgent (0x0x7f5eb91037b8) 0 + vptr=((& QBluetoothDeviceDiscoveryAgent::_ZTV30QBluetoothDeviceDiscoveryAgent) + 16) + QObject (0x0x7f5eb8dcca80) 0 + primary-for QBluetoothDeviceDiscoveryAgent (0x0x7f5eb91037b8) + +Class QBluetoothHostInfo + size=8 align=8 + base size=8 base align=8 +QBluetoothHostInfo (0x0x7f5eb8e2b600) 0 + +Class QBluetoothLocalDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothLocalDevice::QPrivateSignal (0x0x7f5eb8e2b960) 0 empty + +Vtable for QBluetoothLocalDevice +QBluetoothLocalDevice::_ZTV21QBluetoothLocalDevice: 14 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QBluetoothLocalDevice) +16 (int (*)(...))QBluetoothLocalDevice::metaObject +24 (int (*)(...))QBluetoothLocalDevice::qt_metacast +32 (int (*)(...))QBluetoothLocalDevice::qt_metacall +40 (int (*)(...))QBluetoothLocalDevice::~QBluetoothLocalDevice +48 (int (*)(...))QBluetoothLocalDevice::~QBluetoothLocalDevice +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 QBluetoothLocalDevice + size=24 align=8 + base size=24 base align=8 +QBluetoothLocalDevice (0x0x7f5eb91038f0) 0 + vptr=((& QBluetoothLocalDevice::_ZTV21QBluetoothLocalDevice) + 16) + QObject (0x0x7f5eb8e2b900) 0 + primary-for QBluetoothLocalDevice (0x0x7f5eb91038f0) + +Class quint128 + size=16 align=1 + base size=16 base align=1 +quint128 (0x0x7f5eb8e73360) 0 + +Class QBluetoothUuid + size=16 align=4 + base size=16 base align=4 +QBluetoothUuid (0x0x7f5eb9103958) 0 + QUuid (0x0x7f5eb8e733c0) 0 + +Class QBluetoothServiceInfo::Sequence + size=8 align=8 + base size=8 base align=8 +QBluetoothServiceInfo::Sequence (0x0x7f5eb91039c0) 0 + QList (0x0x7f5eb9103a28) 0 + QListSpecialMethods (0x0x7f5eb8e738a0) 0 empty + +Class QBluetoothServiceInfo::Alternative + size=8 align=8 + base size=8 base align=8 +QBluetoothServiceInfo::Alternative (0x0x7f5eb9103a90) 0 + QList (0x0x7f5eb9103af8) 0 + QListSpecialMethods (0x0x7f5eb8e73900) 0 empty + +Class QBluetoothServiceInfo + size=16 align=8 + base size=16 base align=8 +QBluetoothServiceInfo (0x0x7f5eb8e73840) 0 + +Class QAbstractSocket::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractSocket::QPrivateSignal (0x0x7f5eb8ef0ae0) 0 empty + +Vtable for QAbstractSocket +QAbstractSocket::_ZTV15QAbstractSocket: 41 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QAbstractSocket) +16 (int (*)(...))QAbstractSocket::metaObject +24 (int (*)(...))QAbstractSocket::qt_metacast +32 (int (*)(...))QAbstractSocket::qt_metacall +40 (int (*)(...))QAbstractSocket::~QAbstractSocket +48 (int (*)(...))QAbstractSocket::~QAbstractSocket +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 (*)(...))QAbstractSocket::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QAbstractSocket::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QAbstractSocket::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QAbstractSocket::bytesAvailable +184 (int (*)(...))QAbstractSocket::bytesToWrite +192 (int (*)(...))QAbstractSocket::canReadLine +200 (int (*)(...))QAbstractSocket::waitForReadyRead +208 (int (*)(...))QAbstractSocket::waitForBytesWritten +216 (int (*)(...))QAbstractSocket::readData +224 (int (*)(...))QAbstractSocket::readLineData +232 (int (*)(...))QAbstractSocket::writeData +240 (int (*)(...))QAbstractSocket::resume +248 (int (*)(...))QAbstractSocket::connectToHost +256 (int (*)(...))QAbstractSocket::connectToHost +264 (int (*)(...))QAbstractSocket::disconnectFromHost +272 (int (*)(...))QAbstractSocket::setReadBufferSize +280 (int (*)(...))QAbstractSocket::socketDescriptor +288 (int (*)(...))QAbstractSocket::setSocketDescriptor +296 (int (*)(...))QAbstractSocket::setSocketOption +304 (int (*)(...))QAbstractSocket::socketOption +312 (int (*)(...))QAbstractSocket::waitForConnected +320 (int (*)(...))QAbstractSocket::waitForDisconnected + +Class QAbstractSocket + size=16 align=8 + base size=16 base align=8 +QAbstractSocket (0x0x7f5eb9103b60) 0 + vptr=((& QAbstractSocket::_ZTV15QAbstractSocket) + 16) + QIODevice (0x0x7f5eb9103bc8) 0 + primary-for QAbstractSocket (0x0x7f5eb9103b60) + QObject (0x0x7f5eb8ef0a80) 0 + primary-for QIODevice (0x0x7f5eb9103bc8) + +Class QBluetoothSocket::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothSocket::QPrivateSignal (0x0x7f5eb8aaa2a0) 0 empty + +Vtable for QBluetoothSocket +QBluetoothSocket::_ZTV16QBluetoothSocket: 30 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QBluetoothSocket) +16 (int (*)(...))QBluetoothSocket::metaObject +24 (int (*)(...))QBluetoothSocket::qt_metacast +32 (int (*)(...))QBluetoothSocket::qt_metacall +40 (int (*)(...))QBluetoothSocket::~QBluetoothSocket +48 (int (*)(...))QBluetoothSocket::~QBluetoothSocket +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 (*)(...))QBluetoothSocket::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QBluetoothSocket::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QIODevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QBluetoothSocket::bytesAvailable +184 (int (*)(...))QBluetoothSocket::bytesToWrite +192 (int (*)(...))QBluetoothSocket::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QBluetoothSocket::readData +224 (int (*)(...))QIODevice::readLineData +232 (int (*)(...))QBluetoothSocket::writeData + +Class QBluetoothSocket + size=24 align=8 + base size=24 base align=8 +QBluetoothSocket (0x0x7f5eb9103dd0) 0 + vptr=((& QBluetoothSocket::_ZTV16QBluetoothSocket) + 16) + QIODevice (0x0x7f5eb9103e38) 0 + primary-for QBluetoothSocket (0x0x7f5eb9103dd0) + QObject (0x0x7f5eb8aaa240) 0 + primary-for QIODevice (0x0x7f5eb9103e38) + +Class QBluetoothServer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothServer::QPrivateSignal (0x0x7f5eb8aaa6c0) 0 empty + +Vtable for QBluetoothServer +QBluetoothServer::_ZTV16QBluetoothServer: 14 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QBluetoothServer) +16 (int (*)(...))QBluetoothServer::metaObject +24 (int (*)(...))QBluetoothServer::qt_metacast +32 (int (*)(...))QBluetoothServer::qt_metacall +40 (int (*)(...))QBluetoothServer::~QBluetoothServer +48 (int (*)(...))QBluetoothServer::~QBluetoothServer +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 QBluetoothServer + size=24 align=8 + base size=24 base align=8 +QBluetoothServer (0x0x7f5eb9103ea0) 0 + vptr=((& QBluetoothServer::_ZTV16QBluetoothServer) + 16) + QObject (0x0x7f5eb8aaa660) 0 + primary-for QBluetoothServer (0x0x7f5eb9103ea0) + +Class QBluetoothServiceDiscoveryAgent::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothServiceDiscoveryAgent::QPrivateSignal (0x0x7f5eb8aaa9c0) 0 empty + +Vtable for QBluetoothServiceDiscoveryAgent +QBluetoothServiceDiscoveryAgent::_ZTV31QBluetoothServiceDiscoveryAgent: 14 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI31QBluetoothServiceDiscoveryAgent) +16 (int (*)(...))QBluetoothServiceDiscoveryAgent::metaObject +24 (int (*)(...))QBluetoothServiceDiscoveryAgent::qt_metacast +32 (int (*)(...))QBluetoothServiceDiscoveryAgent::qt_metacall +40 (int (*)(...))QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent +48 (int (*)(...))QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent +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 QBluetoothServiceDiscoveryAgent + size=24 align=8 + base size=24 base align=8 +QBluetoothServiceDiscoveryAgent (0x0x7f5eb9103f08) 0 + vptr=((& QBluetoothServiceDiscoveryAgent::_ZTV31QBluetoothServiceDiscoveryAgent) + 16) + QObject (0x0x7f5eb8aaa960) 0 + primary-for QBluetoothServiceDiscoveryAgent (0x0x7f5eb9103f08) + +Class QBluetoothTransferManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothTransferManager::QPrivateSignal (0x0x7f5eb8aaad80) 0 empty + +Vtable for QBluetoothTransferManager +QBluetoothTransferManager::_ZTV25QBluetoothTransferManager: 14 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI25QBluetoothTransferManager) +16 (int (*)(...))QBluetoothTransferManager::metaObject +24 (int (*)(...))QBluetoothTransferManager::qt_metacast +32 (int (*)(...))QBluetoothTransferManager::qt_metacall +40 (int (*)(...))QBluetoothTransferManager::~QBluetoothTransferManager +48 (int (*)(...))QBluetoothTransferManager::~QBluetoothTransferManager +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 QBluetoothTransferManager + size=16 align=8 + base size=16 base align=8 +QBluetoothTransferManager (0x0x7f5eb9103f70) 0 + vptr=((& QBluetoothTransferManager::_ZTV25QBluetoothTransferManager) + 16) + QObject (0x0x7f5eb8aaad20) 0 + primary-for QBluetoothTransferManager (0x0x7f5eb9103f70) + +Class QBluetoothTransferRequest + size=8 align=8 + base size=8 base align=8 +QBluetoothTransferRequest (0x0x7f5eb8aaaea0) 0 + +Class QBluetoothTransferReply::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothTransferReply::QPrivateSignal (0x0x7f5eb8b16060) 0 empty + +Vtable for QBluetoothTransferReply +QBluetoothTransferReply::_ZTV23QBluetoothTransferReply: 18 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI23QBluetoothTransferReply) +16 (int (*)(...))QBluetoothTransferReply::metaObject +24 (int (*)(...))QBluetoothTransferReply::qt_metacast +32 (int (*)(...))QBluetoothTransferReply::qt_metacall +40 0 +48 0 +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 + +Class QBluetoothTransferReply + size=24 align=8 + base size=24 base align=8 +QBluetoothTransferReply (0x0x7f5eb8b15000) 0 + vptr=((& QBluetoothTransferReply::_ZTV23QBluetoothTransferReply) + 16) + QObject (0x0x7f5eb8b16000) 0 + primary-for QBluetoothTransferReply (0x0x7f5eb8b15000) + +Class QLowEnergyAdvertisingData + size=8 align=8 + base size=8 base align=8 +QLowEnergyAdvertisingData (0x0x7f5eb8b164e0) 0 + +Class QLowEnergyDescriptor + size=24 align=8 + base size=24 base align=8 +QLowEnergyDescriptor (0x0x7f5eb8b79660) 0 + +Class QLowEnergyCharacteristic + size=24 align=8 + base size=24 base align=8 +QLowEnergyCharacteristic (0x0x7f5eb8b79900) 0 + +Class QLowEnergyService::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLowEnergyService::QPrivateSignal (0x0x7f5eb8bef2a0) 0 empty + +Vtable for QLowEnergyService +QLowEnergyService::_ZTV17QLowEnergyService: 14 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QLowEnergyService) +16 (int (*)(...))QLowEnergyService::metaObject +24 (int (*)(...))QLowEnergyService::qt_metacast +32 (int (*)(...))QLowEnergyService::qt_metacall +40 (int (*)(...))QLowEnergyService::~QLowEnergyService +48 (int (*)(...))QLowEnergyService::~QLowEnergyService +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 QLowEnergyService + size=32 align=8 + base size=32 base align=8 +QLowEnergyService (0x0x7f5eb8b7a958) 0 + vptr=((& QLowEnergyService::_ZTV17QLowEnergyService) + 16) + QObject (0x0x7f5eb8bef240) 0 + primary-for QLowEnergyService (0x0x7f5eb8b7a958) + +Class QLowEnergyController::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLowEnergyController::QPrivateSignal (0x0x7f5eb8c43660) 0 empty + +Vtable for QLowEnergyController +QLowEnergyController::_ZTV20QLowEnergyController: 14 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI20QLowEnergyController) +16 (int (*)(...))QLowEnergyController::metaObject +24 (int (*)(...))QLowEnergyController::qt_metacast +32 (int (*)(...))QLowEnergyController::qt_metacall +40 (int (*)(...))QLowEnergyController::~QLowEnergyController +48 (int (*)(...))QLowEnergyController::~QLowEnergyController +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 QLowEnergyController + size=24 align=8 + base size=24 base align=8 +QLowEnergyController (0x0x7f5eb8b7aa90) 0 + vptr=((& QLowEnergyController::_ZTV20QLowEnergyController) + 16) + QObject (0x0x7f5eb8c43600) 0 + primary-for QLowEnergyController (0x0x7f5eb8b7aa90) + +Class QLowEnergyAdvertisingParameters::AddressInfo + size=16 align=8 + base size=12 base align=8 +QLowEnergyAdvertisingParameters::AddressInfo (0x0x7f5eb888c360) 0 + +Class QLowEnergyAdvertisingParameters + size=8 align=8 + base size=8 base align=8 +QLowEnergyAdvertisingParameters (0x0x7f5eb888c300) 0 + +Class QLowEnergyCharacteristicData + size=8 align=8 + base size=8 base align=8 +QLowEnergyCharacteristicData (0x0x7f5eb8915120) 0 + +Class QLowEnergyConnectionParameters + size=8 align=8 + base size=8 base align=8 +QLowEnergyConnectionParameters (0x0x7f5eb8971240) 0 + +Class QLowEnergyDescriptorData + size=8 align=8 + base size=8 base align=8 +QLowEnergyDescriptorData (0x0x7f5eb89ca540) 0 + +Class QLowEnergyServiceData + size=8 align=8 + base size=8 base align=8 +QLowEnergyServiceData (0x0x7f5eb8a26840) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb86cd000) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb86cd360) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb86cd540) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb86cd8a0) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb86cda80) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb86cdde0) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb8709000) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb8709360) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb8709540) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb87098a0) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb8709a80) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb8709de0) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb8742000) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb8742360) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb8742540) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb87428a0) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb8770d80) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb87a2120) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb87a22a0) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb87a2600) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb87a2780) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb87a2ae0) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb87a2c60) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb87d3000) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb87d3180) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb87d34e0) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb87d3660) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb87d39c0) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb87d3b40) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb87d3ea0) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7f5eb8801060) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7f5eb88013c0) 0 empty + diff --git a/tests/auto/bic/data/QtBluetooth.5.14.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtBluetooth.5.14.0.linux-gcc-amd64.txt new file mode 100644 index 0000000..d69a6b7 --- /dev/null +++ b/tests/auto/bic/data/QtBluetooth.5.14.0.linux-gcc-amd64.txt @@ -0,0 +1,5462 @@ +Class std::__failure_type + size=1 align=1 + base size=0 base align=1 +std::__failure_type (0x0x7faa71123720) 0 empty + +Class std::__do_is_destructible_impl + size=1 align=1 + base size=0 base align=1 +std::__do_is_destructible_impl (0x0x7faa7117eea0) 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 (0x0x7faa711a7120) 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 (0x0x7faa711a7360) 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 (0x0x7faa711a75a0) 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 (0x0x7faa711a7720) 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 (0x0x7faa711a7ae0) 0 empty + +Class std::__do_is_implicitly_default_constructible_impl + size=1 align=1 + base size=0 base align=1 +std::__do_is_implicitly_default_constructible_impl (0x0x7faa711e1c00) 0 empty + +Class std::__do_common_type_impl + size=1 align=1 + base size=0 base align=1 +std::__do_common_type_impl (0x0x7faa71268300) 0 empty + +Class std::__do_member_type_wrapper + size=1 align=1 + base size=0 base align=1 +std::__do_member_type_wrapper (0x0x7faa712683c0) 0 empty + +Class std::__invoke_memfun_ref + size=1 align=1 + base size=0 base align=1 +std::__invoke_memfun_ref (0x0x7faa71268780) 0 empty + +Class std::__invoke_memfun_deref + size=1 align=1 + base size=0 base align=1 +std::__invoke_memfun_deref (0x0x7faa712687e0) 0 empty + +Class std::__invoke_memobj_ref + size=1 align=1 + base size=0 base align=1 +std::__invoke_memobj_ref (0x0x7faa71268840) 0 empty + +Class std::__invoke_memobj_deref + size=1 align=1 + base size=0 base align=1 +std::__invoke_memobj_deref (0x0x7faa712688a0) 0 empty + +Class std::__invoke_other + size=1 align=1 + base size=0 base align=1 +std::__invoke_other (0x0x7faa71268900) 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 (0x0x7faa712689c0) 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 (0x0x7faa71268a80) 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 (0x0x7faa71268b40) 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 (0x0x7faa71268c00) 0 empty + +Class std::__result_of_other_impl + size=1 align=1 + base size=0 base align=1 +std::__result_of_other_impl (0x0x7faa71268f60) 0 empty + +Class std::__swappable_details::__do_is_swappable_impl + size=1 align=1 + base size=0 base align=1 +std::__swappable_details::__do_is_swappable_impl (0x0x7faa70ea2300) 0 empty + +Class std::__swappable_details::__do_is_nothrow_swappable_impl + size=1 align=1 + base size=0 base align=1 +std::__swappable_details::__do_is_nothrow_swappable_impl (0x0x7faa70ea2360) 0 empty + +Class std::__nonesuch + size=1 align=1 + base size=0 base align=1 +std::__nonesuch (0x0x7faa70ea2900) 0 empty + +Class std::piecewise_construct_t + size=1 align=1 + base size=0 base align=1 +std::piecewise_construct_t (0x0x7faa70ea2f60) 0 empty + +Class std::__nonesuch_no_braces + size=1 align=1 + base size=1 base align=1 +std::__nonesuch_no_braces (0x0x7faa70ea5618) 0 empty + std::__nonesuch (0x0x7faa70ee7480) 0 empty + +Class std::__true_type + size=1 align=1 + base size=0 base align=1 +std::__true_type (0x0x7faa70f36de0) 0 empty + +Class std::__false_type + size=1 align=1 + base size=0 base align=1 +std::__false_type (0x0x7faa70f36e40) 0 empty + +Class std::input_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::input_iterator_tag (0x0x7faa70f96b40) 0 empty + +Class std::output_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::output_iterator_tag (0x0x7faa70f96ba0) 0 empty + +Class std::forward_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::forward_iterator_tag (0x0x7faa70ea5af8) 0 empty + std::input_iterator_tag (0x0x7faa70f96c00) 0 empty + +Class std::bidirectional_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::bidirectional_iterator_tag (0x0x7faa70ea5b60) 0 empty + std::forward_iterator_tag (0x0x7faa70ea5bc8) 0 empty + std::input_iterator_tag (0x0x7faa70f96c60) 0 empty + +Class std::random_access_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::random_access_iterator_tag (0x0x7faa70ea5c30) 0 empty + std::bidirectional_iterator_tag (0x0x7faa70ea5c98) 0 empty + std::forward_iterator_tag (0x0x7faa70ea5d00) 0 empty + std::input_iterator_tag (0x0x7faa70f96cc0) 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 (0x0x7faa710467e0) 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 (0x0x7faa71046900) 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 (0x0x7faa71046c00) 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 (0x0x7faa71046f00) 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 (0x0x7faa71077060) 0 empty + +Class __locale_struct + size=232 align=8 + base size=232 base align=8 +__locale_struct (0x0x7faa70d01360) 0 + +Class timeval + size=16 align=8 + base size=16 base align=8 +timeval (0x0x7faa70d01660) 0 + +Class timespec + size=16 align=8 + base size=16 base align=8 +timespec (0x0x7faa70d016c0) 0 + +Class __pthread_rwlock_arch_t + size=56 align=8 + base size=56 base align=8 +__pthread_rwlock_arch_t (0x0x7faa70d01780) 0 + +Class __pthread_internal_list + size=16 align=8 + base size=16 base align=8 +__pthread_internal_list (0x0x7faa70d017e0) 0 + +Class __pthread_mutex_s + size=40 align=8 + base size=40 base align=8 +__pthread_mutex_s (0x0x7faa70d01840) 0 + +Class __pthread_cond_s + size=48 align=8 + base size=48 base align=8 +__pthread_cond_s (0x0x7faa70d018a0) 0 + +Class pthread_attr_t + size=56 align=8 + base size=56 base align=8 +pthread_attr_t (0x0x7faa70d01b40) 0 + +Class random_data + size=48 align=8 + base size=48 base align=8 +random_data (0x0x7faa70d01de0) 0 + +Class drand48_data + size=24 align=8 + base size=24 base align=8 +drand48_data (0x0x7faa70d01e40) 0 + +Vtable for std::exception +std::exception::_ZTVSt9exception: 5 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 (0x0x7faa70d5cc00) 0 nearly-empty + vptr=((& std::exception::_ZTVSt9exception) + 16) + +Vtable for std::bad_exception +std::bad_exception::_ZTVSt13bad_exception: 5 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 (0x0x7faa71012068) 0 nearly-empty + vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16) + std::exception (0x0x7faa70d5cde0) 0 nearly-empty + primary-for std::bad_exception (0x0x7faa71012068) + +Vtable for std::type_info +std::type_info::_ZTVSt9type_info: 8 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 (0x0x7faa70dfd000) 0 + vptr=((& std::type_info::_ZTVSt9type_info) + 16) + +Vtable for std::bad_cast +std::bad_cast::_ZTVSt8bad_cast: 5 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 (0x0x7faa710120d0) 0 nearly-empty + vptr=((& std::bad_cast::_ZTVSt8bad_cast) + 16) + std::exception (0x0x7faa70dfd3c0) 0 nearly-empty + primary-for std::bad_cast (0x0x7faa710120d0) + +Vtable for std::bad_typeid +std::bad_typeid::_ZTVSt10bad_typeid: 5 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 (0x0x7faa71012138) 0 nearly-empty + vptr=((& std::bad_typeid::_ZTVSt10bad_typeid) + 16) + std::exception (0x0x7faa70dfd5a0) 0 nearly-empty + primary-for std::bad_typeid (0x0x7faa71012138) + +Class std::__exception_ptr::exception_ptr + size=8 align=8 + base size=8 base align=8 +std::__exception_ptr::exception_ptr (0x0x7faa70dfd780) 0 + +Vtable for std::nested_exception +std::nested_exception::_ZTVSt16nested_exception: 4 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 (0x0x7faa70dfdd20) 0 + vptr=((& std::nested_exception::_ZTVSt16nested_exception) + 16) + +Vtable for std::bad_alloc +std::bad_alloc::_ZTVSt9bad_alloc: 5 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 (0x0x7faa710121a0) 0 nearly-empty + vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16) + std::exception (0x0x7faa70e34420) 0 nearly-empty + primary-for std::bad_alloc (0x0x7faa710121a0) + +Vtable for std::bad_array_new_length +std::bad_array_new_length::_ZTVSt20bad_array_new_length: 5 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 (0x0x7faa71012208) 0 nearly-empty + vptr=((& std::bad_array_new_length::_ZTVSt20bad_array_new_length) + 16) + std::bad_alloc (0x0x7faa71012270) 0 nearly-empty + primary-for std::bad_array_new_length (0x0x7faa71012208) + std::exception (0x0x7faa70e34600) 0 nearly-empty + primary-for std::bad_alloc (0x0x7faa71012270) + +Class std::nothrow_t + size=1 align=1 + base size=0 base align=1 +std::nothrow_t (0x0x7faa70e347e0) 0 empty + +Class std::__allocator_traits_base + size=1 align=1 + base size=0 base align=1 +std::__allocator_traits_base (0x0x7faa70e349c0) 0 empty + +Class std::__numeric_limits_base + size=1 align=1 + base size=0 base align=1 +std::__numeric_limits_base (0x0x7faa70aafea0) 0 empty + +Class QSysInfo + size=1 align=1 + base size=0 base align=1 +QSysInfo (0x0x7faa70746420) 0 empty + +Class QMessageLogContext + size=32 align=8 + base size=32 base align=8 +QMessageLogContext (0x0x7faa70746540) 0 + +Class QMessageLogger + size=32 align=8 + base size=32 base align=8 +QMessageLogger (0x0x7faa70746720) 0 + +Class QFlag + size=4 align=4 + base size=4 base align=4 +QFlag (0x0x7faa70746de0) 0 + +Class QIncompatibleFlag + size=4 align=4 + base size=4 base align=4 +QIncompatibleFlag (0x0x7faa707c35a0) 0 + +Class std::__atomic_flag_base + size=1 align=1 + base size=1 base align=1 +std::__atomic_flag_base (0x0x7faa7085aa80) 0 + +Class std::atomic_flag + size=1 align=1 + base size=1 base align=1 +std::atomic_flag (0x0x7faa7080b0d0) 0 + std::__atomic_flag_base (0x0x7faa7085aae0) 0 + +Class QAtomicInt + size=4 align=4 + base size=4 base align=4 +QAtomicInt (0x0x7faa7080b820) 0 + QAtomicInteger (0x0x7faa7080b888) 0 + QBasicAtomicInteger (0x0x7faa70393d20) 0 + +Class QInternal + size=1 align=1 + base size=0 base align=1 +QInternal (0x0x7faa6ffe78a0) 0 empty + +Class QtPrivate::QSlotObjectBase + size=16 align=8 + base size=16 base align=8 +QtPrivate::QSlotObjectBase (0x0x7faa70015e40) 0 + +Class QGenericArgument + size=16 align=8 + base size=16 base align=8 +QGenericArgument (0x0x7faa700635a0) 0 + +Class QGenericReturnArgument + size=16 align=8 + base size=16 base align=8 +QGenericReturnArgument (0x0x7faa700174e0) 0 + QGenericArgument (0x0x7faa70063840) 0 + +Class QMetaObject::SuperData + size=8 align=8 + base size=8 base align=8 +QMetaObject::SuperData (0x0x7faa70063cc0) 0 + +Class QMetaObject + size=48 align=8 + base size=48 base align=8 +QMetaObject (0x0x7faa70063c60) 0 + +Class QMetaObject::Connection + size=8 align=8 + base size=8 base align=8 +QMetaObject::Connection (0x0x7faa6fcb75a0) 0 + +Class QLatin1Char + size=1 align=1 + base size=1 base align=1 +QLatin1Char (0x0x7faa6fd380c0) 0 + +Class QChar + size=2 align=2 + base size=2 base align=2 +QChar (0x0x7faa6fd387e0) 0 + +Class QtPrivate::RefCount + size=4 align=4 + base size=4 base align=4 +QtPrivate::RefCount (0x0x7faa6fe08600) 0 + +Class QArrayData + size=24 align=8 + base size=24 base align=8 +QArrayData (0x0x7faa6fe08960) 0 + +Class QtPrivate::QContainerImplHelper + size=1 align=1 + base size=0 base align=1 +QtPrivate::QContainerImplHelper (0x0x7faa6fe66c60) 0 empty + +Class lconv + size=96 align=8 + base size=96 base align=8 +lconv (0x0x7faa6fb5c4e0) 0 + +Vtable for __cxxabiv1::__forced_unwind +__cxxabiv1::__forced_unwind::_ZTVN10__cxxabiv115__forced_unwindE: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN10__cxxabiv115__forced_unwindE) +16 0 +24 0 +32 (int (*)(...))__cxa_pure_virtual + +Class __cxxabiv1::__forced_unwind + size=8 align=8 + base size=8 base align=8 +__cxxabiv1::__forced_unwind (0x0x7faa6fb5c5a0) 0 nearly-empty + vptr=((& __cxxabiv1::__forced_unwind::_ZTVN10__cxxabiv115__forced_unwindE) + 16) + +Class sched_param + size=4 align=4 + base size=4 base align=4 +sched_param (0x0x7faa6fc116c0) 0 + +Class timex + size=208 align=8 + base size=208 base align=8 +timex (0x0x7faa6fc11780) 0 + +Class tm + size=56 align=8 + base size=56 base align=8 +tm (0x0x7faa6fc117e0) 0 + +Class itimerspec + size=32 align=8 + base size=32 base align=8 +itimerspec (0x0x7faa6fc11840) 0 + +Class _pthread_cleanup_buffer + size=32 align=8 + base size=32 base align=8 +_pthread_cleanup_buffer (0x0x7faa6fc118a0) 0 + +Class __pthread_cleanup_frame + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_frame (0x0x7faa6fc119c0) 0 + +Class __pthread_cleanup_class + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_class (0x0x7faa6fc11a20) 0 + +Class _IO_marker + size=24 align=8 + base size=24 base align=8 +_IO_marker (0x0x7faa6f9519c0) 0 + +Class _IO_FILE + size=216 align=8 + base size=216 base align=8 +_IO_FILE (0x0x7faa6f951a20) 0 + +Class std::_Hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Hash_impl (0x0x7faa6f70ea80) 0 empty + +Class std::_Fnv_hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Fnv_hash_impl (0x0x7faa6f70ec00) 0 empty + +Class std::locale + size=8 align=8 + base size=8 base align=8 +std::locale (0x0x7faa6f880d80) 0 + +Vtable for std::locale::facet +std::locale::facet::_ZTVNSt6locale5facetE: 4 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 (0x0x7faa6f4d0180) 0 + vptr=((& std::locale::facet::_ZTVNSt6locale5facetE) + 16) + +Class std::locale::id + size=8 align=8 + base size=8 base align=8 +std::locale::id (0x0x7faa6f4d0420) 0 + +Class std::locale::_Impl + size=40 align=8 + base size=40 base align=8 +std::locale::_Impl (0x0x7faa6f4d0600) 0 + +Class std::__cow_string + size=8 align=8 + base size=8 base align=8 +std::__cow_string (0x0x7faa6f519600) 0 + +Vtable for std::logic_error +std::logic_error::_ZTVSt11logic_error: 5 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 (0x0x7faa6f4f2478) 0 + vptr=((& std::logic_error::_ZTVSt11logic_error) + 16) + std::exception (0x0x7faa6f5196c0) 0 nearly-empty + primary-for std::logic_error (0x0x7faa6f4f2478) + +Vtable for std::domain_error +std::domain_error::_ZTVSt12domain_error: 5 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 (0x0x7faa6f4f24e0) 0 + vptr=((& std::domain_error::_ZTVSt12domain_error) + 16) + std::logic_error (0x0x7faa6f4f2548) 0 + primary-for std::domain_error (0x0x7faa6f4f24e0) + std::exception (0x0x7faa6f519720) 0 nearly-empty + primary-for std::logic_error (0x0x7faa6f4f2548) + +Vtable for std::invalid_argument +std::invalid_argument::_ZTVSt16invalid_argument: 5 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 (0x0x7faa6f4f25b0) 0 + vptr=((& std::invalid_argument::_ZTVSt16invalid_argument) + 16) + std::logic_error (0x0x7faa6f4f2618) 0 + primary-for std::invalid_argument (0x0x7faa6f4f25b0) + std::exception (0x0x7faa6f519780) 0 nearly-empty + primary-for std::logic_error (0x0x7faa6f4f2618) + +Vtable for std::length_error +std::length_error::_ZTVSt12length_error: 5 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 (0x0x7faa6f4f2680) 0 + vptr=((& std::length_error::_ZTVSt12length_error) + 16) + std::logic_error (0x0x7faa6f4f26e8) 0 + primary-for std::length_error (0x0x7faa6f4f2680) + std::exception (0x0x7faa6f5197e0) 0 nearly-empty + primary-for std::logic_error (0x0x7faa6f4f26e8) + +Vtable for std::out_of_range +std::out_of_range::_ZTVSt12out_of_range: 5 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 (0x0x7faa6f4f2750) 0 + vptr=((& std::out_of_range::_ZTVSt12out_of_range) + 16) + std::logic_error (0x0x7faa6f4f27b8) 0 + primary-for std::out_of_range (0x0x7faa6f4f2750) + std::exception (0x0x7faa6f519840) 0 nearly-empty + primary-for std::logic_error (0x0x7faa6f4f27b8) + +Vtable for std::runtime_error +std::runtime_error::_ZTVSt13runtime_error: 5 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 (0x0x7faa6f4f2820) 0 + vptr=((& std::runtime_error::_ZTVSt13runtime_error) + 16) + std::exception (0x0x7faa6f5198a0) 0 nearly-empty + primary-for std::runtime_error (0x0x7faa6f4f2820) + +Vtable for std::range_error +std::range_error::_ZTVSt11range_error: 5 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 (0x0x7faa6f4f2888) 0 + vptr=((& std::range_error::_ZTVSt11range_error) + 16) + std::runtime_error (0x0x7faa6f4f28f0) 0 + primary-for std::range_error (0x0x7faa6f4f2888) + std::exception (0x0x7faa6f519900) 0 nearly-empty + primary-for std::runtime_error (0x0x7faa6f4f28f0) + +Vtable for std::overflow_error +std::overflow_error::_ZTVSt14overflow_error: 5 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 (0x0x7faa6f4f2958) 0 + vptr=((& std::overflow_error::_ZTVSt14overflow_error) + 16) + std::runtime_error (0x0x7faa6f4f29c0) 0 + primary-for std::overflow_error (0x0x7faa6f4f2958) + std::exception (0x0x7faa6f519960) 0 nearly-empty + primary-for std::runtime_error (0x0x7faa6f4f29c0) + +Vtable for std::underflow_error +std::underflow_error::_ZTVSt15underflow_error: 5 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 (0x0x7faa6f4f2a28) 0 + vptr=((& std::underflow_error::_ZTVSt15underflow_error) + 16) + std::runtime_error (0x0x7faa6f4f2a90) 0 + primary-for std::underflow_error (0x0x7faa6f4f2a28) + std::exception (0x0x7faa6f5199c0) 0 nearly-empty + primary-for std::runtime_error (0x0x7faa6f4f2a90) + +Vtable for std::_V2::error_category +std::_V2::error_category::_ZTVNSt3_V214error_categoryE: 10 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt3_V214error_categoryE) +16 0 +24 0 +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 (0x0x7faa6f519b40) 0 nearly-empty + vptr=((& std::_V2::error_category::_ZTVNSt3_V214error_categoryE) + 16) + +Class std::error_code + size=16 align=8 + base size=16 base align=8 +std::error_code (0x0x7faa6f519ea0) 0 + +Class std::error_condition + size=16 align=8 + base size=16 base align=8 +std::error_condition (0x0x7faa6f577720) 0 + +Vtable for std::system_error +std::system_error::_ZTVSt12system_error: 5 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 (0x0x7faa6f4f2ea0) 0 + vptr=((& std::system_error::_ZTVSt12system_error) + 16) + std::runtime_error (0x0x7faa6f4f2f08) 0 + primary-for std::system_error (0x0x7faa6f4f2ea0) + std::exception (0x0x7faa6f5a2300) 0 nearly-empty + primary-for std::runtime_error (0x0x7faa6f4f2f08) + +Vtable for std::ios_base::failure +std::ios_base::failure::_ZTVNSt8ios_base7failureB5cxx11E: 5 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 (0x0x7faa6f5cb1a0) 0 + vptr=((& std::ios_base::failure::_ZTVNSt8ios_base7failureB5cxx11E) + 16) + std::system_error (0x0x7faa6f5cb208) 0 + primary-for std::ios_base::failure (0x0x7faa6f5cb1a0) + std::runtime_error (0x0x7faa6f5cb270) 0 + primary-for std::system_error (0x0x7faa6f5cb208) + std::exception (0x0x7faa6f5d48a0) 0 nearly-empty + primary-for std::runtime_error (0x0x7faa6f5cb270) + +Class std::ios_base::_Callback_list + size=24 align=8 + base size=24 base align=8 +std::ios_base::_Callback_list (0x0x7faa6f5d4900) 0 + +Class std::ios_base::_Words + size=16 align=8 + base size=16 base align=8 +std::ios_base::_Words (0x0x7faa6f5d4960) 0 + +Class std::ios_base::Init + size=1 align=1 + base size=0 base align=1 +std::ios_base::Init (0x0x7faa6f5d49c0) 0 empty + +Vtable for std::ios_base +std::ios_base::_ZTVSt8ios_base: 4 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 (0x0x7faa6f5d4840) 0 + vptr=((& std::ios_base::_ZTVSt8ios_base) + 16) + +Class std::ctype_base + size=1 align=1 + base size=0 base align=1 +std::ctype_base (0x0x7faa6f2c4300) 0 empty + +Class std::__num_base + size=1 align=1 + base size=0 base align=1 +std::__num_base (0x0x7faa6f38f4e0) 0 empty + +VTT for std::basic_ostream +std::basic_ostream::_ZTTSo: 2 entries +0 ((& std::basic_ostream::_ZTVSo) + 24) +8 ((& std::basic_ostream::_ZTVSo) + 64) + +VTT for std::basic_ostream +std::basic_ostream::_ZTTSt13basic_ostreamIwSt11char_traitsIwEE: 2 entries +0 ((& std::basic_ostream::_ZTVSt13basic_ostreamIwSt11char_traitsIwEE) + 24) +8 ((& std::basic_ostream::_ZTVSt13basic_ostreamIwSt11char_traitsIwEE) + 64) + +VTT for std::basic_istream +std::basic_istream::_ZTTSi: 2 entries +0 ((& std::basic_istream::_ZTVSi) + 24) +8 ((& std::basic_istream::_ZTVSi) + 64) + +VTT for std::basic_istream +std::basic_istream::_ZTTSt13basic_istreamIwSt11char_traitsIwEE: 2 entries +0 ((& std::basic_istream::_ZTVSt13basic_istreamIwSt11char_traitsIwEE) + 24) +8 ((& std::basic_istream::_ZTVSt13basic_istreamIwSt11char_traitsIwEE) + 64) + +Construction vtable for std::basic_istream (0x0x7faa6ef25958 instance) in std::basic_iostream +std::basic_iostream::_ZTCSd0_Si: 10 entries +0 24 +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISi) +24 0 +32 0 +40 18446744073709551592 +48 (int (*)(...))-24 +56 (int (*)(...))(& _ZTISi) +64 0 +72 0 + +Construction vtable for std::basic_ostream (0x0x7faa6ef25a28 instance) in std::basic_iostream +std::basic_iostream::_ZTCSd16_So: 10 entries +0 8 +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISo) +24 0 +32 0 +40 18446744073709551608 +48 (int (*)(...))-8 +56 (int (*)(...))(& _ZTISo) +64 0 +72 0 + +VTT for std::basic_iostream +std::basic_iostream::_ZTTSd: 7 entries +0 ((& std::basic_iostream::_ZTVSd) + 24) +8 ((& std::basic_iostream::_ZTCSd0_Si) + 24) +16 ((& std::basic_iostream::_ZTCSd0_Si) + 64) +24 ((& std::basic_iostream::_ZTCSd16_So) + 24) +32 ((& std::basic_iostream::_ZTCSd16_So) + 64) +40 ((& std::basic_iostream::_ZTVSd) + 104) +48 ((& std::basic_iostream::_ZTVSd) + 64) + +Construction vtable for std::basic_istream (0x0x7faa6ef666e8 instance) in std::basic_iostream +std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE0_St13basic_istreamIwS1_E: 10 entries +0 24 +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISt13basic_istreamIwSt11char_traitsIwEE) +24 0 +32 0 +40 18446744073709551592 +48 (int (*)(...))-24 +56 (int (*)(...))(& _ZTISt13basic_istreamIwSt11char_traitsIwEE) +64 0 +72 0 + +Construction vtable for std::basic_ostream (0x0x7faa6ef667b8 instance) in std::basic_iostream +std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE16_St13basic_ostreamIwS1_E: 10 entries +0 8 +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISt13basic_ostreamIwSt11char_traitsIwEE) +24 0 +32 0 +40 18446744073709551608 +48 (int (*)(...))-8 +56 (int (*)(...))(& _ZTISt13basic_ostreamIwSt11char_traitsIwEE) +64 0 +72 0 + +VTT for std::basic_iostream +std::basic_iostream::_ZTTSt14basic_iostreamIwSt11char_traitsIwEE: 7 entries +0 ((& std::basic_iostream::_ZTVSt14basic_iostreamIwSt11char_traitsIwEE) + 24) +8 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE0_St13basic_istreamIwS1_E) + 24) +16 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE0_St13basic_istreamIwS1_E) + 64) +24 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE16_St13basic_ostreamIwS1_E) + 24) +32 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE16_St13basic_ostreamIwS1_E) + 64) +40 ((& std::basic_iostream::_ZTVSt14basic_iostreamIwSt11char_traitsIwEE) + 104) +48 ((& std::basic_iostream::_ZTVSt14basic_iostreamIwSt11char_traitsIwEE) + 64) + +Class QByteArrayDataPtr + size=8 align=8 + base size=8 base align=8 +QByteArrayDataPtr (0x0x7faa6ef6ae40) 0 + +Class QByteArray + size=8 align=8 + base size=8 base align=8 +QByteArray (0x0x7faa6ef6aea0) 0 + +Class QByteRef + size=16 align=8 + base size=12 base align=8 +QByteRef (0x0x7faa6ecd52a0) 0 + +Class QStringDataPtr + size=8 align=8 + base size=8 base align=8 +QStringDataPtr (0x0x7faa6ed71120) 0 + +Class QStringView + size=16 align=8 + base size=16 base align=8 +QStringView (0x0x7faa6ed715a0) 0 + +Class QLatin1String + size=16 align=8 + base size=16 base align=8 +QLatin1String (0x0x7faa6ee5c660) 0 + +Class QString::Null + size=1 align=1 + base size=0 base align=1 +QString::Null (0x0x7faa6eb07600) 0 empty + +Class QString + size=8 align=8 + base size=8 base align=8 +QString (0x0x7faa6eb074e0) 0 + +Class QCharRef + size=16 align=8 + base size=12 base align=8 +QCharRef (0x0x7faa6e9e4480) 0 + +Class QStringRef + size=16 align=8 + base size=16 base align=8 +QStringRef (0x0x7faa6e765060) 0 + +Class QtPrivate::ArgBase + size=1 align=1 + base size=1 base align=1 +QtPrivate::ArgBase (0x0x7faa6e4c6e40) 0 + +Class QtPrivate::QStringViewArg + size=24 align=8 + base size=24 base align=8 +QtPrivate::QStringViewArg (0x0x7faa6e7f7618) 0 + QtPrivate::ArgBase (0x0x7faa6e4c6ea0) 0 + +Class QtPrivate::QLatin1StringArg + size=24 align=8 + base size=24 base align=8 +QtPrivate::QLatin1StringArg (0x0x7faa6e7f7680) 0 + QtPrivate::ArgBase (0x0x7faa6e5010c0) 0 + +Class std::__erased_type + size=1 align=1 + base size=0 base align=1 +std::__erased_type (0x0x7faa6e5c5000) 0 empty + +Class std::allocator_arg_t + size=1 align=1 + base size=0 base align=1 +std::allocator_arg_t (0x0x7faa6e5c5060) 0 empty + +Class std::__uses_alloc_base + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc_base (0x0x7faa6e5c51e0) 0 empty + +Class std::__uses_alloc0::_Sink + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc0::_Sink (0x0x7faa6e5c52a0) 0 empty + +Class std::__uses_alloc0 + size=1 align=1 + base size=1 base align=1 +std::__uses_alloc0 (0x0x7faa6e7f7a28) 0 + std::__uses_alloc_base (0x0x7faa6e5c5240) 0 empty + +Class std::_Swallow_assign + size=1 align=1 + base size=0 base align=1 +std::_Swallow_assign (0x0x7faa6e32f600) 0 empty + +Vtable for std::bad_function_call +std::bad_function_call::_ZTVSt17bad_function_call: 5 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 (0x0x7faa6e2c3c98) 0 nearly-empty + vptr=((& std::bad_function_call::_ZTVSt17bad_function_call) + 16) + std::exception (0x0x7faa6e372f00) 0 nearly-empty + primary-for std::bad_function_call (0x0x7faa6e2c3c98) + +Class std::_Nocopy_types + size=16 align=8 + base size=16 base align=8 +std::_Nocopy_types (0x0x7faa6e3a5000) 0 + +Class std::_Any_data + size=16 align=8 + base size=16 base align=8 +std::_Any_data (0x0x7faa6e3a5060) 0 + +Class std::_Function_base + size=24 align=8 + base size=24 base align=8 +std::_Function_base (0x0x7faa6e3a5360) 0 + +Class QtPrivate::QHashCombine + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombine (0x0x7faa6e1987e0) 0 empty + +Class QtPrivate::QHashCombineCommutative + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombineCommutative (0x0x7faa6e1988a0) 0 empty + +Class std::_Bit_reference + size=16 align=8 + base size=16 base align=8 +std::_Bit_reference (0x0x7faa6deca000) 0 + +Class std::_Bit_iterator_base + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator_base (0x0x7faa6e1eb820) 0 + std::iterator (0x0x7faa6deca720) 0 empty + +Class std::_Bit_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator (0x0x7faa6e1eb958) 0 + std::_Bit_iterator_base (0x0x7faa6e1eb9c0) 0 + std::iterator (0x0x7faa6decad80) 0 empty + +Class std::_Bit_const_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_const_iterator (0x0x7faa6e1eba28) 0 + std::_Bit_iterator_base (0x0x7faa6e1eba90) 0 + std::iterator (0x0x7faa6df025a0) 0 empty + +Class std::__detail::_List_node_base + size=16 align=8 + base size=16 base align=8 +std::__detail::_List_node_base (0x0x7faa6dd4c120) 0 + +Class QListData::NotArrayCompatibleLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotArrayCompatibleLayout (0x0x7faa6ddfbea0) 0 empty + +Class QListData::NotIndirectLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotIndirectLayout (0x0x7faa6ddfbf00) 0 empty + +Class QListData::ArrayCompatibleLayout + size=1 align=1 + base size=1 base align=1 +QListData::ArrayCompatibleLayout (0x0x7faa6e0265b0) 0 empty + QListData::NotIndirectLayout (0x0x7faa6ddfbf60) 0 empty + +Class QListData::InlineWithPaddingLayout + size=1 align=1 + base size=1 base align=1 +QListData::InlineWithPaddingLayout (0x0x7faa6dd668c0) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7faa6de12000) 0 empty + QListData::NotIndirectLayout (0x0x7faa6de12060) 0 empty + +Class QListData::IndirectLayout + size=1 align=1 + base size=1 base align=1 +QListData::IndirectLayout (0x0x7faa6e026618) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7faa6de120c0) 0 empty + +Class QListData::Data + size=24 align=8 + base size=24 base align=8 +QListData::Data (0x0x7faa6de12120) 0 + +Class QListData + size=8 align=8 + base size=8 base align=8 +QListData (0x0x7faa6ddfbe40) 0 + +Class QRegExp + size=8 align=8 + base size=8 base align=8 +QRegExp (0x0x7faa6db0d2a0) 0 + +Class QStringMatcher::Data + size=272 align=8 + base size=272 base align=8 +QStringMatcher::Data (0x0x7faa6dbe97e0) 0 + +Class QStringMatcher + size=1048 align=8 + base size=1048 base align=8 +QStringMatcher (0x0x7faa6dbe9780) 0 + +Class QStringList + size=8 align=8 + base size=8 base align=8 +QStringList (0x0x7faa6dbee2d8) 0 + QList (0x0x7faa6dbee340) 0 + QListSpecialMethods (0x0x7faa6dbe9a20) 0 empty + +Class QScopedPointerPodDeleter + size=1 align=1 + base size=0 base align=1 +QScopedPointerPodDeleter (0x0x7faa6d8b9960) 0 empty + +Class std::_Rb_tree_node_base + size=32 align=8 + base size=32 base align=8 +std::_Rb_tree_node_base (0x0x7faa6d94dba0) 0 + +Class std::_Rb_tree_header + size=40 align=8 + base size=40 base align=8 +std::_Rb_tree_header (0x0x7faa6d94df00) 0 + +Class QtPrivate::AbstractDebugStreamFunction + size=16 align=8 + base size=16 base align=8 +QtPrivate::AbstractDebugStreamFunction (0x0x7faa6d6ab540) 0 + +Class QtPrivate::AbstractComparatorFunction + size=24 align=8 + base size=24 base align=8 +QtPrivate::AbstractComparatorFunction (0x0x7faa6d6ab8a0) 0 + +Class QtPrivate::AbstractConverterFunction + size=8 align=8 + base size=8 base align=8 +QtPrivate::AbstractConverterFunction (0x0x7faa6d6abde0) 0 + +Class QMetaType + size=80 align=8 + base size=80 base align=8 +QMetaType (0x0x7faa6d6d2360) 0 + +Class QtMetaTypePrivate::VariantData + size=24 align=8 + base size=20 base align=8 +QtMetaTypePrivate::VariantData (0x0x7faa6d73b540) 0 + +Class QtMetaTypePrivate::VectorBoolElements + size=1 align=1 + base size=0 base align=1 +QtMetaTypePrivate::VectorBoolElements (0x0x7faa6d73bc00) 0 empty + +Class QtMetaTypePrivate::QSequentialIterableImpl + size=104 align=8 + base size=104 base align=8 +QtMetaTypePrivate::QSequentialIterableImpl (0x0x7faa6d390a80) 0 + +Class QtMetaTypePrivate::QAssociativeIterableImpl + size=112 align=8 + base size=112 base align=8 +QtMetaTypePrivate::QAssociativeIterableImpl (0x0x7faa6d44d180) 0 + +Class QtMetaTypePrivate::QPairVariantInterfaceImpl + size=40 align=8 + base size=40 base align=8 +QtMetaTypePrivate::QPairVariantInterfaceImpl (0x0x7faa6d4a26c0) 0 + +Class std::chrono::_V2::system_clock + size=1 align=1 + base size=0 base align=1 +std::chrono::_V2::system_clock (0x0x7faa6d337c60) 0 empty + +Class std::chrono::_V2::steady_clock + size=1 align=1 + base size=0 base align=1 +std::chrono::_V2::steady_clock (0x0x7faa6d06d720) 0 empty + +Vtable for QObjectData +QObjectData::_ZTV11QObjectData: 4 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 (0x0x7faa6d06d780) 0 + vptr=((& QObjectData::_ZTV11QObjectData) + 16) + +Class QObject::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObject::QPrivateSignal (0x0x7faa6d06d960) 0 empty + +Vtable for QObject +QObject::_ZTV7QObject: 14 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 (0x0x7faa6d06d900) 0 + vptr=((& QObject::_ZTV7QObject) + 16) + +Vtable for QObjectUserData +QObjectUserData::_ZTV15QObjectUserData: 4 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 (0x0x7faa6d150780) 0 nearly-empty + vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16) + +Class QSignalBlocker + size=16 align=8 + base size=10 base align=8 +QSignalBlocker (0x0x7faa6d150900) 0 + +Class QAbstractAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractAnimation::QPrivateSignal (0x0x7faa6d1721e0) 0 empty + +Vtable for QAbstractAnimation +QAbstractAnimation::_ZTV18QAbstractAnimation: 18 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QAbstractAnimation) +16 (int (*)(...))QAbstractAnimation::metaObject +24 (int (*)(...))QAbstractAnimation::qt_metacast +32 (int (*)(...))QAbstractAnimation::qt_metacall +40 0 +48 0 +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 (0x0x7faa6d152478) 0 + vptr=((& QAbstractAnimation::_ZTV18QAbstractAnimation) + 16) + QObject (0x0x7faa6d172180) 0 + primary-for QAbstractAnimation (0x0x7faa6d152478) + +Class QAnimationDriver::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationDriver::QPrivateSignal (0x0x7faa6d1725a0) 0 empty + +Vtable for QAnimationDriver +QAnimationDriver::_ZTV16QAnimationDriver: 18 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 (0x0x7faa6d1524e0) 0 + vptr=((& QAnimationDriver::_ZTV16QAnimationDriver) + 16) + QObject (0x0x7faa6d172540) 0 + primary-for QAnimationDriver (0x0x7faa6d1524e0) + +Class QEventLoop::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventLoop::QPrivateSignal (0x0x7faa6d1727e0) 0 empty + +Vtable for QEventLoop +QEventLoop::_ZTV10QEventLoop: 14 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 (0x0x7faa6d152548) 0 + vptr=((& QEventLoop::_ZTV10QEventLoop) + 16) + QObject (0x0x7faa6d172780) 0 + primary-for QEventLoop (0x0x7faa6d152548) + +Class QEventLoopLocker + size=8 align=8 + base size=8 base align=8 +QEventLoopLocker (0x0x7faa6cdcf0c0) 0 + +Class QAbstractEventDispatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractEventDispatcher::QPrivateSignal (0x0x7faa6cdcf180) 0 empty + +Class QAbstractEventDispatcher::TimerInfo + size=12 align=4 + base size=12 base align=4 +QAbstractEventDispatcher::TimerInfo (0x0x7faa6cdcf1e0) 0 + +Vtable for QAbstractEventDispatcher +QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher: 28 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI24QAbstractEventDispatcher) +16 (int (*)(...))QAbstractEventDispatcher::metaObject +24 (int (*)(...))QAbstractEventDispatcher::qt_metacast +32 (int (*)(...))QAbstractEventDispatcher::qt_metacall +40 0 +48 0 +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 (0x0x7faa6d152680) 0 + vptr=((& QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher) + 16) + QObject (0x0x7faa6cdcf120) 0 + primary-for QAbstractEventDispatcher (0x0x7faa6d152680) + +Class QMapNodeBase + size=24 align=8 + base size=24 base align=8 +QMapNodeBase (0x0x7faa6ce261e0) 0 + +Class QMapDataBase + size=40 align=8 + base size=40 base align=8 +QMapDataBase (0x0x7faa6ce26e40) 0 + +Class QHashData::Node + size=16 align=8 + base size=16 base align=8 +QHashData::Node (0x0x7faa6cf1a7e0) 0 + +Class QHashData + size=48 align=8 + base size=44 base align=8 +QHashData (0x0x7faa6cf1a780) 0 + +Class QHashDummyValue + size=1 align=1 + base size=0 base align=1 +QHashDummyValue (0x0x7faa6cf1aa80) 0 empty + +Class QVariant::PrivateShared + size=16 align=8 + base size=12 base align=8 +QVariant::PrivateShared (0x0x7faa6cc4a1e0) 0 + +Class QVariant::Private::Data + size=8 align=8 + base size=8 base align=8 +QVariant::Private::Data (0x0x7faa6cc4a2a0) 0 + +Class QVariant::Private + size=16 align=8 + base size=12 base align=8 +QVariant::Private (0x0x7faa6cc4a240) 0 + +Class QVariant::Handler + size=72 align=8 + base size=72 base align=8 +QVariant::Handler (0x0x7faa6cc4a300) 0 + +Class QVariant + size=16 align=8 + base size=16 base align=8 +QVariant (0x0x7faa6cc4a180) 0 + +Class QVariantComparisonHelper + size=8 align=8 + base size=8 base align=8 +QVariantComparisonHelper (0x0x7faa6c9ac5a0) 0 + +Class QSequentialIterable::const_iterator + size=112 align=8 + base size=112 base align=8 +QSequentialIterable::const_iterator (0x0x7faa6c9f1c00) 0 + +Class QSequentialIterable + size=104 align=8 + base size=104 base align=8 +QSequentialIterable (0x0x7faa6c9f1ba0) 0 + +Class QAssociativeIterable::const_iterator + size=120 align=8 + base size=120 base align=8 +QAssociativeIterable::const_iterator (0x0x7faa6c9f1d20) 0 + +Class QAssociativeIterable + size=112 align=8 + base size=112 base align=8 +QAssociativeIterable (0x0x7faa6c9f1cc0) 0 + +Class QModelIndex + size=24 align=8 + base size=24 base align=8 +QModelIndex (0x0x7faa6cabbea0) 0 + +Class QPersistentModelIndex + size=8 align=8 + base size=8 base align=8 +QPersistentModelIndex (0x0x7faa6cb2dae0) 0 + +Class QAbstractItemModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractItemModel::QPrivateSignal (0x0x7faa6c7fd900) 0 empty + +Vtable for QAbstractItemModel +QAbstractItemModel::_ZTV18QAbstractItemModel: 48 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QAbstractItemModel) +16 (int (*)(...))QAbstractItemModel::metaObject +24 (int (*)(...))QAbstractItemModel::qt_metacast +32 (int (*)(...))QAbstractItemModel::qt_metacall +40 0 +48 0 +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 (0x0x7faa6c806820) 0 + vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16) + QObject (0x0x7faa6c7fd8a0) 0 + primary-for QAbstractItemModel (0x0x7faa6c806820) + +Class QAbstractTableModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTableModel::QPrivateSignal (0x0x7faa6c875cc0) 0 empty + +Vtable for QAbstractTableModel +QAbstractTableModel::_ZTV19QAbstractTableModel: 48 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QAbstractTableModel) +16 (int (*)(...))QAbstractTableModel::metaObject +24 (int (*)(...))QAbstractTableModel::qt_metacast +32 (int (*)(...))QAbstractTableModel::qt_metacall +40 0 +48 0 +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 (0x0x7faa6c806e38) 0 + vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16) + QAbstractItemModel (0x0x7faa6c806ea0) 0 + primary-for QAbstractTableModel (0x0x7faa6c806e38) + QObject (0x0x7faa6c875c60) 0 + primary-for QAbstractItemModel (0x0x7faa6c806ea0) + +Class QAbstractListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractListModel::QPrivateSignal (0x0x7faa6c875e40) 0 empty + +Vtable for QAbstractListModel +QAbstractListModel::_ZTV18QAbstractListModel: 48 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QAbstractListModel) +16 (int (*)(...))QAbstractListModel::metaObject +24 (int (*)(...))QAbstractListModel::qt_metacast +32 (int (*)(...))QAbstractListModel::qt_metacall +40 0 +48 0 +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 (0x0x7faa6c806f08) 0 + vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16) + QAbstractItemModel (0x0x7faa6c806f70) 0 + primary-for QAbstractListModel (0x0x7faa6c806f08) + QObject (0x0x7faa6c875de0) 0 + primary-for QAbstractItemModel (0x0x7faa6c806f70) + +Vtable for QAbstractNativeEventFilter +QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI26QAbstractNativeEventFilter) +16 0 +24 0 +32 (int (*)(...))__cxa_pure_virtual + +Class QAbstractNativeEventFilter + size=16 align=8 + base size=16 base align=8 +QAbstractNativeEventFilter (0x0x7faa6c8fc5a0) 0 + vptr=((& QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter) + 16) + +Class QAbstractProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractProxyModel::QPrivateSignal (0x0x7faa6c8fc660) 0 empty + +Vtable for QAbstractProxyModel +QAbstractProxyModel::_ZTV19QAbstractProxyModel: 53 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QAbstractProxyModel) +16 (int (*)(...))QAbstractProxyModel::metaObject +24 (int (*)(...))QAbstractProxyModel::qt_metacast +32 (int (*)(...))QAbstractProxyModel::qt_metacall +40 0 +48 0 +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 (0x0x7faa6c90d068) 0 + vptr=((& QAbstractProxyModel::_ZTV19QAbstractProxyModel) + 16) + QAbstractItemModel (0x0x7faa6c90d0d0) 0 + primary-for QAbstractProxyModel (0x0x7faa6c90d068) + QObject (0x0x7faa6c8fc600) 0 + primary-for QAbstractItemModel (0x0x7faa6c90d0d0) + +Class QAbstractState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractState::QPrivateSignal (0x0x7faa6c8fc8a0) 0 empty + +Vtable for QAbstractState +QAbstractState::_ZTV14QAbstractState: 16 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI14QAbstractState) +16 (int (*)(...))QAbstractState::metaObject +24 (int (*)(...))QAbstractState::qt_metacast +32 (int (*)(...))QAbstractState::qt_metacall +40 0 +48 0 +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 (0x0x7faa6c90d138) 0 + vptr=((& QAbstractState::_ZTV14QAbstractState) + 16) + QObject (0x0x7faa6c8fc840) 0 + primary-for QAbstractState (0x0x7faa6c90d138) + +Class QAbstractTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTransition::QPrivateSignal (0x0x7faa6c8fcae0) 0 empty + +Vtable for QAbstractTransition +QAbstractTransition::_ZTV19QAbstractTransition: 16 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QAbstractTransition) +16 (int (*)(...))QAbstractTransition::metaObject +24 (int (*)(...))QAbstractTransition::qt_metacast +32 (int (*)(...))QAbstractTransition::qt_metacall +40 0 +48 0 +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 (0x0x7faa6c90d1a0) 0 + vptr=((& QAbstractTransition::_ZTV19QAbstractTransition) + 16) + QObject (0x0x7faa6c8fca80) 0 + primary-for QAbstractTransition (0x0x7faa6c90d1a0) + +Class QAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationGroup::QPrivateSignal (0x0x7faa6c8fcde0) 0 empty + +Vtable for QAnimationGroup +QAnimationGroup::_ZTV15QAnimationGroup: 18 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QAnimationGroup) +16 (int (*)(...))QAnimationGroup::metaObject +24 (int (*)(...))QAnimationGroup::qt_metacast +32 (int (*)(...))QAnimationGroup::qt_metacall +40 0 +48 0 +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 (0x0x7faa6c90d208) 0 + vptr=((& QAnimationGroup::_ZTV15QAnimationGroup) + 16) + QAbstractAnimation (0x0x7faa6c90d270) 0 + primary-for QAnimationGroup (0x0x7faa6c90d208) + QObject (0x0x7faa6c8fcd80) 0 + primary-for QAbstractAnimation (0x0x7faa6c90d270) + +Class QBasicTimer + size=4 align=4 + base size=4 base align=4 +QBasicTimer (0x0x7faa6c5d0120) 0 + +Class QBitArray + size=8 align=8 + base size=8 base align=8 +QBitArray (0x0x7faa6c64fa80) 0 + +Class QBitRef + size=16 align=8 + base size=12 base align=8 +QBitRef (0x0x7faa6c6a1f00) 0 + +Class QIODevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIODevice::QPrivateSignal (0x0x7faa6c7161e0) 0 empty + +Vtable for QIODevice +QIODevice::_ZTV9QIODevice: 30 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QIODevice) +16 (int (*)(...))QIODevice::metaObject +24 (int (*)(...))QIODevice::qt_metacast +32 (int (*)(...))QIODevice::qt_metacall +40 0 +48 0 +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 (0x0x7faa6c70c820) 0 + vptr=((& QIODevice::_ZTV9QIODevice) + 16) + QObject (0x0x7faa6c716180) 0 + primary-for QIODevice (0x0x7faa6c70c820) + +Class QBuffer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBuffer::QPrivateSignal (0x0x7faa6c716b40) 0 empty + +Vtable for QBuffer +QBuffer::_ZTV7QBuffer: 30 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 (0x0x7faa6c70c958) 0 + vptr=((& QBuffer::_ZTV7QBuffer) + 16) + QIODevice (0x0x7faa6c70c9c0) 0 + primary-for QBuffer (0x0x7faa6c70c958) + QObject (0x0x7faa6c716ae0) 0 + primary-for QIODevice (0x0x7faa6c70c9c0) + +Class QByteArrayMatcher::Data + size=272 align=8 + base size=272 base align=8 +QByteArrayMatcher::Data (0x0x7faa6c716de0) 0 + +Class QByteArrayMatcher + size=1040 align=8 + base size=1040 base align=8 +QByteArrayMatcher (0x0x7faa6c716d80) 0 + +Class QStaticByteArrayMatcherBase::Skiptable + size=256 align=1 + base size=256 base align=1 +QStaticByteArrayMatcherBase::Skiptable (0x0x7faa6c716f60) 0 + +Class QStaticByteArrayMatcherBase + size=256 align=16 + base size=256 base align=16 +QStaticByteArrayMatcherBase (0x0x7faa6c716f00) 0 + +Class QSharedData + size=4 align=4 + base size=4 base align=4 +QSharedData (0x0x7faa6c77ce40) 0 + +Class QLocale + size=8 align=8 + base size=8 base align=8 +QLocale (0x0x7faa6c3dad20) 0 + +Class QCalendar::YearMonthDay + size=12 align=4 + base size=12 base align=4 +QCalendar::YearMonthDay (0x0x7faa6c567240) 0 + +Class QCalendar + size=8 align=8 + base size=8 base align=8 +QCalendar (0x0x7faa6c5671e0) 0 + +Class QDate + size=8 align=8 + base size=8 base align=8 +QDate (0x0x7faa6c567a20) 0 + +Class QTime + size=4 align=4 + base size=4 base align=4 +QTime (0x0x7faa6c1ed300) 0 + +Class QDateTime::ShortData + size=8 align=8 + base size=8 base align=8 +QDateTime::ShortData (0x0x7faa6c23df60) 0 + +Class QDateTime::Data + size=8 align=8 + base size=8 base align=8 +QDateTime::Data (0x0x7faa6c258000) 0 + +Class QDateTime + size=8 align=8 + base size=8 base align=8 +QDateTime (0x0x7faa6c23df00) 0 + +Vtable for QTextStream +QTextStream::_ZTV11QTextStream: 4 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 (0x0x7faa6c32e6c0) 0 + vptr=((& QTextStream::_ZTV11QTextStream) + 16) + +Class QTextStreamManipulator + size=40 align=8 + base size=38 base align=8 +QTextStreamManipulator (0x0x7faa6c32ef60) 0 + +Class QContiguousCacheData + size=24 align=4 + base size=24 base align=4 +QContiguousCacheData (0x0x7faa6bffdc00) 0 + +Vtable for __gnu_cxx::__concurrence_lock_error +__gnu_cxx::__concurrence_lock_error::_ZTVN9__gnu_cxx24__concurrence_lock_errorE: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx24__concurrence_lock_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_lock_error::~__concurrence_lock_error +24 (int (*)(...))__gnu_cxx::__concurrence_lock_error::~__concurrence_lock_error +32 (int (*)(...))__gnu_cxx::__concurrence_lock_error::what + +Class __gnu_cxx::__concurrence_lock_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_lock_error (0x0x7faa6c32d9c0) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_lock_error::_ZTVN9__gnu_cxx24__concurrence_lock_errorE) + 16) + std::exception (0x0x7faa6c04ca80) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_lock_error (0x0x7faa6c32d9c0) + +Vtable for __gnu_cxx::__concurrence_unlock_error +__gnu_cxx::__concurrence_unlock_error::_ZTVN9__gnu_cxx26__concurrence_unlock_errorE: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx26__concurrence_unlock_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::~__concurrence_unlock_error +24 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::~__concurrence_unlock_error +32 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::what + +Class __gnu_cxx::__concurrence_unlock_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_unlock_error (0x0x7faa6c32da28) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_unlock_error::_ZTVN9__gnu_cxx26__concurrence_unlock_errorE) + 16) + std::exception (0x0x7faa6c04cba0) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_unlock_error (0x0x7faa6c32da28) + +Vtable for __gnu_cxx::__concurrence_broadcast_error +__gnu_cxx::__concurrence_broadcast_error::_ZTVN9__gnu_cxx29__concurrence_broadcast_errorE: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx29__concurrence_broadcast_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::~__concurrence_broadcast_error +24 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::~__concurrence_broadcast_error +32 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::what + +Class __gnu_cxx::__concurrence_broadcast_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_broadcast_error (0x0x7faa6c32da90) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_broadcast_error::_ZTVN9__gnu_cxx29__concurrence_broadcast_errorE) + 16) + std::exception (0x0x7faa6c04ccc0) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_broadcast_error (0x0x7faa6c32da90) + +Vtable for __gnu_cxx::__concurrence_wait_error +__gnu_cxx::__concurrence_wait_error::_ZTVN9__gnu_cxx24__concurrence_wait_errorE: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx24__concurrence_wait_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_wait_error::~__concurrence_wait_error +24 (int (*)(...))__gnu_cxx::__concurrence_wait_error::~__concurrence_wait_error +32 (int (*)(...))__gnu_cxx::__concurrence_wait_error::what + +Class __gnu_cxx::__concurrence_wait_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_wait_error (0x0x7faa6c32db60) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_wait_error::_ZTVN9__gnu_cxx24__concurrence_wait_errorE) + 16) + std::exception (0x0x7faa6c04cde0) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_wait_error (0x0x7faa6c32db60) + +Class __gnu_cxx::__mutex + size=40 align=8 + base size=40 base align=8 +__gnu_cxx::__mutex (0x0x7faa6c076e40) 0 + +Class __gnu_cxx::__recursive_mutex + size=40 align=8 + base size=40 base align=8 +__gnu_cxx::__recursive_mutex (0x0x7faa6c09a180) 0 + +Class __gnu_cxx::__scoped_lock + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__scoped_lock (0x0x7faa6c09a480) 0 + +Class __gnu_cxx::__cond + size=48 align=8 + base size=48 base align=8 +__gnu_cxx::__cond (0x0x7faa6c09a7e0) 0 + +Vtable for std::bad_weak_ptr +std::bad_weak_ptr::_ZTVSt12bad_weak_ptr: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt12bad_weak_ptr) +16 (int (*)(...))std::bad_weak_ptr::~bad_weak_ptr +24 (int (*)(...))std::bad_weak_ptr::~bad_weak_ptr +32 (int (*)(...))std::bad_weak_ptr::what + +Class std::bad_weak_ptr + size=8 align=8 + base size=8 base align=8 +std::bad_weak_ptr (0x0x7faa6c32dbc8) 0 nearly-empty + vptr=((& std::bad_weak_ptr::_ZTVSt12bad_weak_ptr) + 16) + std::exception (0x0x7faa6c1119c0) 0 nearly-empty + primary-for std::bad_weak_ptr (0x0x7faa6c32dbc8) + +Class std::_Sp_make_shared_tag + size=1 align=1 + base size=0 base align=1 +std::_Sp_make_shared_tag (0x0x7faa6c17e960) 0 empty + +Class std::__sp_array_delete + size=1 align=1 + base size=0 base align=1 +std::__sp_array_delete (0x0x7faa6c17ed80) 0 empty + +Class std::_Sp_locker + size=2 align=1 + base size=2 base align=1 +std::_Sp_locker (0x0x7faa6beb5c00) 0 + +Class QtSharedPointer::NormalDeleter + size=1 align=1 + base size=0 base align=1 +QtSharedPointer::NormalDeleter (0x0x7faa6bf17120) 0 empty + +Class QtSharedPointer::ExternalRefCountData + size=16 align=8 + base size=16 base align=8 +QtSharedPointer::ExternalRefCountData (0x0x7faa6bf172a0) 0 + +Class QtPrivate::EnableInternalData + size=1 align=1 + base size=0 base align=1 +QtPrivate::EnableInternalData (0x0x7faa6bf77ba0) 0 empty + +Class QDebug::Stream + size=80 align=8 + base size=76 base align=8 +QDebug::Stream (0x0x7faa6bbcf2a0) 0 + +Class QDebug + size=8 align=8 + base size=8 base align=8 +QDebug (0x0x7faa6bbcf240) 0 + +Class QDebugStateSaver + size=8 align=8 + base size=8 base align=8 +QDebugStateSaver (0x0x7faa6bd3eba0) 0 + +Class QNoDebug + size=1 align=1 + base size=0 base align=1 +QNoDebug (0x0x7faa6bd3ec60) 0 empty + +Class QCborError + size=4 align=4 + base size=4 base align=4 +QCborError (0x0x7faa6b9beea0) 0 + +Class QRegularExpression + size=8 align=8 + base size=8 base align=8 +QRegularExpression (0x0x7faa6b9f0660) 0 + +Class QRegularExpressionMatch + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatch (0x0x7faa6ba9e540) 0 + +Class QRegularExpressionMatchIterator + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatchIterator (0x0x7faa6bb06300) 0 + +Class QUrl + size=8 align=8 + base size=8 base align=8 +QUrl (0x0x7faa6bb59d20) 0 + +Class QUuid + size=16 align=4 + base size=16 base align=4 +QUuid (0x0x7faa6b89fcc0) 0 + +Class QCborParserError + size=16 align=8 + base size=12 base align=8 +QCborParserError (0x0x7faa6b933840) 0 + +Class QCborValue + size=24 align=8 + base size=20 base align=8 +QCborValue (0x0x7faa6b933900) 0 + +Class QCborValueRef + size=16 align=8 + base size=16 base align=8 +QCborValueRef (0x0x7faa6b3b24e0) 0 + +Class QCborArray::Iterator + size=16 align=8 + base size=16 base align=8 +QCborArray::Iterator (0x0x7faa6b423f00) 0 + +Class QCborArray::ConstIterator + size=16 align=8 + base size=16 base align=8 +QCborArray::ConstIterator (0x0x7faa6b423f60) 0 + +Class QCborArray + size=8 align=8 + base size=8 base align=8 +QCborArray (0x0x7faa6b423ea0) 0 + +Class QCborMap::Iterator + size=16 align=8 + base size=16 base align=8 +QCborMap::Iterator (0x0x7faa6b1aab40) 0 + +Class QCborMap::ConstIterator + size=16 align=8 + base size=16 base align=8 +QCborMap::ConstIterator (0x0x7faa6b1aaba0) 0 + +Class QCborMap + size=8 align=8 + base size=8 base align=8 +QCborMap (0x0x7faa6b1aaae0) 0 + +Class qfloat16::Wrap + size=2 align=2 + base size=2 base align=2 +qfloat16::Wrap (0x0x7faa6afc8360) 0 + +Class qfloat16 + size=2 align=2 + base size=2 base align=2 +qfloat16 (0x0x7faa6afc8300) 0 + +Class QCborStreamWriter + size=8 align=8 + base size=8 base align=8 +QCborStreamWriter (0x0x7faa6b0b5000) 0 + +Class QCborStreamReader + size=24 align=8 + base size=20 base align=8 +QCborStreamReader (0x0x7faa6b0b5d20) 0 + +Class QCollatorSortKey + size=8 align=8 + base size=8 base align=8 +QCollatorSortKey (0x0x7faa6b14ae40) 0 + +Class QCollator + size=8 align=8 + base size=8 base align=8 +QCollator (0x0x7faa6b175060) 0 + +Class QCommandLineOption + size=8 align=8 + base size=8 base align=8 +QCommandLineOption (0x0x7faa6ae64660) 0 + +Vtable for QEvent +QEvent::_ZTV6QEvent: 4 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 (0x0x7faa6af26ba0) 0 + vptr=((& QEvent::_ZTV6QEvent) + 16) + +Vtable for QTimerEvent +QTimerEvent::_ZTV11QTimerEvent: 4 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 (0x0x7faa6af25618) 0 + vptr=((& QTimerEvent::_ZTV11QTimerEvent) + 16) + QEvent (0x0x7faa6af26f60) 0 + primary-for QTimerEvent (0x0x7faa6af25618) + +Vtable for QChildEvent +QChildEvent::_ZTV11QChildEvent: 4 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 (0x0x7faa6af25680) 0 + vptr=((& QChildEvent::_ZTV11QChildEvent) + 16) + QEvent (0x0x7faa6af70060) 0 + primary-for QChildEvent (0x0x7faa6af25680) + +Vtable for QDynamicPropertyChangeEvent +QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent: 4 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 (0x0x7faa6af25bc8) 0 + vptr=((& QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent) + 16) + QEvent (0x0x7faa6af706c0) 0 + primary-for QDynamicPropertyChangeEvent (0x0x7faa6af25bc8) + +Vtable for QDeferredDeleteEvent +QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent: 4 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 (0x0x7faa6af25c30) 0 + vptr=((& QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent) + 16) + QEvent (0x0x7faa6af70780) 0 + primary-for QDeferredDeleteEvent (0x0x7faa6af25c30) + +Class QCoreApplication::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QCoreApplication::QPrivateSignal (0x0x7faa6af708a0) 0 empty + +Vtable for QCoreApplication +QCoreApplication::_ZTV16QCoreApplication: 16 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 (0x0x7faa6af25c98) 0 + vptr=((& QCoreApplication::_ZTV16QCoreApplication) + 16) + QObject (0x0x7faa6af70840) 0 + primary-for QCoreApplication (0x0x7faa6af25c98) + +Class QCommandLineParser + size=8 align=8 + base size=8 base align=8 +QCommandLineParser (0x0x7faa6af70ae0) 0 + +Class QConcatenateTablesProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QConcatenateTablesProxyModel::QPrivateSignal (0x0x7faa6af70c60) 0 empty + +Vtable for QConcatenateTablesProxyModel +QConcatenateTablesProxyModel::_ZTV28QConcatenateTablesProxyModel: 48 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI28QConcatenateTablesProxyModel) +16 (int (*)(...))QConcatenateTablesProxyModel::metaObject +24 (int (*)(...))QConcatenateTablesProxyModel::qt_metacast +32 (int (*)(...))QConcatenateTablesProxyModel::qt_metacall +40 (int (*)(...))QConcatenateTablesProxyModel::~QConcatenateTablesProxyModel +48 (int (*)(...))QConcatenateTablesProxyModel::~QConcatenateTablesProxyModel +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 (*)(...))QConcatenateTablesProxyModel::index +120 (int (*)(...))QConcatenateTablesProxyModel::parent +128 (int (*)(...))QAbstractItemModel::sibling +136 (int (*)(...))QConcatenateTablesProxyModel::rowCount +144 (int (*)(...))QConcatenateTablesProxyModel::columnCount +152 (int (*)(...))QAbstractItemModel::hasChildren +160 (int (*)(...))QConcatenateTablesProxyModel::data +168 (int (*)(...))QConcatenateTablesProxyModel::setData +176 (int (*)(...))QConcatenateTablesProxyModel::headerData +184 (int (*)(...))QAbstractItemModel::setHeaderData +192 (int (*)(...))QConcatenateTablesProxyModel::itemData +200 (int (*)(...))QConcatenateTablesProxyModel::setItemData +208 (int (*)(...))QConcatenateTablesProxyModel::mimeTypes +216 (int (*)(...))QConcatenateTablesProxyModel::mimeData +224 (int (*)(...))QConcatenateTablesProxyModel::canDropMimeData +232 (int (*)(...))QConcatenateTablesProxyModel::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 (*)(...))QConcatenateTablesProxyModel::flags +328 (int (*)(...))QAbstractItemModel::sort +336 (int (*)(...))QAbstractItemModel::buddy +344 (int (*)(...))QAbstractItemModel::match +352 (int (*)(...))QConcatenateTablesProxyModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractItemModel::submit +376 (int (*)(...))QAbstractItemModel::revert + +Class QConcatenateTablesProxyModel + size=16 align=8 + base size=16 base align=8 +QConcatenateTablesProxyModel (0x0x7faa6af25d00) 0 + vptr=((& QConcatenateTablesProxyModel::_ZTV28QConcatenateTablesProxyModel) + 16) + QAbstractItemModel (0x0x7faa6af25d68) 0 + primary-for QConcatenateTablesProxyModel (0x0x7faa6af25d00) + QObject (0x0x7faa6af70c00) 0 + primary-for QAbstractItemModel (0x0x7faa6af25d68) + +Class QCryptographicHash + size=8 align=8 + base size=8 base align=8 +QCryptographicHash (0x0x7faa6af70e40) 0 + +Class QDataStream + size=32 align=8 + base size=32 base align=8 +QDataStream (0x0x7faa6af70f60) 0 + +Class QtPrivate::StreamStateSaver + size=16 align=8 + base size=12 base align=8 +QtPrivate::StreamStateSaver (0x0x7faa6abf3120) 0 + +Class QElapsedTimer + size=16 align=8 + base size=16 base align=8 +QElapsedTimer (0x0x7faa6ac2f840) 0 + +Class QDeadlineTimer + size=16 align=8 + base size=16 base align=8 +QDeadlineTimer (0x0x7faa6ac2ff60) 0 + +Class QFileDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileDevice::QPrivateSignal (0x0x7faa6ad81c60) 0 empty + +Vtable for QFileDevice +QFileDevice::_ZTV11QFileDevice: 34 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 (0x0x7faa6ad79f70) 0 + vptr=((& QFileDevice::_ZTV11QFileDevice) + 16) + QIODevice (0x0x7faa6a998000) 0 + primary-for QFileDevice (0x0x7faa6ad79f70) + QObject (0x0x7faa6ad81c00) 0 + primary-for QIODevice (0x0x7faa6a998000) + +Class QFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFile::QPrivateSignal (0x0x7faa6a9cc5a0) 0 empty + +Vtable for QFile +QFile::_ZTV5QFile: 34 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 (0x0x7faa6a998138) 0 + vptr=((& QFile::_ZTV5QFile) + 16) + QFileDevice (0x0x7faa6a9981a0) 0 + primary-for QFile (0x0x7faa6a998138) + QIODevice (0x0x7faa6a998208) 0 + primary-for QFileDevice (0x0x7faa6a9981a0) + QObject (0x0x7faa6a9cc540) 0 + primary-for QIODevice (0x0x7faa6a998208) + +Class QFileInfo + size=8 align=8 + base size=8 base align=8 +QFileInfo (0x0x7faa6a9ccc00) 0 + +Class QDir + size=8 align=8 + base size=8 base align=8 +QDir (0x0x7faa6aac3ae0) 0 + +Class QDirIterator + size=8 align=8 + base size=8 base align=8 +QDirIterator (0x0x7faa6a7deae0) 0 + +Class QEasingCurve + size=8 align=8 + base size=8 base align=8 +QEasingCurve (0x0x7faa6a8352a0) 0 + +Class QEventTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventTransition::QPrivateSignal (0x0x7faa6a9333c0) 0 empty + +Vtable for QEventTransition +QEventTransition::_ZTV16QEventTransition: 16 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 (0x0x7faa6a8e8ea0) 0 + vptr=((& QEventTransition::_ZTV16QEventTransition) + 16) + QAbstractTransition (0x0x7faa6a8e8f08) 0 + primary-for QEventTransition (0x0x7faa6a8e8ea0) + QObject (0x0x7faa6a933360) 0 + primary-for QAbstractTransition (0x0x7faa6a8e8f08) + +Vtable for QException +QException::_ZTV10QException: 7 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 (0x0x7faa6a8e8f70) 0 nearly-empty + vptr=((& QException::_ZTV10QException) + 16) + std::exception (0x0x7faa6a9335a0) 0 nearly-empty + primary-for QException (0x0x7faa6a8e8f70) + +Vtable for QUnhandledException +QUnhandledException::_ZTV19QUnhandledException: 7 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 (0x0x7faa6a95a000) 0 nearly-empty + vptr=((& QUnhandledException::_ZTV19QUnhandledException) + 16) + QException (0x0x7faa6a95a068) 0 nearly-empty + primary-for QUnhandledException (0x0x7faa6a95a000) + std::exception (0x0x7faa6a933600) 0 nearly-empty + primary-for QException (0x0x7faa6a95a068) + +Class QtPrivate::ExceptionHolder + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionHolder (0x0x7faa6a933660) 0 + +Class QtPrivate::ExceptionStore + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionStore (0x0x7faa6a933720) 0 + +Vtable for QFactoryInterface +QFactoryInterface::_ZTV17QFactoryInterface: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QFactoryInterface) +16 0 +24 0 +32 (int (*)(...))__cxa_pure_virtual + +Class QFactoryInterface + size=8 align=8 + base size=8 base align=8 +QFactoryInterface (0x0x7faa6a933780) 0 nearly-empty + vptr=((& QFactoryInterface::_ZTV17QFactoryInterface) + 16) + +Class QFileSelector::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSelector::QPrivateSignal (0x0x7faa6a9339c0) 0 empty + +Vtable for QFileSelector +QFileSelector::_ZTV13QFileSelector: 14 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 (0x0x7faa6a95a0d0) 0 + vptr=((& QFileSelector::_ZTV13QFileSelector) + 16) + QObject (0x0x7faa6a933960) 0 + primary-for QFileSelector (0x0x7faa6a95a0d0) + +Class QFileSystemWatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSystemWatcher::QPrivateSignal (0x0x7faa6a933c00) 0 empty + +Vtable for QFileSystemWatcher +QFileSystemWatcher::_ZTV18QFileSystemWatcher: 14 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 (0x0x7faa6a95a138) 0 + vptr=((& QFileSystemWatcher::_ZTV18QFileSystemWatcher) + 16) + QObject (0x0x7faa6a933ba0) 0 + primary-for QFileSystemWatcher (0x0x7faa6a95a138) + +Class QFinalState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFinalState::QPrivateSignal (0x0x7faa6a933e40) 0 empty + +Vtable for QFinalState +QFinalState::_ZTV11QFinalState: 16 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 (0x0x7faa6a95a1a0) 0 + vptr=((& QFinalState::_ZTV11QFinalState) + 16) + QAbstractState (0x0x7faa6a95a208) 0 + primary-for QFinalState (0x0x7faa6a95a1a0) + QObject (0x0x7faa6a933de0) 0 + primary-for QAbstractState (0x0x7faa6a95a208) + +Vtable for QRunnable +QRunnable::_ZTV9QRunnable: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QRunnable) +16 (int (*)(...))__cxa_pure_virtual +24 0 +32 0 + +Class QRunnable + size=16 align=8 + base size=12 base align=8 +QRunnable (0x0x7faa6a556060) 0 + vptr=((& QRunnable::_ZTV9QRunnable) + 16) + +Class QBasicMutex + size=8 align=8 + base size=8 base align=8 +QBasicMutex (0x0x7faa6a556300) 0 + +Class QMutex + size=8 align=8 + base size=8 base align=8 +QMutex (0x0x7faa6a95a2d8) 0 + QBasicMutex (0x0x7faa6a556f60) 0 + +Class QRecursiveMutex + size=8 align=8 + base size=8 base align=8 +QRecursiveMutex (0x0x7faa6a95a340) 0 + QMutex (0x0x7faa6a95a3a8) 0 + QBasicMutex (0x0x7faa6a5df1e0) 0 + +Class QMutexLocker + size=8 align=8 + base size=8 base align=8 +QMutexLocker (0x0x7faa6a5df240) 0 + +Class QtPrivate::ResultItem + size=16 align=8 + base size=16 base align=8 +QtPrivate::ResultItem (0x0x7faa6a5df840) 0 + +Class QtPrivate::ResultIteratorBase + size=16 align=8 + base size=12 base align=8 +QtPrivate::ResultIteratorBase (0x0x7faa6a5dfe40) 0 + +Vtable for QtPrivate::ResultStoreBase +QtPrivate::ResultStoreBase::_ZTVN9QtPrivate15ResultStoreBaseE: 4 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 (0x0x7faa6a62f060) 0 + vptr=((& QtPrivate::ResultStoreBase::_ZTVN9QtPrivate15ResultStoreBaseE) + 16) + +Class std::__mutex_base + size=40 align=8 + base size=40 base align=8 +std::__mutex_base (0x0x7faa6a67c840) 0 + +Class std::mutex + size=40 align=8 + base size=40 base align=8 +std::mutex (0x0x7faa6a671c98) 0 + std::__mutex_base (0x0x7faa6a67c8a0) 0 + +Class std::defer_lock_t + size=1 align=1 + base size=0 base align=1 +std::defer_lock_t (0x0x7faa6a67ca80) 0 empty + +Class std::try_to_lock_t + size=1 align=1 + base size=0 base align=1 +std::try_to_lock_t (0x0x7faa6a67cae0) 0 empty + +Class std::adopt_lock_t + size=1 align=1 + base size=0 base align=1 +std::adopt_lock_t (0x0x7faa6a67cb40) 0 empty + +Class std::__recursive_mutex_base + size=40 align=8 + base size=40 base align=8 +std::__recursive_mutex_base (0x0x7faa6a6af5a0) 0 + +Class std::recursive_mutex + size=40 align=8 + base size=40 base align=8 +std::recursive_mutex (0x0x7faa6a671d00) 0 + std::__recursive_mutex_base (0x0x7faa6a6af600) 0 + +Class std::timed_mutex + size=40 align=8 + base size=40 base align=8 +std::timed_mutex (0x0x7faa6a68eaf0) 0 + std::__mutex_base (0x0x7faa6a6af9c0) 0 + std::__timed_mutex_impl (0x0x7faa6a6afa20) 0 empty + +Class std::recursive_timed_mutex + size=40 align=8 + base size=40 base align=8 +std::recursive_timed_mutex (0x0x7faa6a68ee70) 0 + std::__recursive_mutex_base (0x0x7faa6a6afd80) 0 + std::__timed_mutex_impl (0x0x7faa6a6afde0) 0 empty + +Class std::once_flag + size=4 align=4 + base size=4 base align=4 +std::once_flag (0x0x7faa6a6ef540) 0 + +Vtable for QFutureInterfaceBase +QFutureInterfaceBase::_ZTV20QFutureInterfaceBase: 4 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 (0x0x7faa6a6ef780) 0 + vptr=((& QFutureInterfaceBase::_ZTV20QFutureInterfaceBase) + 16) + +Class QFutureWatcherBase::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFutureWatcherBase::QPrivateSignal (0x0x7faa6a39fae0) 0 empty + +Vtable for QFutureWatcherBase +QFutureWatcherBase::_ZTV18QFutureWatcherBase: 16 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QFutureWatcherBase) +16 (int (*)(...))QFutureWatcherBase::metaObject +24 (int (*)(...))QFutureWatcherBase::qt_metacast +32 (int (*)(...))QFutureWatcherBase::qt_metacall +40 0 +48 0 +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 (0x0x7faa6a72baf8) 0 + vptr=((& QFutureWatcherBase::_ZTV18QFutureWatcherBase) + 16) + QObject (0x0x7faa6a39fa80) 0 + primary-for QFutureWatcherBase (0x0x7faa6a72baf8) + +Class QHistoryState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QHistoryState::QPrivateSignal (0x0x7faa6a3c6e40) 0 empty + +Vtable for QHistoryState +QHistoryState::_ZTV13QHistoryState: 16 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 (0x0x7faa6a3e3340) 0 + vptr=((& QHistoryState::_ZTV13QHistoryState) + 16) + QAbstractState (0x0x7faa6a3e33a8) 0 + primary-for QHistoryState (0x0x7faa6a3e3340) + QObject (0x0x7faa6a3c6de0) 0 + primary-for QAbstractState (0x0x7faa6a3e33a8) + +Class QIdentityProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIdentityProxyModel::QPrivateSignal (0x0x7faa6a3f8180) 0 empty + +Vtable for QIdentityProxyModel +QIdentityProxyModel::_ZTV19QIdentityProxyModel: 53 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 (0x0x7faa6a3e3410) 0 + vptr=((& QIdentityProxyModel::_ZTV19QIdentityProxyModel) + 16) + QAbstractProxyModel (0x0x7faa6a3e3478) 0 + primary-for QIdentityProxyModel (0x0x7faa6a3e3410) + QAbstractItemModel (0x0x7faa6a3e34e0) 0 + primary-for QAbstractProxyModel (0x0x7faa6a3e3478) + QObject (0x0x7faa6a3f8120) 0 + primary-for QAbstractItemModel (0x0x7faa6a3e34e0) + +Class QItemSelectionRange + size=16 align=8 + base size=16 base align=8 +QItemSelectionRange (0x0x7faa6a3f8360) 0 + +Class QItemSelectionModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QItemSelectionModel::QPrivateSignal (0x0x7faa6a4b2c60) 0 empty + +Vtable for QItemSelectionModel +QItemSelectionModel::_ZTV19QItemSelectionModel: 20 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 (0x0x7faa6a4afe38) 0 + vptr=((& QItemSelectionModel::_ZTV19QItemSelectionModel) + 16) + QObject (0x0x7faa6a4b2c00) 0 + primary-for QItemSelectionModel (0x0x7faa6a4afe38) + +Class QItemSelection + size=8 align=8 + base size=8 base align=8 +QItemSelection (0x0x7faa6a536000) 0 + QList (0x0x7faa6a536068) 0 + QListSpecialMethods (0x0x7faa6a4f1780) 0 empty + +Class QJsonValue + size=24 align=8 + base size=20 base align=8 +QJsonValue (0x0x7faa6a1840c0) 0 + +Class QJsonValueRef + size=16 align=8 + base size=12 base align=8 +QJsonValueRef (0x0x7faa6a2b1d20) 0 + +Class QJsonValuePtr + size=24 align=8 + base size=24 base align=8 +QJsonValuePtr (0x0x7faa6a2f1cc0) 0 + +Class QJsonValueRefPtr + size=16 align=8 + base size=16 base align=8 +QJsonValueRefPtr (0x0x7faa6a2f1f60) 0 + +Class QJsonArray::iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::iterator (0x0x7faa69f6c300) 0 + +Class QJsonArray::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::const_iterator (0x0x7faa69f6c360) 0 + +Class QJsonArray + size=16 align=8 + base size=16 base align=8 +QJsonArray (0x0x7faa69f6c2a0) 0 + +Class QJsonParseError + size=8 align=4 + base size=8 base align=4 +QJsonParseError (0x0x7faa6a09b240) 0 + +Class QJsonDocument + size=8 align=8 + base size=8 base align=8 +QJsonDocument (0x0x7faa6a09b2a0) 0 + +Class QJsonObject::iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::iterator (0x0x7faa6a0eda80) 0 + +Class QJsonObject::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::const_iterator (0x0x7faa6a0edae0) 0 + +Class QJsonObject + size=16 align=8 + base size=16 base align=8 +QJsonObject (0x0x7faa6a0eda20) 0 + +Class QLibrary::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLibrary::QPrivateSignal (0x0x7faa69e08f00) 0 empty + +Vtable for QLibrary +QLibrary::_ZTV8QLibrary: 14 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 (0x0x7faa69e0dc98) 0 + vptr=((& QLibrary::_ZTV8QLibrary) + 16) + QObject (0x0x7faa69e08ea0) 0 + primary-for QLibrary (0x0x7faa69e0dc98) + +Class QVersionNumber::SegmentStorage + size=8 align=8 + base size=8 base align=8 +QVersionNumber::SegmentStorage (0x0x7faa69e38d80) 0 + +Class QVersionNumber + size=8 align=8 + base size=8 base align=8 +QVersionNumber (0x0x7faa69e388a0) 0 + +Class QLibraryInfo + size=1 align=1 + base size=0 base align=1 +QLibraryInfo (0x0x7faa69f09540) 0 empty + +Class QPoint + size=8 align=4 + base size=8 base align=4 +QPoint (0x0x7faa69f095a0) 0 + +Class QPointF + size=16 align=8 + base size=16 base align=8 +QPointF (0x0x7faa69b82420) 0 + +Class QLine + size=16 align=4 + base size=16 base align=4 +QLine (0x0x7faa69bf3600) 0 + +Class QLineF + size=32 align=8 + base size=32 base align=8 +QLineF (0x0x7faa69c5f9c0) 0 + +Class QLinkedListData + size=32 align=8 + base size=25 base align=8 +QLinkedListData (0x0x7faa69cdcc60) 0 + +Class QLockFile + size=8 align=8 + base size=8 base align=8 +QLockFile (0x0x7faa6999f1e0) 0 + +Class QLoggingCategory::AtomicBools + size=4 align=1 + base size=4 base align=1 +QLoggingCategory::AtomicBools (0x0x7faa6999f420) 0 + +Class QLoggingCategory + size=24 align=8 + base size=24 base align=8 +QLoggingCategory (0x0x7faa6999f3c0) 0 + +Class QMargins + size=16 align=4 + base size=16 base align=4 +QMargins (0x0x7faa6999f840) 0 + +Class QMarginsF + size=32 align=8 + base size=32 base align=8 +QMarginsF (0x0x7faa69a61780) 0 + +Class QMessageAuthenticationCode + size=8 align=8 + base size=8 base align=8 +QMessageAuthenticationCode (0x0x7faa698a9f60) 0 + +Class QMetaMethod + size=16 align=8 + base size=12 base align=8 +QMetaMethod (0x0x7faa698d2000) 0 + +Class QMetaEnum + size=16 align=8 + base size=12 base align=8 +QMetaEnum (0x0x7faa69932840) 0 + +Class QMetaProperty + size=32 align=8 + base size=32 base align=8 +QMetaProperty (0x0x7faa694f4a20) 0 + +Class QMetaClassInfo + size=16 align=8 + base size=12 base align=8 +QMetaClassInfo (0x0x7faa694f4b40) 0 + +Class QMimeData::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QMimeData::QPrivateSignal (0x0x7faa6954f120) 0 empty + +Vtable for QMimeData +QMimeData::_ZTV9QMimeData: 17 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 (0x0x7faa695458f0) 0 + vptr=((& QMimeData::_ZTV9QMimeData) + 16) + QObject (0x0x7faa6954f0c0) 0 + primary-for QMimeData (0x0x7faa695458f0) + +Class QMimeType + size=8 align=8 + base size=8 base align=8 +QMimeType (0x0x7faa6954f300) 0 + +Class QMimeDatabase + size=8 align=8 + base size=8 base align=8 +QMimeDatabase (0x0x7faa69623240) 0 + +Class QObjectCleanupHandler::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObjectCleanupHandler::QPrivateSignal (0x0x7faa69623300) 0 empty + +Vtable for QObjectCleanupHandler +QObjectCleanupHandler::_ZTV21QObjectCleanupHandler: 14 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 (0x0x7faa6961c478) 0 + vptr=((& QObjectCleanupHandler::_ZTV21QObjectCleanupHandler) + 16) + QObject (0x0x7faa696232a0) 0 + primary-for QObjectCleanupHandler (0x0x7faa6961c478) + +Class QOperatingSystemVersion + size=16 align=4 + base size=16 base align=4 +QOperatingSystemVersion (0x0x7faa69623420) 0 + +Class QParallelAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QParallelAnimationGroup::QPrivateSignal (0x0x7faa6968dba0) 0 empty + +Vtable for QParallelAnimationGroup +QParallelAnimationGroup::_ZTV23QParallelAnimationGroup: 18 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 (0x0x7faa6968ed00) 0 + vptr=((& QParallelAnimationGroup::_ZTV23QParallelAnimationGroup) + 16) + QAnimationGroup (0x0x7faa6968ed68) 0 + primary-for QParallelAnimationGroup (0x0x7faa6968ed00) + QAbstractAnimation (0x0x7faa6968edd0) 0 + primary-for QAnimationGroup (0x0x7faa6968ed68) + QObject (0x0x7faa6968db40) 0 + primary-for QAbstractAnimation (0x0x7faa6968edd0) + +Class QPauseAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPauseAnimation::QPrivateSignal (0x0x7faa6968dde0) 0 empty + +Vtable for QPauseAnimation +QPauseAnimation::_ZTV15QPauseAnimation: 18 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 (0x0x7faa6968ee38) 0 + vptr=((& QPauseAnimation::_ZTV15QPauseAnimation) + 16) + QAbstractAnimation (0x0x7faa6968eea0) 0 + primary-for QPauseAnimation (0x0x7faa6968ee38) + QObject (0x0x7faa6968dd80) 0 + primary-for QAbstractAnimation (0x0x7faa6968eea0) + +Class QStaticPlugin + size=16 align=8 + base size=16 base align=8 +QStaticPlugin (0x0x7faa696be960) 0 + +Class QPluginLoader::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPluginLoader::QPrivateSignal (0x0x7faa69309ae0) 0 empty + +Vtable for QPluginLoader +QPluginLoader::_ZTV13QPluginLoader: 14 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 (0x0x7faa69317208) 0 + vptr=((& QPluginLoader::_ZTV13QPluginLoader) + 16) + QObject (0x0x7faa69309a80) 0 + primary-for QPluginLoader (0x0x7faa69317208) + +Class QProcessEnvironment + size=8 align=8 + base size=8 base align=8 +QProcessEnvironment (0x0x7faa69309c00) 0 + +Class QProcess::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QProcess::QPrivateSignal (0x0x7faa693f00c0) 0 empty + +Vtable for QProcess +QProcess::_ZTV8QProcess: 31 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 (0x0x7faa693e6680) 0 + vptr=((& QProcess::_ZTV8QProcess) + 16) + QIODevice (0x0x7faa693e66e8) 0 + primary-for QProcess (0x0x7faa693e6680) + QObject (0x0x7faa693f0060) 0 + primary-for QIODevice (0x0x7faa693e66e8) + +Class QVariantAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QVariantAnimation::QPrivateSignal (0x0x7faa693f0780) 0 empty + +Vtable for QVariantAnimation +QVariantAnimation::_ZTV17QVariantAnimation: 20 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 (0x0x7faa693e6750) 0 + vptr=((& QVariantAnimation::_ZTV17QVariantAnimation) + 16) + QAbstractAnimation (0x0x7faa693e67b8) 0 + primary-for QVariantAnimation (0x0x7faa693e6750) + QObject (0x0x7faa693f0720) 0 + primary-for QAbstractAnimation (0x0x7faa693e67b8) + +Class QPropertyAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPropertyAnimation::QPrivateSignal (0x0x7faa693f0a20) 0 empty + +Vtable for QPropertyAnimation +QPropertyAnimation::_ZTV18QPropertyAnimation: 20 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 (0x0x7faa693e6888) 0 + vptr=((& QPropertyAnimation::_ZTV18QPropertyAnimation) + 16) + QVariantAnimation (0x0x7faa693e68f0) 0 + primary-for QPropertyAnimation (0x0x7faa693e6888) + QAbstractAnimation (0x0x7faa693e6958) 0 + primary-for QVariantAnimation (0x0x7faa693e68f0) + QObject (0x0x7faa693f09c0) 0 + primary-for QAbstractAnimation (0x0x7faa693e6958) + +Class std::random_device + size=5000 align=8 + base size=5000 base align=8 +std::random_device (0x0x7faa694be180) 0 + +Class std::bernoulli_distribution::param_type + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution::param_type (0x0x7faa6919bea0) 0 + +Class std::bernoulli_distribution + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution (0x0x7faa6919be40) 0 + +Class std::seed_seq + size=24 align=8 + base size=24 base align=8 +std::seed_seq (0x0x7faa68f8ac00) 0 + +Class QRandomGenerator::Storage + size=2504 align=8 + base size=2504 base align=8 +QRandomGenerator::Storage (0x0x7faa68dc88a0) 0 + +Class QRandomGenerator + size=2512 align=8 + base size=2512 base align=8 +QRandomGenerator (0x0x7faa68dc8840) 0 + +Class QRandomGenerator64 + size=2512 align=8 + base size=2512 base align=8 +QRandomGenerator64 (0x0x7faa68e4d618) 0 + QRandomGenerator (0x0x7faa68e6c3c0) 0 + +Class QReadWriteLock + size=8 align=8 + base size=8 base align=8 +QReadWriteLock (0x0x7faa68e6cf60) 0 + +Class QReadLocker + size=8 align=8 + base size=8 base align=8 +QReadLocker (0x0x7faa68e8f240) 0 + +Class QWriteLocker + size=8 align=8 + base size=8 base align=8 +QWriteLocker (0x0x7faa68e8f720) 0 + +Class QSize + size=8 align=4 + base size=8 base align=4 +QSize (0x0x7faa68e8fc00) 0 + +Class QSizeF + size=16 align=8 + base size=16 base align=8 +QSizeF (0x0x7faa68b64ae0) 0 + +Class QRect + size=16 align=4 + base size=16 base align=4 +QRect (0x0x7faa68bdeb40) 0 + +Class QRectF + size=32 align=8 + base size=32 base align=8 +QRectF (0x0x7faa68c8fba0) 0 + +Class QResource + size=8 align=8 + base size=8 base align=8 +QResource (0x0x7faa68950cc0) 0 + +Class QSaveFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSaveFile::QPrivateSignal (0x0x7faa68950f60) 0 empty + +Vtable for QSaveFile +QSaveFile::_ZTV9QSaveFile: 34 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 (0x0x7faa6899b000) 0 + vptr=((& QSaveFile::_ZTV9QSaveFile) + 16) + QFileDevice (0x0x7faa6899b068) 0 + primary-for QSaveFile (0x0x7faa6899b000) + QIODevice (0x0x7faa6899b0d0) 0 + primary-for QFileDevice (0x0x7faa6899b068) + QObject (0x0x7faa68950f00) 0 + primary-for QIODevice (0x0x7faa6899b0d0) + +Class QSemaphore + size=8 align=8 + base size=8 base align=8 +QSemaphore (0x0x7faa689a75a0) 0 + +Class QSemaphoreReleaser + size=16 align=8 + base size=12 base align=8 +QSemaphoreReleaser (0x0x7faa689a7720) 0 + +Class QSequentialAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSequentialAnimationGroup::QPrivateSignal (0x0x7faa68a7c360) 0 empty + +Vtable for QSequentialAnimationGroup +QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup: 18 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 (0x0x7faa68a7a888) 0 + vptr=((& QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup) + 16) + QAnimationGroup (0x0x7faa68a7a8f0) 0 + primary-for QSequentialAnimationGroup (0x0x7faa68a7a888) + QAbstractAnimation (0x0x7faa68a7a958) 0 + primary-for QAnimationGroup (0x0x7faa68a7a8f0) + QObject (0x0x7faa68a7c300) 0 + primary-for QAbstractAnimation (0x0x7faa68a7a958) + +Class QSettings::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSettings::QPrivateSignal (0x0x7faa68a7c5a0) 0 empty + +Vtable for QSettings +QSettings::_ZTV9QSettings: 14 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 (0x0x7faa68a7a9c0) 0 + vptr=((& QSettings::_ZTV9QSettings) + 16) + QObject (0x0x7faa68a7c540) 0 + primary-for QSettings (0x0x7faa68a7a9c0) + +Class QSharedMemory::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSharedMemory::QPrivateSignal (0x0x7faa68a7ca20) 0 empty + +Vtable for QSharedMemory +QSharedMemory::_ZTV13QSharedMemory: 14 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 (0x0x7faa68a7aa28) 0 + vptr=((& QSharedMemory::_ZTV13QSharedMemory) + 16) + QObject (0x0x7faa68a7c9c0) 0 + primary-for QSharedMemory (0x0x7faa68a7aa28) + +Class QSignalMapper::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalMapper::QPrivateSignal (0x0x7faa68a7cc60) 0 empty + +Vtable for QSignalMapper +QSignalMapper::_ZTV13QSignalMapper: 14 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 (0x0x7faa68a7aa90) 0 + vptr=((& QSignalMapper::_ZTV13QSignalMapper) + 16) + QObject (0x0x7faa68a7cc00) 0 + primary-for QSignalMapper (0x0x7faa68a7aa90) + +Class QSignalTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalTransition::QPrivateSignal (0x0x7faa68a7cea0) 0 empty + +Vtable for QSignalTransition +QSignalTransition::_ZTV17QSignalTransition: 16 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 (0x0x7faa68a7aaf8) 0 + vptr=((& QSignalTransition::_ZTV17QSignalTransition) + 16) + QAbstractTransition (0x0x7faa68a7ab60) 0 + primary-for QSignalTransition (0x0x7faa68a7aaf8) + QObject (0x0x7faa68a7ce40) 0 + primary-for QAbstractTransition (0x0x7faa68a7ab60) + +Class QSocketNotifier::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSocketNotifier::QPrivateSignal (0x0x7faa68664180) 0 empty + +Vtable for QSocketNotifier +QSocketNotifier::_ZTV15QSocketNotifier: 14 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 (0x0x7faa68a7abc8) 0 + vptr=((& QSocketNotifier::_ZTV15QSocketNotifier) + 16) + QObject (0x0x7faa68664120) 0 + primary-for QSocketNotifier (0x0x7faa68a7abc8) + +Class QSortFilterProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSortFilterProxyModel::QPrivateSignal (0x0x7faa686643c0) 0 empty + +Vtable for QSortFilterProxyModel +QSortFilterProxyModel::_ZTV21QSortFilterProxyModel: 56 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 (0x0x7faa68a7ac30) 0 + vptr=((& QSortFilterProxyModel::_ZTV21QSortFilterProxyModel) + 16) + QAbstractProxyModel (0x0x7faa68a7ac98) 0 + primary-for QSortFilterProxyModel (0x0x7faa68a7ac30) + QAbstractItemModel (0x0x7faa68a7ad00) 0 + primary-for QAbstractProxyModel (0x0x7faa68a7ac98) + QObject (0x0x7faa68664360) 0 + primary-for QAbstractItemModel (0x0x7faa68a7ad00) + +Class QStandardPaths + size=1 align=1 + base size=0 base align=1 +QStandardPaths (0x0x7faa686647e0) 0 empty + +Class QState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QState::QPrivateSignal (0x0x7faa686cd120) 0 empty + +Vtable for QState +QState::_ZTV6QState: 16 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 (0x0x7faa68a7aea0) 0 + vptr=((& QState::_ZTV6QState) + 16) + QAbstractState (0x0x7faa68a7af08) 0 + primary-for QState (0x0x7faa68a7aea0) + QObject (0x0x7faa686cd0c0) 0 + primary-for QAbstractState (0x0x7faa68a7af08) + +Class QStateMachine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStateMachine::QPrivateSignal (0x0x7faa686cd5a0) 0 empty + +Vtable for QStateMachine::SignalEvent +QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE: 4 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 (0x0x7faa686eb0d0) 0 + vptr=((& QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE) + 16) + QEvent (0x0x7faa686cd600) 0 + primary-for QStateMachine::SignalEvent (0x0x7faa686eb0d0) + +Vtable for QStateMachine::WrappedEvent +QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE: 4 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 (0x0x7faa686eb138) 0 + vptr=((& QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE) + 16) + QEvent (0x0x7faa686cd660) 0 + primary-for QStateMachine::WrappedEvent (0x0x7faa686eb138) + +Vtable for QStateMachine +QStateMachine::_ZTV13QStateMachine: 20 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 (0x0x7faa68a7af70) 0 + vptr=((& QStateMachine::_ZTV13QStateMachine) + 16) + QState (0x0x7faa686eb000) 0 + primary-for QStateMachine (0x0x7faa68a7af70) + QAbstractState (0x0x7faa686eb068) 0 + primary-for QState (0x0x7faa686eb000) + QObject (0x0x7faa686cd540) 0 + primary-for QAbstractState (0x0x7faa686eb068) + +Class QStorageInfo + size=8 align=8 + base size=8 base align=8 +QStorageInfo (0x0x7faa686cda20) 0 + +Class QAbstractConcatenable + size=1 align=1 + base size=0 base align=1 +QAbstractConcatenable (0x0x7faa687f27e0) 0 empty + +Class QStringListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStringListModel::QPrivateSignal (0x0x7faa6847ab40) 0 empty + +Vtable for QStringListModel +QStringListModel::_ZTV16QStringListModel: 48 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 (*)(...))QStringListModel::itemData +200 (int (*)(...))QStringListModel::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 (*)(...))QStringListModel::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 (0x0x7faa6846ea28) 0 + vptr=((& QStringListModel::_ZTV16QStringListModel) + 16) + QAbstractListModel (0x0x7faa6846ea90) 0 + primary-for QStringListModel (0x0x7faa6846ea28) + QAbstractItemModel (0x0x7faa6846eaf8) 0 + primary-for QAbstractListModel (0x0x7faa6846ea90) + QObject (0x0x7faa6847aae0) 0 + primary-for QAbstractItemModel (0x0x7faa6846eaf8) + +Class QSystemSemaphore + size=8 align=8 + base size=8 base align=8 +QSystemSemaphore (0x0x7faa6847ac60) 0 + +Class QTemporaryDir + size=8 align=8 + base size=8 base align=8 +QTemporaryDir (0x0x7faa6847ad20) 0 + +Class QTemporaryFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTemporaryFile::QPrivateSignal (0x0x7faa6847ae40) 0 empty + +Vtable for QTemporaryFile +QTemporaryFile::_ZTV14QTemporaryFile: 34 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 (0x0x7faa6846eb60) 0 + vptr=((& QTemporaryFile::_ZTV14QTemporaryFile) + 16) + QFile (0x0x7faa6846ebc8) 0 + primary-for QTemporaryFile (0x0x7faa6846eb60) + QFileDevice (0x0x7faa6846ec30) 0 + primary-for QFile (0x0x7faa6846ebc8) + QIODevice (0x0x7faa6846ec98) 0 + primary-for QFileDevice (0x0x7faa6846ec30) + QObject (0x0x7faa6847ade0) 0 + primary-for QIODevice (0x0x7faa6846ec98) + +Class QTextBoundaryFinder + size=48 align=8 + base size=48 base align=8 +QTextBoundaryFinder (0x0x7faa684d51e0) 0 + +Class QTextCodec::ConverterState + size=32 align=8 + base size=32 base align=8 +QTextCodec::ConverterState (0x0x7faa684d5a20) 0 + +Vtable for QTextCodec +QTextCodec::_ZTV10QTextCodec: 9 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 0 +64 0 + +Class QTextCodec + size=8 align=8 + base size=8 base align=8 +QTextCodec (0x0x7faa684d59c0) 0 nearly-empty + vptr=((& QTextCodec::_ZTV10QTextCodec) + 16) + +Class QTextEncoder + size=40 align=8 + base size=40 base align=8 +QTextEncoder (0x0x7faa6853a420) 0 + +Class QTextDecoder + size=40 align=8 + base size=40 base align=8 +QTextDecoder (0x0x7faa6853a600) 0 + +Vtable for std::thread::_State +std::thread::_State::_ZTVNSt6thread6_StateE: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt6thread6_StateE) +16 0 +24 0 +32 (int (*)(...))__cxa_pure_virtual + +Class std::thread::_State + size=8 align=8 + base size=8 base align=8 +std::thread::_State (0x0x7faa6853a840) 0 nearly-empty + vptr=((& std::thread::_State::_ZTVNSt6thread6_StateE) + 16) + +Class std::thread::id + size=8 align=8 + base size=8 base align=8 +std::thread::id (0x0x7faa6853a8a0) 0 + +Class std::thread + size=8 align=8 + base size=8 base align=8 +std::thread (0x0x7faa6853a7e0) 0 + +Class std::condition_variable + size=48 align=8 + base size=48 base align=8 +std::condition_variable (0x0x7faa683ddc60) 0 + +Class std::__at_thread_exit_elt + size=16 align=8 + base size=16 base align=8 +std::__at_thread_exit_elt (0x0x7faa6842a060) 0 + +Class std::_V2::condition_variable_any + size=64 align=8 + base size=64 base align=8 +std::_V2::condition_variable_any (0x0x7faa6842a0c0) 0 + +Class std::__atomic_futex_unsigned_base + size=1 align=1 + base size=0 base align=1 +std::__atomic_futex_unsigned_base (0x0x7faa681913c0) 0 empty + +Vtable for std::future_error +std::future_error::_ZTVSt12future_error: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt12future_error) +16 (int (*)(...))std::future_error::~future_error +24 (int (*)(...))std::future_error::~future_error +32 (int (*)(...))std::future_error::what + +Class std::future_error + size=32 align=8 + base size=32 base align=8 +std::future_error (0x0x7faa681b2068) 0 + vptr=((& std::future_error::_ZTVSt12future_error) + 16) + std::logic_error (0x0x7faa681b20d0) 0 + primary-for std::future_error (0x0x7faa681b2068) + std::exception (0x0x7faa68191ae0) 0 nearly-empty + primary-for std::logic_error (0x0x7faa681b20d0) + +Class std::__future_base::_Result_base::_Deleter + size=1 align=1 + base size=0 base align=1 +std::__future_base::_Result_base::_Deleter (0x0x7faa681c3240) 0 empty + +Vtable for std::__future_base::_Result_base +std::__future_base::_Result_base::_ZTVNSt13__future_base12_Result_baseE: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt13__future_base12_Result_baseE) +16 (int (*)(...))__cxa_pure_virtual +24 0 +32 0 + +Class std::__future_base::_Result_base + size=16 align=8 + base size=16 base align=8 +std::__future_base::_Result_base (0x0x7faa681c31e0) 0 + vptr=((& std::__future_base::_Result_base::_ZTVNSt13__future_base12_Result_baseE) + 16) + +Class std::__future_base::_State_baseV2::__exception_ptr_tag + size=1 align=1 + base size=0 base align=1 +std::__future_base::_State_baseV2::__exception_ptr_tag (0x0x7faa67fa3960) 0 empty + +Class std::__future_base::_State_baseV2::_Make_ready + size=32 align=8 + base size=32 base align=8 +std::__future_base::_State_baseV2::_Make_ready (0x0x7faa67f858f0) 0 + std::__at_thread_exit_elt (0x0x7faa67fa3a20) 0 + +Vtable for std::__future_base::_State_baseV2 +std::__future_base::_State_baseV2::_ZTVNSt13__future_base13_State_baseV2E: 6 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt13__future_base13_State_baseV2E) +16 (int (*)(...))std::__future_base::_State_baseV2::~_State_baseV2 +24 (int (*)(...))std::__future_base::_State_baseV2::~_State_baseV2 +32 (int (*)(...))std::__future_base::_State_baseV2::_M_complete_async +40 (int (*)(...))std::__future_base::_State_baseV2::_M_is_deferred_future + +Class std::__future_base::_State_baseV2 + size=32 align=8 + base size=28 base align=8 +std::__future_base::_State_baseV2 (0x0x7faa681c33c0) 0 + vptr=((& std::__future_base::_State_baseV2::_ZTVNSt13__future_base13_State_baseV2E) + 16) + +Class std::__future_base + size=1 align=1 + base size=0 base align=1 +std::__future_base (0x0x7faa681c3180) 0 empty + +Vtable for std::__future_base::_Async_state_commonV2 +std::__future_base::_Async_state_commonV2::_ZTVNSt13__future_base21_Async_state_commonV2E: 6 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt13__future_base21_Async_state_commonV2E) +16 (int (*)(...))std::__future_base::_Async_state_commonV2::~_Async_state_commonV2 +24 (int (*)(...))std::__future_base::_Async_state_commonV2::~_Async_state_commonV2 +32 (int (*)(...))std::__future_base::_Async_state_commonV2::_M_complete_async +40 (int (*)(...))std::__future_base::_State_baseV2::_M_is_deferred_future + +Class std::__future_base::_Async_state_commonV2 + size=48 align=8 + base size=44 base align=8 +std::__future_base::_Async_state_commonV2 (0x0x7faa67727618) 0 + vptr=((& std::__future_base::_Async_state_commonV2::_ZTVNSt13__future_base21_Async_state_commonV2E) + 16) + std::__future_base::_State_baseV2 (0x0x7faa67749a20) 0 + primary-for std::__future_base::_Async_state_commonV2 (0x0x7faa67727618) + +Class QThread::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThread::QPrivateSignal (0x0x7faa6777e300) 0 empty + +Vtable for QThread +QThread::_ZTV7QThread: 15 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 (0x0x7faa67727958) 0 + vptr=((& QThread::_ZTV7QThread) + 16) + QObject (0x0x7faa6777e2a0) 0 + primary-for QThread (0x0x7faa67727958) + +Class QThreadPool::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThreadPool::QPrivateSignal (0x0x7faa6777e6c0) 0 empty + +Vtable for QThreadPool +QThreadPool::_ZTV11QThreadPool: 14 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 (0x0x7faa677279c0) 0 + vptr=((& QThreadPool::_ZTV11QThreadPool) + 16) + QObject (0x0x7faa6777e660) 0 + primary-for QThreadPool (0x0x7faa677279c0) + +Class QThreadStorageData + size=4 align=4 + base size=4 base align=4 +QThreadStorageData (0x0x7faa6777e8a0) 0 + +Class QTimeLine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimeLine::QPrivateSignal (0x0x7faa6777ef60) 0 empty + +Vtable for QTimeLine +QTimeLine::_ZTV9QTimeLine: 15 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 (0x0x7faa67727a28) 0 + vptr=((& QTimeLine::_ZTV9QTimeLine) + 16) + QObject (0x0x7faa6777ef00) 0 + primary-for QTimeLine (0x0x7faa67727a28) + +Class QTimer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimer::QPrivateSignal (0x0x7faa677d01e0) 0 empty + +Vtable for QTimer +QTimer::_ZTV6QTimer: 14 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 (0x0x7faa67727a90) 0 + vptr=((& QTimer::_ZTV6QTimer) + 16) + QObject (0x0x7faa677d0180) 0 + primary-for QTimer (0x0x7faa67727a90) + +Class QTimeZone::OffsetData + size=32 align=8 + base size=28 base align=8 +QTimeZone::OffsetData (0x0x7faa67808b40) 0 + +Class QTimeZone + size=8 align=8 + base size=8 base align=8 +QTimeZone (0x0x7faa67808ae0) 0 + +Class QTranslator::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTranslator::QPrivateSignal (0x0x7faa674a6c00) 0 empty + +Vtable for QTranslator +QTranslator::_ZTV11QTranslator: 16 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 (0x0x7faa674bc1a0) 0 + vptr=((& QTranslator::_ZTV11QTranslator) + 16) + QObject (0x0x7faa674a6ba0) 0 + primary-for QTranslator (0x0x7faa674bc1a0) + +Class QTransposeProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTransposeProxyModel::QPrivateSignal (0x0x7faa674a6e40) 0 empty + +Vtable for QTransposeProxyModel +QTransposeProxyModel::_ZTV20QTransposeProxyModel: 53 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI20QTransposeProxyModel) +16 (int (*)(...))QTransposeProxyModel::metaObject +24 (int (*)(...))QTransposeProxyModel::qt_metacast +32 (int (*)(...))QTransposeProxyModel::qt_metacall +40 (int (*)(...))QTransposeProxyModel::~QTransposeProxyModel +48 (int (*)(...))QTransposeProxyModel::~QTransposeProxyModel +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 (*)(...))QTransposeProxyModel::index +120 (int (*)(...))QTransposeProxyModel::parent +128 (int (*)(...))QAbstractProxyModel::sibling +136 (int (*)(...))QTransposeProxyModel::rowCount +144 (int (*)(...))QTransposeProxyModel::columnCount +152 (int (*)(...))QAbstractProxyModel::hasChildren +160 (int (*)(...))QAbstractProxyModel::data +168 (int (*)(...))QAbstractProxyModel::setData +176 (int (*)(...))QTransposeProxyModel::headerData +184 (int (*)(...))QTransposeProxyModel::setHeaderData +192 (int (*)(...))QTransposeProxyModel::itemData +200 (int (*)(...))QTransposeProxyModel::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 (*)(...))QTransposeProxyModel::insertRows +264 (int (*)(...))QTransposeProxyModel::insertColumns +272 (int (*)(...))QTransposeProxyModel::removeRows +280 (int (*)(...))QTransposeProxyModel::removeColumns +288 (int (*)(...))QTransposeProxyModel::moveRows +296 (int (*)(...))QTransposeProxyModel::moveColumns +304 (int (*)(...))QAbstractProxyModel::fetchMore +312 (int (*)(...))QAbstractProxyModel::canFetchMore +320 (int (*)(...))QAbstractProxyModel::flags +328 (int (*)(...))QTransposeProxyModel::sort +336 (int (*)(...))QAbstractProxyModel::buddy +344 (int (*)(...))QAbstractItemModel::match +352 (int (*)(...))QTransposeProxyModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractProxyModel::submit +376 (int (*)(...))QAbstractProxyModel::revert +384 (int (*)(...))QTransposeProxyModel::setSourceModel +392 (int (*)(...))QTransposeProxyModel::mapToSource +400 (int (*)(...))QTransposeProxyModel::mapFromSource +408 (int (*)(...))QAbstractProxyModel::mapSelectionToSource +416 (int (*)(...))QAbstractProxyModel::mapSelectionFromSource + +Class QTransposeProxyModel + size=16 align=8 + base size=16 base align=8 +QTransposeProxyModel (0x0x7faa674bc208) 0 + vptr=((& QTransposeProxyModel::_ZTV20QTransposeProxyModel) + 16) + QAbstractProxyModel (0x0x7faa674bc270) 0 + primary-for QTransposeProxyModel (0x0x7faa674bc208) + QAbstractItemModel (0x0x7faa674bc2d8) 0 + primary-for QAbstractProxyModel (0x0x7faa674bc270) + QObject (0x0x7faa674a6de0) 0 + primary-for QAbstractItemModel (0x0x7faa674bc2d8) + +Class QUrlQuery + size=8 align=8 + base size=8 base align=8 +QUrlQuery (0x0x7faa674ec060) 0 + +Class QWaitCondition + size=8 align=8 + base size=8 base align=8 +QWaitCondition (0x0x7faa675c3540) 0 + +Class QXmlStreamStringRef + size=16 align=8 + base size=16 base align=8 +QXmlStreamStringRef (0x0x7faa675c3660) 0 + +Class QXmlStreamAttribute + size=80 align=8 + base size=73 base align=8 +QXmlStreamAttribute (0x0x7faa67154a20) 0 + +Class QXmlStreamAttributes + size=8 align=8 + base size=8 base align=8 +QXmlStreamAttributes (0x0x7faa671c75b0) 0 + QVector (0x0x7faa671cd180) 0 + +Class QXmlStreamNamespaceDeclaration + size=40 align=8 + base size=40 base align=8 +QXmlStreamNamespaceDeclaration (0x0x7faa671cd480) 0 + +Class QXmlStreamNotationDeclaration + size=56 align=8 + base size=56 base align=8 +QXmlStreamNotationDeclaration (0x0x7faa67259420) 0 + +Class QXmlStreamEntityDeclaration + size=88 align=8 + base size=88 base align=8 +QXmlStreamEntityDeclaration (0x0x7faa672b7420) 0 + +Vtable for QXmlStreamEntityResolver +QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver: 6 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 (0x0x7faa673224e0) 0 nearly-empty + vptr=((& QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver) + 16) + +Class QXmlStreamReader + size=8 align=8 + base size=8 base align=8 +QXmlStreamReader (0x0x7faa67322540) 0 + +Class QXmlStreamWriter + size=8 align=8 + base size=8 base align=8 +QXmlStreamWriter (0x0x7faa66f7f420) 0 + +Class QBluetoothAddress + size=8 align=8 + base size=8 base align=8 +QBluetoothAddress (0x0x7faa66fe53c0) 0 + +Class QBluetoothDeviceInfo + size=8 align=8 + base size=8 base align=8 +QBluetoothDeviceInfo (0x0x7faa66fe5720) 0 + +Class QBluetoothDeviceDiscoveryAgent::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothDeviceDiscoveryAgent::QPrivateSignal (0x0x7faa6704f840) 0 empty + +Vtable for QBluetoothDeviceDiscoveryAgent +QBluetoothDeviceDiscoveryAgent::_ZTV30QBluetoothDeviceDiscoveryAgent: 14 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI30QBluetoothDeviceDiscoveryAgent) +16 (int (*)(...))QBluetoothDeviceDiscoveryAgent::metaObject +24 (int (*)(...))QBluetoothDeviceDiscoveryAgent::qt_metacast +32 (int (*)(...))QBluetoothDeviceDiscoveryAgent::qt_metacall +40 (int (*)(...))QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent +48 (int (*)(...))QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent +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 QBluetoothDeviceDiscoveryAgent + size=24 align=8 + base size=24 base align=8 +QBluetoothDeviceDiscoveryAgent (0x0x7faa66f805b0) 0 + vptr=((& QBluetoothDeviceDiscoveryAgent::_ZTV30QBluetoothDeviceDiscoveryAgent) + 16) + QObject (0x0x7faa6704f7e0) 0 + primary-for QBluetoothDeviceDiscoveryAgent (0x0x7faa66f805b0) + +Class QBluetoothHostInfo + size=8 align=8 + base size=8 base align=8 +QBluetoothHostInfo (0x0x7faa670b7360) 0 + +Class QBluetoothLocalDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothLocalDevice::QPrivateSignal (0x0x7faa670b76c0) 0 empty + +Vtable for QBluetoothLocalDevice +QBluetoothLocalDevice::_ZTV21QBluetoothLocalDevice: 14 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QBluetoothLocalDevice) +16 (int (*)(...))QBluetoothLocalDevice::metaObject +24 (int (*)(...))QBluetoothLocalDevice::qt_metacast +32 (int (*)(...))QBluetoothLocalDevice::qt_metacall +40 (int (*)(...))QBluetoothLocalDevice::~QBluetoothLocalDevice +48 (int (*)(...))QBluetoothLocalDevice::~QBluetoothLocalDevice +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 QBluetoothLocalDevice + size=24 align=8 + base size=24 base align=8 +QBluetoothLocalDevice (0x0x7faa66f806e8) 0 + vptr=((& QBluetoothLocalDevice::_ZTV21QBluetoothLocalDevice) + 16) + QObject (0x0x7faa670b7660) 0 + primary-for QBluetoothLocalDevice (0x0x7faa66f806e8) + +Class quint128 + size=16 align=1 + base size=16 base align=1 +quint128 (0x0x7faa670fb0c0) 0 + +Class QBluetoothUuid + size=16 align=4 + base size=16 base align=4 +QBluetoothUuid (0x0x7faa66f80750) 0 + QUuid (0x0x7faa670fb120) 0 + +Class QBluetoothServiceInfo::Sequence + size=8 align=8 + base size=8 base align=8 +QBluetoothServiceInfo::Sequence (0x0x7faa66f807b8) 0 + QList (0x0x7faa66f80820) 0 + QListSpecialMethods (0x0x7faa670fb660) 0 empty + +Class QBluetoothServiceInfo::Alternative + size=8 align=8 + base size=8 base align=8 +QBluetoothServiceInfo::Alternative (0x0x7faa66f80888) 0 + QList (0x0x7faa66f808f0) 0 + QListSpecialMethods (0x0x7faa670fb6c0) 0 empty + +Class QBluetoothServiceInfo + size=16 align=8 + base size=16 base align=8 +QBluetoothServiceInfo (0x0x7faa670fb600) 0 + +Class QAbstractSocket::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractSocket::QPrivateSignal (0x0x7faa66d848a0) 0 empty + +Vtable for QAbstractSocket +QAbstractSocket::_ZTV15QAbstractSocket: 41 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QAbstractSocket) +16 (int (*)(...))QAbstractSocket::metaObject +24 (int (*)(...))QAbstractSocket::qt_metacast +32 (int (*)(...))QAbstractSocket::qt_metacall +40 (int (*)(...))QAbstractSocket::~QAbstractSocket +48 (int (*)(...))QAbstractSocket::~QAbstractSocket +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 (*)(...))QAbstractSocket::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QAbstractSocket::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QAbstractSocket::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QAbstractSocket::bytesAvailable +184 (int (*)(...))QAbstractSocket::bytesToWrite +192 (int (*)(...))QAbstractSocket::canReadLine +200 (int (*)(...))QAbstractSocket::waitForReadyRead +208 (int (*)(...))QAbstractSocket::waitForBytesWritten +216 (int (*)(...))QAbstractSocket::readData +224 (int (*)(...))QAbstractSocket::readLineData +232 (int (*)(...))QAbstractSocket::writeData +240 (int (*)(...))QAbstractSocket::resume +248 (int (*)(...))QAbstractSocket::connectToHost +256 (int (*)(...))QAbstractSocket::connectToHost +264 (int (*)(...))QAbstractSocket::disconnectFromHost +272 (int (*)(...))QAbstractSocket::setReadBufferSize +280 (int (*)(...))QAbstractSocket::socketDescriptor +288 (int (*)(...))QAbstractSocket::setSocketDescriptor +296 (int (*)(...))QAbstractSocket::setSocketOption +304 (int (*)(...))QAbstractSocket::socketOption +312 (int (*)(...))QAbstractSocket::waitForConnected +320 (int (*)(...))QAbstractSocket::waitForDisconnected + +Class QAbstractSocket + size=16 align=8 + base size=16 base align=8 +QAbstractSocket (0x0x7faa66f80958) 0 + vptr=((& QAbstractSocket::_ZTV15QAbstractSocket) + 16) + QIODevice (0x0x7faa66f809c0) 0 + primary-for QAbstractSocket (0x0x7faa66f80958) + QObject (0x0x7faa66d84840) 0 + primary-for QIODevice (0x0x7faa66f809c0) + +Class QBluetoothSocket::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothSocket::QPrivateSignal (0x0x7faa66e37060) 0 empty + +Vtable for QBluetoothSocket +QBluetoothSocket::_ZTV16QBluetoothSocket: 30 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QBluetoothSocket) +16 (int (*)(...))QBluetoothSocket::metaObject +24 (int (*)(...))QBluetoothSocket::qt_metacast +32 (int (*)(...))QBluetoothSocket::qt_metacall +40 (int (*)(...))QBluetoothSocket::~QBluetoothSocket +48 (int (*)(...))QBluetoothSocket::~QBluetoothSocket +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 (*)(...))QBluetoothSocket::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QBluetoothSocket::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QIODevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QBluetoothSocket::bytesAvailable +184 (int (*)(...))QBluetoothSocket::bytesToWrite +192 (int (*)(...))QBluetoothSocket::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QBluetoothSocket::readData +224 (int (*)(...))QIODevice::readLineData +232 (int (*)(...))QBluetoothSocket::writeData + +Class QBluetoothSocket + size=24 align=8 + base size=24 base align=8 +QBluetoothSocket (0x0x7faa66f80bc8) 0 + vptr=((& QBluetoothSocket::_ZTV16QBluetoothSocket) + 16) + QIODevice (0x0x7faa66f80c30) 0 + primary-for QBluetoothSocket (0x0x7faa66f80bc8) + QObject (0x0x7faa66e37000) 0 + primary-for QIODevice (0x0x7faa66f80c30) + +Class QBluetoothServer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothServer::QPrivateSignal (0x0x7faa66e37480) 0 empty + +Vtable for QBluetoothServer +QBluetoothServer::_ZTV16QBluetoothServer: 14 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QBluetoothServer) +16 (int (*)(...))QBluetoothServer::metaObject +24 (int (*)(...))QBluetoothServer::qt_metacast +32 (int (*)(...))QBluetoothServer::qt_metacall +40 (int (*)(...))QBluetoothServer::~QBluetoothServer +48 (int (*)(...))QBluetoothServer::~QBluetoothServer +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 QBluetoothServer + size=24 align=8 + base size=24 base align=8 +QBluetoothServer (0x0x7faa66f80c98) 0 + vptr=((& QBluetoothServer::_ZTV16QBluetoothServer) + 16) + QObject (0x0x7faa66e37420) 0 + primary-for QBluetoothServer (0x0x7faa66f80c98) + +Class QBluetoothServiceDiscoveryAgent::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothServiceDiscoveryAgent::QPrivateSignal (0x0x7faa66e37780) 0 empty + +Vtable for QBluetoothServiceDiscoveryAgent +QBluetoothServiceDiscoveryAgent::_ZTV31QBluetoothServiceDiscoveryAgent: 14 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI31QBluetoothServiceDiscoveryAgent) +16 (int (*)(...))QBluetoothServiceDiscoveryAgent::metaObject +24 (int (*)(...))QBluetoothServiceDiscoveryAgent::qt_metacast +32 (int (*)(...))QBluetoothServiceDiscoveryAgent::qt_metacall +40 (int (*)(...))QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent +48 (int (*)(...))QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent +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 QBluetoothServiceDiscoveryAgent + size=24 align=8 + base size=24 base align=8 +QBluetoothServiceDiscoveryAgent (0x0x7faa66f80d00) 0 + vptr=((& QBluetoothServiceDiscoveryAgent::_ZTV31QBluetoothServiceDiscoveryAgent) + 16) + QObject (0x0x7faa66e37720) 0 + primary-for QBluetoothServiceDiscoveryAgent (0x0x7faa66f80d00) + +Class QBluetoothTransferManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothTransferManager::QPrivateSignal (0x0x7faa66e37b40) 0 empty + +Vtable for QBluetoothTransferManager +QBluetoothTransferManager::_ZTV25QBluetoothTransferManager: 14 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI25QBluetoothTransferManager) +16 (int (*)(...))QBluetoothTransferManager::metaObject +24 (int (*)(...))QBluetoothTransferManager::qt_metacast +32 (int (*)(...))QBluetoothTransferManager::qt_metacall +40 (int (*)(...))QBluetoothTransferManager::~QBluetoothTransferManager +48 (int (*)(...))QBluetoothTransferManager::~QBluetoothTransferManager +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 QBluetoothTransferManager + size=16 align=8 + base size=16 base align=8 +QBluetoothTransferManager (0x0x7faa66f80d68) 0 + vptr=((& QBluetoothTransferManager::_ZTV25QBluetoothTransferManager) + 16) + QObject (0x0x7faa66e37ae0) 0 + primary-for QBluetoothTransferManager (0x0x7faa66f80d68) + +Class QBluetoothTransferRequest + size=8 align=8 + base size=8 base align=8 +QBluetoothTransferRequest (0x0x7faa66e37c60) 0 + +Class QBluetoothTransferReply::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothTransferReply::QPrivateSignal (0x0x7faa66e37de0) 0 empty + +Vtable for QBluetoothTransferReply +QBluetoothTransferReply::_ZTV23QBluetoothTransferReply: 18 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI23QBluetoothTransferReply) +16 (int (*)(...))QBluetoothTransferReply::metaObject +24 (int (*)(...))QBluetoothTransferReply::qt_metacast +32 (int (*)(...))QBluetoothTransferReply::qt_metacall +40 0 +48 0 +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 + +Class QBluetoothTransferReply + size=24 align=8 + base size=24 base align=8 +QBluetoothTransferReply (0x0x7faa66f80dd0) 0 + vptr=((& QBluetoothTransferReply::_ZTV23QBluetoothTransferReply) + 16) + QObject (0x0x7faa66e37d80) 0 + primary-for QBluetoothTransferReply (0x0x7faa66f80dd0) + +Class QLowEnergyAdvertisingData + size=8 align=8 + base size=8 base align=8 +QLowEnergyAdvertisingData (0x0x7faa66ea72a0) 0 + +Class QLowEnergyDescriptor + size=24 align=8 + base size=24 base align=8 +QLowEnergyDescriptor (0x0x7faa66b764e0) 0 + +Class QLowEnergyCharacteristic + size=24 align=8 + base size=24 base align=8 +QLowEnergyCharacteristic (0x0x7faa66b76780) 0 + +Class QLowEnergyService::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLowEnergyService::QPrivateSignal (0x0x7faa66bf0120) 0 empty + +Vtable for QLowEnergyService +QLowEnergyService::_ZTV17QLowEnergyService: 14 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QLowEnergyService) +16 (int (*)(...))QLowEnergyService::metaObject +24 (int (*)(...))QLowEnergyService::qt_metacast +32 (int (*)(...))QLowEnergyService::qt_metacall +40 (int (*)(...))QLowEnergyService::~QLowEnergyService +48 (int (*)(...))QLowEnergyService::~QLowEnergyService +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 QLowEnergyService + size=32 align=8 + base size=32 base align=8 +QLowEnergyService (0x0x7faa66bc50d0) 0 + vptr=((& QLowEnergyService::_ZTV17QLowEnergyService) + 16) + QObject (0x0x7faa66bf00c0) 0 + primary-for QLowEnergyService (0x0x7faa66bc50d0) + +Class QLowEnergyController::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLowEnergyController::QPrivateSignal (0x0x7faa66c4a4e0) 0 empty + +Vtable for QLowEnergyController +QLowEnergyController::_ZTV20QLowEnergyController: 14 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI20QLowEnergyController) +16 (int (*)(...))QLowEnergyController::metaObject +24 (int (*)(...))QLowEnergyController::qt_metacast +32 (int (*)(...))QLowEnergyController::qt_metacall +40 (int (*)(...))QLowEnergyController::~QLowEnergyController +48 (int (*)(...))QLowEnergyController::~QLowEnergyController +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 QLowEnergyController + size=24 align=8 + base size=24 base align=8 +QLowEnergyController (0x0x7faa66bc5208) 0 + vptr=((& QLowEnergyController::_ZTV20QLowEnergyController) + 16) + QObject (0x0x7faa66c4a480) 0 + primary-for QLowEnergyController (0x0x7faa66bc5208) + +Class QLowEnergyAdvertisingParameters::AddressInfo + size=16 align=8 + base size=12 base align=8 +QLowEnergyAdvertisingParameters::AddressInfo (0x0x7faa66c941e0) 0 + +Class QLowEnergyAdvertisingParameters + size=8 align=8 + base size=8 base align=8 +QLowEnergyAdvertisingParameters (0x0x7faa66c94180) 0 + +Class QLowEnergyCharacteristicData + size=8 align=8 + base size=8 base align=8 +QLowEnergyCharacteristicData (0x0x7faa66965f00) 0 + +Class QLowEnergyConnectionParameters + size=8 align=8 + base size=8 base align=8 +QLowEnergyConnectionParameters (0x0x7faa66a56060) 0 + +Class QLowEnergyDescriptorData + size=8 align=8 + base size=8 base align=8 +QLowEnergyDescriptorData (0x0x7faa66b1b420) 0 + +Class QLowEnergyServiceData + size=8 align=8 + base size=8 base align=8 +QLowEnergyServiceData (0x0x7faa667e3900) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7faa668fc000) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7faa668fc360) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7faa668fc540) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7faa668fc8a0) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7faa668fca80) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7faa668fcde0) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7faa6693a000) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7faa6693a360) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7faa6693a540) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7faa6693a8a0) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7faa6693aa80) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7faa6693ade0) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7faa66570000) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7faa66570360) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7faa66570540) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7faa665708a0) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7faa6659dd80) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7faa665cc120) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7faa665cc2a0) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7faa665cc600) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7faa665cc780) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7faa665ccae0) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7faa665ccc60) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7faa665fd000) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7faa665fd180) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7faa665fd4e0) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7faa665fd660) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7faa665fd9c0) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7faa665fdb40) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7faa665fdea0) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7faa6662d060) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7faa6662d3c0) 0 empty + diff --git a/tests/auto/bic/data/QtBluetooth.5.2.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtBluetooth.5.2.0.linux-gcc-amd64.txt new file mode 100644 index 0000000..be0a7dc --- /dev/null +++ b/tests/auto/bic/data/QtBluetooth.5.2.0.linux-gcc-amd64.txt @@ -0,0 +1,3931 @@ +Class std::__true_type + size=1 align=1 + base size=0 base align=1 +std::__true_type (0x0x7fd1f95e4060) 0 empty + +Class std::__false_type + size=1 align=1 + base size=0 base align=1 +std::__false_type (0x0x7fd1f95e40c0) 0 empty + +Class std::input_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::input_iterator_tag (0x0x7fd1f9625c60) 0 empty + +Class std::output_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::output_iterator_tag (0x0x7fd1f9625cc0) 0 empty + +Class std::forward_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::forward_iterator_tag (0x0x7fd1f95b1548) 0 empty + std::input_iterator_tag (0x0x7fd1f9625d20) 0 empty + +Class std::bidirectional_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::bidirectional_iterator_tag (0x0x7fd1f95b15b0) 0 empty + std::forward_iterator_tag (0x0x7fd1f95b1618) 0 empty + std::input_iterator_tag (0x0x7fd1f9625d80) 0 empty + +Class std::random_access_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::random_access_iterator_tag (0x0x7fd1f95b1680) 0 empty + std::bidirectional_iterator_tag (0x0x7fd1f95b16e8) 0 empty + std::forward_iterator_tag (0x0x7fd1f95b1750) 0 empty + std::input_iterator_tag (0x0x7fd1f9625de0) 0 empty + +Class wait + size=4 align=4 + base size=4 base align=4 +wait (0x0x7fd1f9658960) 0 + +Class __locale_struct + size=232 align=8 + base size=232 base align=8 +__locale_struct (0x0x7fd1f9658ba0) 0 + +Class timespec + size=16 align=8 + base size=16 base align=8 +timespec (0x0x7fd1f9658c60) 0 + +Class timeval + size=16 align=8 + base size=16 base align=8 +timeval (0x0x7fd1f9658cc0) 0 + +Class pthread_attr_t + size=56 align=8 + base size=56 base align=8 +pthread_attr_t (0x0x7fd1f9658d80) 0 + +Class __pthread_internal_list + size=16 align=8 + base size=16 base align=8 +__pthread_internal_list (0x0x7fd1f9658de0) 0 + +Class random_data + size=48 align=8 + base size=48 base align=8 +random_data (0x0x7fd1f97402a0) 0 + +Class drand48_data + size=24 align=8 + base size=24 base align=8 +drand48_data (0x0x7fd1f9740300) 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 (0x0x7fd1f9740360) 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 (0x0x7fd1f95b1a90) 0 nearly-empty + vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16u) + std::exception (0x0x7fd1f97403c0) 0 nearly-empty + primary-for std::bad_exception (0x0x7fd1f95b1a90) + +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 (0x0x7fd1f95b1af8) 0 nearly-empty + vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16u) + std::exception (0x0x7fd1f9740420) 0 nearly-empty + primary-for std::bad_alloc (0x0x7fd1f95b1af8) + +Class std::nothrow_t + size=1 align=1 + base size=0 base align=1 +std::nothrow_t (0x0x7fd1f9740480) 0 empty + +Class qIsNull(double)::U + size=8 align=8 + base size=8 base align=8 +qIsNull(double)::U (0x0x7fd1f85387e0) 0 + +Class qIsNull(float)::U + size=4 align=4 + base size=4 base align=4 +qIsNull(float)::U (0x0x7fd1f8538840) 0 + +Class QAtomicInt + size=4 align=4 + base size=4 base align=4 +QAtomicInt (0x0x7fd1f81da548) 0 + QBasicAtomicInteger (0x0x7fd1f823a4e0) 0 + +Class QMessageLogContext + size=32 align=8 + base size=32 base align=8 +QMessageLogContext (0x0x7fd1f823a6c0) 0 + +Class QMessageLogger + size=32 align=8 + base size=32 base align=8 +QMessageLogger (0x0x7fd1f823a720) 0 + +Class QtPrivate::big_ + size=2 align=1 + base size=2 base align=1 +QtPrivate::big_ (0x0x7fd1f7f81180) 0 + +Class QFlag + size=4 align=4 + base size=4 base align=4 +QFlag (0x0x7fd1f7fced80) 0 + +Class QIncompatibleFlag + size=4 align=4 + base size=4 base align=4 +QIncompatibleFlag (0x0x7fd1f7fcee40) 0 + +Class QSysInfo + size=1 align=1 + base size=0 base align=1 +QSysInfo (0x0x7fd1f7fcef60) 0 empty + +Class QInternal + size=1 align=1 + base size=0 base align=1 +QInternal (0x0x7fd1f8094e40) 0 empty + +Class QGenericArgument + size=16 align=8 + base size=16 base align=8 +QGenericArgument (0x0x7fd1f7e2ed80) 0 + +Class QGenericReturnArgument + size=16 align=8 + base size=16 base align=8 +QGenericReturnArgument (0x0x7fd1f80aad68) 0 + QGenericArgument (0x0x7fd1f7e2ede0) 0 + +Class QMetaObject + size=48 align=8 + base size=48 base align=8 +QMetaObject (0x0x7fd1f7e2ef60) 0 + +Class QMetaObject::Connection + size=8 align=8 + base size=8 base align=8 +QMetaObject::Connection (0x0x7fd1f7ea10c0) 0 + +Class QLatin1Char + size=1 align=1 + base size=1 base align=1 +QLatin1Char (0x0x7fd1f7ea1300) 0 + +Class QChar + size=2 align=2 + base size=2 base align=2 +QChar (0x0x7fd1f7ea1360) 0 + +Class QtPrivate::RefCount + size=4 align=4 + base size=4 base align=4 +QtPrivate::RefCount (0x0x7fd1f7ea1420) 0 + +Class QArrayData + size=24 align=8 + base size=24 base align=8 +QArrayData (0x0x7fd1f7ea1480) 0 + +Class QByteArrayDataPtr + size=8 align=8 + base size=8 base align=8 +QByteArrayDataPtr (0x0x7fd1f7ea17e0) 0 + +Class QByteArray + size=8 align=8 + base size=8 base align=8 +QByteArray (0x0x7fd1f7ea1840) 0 + +Class QByteRef + size=16 align=8 + base size=12 base align=8 +QByteRef (0x0x7fd1f7ea19c0) 0 + +Class lconv + size=96 align=8 + base size=96 base align=8 +lconv (0x0x7fd1f7ea1d80) 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 (0x0x7fd1f7ea1de0) 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 (0x0x7fd1f79838a0) 0 + +Class __sched_param + size=4 align=4 + base size=4 base align=4 +__sched_param (0x0x7fd1f7983900) 0 + +Class timex + size=208 align=8 + base size=208 base align=8 +timex (0x0x7fd1f79839c0) 0 + +Class tm + size=56 align=8 + base size=56 base align=8 +tm (0x0x7fd1f7983a20) 0 + +Class itimerspec + size=32 align=8 + base size=32 base align=8 +itimerspec (0x0x7fd1f7983a80) 0 + +Class _pthread_cleanup_buffer + size=32 align=8 + base size=32 base align=8 +_pthread_cleanup_buffer (0x0x7fd1f7983ae0) 0 + +Class __pthread_cleanup_frame + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_frame (0x0x7fd1f7983c00) 0 + +Class __pthread_cleanup_class + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_class (0x0x7fd1f7983c60) 0 + +Class QLatin1String + size=16 align=8 + base size=16 base align=8 +QLatin1String (0x0x7fd1f775e3c0) 0 + +Class QStringDataPtr + size=8 align=8 + base size=8 base align=8 +QStringDataPtr (0x0x7fd1f775e4e0) 0 + +Class QString::Null + size=1 align=1 + base size=0 base align=1 +QString::Null (0x0x7fd1f775e5a0) 0 empty + +Class QString + size=8 align=8 + base size=8 base align=8 +QString (0x0x7fd1f775e540) 0 + +Class QCharRef + size=16 align=8 + base size=12 base align=8 +QCharRef (0x0x7fd1f775e720) 0 + +Class QStringRef + size=16 align=8 + base size=16 base align=8 +QStringRef (0x0x7fd1f775e900) 0 + +Class std::locale + size=8 align=8 + base size=8 base align=8 +std::locale (0x0x7fd1f775ea80) 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 (0x0x7fd1f775eae0) 0 + vptr=((& std::locale::facet::_ZTVNSt6locale5facetE) + 16u) + +Class std::locale::id + size=8 align=8 + base size=8 base align=8 +std::locale::id (0x0x7fd1f775eb40) 0 + +Class std::locale::_Impl + size=40 align=8 + base size=40 base align=8 +std::locale::_Impl (0x0x7fd1f775eba0) 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 (0x0x7fd1f77343a8) 0 + vptr=((& std::ios_base::failure::_ZTVNSt8ios_base7failureE) + 16u) + std::exception (0x0x7fd1f7376000) 0 nearly-empty + primary-for std::ios_base::failure (0x0x7fd1f77343a8) + +Class std::ios_base::_Callback_list + size=24 align=8 + base size=24 base align=8 +std::ios_base::_Callback_list (0x0x7fd1f7376060) 0 + +Class std::ios_base::_Words + size=16 align=8 + base size=16 base align=8 +std::ios_base::_Words (0x0x7fd1f73760c0) 0 + +Class std::ios_base::Init + size=1 align=1 + base size=0 base align=1 +std::ios_base::Init (0x0x7fd1f7376120) 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 (0x0x7fd1f775ef60) 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 (0x0x7fd1f73762a0) 0 empty + +Class std::__num_base + size=1 align=1 + base size=0 base align=1 +std::__num_base (0x0x7fd1f7376960) 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 (0x0x7fd1f72da820 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 (0x0x7fd1f72dae38 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 (0x0x7fd1f6fee270 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 (0x0x7fd1f6fee340 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 (0x0x7fd1f71b4d20) 0 + +Class QListData::Data + size=24 align=8 + base size=24 base align=8 +QListData::Data (0x0x7fd1f70b3060) 0 + +Class QListData + size=8 align=8 + base size=8 base align=8 +QListData (0x0x7fd1f70b3000) 0 + +Class QScopedPointerPodDeleter + size=1 align=1 + base size=0 base align=1 +QScopedPointerPodDeleter (0x0x7fd1f70b3420) 0 empty + +Class std::_Bit_reference + size=16 align=8 + base size=16 base align=8 +std::_Bit_reference (0x0x7fd1f6e1e240) 0 + +Class std::_Bit_iterator_base + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator_base (0x0x7fd1f6feea28) 0 + std::iterator (0x0x7fd1f6e1e300) 0 empty + +Class std::_Bit_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator (0x0x7fd1f6feea90) 0 + std::_Bit_iterator_base (0x0x7fd1f6feeaf8) 0 + std::iterator (0x0x7fd1f6e1e360) 0 empty + +Class std::_Bit_const_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_const_iterator (0x0x7fd1f6feeb60) 0 + std::_Bit_iterator_base (0x0x7fd1f6feebc8) 0 + std::iterator (0x0x7fd1f6e1e3c0) 0 empty + +Class std::_Rb_tree_node_base + size=32 align=8 + base size=32 base align=8 +std::_Rb_tree_node_base (0x0x7fd1f6e1e780) 0 + +Class QtPrivate::AbstractDebugStreamFunction + size=16 align=8 + base size=16 base align=8 +QtPrivate::AbstractDebugStreamFunction (0x0x7fd1f6e1eba0) 0 + +Class QtPrivate::AbstractComparatorFunction + size=24 align=8 + base size=24 base align=8 +QtPrivate::AbstractComparatorFunction (0x0x7fd1f6e1ec60) 0 + +Class QtPrivate::AbstractConverterFunction + size=8 align=8 + base size=8 base align=8 +QtPrivate::AbstractConverterFunction (0x0x7fd1f6e1ed20) 0 + +Class QMetaType + size=80 align=8 + base size=80 base align=8 +QMetaType (0x0x7fd1f6cef180) 0 + +Class QtMetaTypePrivate::VariantData + size=24 align=8 + base size=20 base align=8 +QtMetaTypePrivate::VariantData (0x0x7fd1f6cef4e0) 0 + +Class QtMetaTypePrivate::QSequentialIterableImpl + size=104 align=8 + base size=104 base align=8 +QtMetaTypePrivate::QSequentialIterableImpl (0x0x7fd1f6cef900) 0 + +Class QtMetaTypePrivate::QAssociativeIterableImpl + size=112 align=8 + base size=112 base align=8 +QtMetaTypePrivate::QAssociativeIterableImpl (0x0x7fd1f6cefae0) 0 + +Class QtMetaTypePrivate::QPairVariantInterfaceImpl + size=40 align=8 + base size=40 base align=8 +QtMetaTypePrivate::QPairVariantInterfaceImpl (0x0x7fd1f6cefba0) 0 + +Class QtPrivate::QSlotObjectBase + size=16 align=8 + base size=16 base align=8 +QtPrivate::QSlotObjectBase (0x0x7fd1f6b09e40) 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 (0x0x7fd1f677a000) 0 + vptr=((& QObjectData::_ZTV11QObjectData) + 16u) + +Class QObject::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObject::QPrivateSignal (0x0x7fd1f677a180) 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 (0x0x7fd1f677a120) 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 (0x0x7fd1f677a480) 0 nearly-empty + vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16u) + +Class QAbstractAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractAnimation::QPrivateSignal (0x0x7fd1f677a540) 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 (0x0x7fd1f676e3a8) 0 + vptr=((& QAbstractAnimation::_ZTV18QAbstractAnimation) + 16u) + QObject (0x0x7fd1f677a4e0) 0 + primary-for QAbstractAnimation (0x0x7fd1f676e3a8) + +Class QAnimationDriver::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationDriver::QPrivateSignal (0x0x7fd1f677a600) 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 (0x0x7fd1f676e410) 0 + vptr=((& QAnimationDriver::_ZTV16QAnimationDriver) + 16u) + QObject (0x0x7fd1f677a5a0) 0 + primary-for QAnimationDriver (0x0x7fd1f676e410) + +Class QAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationGroup::QPrivateSignal (0x0x7fd1f677a6c0) 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 (0x0x7fd1f676e478) 0 + vptr=((& QAnimationGroup::_ZTV15QAnimationGroup) + 16u) + QAbstractAnimation (0x0x7fd1f676e4e0) 0 + primary-for QAnimationGroup (0x0x7fd1f676e478) + QObject (0x0x7fd1f677a660) 0 + primary-for QAbstractAnimation (0x0x7fd1f676e4e0) + +Class QParallelAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QParallelAnimationGroup::QPrivateSignal (0x0x7fd1f677a780) 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 (0x0x7fd1f676e548) 0 + vptr=((& QParallelAnimationGroup::_ZTV23QParallelAnimationGroup) + 16u) + QAnimationGroup (0x0x7fd1f676e5b0) 0 + primary-for QParallelAnimationGroup (0x0x7fd1f676e548) + QAbstractAnimation (0x0x7fd1f676e618) 0 + primary-for QAnimationGroup (0x0x7fd1f676e5b0) + QObject (0x0x7fd1f677a720) 0 + primary-for QAbstractAnimation (0x0x7fd1f676e618) + +Class QPauseAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPauseAnimation::QPrivateSignal (0x0x7fd1f677a840) 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 (0x0x7fd1f676e680) 0 + vptr=((& QPauseAnimation::_ZTV15QPauseAnimation) + 16u) + QAbstractAnimation (0x0x7fd1f676e6e8) 0 + primary-for QPauseAnimation (0x0x7fd1f676e680) + QObject (0x0x7fd1f677a7e0) 0 + primary-for QAbstractAnimation (0x0x7fd1f676e6e8) + +Class QEasingCurve + size=8 align=8 + base size=8 base align=8 +QEasingCurve (0x0x7fd1f677aa20) 0 + +Class QMapNodeBase + size=24 align=8 + base size=24 base align=8 +QMapNodeBase (0x0x7fd1f677aba0) 0 + +Class QMapDataBase + size=40 align=8 + base size=40 base align=8 +QMapDataBase (0x0x7fd1f677ac60) 0 + +Class QHashData::Node + size=16 align=8 + base size=16 base align=8 +QHashData::Node (0x0x7fd1f6659000) 0 + +Class QHashData + size=48 align=8 + base size=48 base align=8 +QHashData (0x0x7fd1f677af60) 0 + +Class QHashDummyValue + size=1 align=1 + base size=0 base align=1 +QHashDummyValue (0x0x7fd1f6659060) 0 empty + +Class QIODevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIODevice::QPrivateSignal (0x0x7fd1f66594e0) 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 (0x0x7fd1f676ef08) 0 + vptr=((& QIODevice::_ZTV9QIODevice) + 16u) + QObject (0x0x7fd1f6659480) 0 + primary-for QIODevice (0x0x7fd1f676ef08) + +Class QDataStream + size=32 align=8 + base size=32 base align=8 +QDataStream (0x0x7fd1f6659600) 0 + +Class QRegExp + size=8 align=8 + base size=8 base align=8 +QRegExp (0x0x7fd1f66596c0) 0 + +Class QStringMatcher::Data + size=272 align=8 + base size=272 base align=8 +QStringMatcher::Data (0x0x7fd1f66597e0) 0 + +Class QStringMatcher + size=1048 align=8 + base size=1048 base align=8 +QStringMatcher (0x0x7fd1f6659780) 0 + +Class QStringList + size=8 align=8 + base size=8 base align=8 +QStringList (0x0x7fd1f63e4000) 0 + QList (0x0x7fd1f6659960) 0 + +Class QVariant::PrivateShared + size=16 align=8 + base size=12 base align=8 +QVariant::PrivateShared (0x0x7fd1f6659c00) 0 + +Class QVariant::Private::Data + size=8 align=8 + base size=8 base align=8 +QVariant::Private::Data (0x0x7fd1f6659cc0) 0 + +Class QVariant::Private + size=16 align=8 + base size=12 base align=8 +QVariant::Private (0x0x7fd1f6659c60) 0 + +Class QVariant::Handler + size=72 align=8 + base size=72 base align=8 +QVariant::Handler (0x0x7fd1f6659d20) 0 + +Class QVariant + size=16 align=8 + base size=16 base align=8 +QVariant (0x0x7fd1f6659ba0) 0 + +Class QVariantComparisonHelper + size=8 align=8 + base size=8 base align=8 +QVariantComparisonHelper (0x0x7fd1f64e7000) 0 + +Class QSequentialIterable::const_iterator + size=112 align=8 + base size=112 base align=8 +QSequentialIterable::const_iterator (0x0x7fd1f64e70c0) 0 + +Class QSequentialIterable + size=104 align=8 + base size=104 base align=8 +QSequentialIterable (0x0x7fd1f64e7060) 0 + +Class QAssociativeIterable::const_iterator + size=120 align=8 + base size=120 base align=8 +QAssociativeIterable::const_iterator (0x0x7fd1f64e7180) 0 + +Class QAssociativeIterable + size=112 align=8 + base size=112 base align=8 +QAssociativeIterable (0x0x7fd1f64e7120) 0 + +Class QVariantAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QVariantAnimation::QPrivateSignal (0x0x7fd1f64e7cc0) 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 (0x0x7fd1f63e4958) 0 + vptr=((& QVariantAnimation::_ZTV17QVariantAnimation) + 16u) + QAbstractAnimation (0x0x7fd1f63e49c0) 0 + primary-for QVariantAnimation (0x0x7fd1f63e4958) + QObject (0x0x7fd1f64e7c60) 0 + primary-for QAbstractAnimation (0x0x7fd1f63e49c0) + +Class QPropertyAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPropertyAnimation::QPrivateSignal (0x0x7fd1f64e7d80) 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 (0x0x7fd1f63e4a90) 0 + vptr=((& QPropertyAnimation::_ZTV18QPropertyAnimation) + 16u) + QVariantAnimation (0x0x7fd1f63e4af8) 0 + primary-for QPropertyAnimation (0x0x7fd1f63e4a90) + QAbstractAnimation (0x0x7fd1f63e4b60) 0 + primary-for QVariantAnimation (0x0x7fd1f63e4af8) + QObject (0x0x7fd1f64e7d20) 0 + primary-for QAbstractAnimation (0x0x7fd1f63e4b60) + +Class QSequentialAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSequentialAnimationGroup::QPrivateSignal (0x0x7fd1f64e7e40) 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 (0x0x7fd1f63e4bc8) 0 + vptr=((& QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup) + 16u) + QAnimationGroup (0x0x7fd1f63e4c30) 0 + primary-for QSequentialAnimationGroup (0x0x7fd1f63e4bc8) + QAbstractAnimation (0x0x7fd1f63e4c98) 0 + primary-for QAnimationGroup (0x0x7fd1f63e4c30) + QObject (0x0x7fd1f64e7de0) 0 + primary-for QAbstractAnimation (0x0x7fd1f63e4c98) + +Class QTextCodec::ConverterState + size=32 align=8 + base size=32 base align=8 +QTextCodec::ConverterState (0x0x7fd1f64e7f00) 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 (0x0x7fd1f64e7ea0) 0 nearly-empty + vptr=((& QTextCodec::_ZTV10QTextCodec) + 16u) + +Class QTextEncoder + size=40 align=8 + base size=40 base align=8 +QTextEncoder (0x0x7fd1f61b5060) 0 + +Class QTextDecoder + size=40 align=8 + base size=40 base align=8 +QTextDecoder (0x0x7fd1f61b50c0) 0 + +Class QSharedData + size=4 align=4 + base size=4 base align=4 +QSharedData (0x0x7fd1f61b5120) 0 + +Class QtSharedPointer::NormalDeleter + size=1 align=1 + base size=0 base align=1 +QtSharedPointer::NormalDeleter (0x0x7fd1f61b53c0) 0 empty + +Class QtSharedPointer::ExternalRefCountData + size=16 align=8 + base size=16 base align=8 +QtSharedPointer::ExternalRefCountData (0x0x7fd1f61b5540) 0 + +Class std::__numeric_limits_base + size=1 align=1 + base size=0 base align=1 +std::__numeric_limits_base (0x0x7fd1f61b59c0) 0 empty + +Class QDate + size=8 align=8 + base size=8 base align=8 +QDate (0x0x7fd1f5f65180) 0 + +Class QTime + size=4 align=4 + base size=4 base align=4 +QTime (0x0x7fd1f5f65240) 0 + +Class QDateTime + size=8 align=8 + base size=8 base align=8 +QDateTime (0x0x7fd1f5f65300) 0 + +Class QLibraryInfo + size=1 align=1 + base size=0 base align=1 +QLibraryInfo (0x0x7fd1f5f65420) 0 empty + +Class QBuffer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBuffer::QPrivateSignal (0x0x7fd1f5f654e0) 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 (0x0x7fd1f5ffa000) 0 + vptr=((& QBuffer::_ZTV7QBuffer) + 16u) + QIODevice (0x0x7fd1f5ffa068) 0 + primary-for QBuffer (0x0x7fd1f5ffa000) + QObject (0x0x7fd1f5f65480) 0 + primary-for QIODevice (0x0x7fd1f5ffa068) + +Class QLocale + size=8 align=8 + base size=8 base align=8 +QLocale (0x0x7fd1f5f65540) 0 + +Class _IO_marker + size=24 align=8 + base size=24 base align=8 +_IO_marker (0x0x7fd1f5f657e0) 0 + +Class _IO_FILE + size=216 align=8 + base size=216 base align=8 +_IO_FILE (0x0x7fd1f5f65840) 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 (0x0x7fd1f5f65900) 0 + vptr=((& QTextStream::_ZTV11QTextStream) + 16u) + +Class QTextStreamManipulator + size=40 align=8 + base size=38 base align=8 +QTextStreamManipulator (0x0x7fd1f5f65ba0) 0 + +Class QContiguousCacheData + size=24 align=4 + base size=24 base align=4 +QContiguousCacheData (0x0x7fd1f5f65de0) 0 + +Class QDebug::Stream + size=72 align=8 + base size=72 base align=8 +QDebug::Stream (0x0x7fd1f5daa480) 0 + +Class QDebug + size=8 align=8 + base size=8 base align=8 +QDebug (0x0x7fd1f5daa420) 0 + +Class QDebugStateSaver + size=8 align=8 + base size=8 base align=8 +QDebugStateSaver (0x0x7fd1f5daa540) 0 + +Class QNoDebug + size=1 align=1 + base size=0 base align=1 +QNoDebug (0x0x7fd1f5daa600) 0 empty + +Class QFileDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileDevice::QPrivateSignal (0x0x7fd1f5daa6c0) 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 (0x0x7fd1f5ffa3a8) 0 + vptr=((& QFileDevice::_ZTV11QFileDevice) + 16u) + QIODevice (0x0x7fd1f5ffa410) 0 + primary-for QFileDevice (0x0x7fd1f5ffa3a8) + QObject (0x0x7fd1f5daa660) 0 + primary-for QIODevice (0x0x7fd1f5ffa410) + +Class QFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFile::QPrivateSignal (0x0x7fd1f5daa840) 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 (0x0x7fd1f5ffa548) 0 + vptr=((& QFile::_ZTV5QFile) + 16u) + QFileDevice (0x0x7fd1f5ffa5b0) 0 + primary-for QFile (0x0x7fd1f5ffa548) + QIODevice (0x0x7fd1f5ffa618) 0 + primary-for QFileDevice (0x0x7fd1f5ffa5b0) + QObject (0x0x7fd1f5daa7e0) 0 + primary-for QIODevice (0x0x7fd1f5ffa618) + +Class QFileInfo + size=8 align=8 + base size=8 base align=8 +QFileInfo (0x0x7fd1f5daa960) 0 + +Class QDir + size=8 align=8 + base size=8 base align=8 +QDir (0x0x7fd1f5daaba0) 0 + +Class QDirIterator + size=8 align=8 + base size=8 base align=8 +QDirIterator (0x0x7fd1f5daae40) 0 + +Class QFileSelector::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSelector::QPrivateSignal (0x0x7fd1f5b63060) 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 (0x0x7fd1f5ffaa28) 0 + vptr=((& QFileSelector::_ZTV13QFileSelector) + 16u) + QObject (0x0x7fd1f5b63000) 0 + primary-for QFileSelector (0x0x7fd1f5ffaa28) + +Class QFileSystemWatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSystemWatcher::QPrivateSignal (0x0x7fd1f5b63120) 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 (0x0x7fd1f5ffaa90) 0 + vptr=((& QFileSystemWatcher::_ZTV18QFileSystemWatcher) + 16u) + QObject (0x0x7fd1f5b630c0) 0 + primary-for QFileSystemWatcher (0x0x7fd1f5ffaa90) + +Class QLockFile + size=8 align=8 + base size=8 base align=8 +QLockFile (0x0x7fd1f5b63180) 0 + +Class QLoggingCategory + size=24 align=8 + base size=24 base align=8 +QLoggingCategory (0x0x7fd1f5b632a0) 0 + +Class QProcessEnvironment + size=8 align=8 + base size=8 base align=8 +QProcessEnvironment (0x0x7fd1f5b63300) 0 + +Class QProcess::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QProcess::QPrivateSignal (0x0x7fd1f5b63480) 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 (0x0x7fd1f5ffaaf8) 0 + vptr=((& QProcess::_ZTV8QProcess) + 16u) + QIODevice (0x0x7fd1f5ffab60) 0 + primary-for QProcess (0x0x7fd1f5ffaaf8) + QObject (0x0x7fd1f5b63420) 0 + primary-for QIODevice (0x0x7fd1f5ffab60) + +Class QResource + size=8 align=8 + base size=8 base align=8 +QResource (0x0x7fd1f5b634e0) 0 + +Class QSaveFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSaveFile::QPrivateSignal (0x0x7fd1f5b63660) 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 (0x0x7fd1f5ffabc8) 0 + vptr=((& QSaveFile::_ZTV9QSaveFile) + 16u) + QFileDevice (0x0x7fd1f5ffac30) 0 + primary-for QSaveFile (0x0x7fd1f5ffabc8) + QIODevice (0x0x7fd1f5ffac98) 0 + primary-for QFileDevice (0x0x7fd1f5ffac30) + QObject (0x0x7fd1f5b63600) 0 + primary-for QIODevice (0x0x7fd1f5ffac98) + +Class QSettings::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSettings::QPrivateSignal (0x0x7fd1f5b63720) 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 (0x0x7fd1f5ffad00) 0 + vptr=((& QSettings::_ZTV9QSettings) + 16u) + QObject (0x0x7fd1f5b636c0) 0 + primary-for QSettings (0x0x7fd1f5ffad00) + +Class QStandardPaths + size=1 align=1 + base size=0 base align=1 +QStandardPaths (0x0x7fd1f5b63780) 0 empty + +Class QTemporaryDir + size=8 align=8 + base size=8 base align=8 +QTemporaryDir (0x0x7fd1f5b638a0) 0 + +Class QTemporaryFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTemporaryFile::QPrivateSignal (0x0x7fd1f5b639c0) 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 (0x0x7fd1f5ffae38) 0 + vptr=((& QTemporaryFile::_ZTV14QTemporaryFile) + 16u) + QFile (0x0x7fd1f5ffaea0) 0 + primary-for QTemporaryFile (0x0x7fd1f5ffae38) + QFileDevice (0x0x7fd1f5ffaf08) 0 + primary-for QFile (0x0x7fd1f5ffaea0) + QIODevice (0x0x7fd1f5ffaf70) 0 + primary-for QFileDevice (0x0x7fd1f5ffaf08) + QObject (0x0x7fd1f5b63960) 0 + primary-for QIODevice (0x0x7fd1f5ffaf70) + +Class QUrl + size=8 align=8 + base size=8 base align=8 +QUrl (0x0x7fd1f5b63ae0) 0 + +Class QUrlQuery + size=8 align=8 + base size=8 base align=8 +QUrlQuery (0x0x7fd1f5b63ea0) 0 + +Class QModelIndex + size=24 align=8 + base size=24 base align=8 +QModelIndex (0x0x7fd1f5d24000) 0 + +Class QPersistentModelIndex + size=8 align=8 + base size=8 base align=8 +QPersistentModelIndex (0x0x7fd1f5d240c0) 0 + +Class QAbstractItemModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractItemModel::QPrivateSignal (0x0x7fd1f5d241e0) 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 (0x0x7fd1f5ca61a0) 0 + vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16u) + QObject (0x0x7fd1f5d24180) 0 + primary-for QAbstractItemModel (0x0x7fd1f5ca61a0) + +Class QAbstractTableModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTableModel::QPrivateSignal (0x0x7fd1f5d244e0) 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 (0x0x7fd1f5ca62d8) 0 + vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16u) + QAbstractItemModel (0x0x7fd1f5ca6340) 0 + primary-for QAbstractTableModel (0x0x7fd1f5ca62d8) + QObject (0x0x7fd1f5d24480) 0 + primary-for QAbstractItemModel (0x0x7fd1f5ca6340) + +Class QAbstractListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractListModel::QPrivateSignal (0x0x7fd1f5d245a0) 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 (0x0x7fd1f5ca63a8) 0 + vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16u) + QAbstractItemModel (0x0x7fd1f5ca6410) 0 + primary-for QAbstractListModel (0x0x7fd1f5ca63a8) + QObject (0x0x7fd1f5d24540) 0 + primary-for QAbstractItemModel (0x0x7fd1f5ca6410) + +Class QAbstractProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractProxyModel::QPrivateSignal (0x0x7fd1f5d24660) 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 (0x0x7fd1f5ca6478) 0 + vptr=((& QAbstractProxyModel::_ZTV19QAbstractProxyModel) + 16u) + QAbstractItemModel (0x0x7fd1f5ca64e0) 0 + primary-for QAbstractProxyModel (0x0x7fd1f5ca6478) + QObject (0x0x7fd1f5d24600) 0 + primary-for QAbstractItemModel (0x0x7fd1f5ca64e0) + +Class QIdentityProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIdentityProxyModel::QPrivateSignal (0x0x7fd1f5d24720) 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 (0x0x7fd1f5ca6548) 0 + vptr=((& QIdentityProxyModel::_ZTV19QIdentityProxyModel) + 16u) + QAbstractProxyModel (0x0x7fd1f5ca65b0) 0 + primary-for QIdentityProxyModel (0x0x7fd1f5ca6548) + QAbstractItemModel (0x0x7fd1f5ca6618) 0 + primary-for QAbstractProxyModel (0x0x7fd1f5ca65b0) + QObject (0x0x7fd1f5d246c0) 0 + primary-for QAbstractItemModel (0x0x7fd1f5ca6618) + +Class QItemSelectionRange + size=16 align=8 + base size=16 base align=8 +QItemSelectionRange (0x0x7fd1f5d24780) 0 + +Class QItemSelectionModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QItemSelectionModel::QPrivateSignal (0x0x7fd1f5d248a0) 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 (0x0x7fd1f5ca6680) 0 + vptr=((& QItemSelectionModel::_ZTV19QItemSelectionModel) + 16u) + QObject (0x0x7fd1f5d24840) 0 + primary-for QItemSelectionModel (0x0x7fd1f5ca6680) + +Class QItemSelection + size=8 align=8 + base size=8 base align=8 +QItemSelection (0x0x7fd1f5ca67b8) 0 + QList (0x0x7fd1f5d24a80) 0 + +Class QSortFilterProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSortFilterProxyModel::QPrivateSignal (0x0x7fd1f5d24b40) 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 (0x0x7fd1f5ca6820) 0 + vptr=((& QSortFilterProxyModel::_ZTV21QSortFilterProxyModel) + 16u) + QAbstractProxyModel (0x0x7fd1f5ca6888) 0 + primary-for QSortFilterProxyModel (0x0x7fd1f5ca6820) + QAbstractItemModel (0x0x7fd1f5ca68f0) 0 + primary-for QAbstractProxyModel (0x0x7fd1f5ca6888) + QObject (0x0x7fd1f5d24ae0) 0 + primary-for QAbstractItemModel (0x0x7fd1f5ca68f0) + +Class QStringListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStringListModel::QPrivateSignal (0x0x7fd1f5d24c00) 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 (0x0x7fd1f5ca6958) 0 + vptr=((& QStringListModel::_ZTV16QStringListModel) + 16u) + QAbstractListModel (0x0x7fd1f5ca69c0) 0 + primary-for QStringListModel (0x0x7fd1f5ca6958) + QAbstractItemModel (0x0x7fd1f5ca6a28) 0 + primary-for QAbstractListModel (0x0x7fd1f5ca69c0) + QObject (0x0x7fd1f5d24ba0) 0 + primary-for QAbstractItemModel (0x0x7fd1f5ca6a28) + +Class QJsonValue + size=24 align=8 + base size=20 base align=8 +QJsonValue (0x0x7fd1f5d24c60) 0 + +Class QJsonValueRef + size=16 align=8 + base size=12 base align=8 +QJsonValueRef (0x0x7fd1f5d24d20) 0 + +Class QJsonArray::iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::iterator (0x0x7fd1f5d24e40) 0 + +Class QJsonArray::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::const_iterator (0x0x7fd1f5d24ea0) 0 + +Class QJsonArray + size=16 align=8 + base size=16 base align=8 +QJsonArray (0x0x7fd1f5d24de0) 0 + +Class QJsonParseError + size=8 align=4 + base size=8 base align=4 +QJsonParseError (0x0x7fd1f5d24f00) 0 + +Class QJsonDocument + size=8 align=8 + base size=8 base align=8 +QJsonDocument (0x0x7fd1f5d24f60) 0 + +Class QJsonObject::iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::iterator (0x0x7fd1f57a1060) 0 + +Class QJsonObject::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::const_iterator (0x0x7fd1f57a10c0) 0 + +Class QJsonObject + size=16 align=8 + base size=16 base align=8 +QJsonObject (0x0x7fd1f57a1000) 0 + +Class QEventLoop::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventLoop::QPrivateSignal (0x0x7fd1f57a11e0) 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 (0x0x7fd1f5ca6a90) 0 + vptr=((& QEventLoop::_ZTV10QEventLoop) + 16u) + QObject (0x0x7fd1f57a1180) 0 + primary-for QEventLoop (0x0x7fd1f5ca6a90) + +Class QEventLoopLocker + size=8 align=8 + base size=8 base align=8 +QEventLoopLocker (0x0x7fd1f57a1300) 0 + +Class QAbstractEventDispatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractEventDispatcher::QPrivateSignal (0x0x7fd1f57a13c0) 0 empty + +Class QAbstractEventDispatcher::TimerInfo + size=12 align=4 + base size=12 base align=4 +QAbstractEventDispatcher::TimerInfo (0x0x7fd1f57a1420) 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 (0x0x7fd1f5ca6bc8) 0 + vptr=((& QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher) + 16u) + QObject (0x0x7fd1f57a1360) 0 + primary-for QAbstractEventDispatcher (0x0x7fd1f5ca6bc8) + +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 (0x0x7fd1f57a1480) 0 + vptr=((& QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter) + 16u) + +Class QBasicTimer + size=4 align=4 + base size=4 base align=4 +QBasicTimer (0x0x7fd1f57a14e0) 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 (0x0x7fd1f57a15a0) 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 (0x0x7fd1f5ca6c30) 0 + vptr=((& QTimerEvent::_ZTV11QTimerEvent) + 16u) + QEvent (0x0x7fd1f57a1600) 0 + primary-for QTimerEvent (0x0x7fd1f5ca6c30) + +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 (0x0x7fd1f5ca6c98) 0 + vptr=((& QChildEvent::_ZTV11QChildEvent) + 16u) + QEvent (0x0x7fd1f57a1660) 0 + primary-for QChildEvent (0x0x7fd1f5ca6c98) + +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 (0x0x7fd1f5ca6d00) 0 + vptr=((& QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent) + 16u) + QEvent (0x0x7fd1f57a16c0) 0 + primary-for QDynamicPropertyChangeEvent (0x0x7fd1f5ca6d00) + +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 (0x0x7fd1f5ca6d68) 0 + vptr=((& QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent) + 16u) + QEvent (0x0x7fd1f57a1720) 0 + primary-for QDeferredDeleteEvent (0x0x7fd1f5ca6d68) + +Class QCoreApplication::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QCoreApplication::QPrivateSignal (0x0x7fd1f57a17e0) 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 (0x0x7fd1f5ca6dd0) 0 + vptr=((& QCoreApplication::_ZTV16QCoreApplication) + 16u) + QObject (0x0x7fd1f57a1780) 0 + primary-for QCoreApplication (0x0x7fd1f5ca6dd0) + +Class __exception + size=40 align=8 + base size=40 base align=8 +__exception (0x0x7fd1f57a1840) 0 + +Class QMetaMethod + size=16 align=8 + base size=12 base align=8 +QMetaMethod (0x0x7fd1f57a18a0) 0 + +Class QMetaEnum + size=16 align=8 + base size=12 base align=8 +QMetaEnum (0x0x7fd1f57a1960) 0 + +Class QMetaProperty + size=32 align=8 + base size=32 base align=8 +QMetaProperty (0x0x7fd1f57a1a20) 0 + +Class QMetaClassInfo + size=16 align=8 + base size=12 base align=8 +QMetaClassInfo (0x0x7fd1f57a1a80) 0 + +Class QMimeData::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QMimeData::QPrivateSignal (0x0x7fd1f57a1ba0) 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 (0x0x7fd1f5ca6f08) 0 + vptr=((& QMimeData::_ZTV9QMimeData) + 16u) + QObject (0x0x7fd1f57a1b40) 0 + primary-for QMimeData (0x0x7fd1f5ca6f08) + +Class QObjectCleanupHandler::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObjectCleanupHandler::QPrivateSignal (0x0x7fd1f57a1c60) 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 (0x0x7fd1f5ca6f70) 0 + vptr=((& QObjectCleanupHandler::_ZTV21QObjectCleanupHandler) + 16u) + QObject (0x0x7fd1f57a1c00) 0 + primary-for QObjectCleanupHandler (0x0x7fd1f5ca6f70) + +Class QSharedMemory::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSharedMemory::QPrivateSignal (0x0x7fd1f57a1ea0) 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 (0x0x7fd1f5954000) 0 + vptr=((& QSharedMemory::_ZTV13QSharedMemory) + 16u) + QObject (0x0x7fd1f57a1e40) 0 + primary-for QSharedMemory (0x0x7fd1f5954000) + +Class QSignalMapper::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalMapper::QPrivateSignal (0x0x7fd1f57a1f60) 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 (0x0x7fd1f5954068) 0 + vptr=((& QSignalMapper::_ZTV13QSignalMapper) + 16u) + QObject (0x0x7fd1f57a1f00) 0 + primary-for QSignalMapper (0x0x7fd1f5954068) + +Class QSocketNotifier::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSocketNotifier::QPrivateSignal (0x0x7fd1f557a060) 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 (0x0x7fd1f59540d0) 0 + vptr=((& QSocketNotifier::_ZTV15QSocketNotifier) + 16u) + QObject (0x0x7fd1f557a000) 0 + primary-for QSocketNotifier (0x0x7fd1f59540d0) + +Class QSystemSemaphore + size=8 align=8 + base size=8 base align=8 +QSystemSemaphore (0x0x7fd1f557a0c0) 0 + +Class QTimer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimer::QPrivateSignal (0x0x7fd1f557a1e0) 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 (0x0x7fd1f5954138) 0 + vptr=((& QTimer::_ZTV6QTimer) + 16u) + QObject (0x0x7fd1f557a180) 0 + primary-for QTimer (0x0x7fd1f5954138) + +Class QTranslator::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTranslator::QPrivateSignal (0x0x7fd1f557a300) 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 (0x0x7fd1f59541a0) 0 + vptr=((& QTranslator::_ZTV11QTranslator) + 16u) + QObject (0x0x7fd1f557a2a0) 0 + primary-for QTranslator (0x0x7fd1f59541a0) + +Class QMimeType + size=8 align=8 + base size=8 base align=8 +QMimeType (0x0x7fd1f557a360) 0 + +Class QMimeDatabase + size=8 align=8 + base size=8 base align=8 +QMimeDatabase (0x0x7fd1f557a480) 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 (0x0x7fd1f557a4e0) 0 nearly-empty + vptr=((& QFactoryInterface::_ZTV17QFactoryInterface) + 16u) + +Class QLibrary::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLibrary::QPrivateSignal (0x0x7fd1f557a600) 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 (0x0x7fd1f5954208) 0 + vptr=((& QLibrary::_ZTV8QLibrary) + 16u) + QObject (0x0x7fd1f557a5a0) 0 + primary-for QLibrary (0x0x7fd1f5954208) + +Class QStaticPlugin + size=16 align=8 + base size=16 base align=8 +QStaticPlugin (0x0x7fd1f557a720) 0 + +Class QPluginLoader::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPluginLoader::QPrivateSignal (0x0x7fd1f557a840) 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 (0x0x7fd1f5954340) 0 + vptr=((& QPluginLoader::_ZTV13QPluginLoader) + 16u) + QObject (0x0x7fd1f557a7e0) 0 + primary-for QPluginLoader (0x0x7fd1f5954340) + +Class QUuid + size=16 align=4 + base size=16 base align=4 +QUuid (0x0x7fd1f557a8a0) 0 + +Class QAbstractState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractState::QPrivateSignal (0x0x7fd1f557a9c0) 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 (0x0x7fd1f59543a8) 0 + vptr=((& QAbstractState::_ZTV14QAbstractState) + 16u) + QObject (0x0x7fd1f557a960) 0 + primary-for QAbstractState (0x0x7fd1f59543a8) + +Class QAbstractTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTransition::QPrivateSignal (0x0x7fd1f557aa80) 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 (0x0x7fd1f5954410) 0 + vptr=((& QAbstractTransition::_ZTV19QAbstractTransition) + 16u) + QObject (0x0x7fd1f557aa20) 0 + primary-for QAbstractTransition (0x0x7fd1f5954410) + +Class QEventTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventTransition::QPrivateSignal (0x0x7fd1f557ab40) 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 (0x0x7fd1f5954478) 0 + vptr=((& QEventTransition::_ZTV16QEventTransition) + 16u) + QAbstractTransition (0x0x7fd1f59544e0) 0 + primary-for QEventTransition (0x0x7fd1f5954478) + QObject (0x0x7fd1f557aae0) 0 + primary-for QAbstractTransition (0x0x7fd1f59544e0) + +Class QFinalState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFinalState::QPrivateSignal (0x0x7fd1f557ac00) 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 (0x0x7fd1f5954548) 0 + vptr=((& QFinalState::_ZTV11QFinalState) + 16u) + QAbstractState (0x0x7fd1f59545b0) 0 + primary-for QFinalState (0x0x7fd1f5954548) + QObject (0x0x7fd1f557aba0) 0 + primary-for QAbstractState (0x0x7fd1f59545b0) + +Class QHistoryState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QHistoryState::QPrivateSignal (0x0x7fd1f557acc0) 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 (0x0x7fd1f5954618) 0 + vptr=((& QHistoryState::_ZTV13QHistoryState) + 16u) + QAbstractState (0x0x7fd1f5954680) 0 + primary-for QHistoryState (0x0x7fd1f5954618) + QObject (0x0x7fd1f557ac60) 0 + primary-for QAbstractState (0x0x7fd1f5954680) + +Class QSignalTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalTransition::QPrivateSignal (0x0x7fd1f557ad80) 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 (0x0x7fd1f59546e8) 0 + vptr=((& QSignalTransition::_ZTV17QSignalTransition) + 16u) + QAbstractTransition (0x0x7fd1f5954750) 0 + primary-for QSignalTransition (0x0x7fd1f59546e8) + QObject (0x0x7fd1f557ad20) 0 + primary-for QAbstractTransition (0x0x7fd1f5954750) + +Class QState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QState::QPrivateSignal (0x0x7fd1f557ae40) 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 (0x0x7fd1f59547b8) 0 + vptr=((& QState::_ZTV6QState) + 16u) + QAbstractState (0x0x7fd1f5954820) 0 + primary-for QState (0x0x7fd1f59547b8) + QObject (0x0x7fd1f557ade0) 0 + primary-for QAbstractState (0x0x7fd1f5954820) + +Class QStateMachine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStateMachine::QPrivateSignal (0x0x7fd1f557af60) 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 (0x0x7fd1f59549c0) 0 + vptr=((& QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE) + 16u) + QEvent (0x0x7fd1f56c9000) 0 + primary-for QStateMachine::SignalEvent (0x0x7fd1f59549c0) + +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 (0x0x7fd1f5954a28) 0 + vptr=((& QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE) + 16u) + QEvent (0x0x7fd1f56c9060) 0 + primary-for QStateMachine::WrappedEvent (0x0x7fd1f5954a28) + +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 (0x0x7fd1f5954888) 0 + vptr=((& QStateMachine::_ZTV13QStateMachine) + 16u) + QState (0x0x7fd1f59548f0) 0 + primary-for QStateMachine (0x0x7fd1f5954888) + QAbstractState (0x0x7fd1f5954958) 0 + primary-for QState (0x0x7fd1f59548f0) + QObject (0x0x7fd1f557af00) 0 + primary-for QAbstractState (0x0x7fd1f5954958) + +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 (0x0x7fd1f5954a90) 0 nearly-empty + vptr=((& QException::_ZTV10QException) + 16u) + std::exception (0x0x7fd1f56c90c0) 0 nearly-empty + primary-for QException (0x0x7fd1f5954a90) + +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 (0x0x7fd1f5954af8) 0 nearly-empty + vptr=((& QUnhandledException::_ZTV19QUnhandledException) + 16u) + QException (0x0x7fd1f5954b60) 0 nearly-empty + primary-for QUnhandledException (0x0x7fd1f5954af8) + std::exception (0x0x7fd1f56c9120) 0 nearly-empty + primary-for QException (0x0x7fd1f5954b60) + +Class QtPrivate::ExceptionHolder + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionHolder (0x0x7fd1f56c9180) 0 + +Class QtPrivate::ExceptionStore + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionStore (0x0x7fd1f56c9240) 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 (0x0x7fd1f56c92a0) 0 + vptr=((& QRunnable::_ZTV9QRunnable) + 16u) + +Class QBasicMutex + size=8 align=8 + base size=8 base align=8 +QBasicMutex (0x0x7fd1f56c9300) 0 + +Class QMutex + size=8 align=8 + base size=8 base align=8 +QMutex (0x0x7fd1f5954d00) 0 + QBasicMutex (0x0x7fd1f56c9420) 0 + +Class QMutexLocker + size=8 align=8 + base size=8 base align=8 +QMutexLocker (0x0x7fd1f56c9480) 0 + +Class QtPrivate::ResultItem + size=16 align=8 + base size=16 base align=8 +QtPrivate::ResultItem (0x0x7fd1f56c94e0) 0 + +Class QtPrivate::ResultIteratorBase + size=16 align=8 + base size=12 base align=8 +QtPrivate::ResultIteratorBase (0x0x7fd1f56c9540) 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 (0x0x7fd1f56c96c0) 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 (0x0x7fd1f56c9780) 0 + vptr=((& QFutureInterfaceBase::_ZTV20QFutureInterfaceBase) + 16u) + +Class QFutureWatcherBase::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFutureWatcherBase::QPrivateSignal (0x0x7fd1f56c9ae0) 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 (0x0x7fd1f5372618) 0 + vptr=((& QFutureWatcherBase::_ZTV18QFutureWatcherBase) + 16u) + QObject (0x0x7fd1f56c9a80) 0 + primary-for QFutureWatcherBase (0x0x7fd1f5372618) + +Class QReadWriteLock + size=8 align=8 + base size=8 base align=8 +QReadWriteLock (0x0x7fd1f56c9c00) 0 + +Class QReadLocker + size=8 align=8 + base size=8 base align=8 +QReadLocker (0x0x7fd1f56c9c60) 0 + +Class QWriteLocker + size=8 align=8 + base size=8 base align=8 +QWriteLocker (0x0x7fd1f56c9d20) 0 + +Class QSemaphore + size=8 align=8 + base size=8 base align=8 +QSemaphore (0x0x7fd1f56c9de0) 0 + +Class QThread::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThread::QPrivateSignal (0x0x7fd1f56c9ea0) 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 (0x0x7fd1f53729c0) 0 + vptr=((& QThread::_ZTV7QThread) + 16u) + QObject (0x0x7fd1f56c9e40) 0 + primary-for QThread (0x0x7fd1f53729c0) + +Class QThreadPool::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThreadPool::QPrivateSignal (0x0x7fd1f56c9f60) 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 (0x0x7fd1f5372a28) 0 + vptr=((& QThreadPool::_ZTV11QThreadPool) + 16u) + QObject (0x0x7fd1f56c9f00) 0 + primary-for QThreadPool (0x0x7fd1f5372a28) + +Class QThreadStorageData + size=4 align=4 + base size=4 base align=4 +QThreadStorageData (0x0x7fd1f5481000) 0 + +Class QWaitCondition + size=8 align=8 + base size=8 base align=8 +QWaitCondition (0x0x7fd1f54810c0) 0 + +Class QBitArray + size=8 align=8 + base size=8 base align=8 +QBitArray (0x0x7fd1f54bd7e0) 0 + +Class QBitRef + size=16 align=8 + base size=12 base align=8 +QBitRef (0x0x7fd1f54bd840) 0 + +Class QByteArrayMatcher::Data + size=272 align=8 + base size=272 base align=8 +QByteArrayMatcher::Data (0x0x7fd1f54bd960) 0 + +Class QByteArrayMatcher + size=1040 align=8 + base size=1040 base align=8 +QByteArrayMatcher (0x0x7fd1f54bd900) 0 + +Class QCollatorSortKey + size=8 align=8 + base size=8 base align=8 +QCollatorSortKey (0x0x7fd1f54bdae0) 0 + +Class QCollator + size=8 align=8 + base size=8 base align=8 +QCollator (0x0x7fd1f54bdba0) 0 + +Class QCommandLineOption + size=8 align=8 + base size=8 base align=8 +QCommandLineOption (0x0x7fd1f54bdcc0) 0 + +Class QCommandLineParser + size=8 align=8 + base size=8 base align=8 +QCommandLineParser (0x0x7fd1f54bdde0) 0 + +Class QCryptographicHash + size=8 align=8 + base size=8 base align=8 +QCryptographicHash (0x0x7fd1f54bde40) 0 + +Class QElapsedTimer + size=16 align=8 + base size=16 base align=8 +QElapsedTimer (0x0x7fd1f54bdea0) 0 + +Class QPoint + size=8 align=4 + base size=8 base align=4 +QPoint (0x0x7fd1f54bdf00) 0 + +Class QPointF + size=16 align=8 + base size=16 base align=8 +QPointF (0x0x7fd1f51ed000) 0 + +Class QLine + size=16 align=4 + base size=16 base align=4 +QLine (0x0x7fd1f51ed0c0) 0 + +Class QLineF + size=32 align=8 + base size=32 base align=8 +QLineF (0x0x7fd1f51ed180) 0 + +Class QLinkedListData + size=32 align=8 + base size=32 base align=8 +QLinkedListData (0x0x7fd1f51ed240) 0 + +Class QSize + size=8 align=4 + base size=8 base align=4 +QSize (0x0x7fd1f51ed5a0) 0 + +Class QSizeF + size=16 align=8 + base size=16 base align=8 +QSizeF (0x0x7fd1f51ed660) 0 + +Class QRect + size=16 align=4 + base size=16 base align=4 +QRect (0x0x7fd1f51ed720) 0 + +Class QRectF + size=32 align=8 + base size=32 base align=8 +QRectF (0x0x7fd1f51ed7e0) 0 + +Class QMargins + size=16 align=4 + base size=16 base align=4 +QMargins (0x0x7fd1f51ed8a0) 0 + +Class QMessageAuthenticationCode + size=8 align=8 + base size=8 base align=8 +QMessageAuthenticationCode (0x0x7fd1f51ed960) 0 + +Class QRegularExpression + size=8 align=8 + base size=8 base align=8 +QRegularExpression (0x0x7fd1f51eda20) 0 + +Class QRegularExpressionMatch + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatch (0x0x7fd1f51edcc0) 0 + +Class QRegularExpressionMatchIterator + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatchIterator (0x0x7fd1f51edde0) 0 + +Class QAbstractConcatenable + size=1 align=1 + base size=0 base align=1 +QAbstractConcatenable (0x0x7fd1f511f000) 0 empty + +Class QTextBoundaryFinder + size=48 align=8 + base size=48 base align=8 +QTextBoundaryFinder (0x0x7fd1f511fa20) 0 + +Class QTimeLine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimeLine::QPrivateSignal (0x0x7fd1f511fba0) 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 (0x0x7fd1f5086bc8) 0 + vptr=((& QTimeLine::_ZTV9QTimeLine) + 16u) + QObject (0x0x7fd1f511fb40) 0 + primary-for QTimeLine (0x0x7fd1f5086bc8) + +Class QTimeZone::OffsetData + size=32 align=8 + base size=28 base align=8 +QTimeZone::OffsetData (0x0x7fd1f511fc60) 0 + +Class QTimeZone + size=8 align=8 + base size=8 base align=8 +QTimeZone (0x0x7fd1f511fc00) 0 + +Class QXmlStreamStringRef + size=16 align=8 + base size=16 base align=8 +QXmlStreamStringRef (0x0x7fd1f511fde0) 0 + +Class QXmlStreamAttribute + size=80 align=8 + base size=73 base align=8 +QXmlStreamAttribute (0x0x7fd1f511fe40) 0 + +Class QXmlStreamAttributes + size=8 align=8 + base size=8 base align=8 +QXmlStreamAttributes (0x0x7fd1f5086d00) 0 + QVector (0x0x7fd1f4e3f000) 0 + +Class QXmlStreamNamespaceDeclaration + size=40 align=8 + base size=40 base align=8 +QXmlStreamNamespaceDeclaration (0x0x7fd1f4e3f060) 0 + +Class QXmlStreamNotationDeclaration + size=56 align=8 + base size=56 base align=8 +QXmlStreamNotationDeclaration (0x0x7fd1f4e3f120) 0 + +Class QXmlStreamEntityDeclaration + size=88 align=8 + base size=88 base align=8 +QXmlStreamEntityDeclaration (0x0x7fd1f4e3f1e0) 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 (0x0x7fd1f4e3f2a0) 0 nearly-empty + vptr=((& QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver) + 16u) + +Class QXmlStreamReader + size=8 align=8 + base size=8 base align=8 +QXmlStreamReader (0x0x7fd1f4e3f300) 0 + +Class QXmlStreamWriter + size=8 align=8 + base size=8 base align=8 +QXmlStreamWriter (0x0x7fd1f4e3f420) 0 + +Class QBluetoothAddress + size=8 align=8 + base size=8 base align=8 +QBluetoothAddress (0x0x7fd1f4e3f600) 0 + +Class QBluetoothDeviceInfo + size=8 align=8 + base size=8 base align=8 +QBluetoothDeviceInfo (0x0x7fd1f4e3f780) 0 + +Class QBluetoothDeviceDiscoveryAgent::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothDeviceDiscoveryAgent::QPrivateSignal (0x0x7fd1f4e3f840) 0 empty + +Vtable for QBluetoothDeviceDiscoveryAgent +QBluetoothDeviceDiscoveryAgent::_ZTV30QBluetoothDeviceDiscoveryAgent: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI30QBluetoothDeviceDiscoveryAgent) +16 (int (*)(...))QBluetoothDeviceDiscoveryAgent::metaObject +24 (int (*)(...))QBluetoothDeviceDiscoveryAgent::qt_metacast +32 (int (*)(...))QBluetoothDeviceDiscoveryAgent::qt_metacall +40 (int (*)(...))QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent +48 (int (*)(...))QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent +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 QBluetoothDeviceDiscoveryAgent + size=24 align=8 + base size=24 base align=8 +QBluetoothDeviceDiscoveryAgent (0x0x7fd1f5086e38) 0 + vptr=((& QBluetoothDeviceDiscoveryAgent::_ZTV30QBluetoothDeviceDiscoveryAgent) + 16u) + QObject (0x0x7fd1f4e3f7e0) 0 + primary-for QBluetoothDeviceDiscoveryAgent (0x0x7fd1f5086e38) + +Class QBluetoothHostInfo + size=8 align=8 + base size=8 base align=8 +QBluetoothHostInfo (0x0x7fd1f4e3f8a0) 0 + +Class QBluetoothLocalDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothLocalDevice::QPrivateSignal (0x0x7fd1f4e3f960) 0 empty + +Vtable for QBluetoothLocalDevice +QBluetoothLocalDevice::_ZTV21QBluetoothLocalDevice: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QBluetoothLocalDevice) +16 (int (*)(...))QBluetoothLocalDevice::metaObject +24 (int (*)(...))QBluetoothLocalDevice::qt_metacast +32 (int (*)(...))QBluetoothLocalDevice::qt_metacall +40 (int (*)(...))QBluetoothLocalDevice::~QBluetoothLocalDevice +48 (int (*)(...))QBluetoothLocalDevice::~QBluetoothLocalDevice +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 QBluetoothLocalDevice + size=24 align=8 + base size=24 base align=8 +QBluetoothLocalDevice (0x0x7fd1f5086ea0) 0 + vptr=((& QBluetoothLocalDevice::_ZTV21QBluetoothLocalDevice) + 16u) + QObject (0x0x7fd1f4e3f900) 0 + primary-for QBluetoothLocalDevice (0x0x7fd1f5086ea0) + +Class quint128 + size=16 align=1 + base size=16 base align=1 +quint128 (0x0x7fd1f4e3fd20) 0 + +Class QBluetoothUuid + size=16 align=4 + base size=16 base align=4 +QBluetoothUuid (0x0x7fd1f5086f08) 0 + QUuid (0x0x7fd1f4e3fd80) 0 + +Class QBluetoothServiceInfo::Sequence + size=8 align=8 + base size=8 base align=8 +QBluetoothServiceInfo::Sequence (0x0x7fd1f5086f70) 0 + QList (0x0x7fd1f4e3ff60) 0 + +Class QBluetoothServiceInfo::Alternative + size=8 align=8 + base size=8 base align=8 +QBluetoothServiceInfo::Alternative (0x0x7fd1f4b5e000) 0 + QList (0x0x7fd1f4b5f000) 0 + +Class QBluetoothServiceInfo + size=16 align=8 + base size=16 base align=8 +QBluetoothServiceInfo (0x0x7fd1f4e3ff00) 0 + +Class QAbstractSocket::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractSocket::QPrivateSignal (0x0x7fd1f4b5f5a0) 0 empty + +Vtable for QAbstractSocket +QAbstractSocket::_ZTV15QAbstractSocket: 41u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QAbstractSocket) +16 (int (*)(...))QAbstractSocket::metaObject +24 (int (*)(...))QAbstractSocket::qt_metacast +32 (int (*)(...))QAbstractSocket::qt_metacall +40 (int (*)(...))QAbstractSocket::~QAbstractSocket +48 (int (*)(...))QAbstractSocket::~QAbstractSocket +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 (*)(...))QAbstractSocket::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QAbstractSocket::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QAbstractSocket::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QAbstractSocket::bytesAvailable +184 (int (*)(...))QAbstractSocket::bytesToWrite +192 (int (*)(...))QAbstractSocket::canReadLine +200 (int (*)(...))QAbstractSocket::waitForReadyRead +208 (int (*)(...))QAbstractSocket::waitForBytesWritten +216 (int (*)(...))QAbstractSocket::readData +224 (int (*)(...))QAbstractSocket::readLineData +232 (int (*)(...))QAbstractSocket::writeData +240 (int (*)(...))QAbstractSocket::resume +248 (int (*)(...))QAbstractSocket::connectToHost +256 (int (*)(...))QAbstractSocket::connectToHost +264 (int (*)(...))QAbstractSocket::disconnectFromHost +272 (int (*)(...))QAbstractSocket::setReadBufferSize +280 (int (*)(...))QAbstractSocket::socketDescriptor +288 (int (*)(...))QAbstractSocket::setSocketDescriptor +296 (int (*)(...))QAbstractSocket::setSocketOption +304 (int (*)(...))QAbstractSocket::socketOption +312 (int (*)(...))QAbstractSocket::waitForConnected +320 (int (*)(...))QAbstractSocket::waitForDisconnected + +Class QAbstractSocket + size=16 align=8 + base size=16 base align=8 +QAbstractSocket (0x0x7fd1f4b5e270) 0 + vptr=((& QAbstractSocket::_ZTV15QAbstractSocket) + 16u) + QIODevice (0x0x7fd1f4b5e2d8) 0 + primary-for QAbstractSocket (0x0x7fd1f4b5e270) + QObject (0x0x7fd1f4b5f540) 0 + primary-for QIODevice (0x0x7fd1f4b5e2d8) + +Class QBluetoothSocket::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothSocket::QPrivateSignal (0x0x7fd1f4b5fa20) 0 empty + +Vtable for QBluetoothSocket +QBluetoothSocket::_ZTV16QBluetoothSocket: 30u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QBluetoothSocket) +16 (int (*)(...))QBluetoothSocket::metaObject +24 (int (*)(...))QBluetoothSocket::qt_metacast +32 (int (*)(...))QBluetoothSocket::qt_metacall +40 (int (*)(...))QBluetoothSocket::~QBluetoothSocket +48 (int (*)(...))QBluetoothSocket::~QBluetoothSocket +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 (*)(...))QBluetoothSocket::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QBluetoothSocket::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QIODevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QBluetoothSocket::bytesAvailable +184 (int (*)(...))QBluetoothSocket::bytesToWrite +192 (int (*)(...))QBluetoothSocket::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QBluetoothSocket::readData +224 (int (*)(...))QIODevice::readLineData +232 (int (*)(...))QBluetoothSocket::writeData + +Class QBluetoothSocket + size=24 align=8 + base size=24 base align=8 +QBluetoothSocket (0x0x7fd1f4b5e4e0) 0 + vptr=((& QBluetoothSocket::_ZTV16QBluetoothSocket) + 16u) + QIODevice (0x0x7fd1f4b5e548) 0 + primary-for QBluetoothSocket (0x0x7fd1f4b5e4e0) + QObject (0x0x7fd1f4b5f9c0) 0 + primary-for QIODevice (0x0x7fd1f4b5e548) + +Class QBluetoothServer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothServer::QPrivateSignal (0x0x7fd1f4b5fae0) 0 empty + +Vtable for QBluetoothServer +QBluetoothServer::_ZTV16QBluetoothServer: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QBluetoothServer) +16 (int (*)(...))QBluetoothServer::metaObject +24 (int (*)(...))QBluetoothServer::qt_metacast +32 (int (*)(...))QBluetoothServer::qt_metacall +40 (int (*)(...))QBluetoothServer::~QBluetoothServer +48 (int (*)(...))QBluetoothServer::~QBluetoothServer +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 QBluetoothServer + size=24 align=8 + base size=24 base align=8 +QBluetoothServer (0x0x7fd1f4b5e5b0) 0 + vptr=((& QBluetoothServer::_ZTV16QBluetoothServer) + 16u) + QObject (0x0x7fd1f4b5fa80) 0 + primary-for QBluetoothServer (0x0x7fd1f4b5e5b0) + +Class QBluetoothServiceDiscoveryAgent::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothServiceDiscoveryAgent::QPrivateSignal (0x0x7fd1f4b5fba0) 0 empty + +Vtable for QBluetoothServiceDiscoveryAgent +QBluetoothServiceDiscoveryAgent::_ZTV31QBluetoothServiceDiscoveryAgent: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI31QBluetoothServiceDiscoveryAgent) +16 (int (*)(...))QBluetoothServiceDiscoveryAgent::metaObject +24 (int (*)(...))QBluetoothServiceDiscoveryAgent::qt_metacast +32 (int (*)(...))QBluetoothServiceDiscoveryAgent::qt_metacall +40 (int (*)(...))QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent +48 (int (*)(...))QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent +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 QBluetoothServiceDiscoveryAgent + size=24 align=8 + base size=24 base align=8 +QBluetoothServiceDiscoveryAgent (0x0x7fd1f4b5e618) 0 + vptr=((& QBluetoothServiceDiscoveryAgent::_ZTV31QBluetoothServiceDiscoveryAgent) + 16u) + QObject (0x0x7fd1f4b5fb40) 0 + primary-for QBluetoothServiceDiscoveryAgent (0x0x7fd1f4b5e618) + +Class QBluetoothTransferManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothTransferManager::QPrivateSignal (0x0x7fd1f4b5fc60) 0 empty + +Vtable for QBluetoothTransferManager +QBluetoothTransferManager::_ZTV25QBluetoothTransferManager: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI25QBluetoothTransferManager) +16 (int (*)(...))QBluetoothTransferManager::metaObject +24 (int (*)(...))QBluetoothTransferManager::qt_metacast +32 (int (*)(...))QBluetoothTransferManager::qt_metacall +40 (int (*)(...))QBluetoothTransferManager::~QBluetoothTransferManager +48 (int (*)(...))QBluetoothTransferManager::~QBluetoothTransferManager +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 QBluetoothTransferManager + size=16 align=8 + base size=16 base align=8 +QBluetoothTransferManager (0x0x7fd1f4b5e680) 0 + vptr=((& QBluetoothTransferManager::_ZTV25QBluetoothTransferManager) + 16u) + QObject (0x0x7fd1f4b5fc00) 0 + primary-for QBluetoothTransferManager (0x0x7fd1f4b5e680) + +Class QBluetoothTransferRequest + size=8 align=8 + base size=8 base align=8 +QBluetoothTransferRequest (0x0x7fd1f4b5fcc0) 0 + +Class QBluetoothTransferReply::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothTransferReply::QPrivateSignal (0x0x7fd1f4b5fd80) 0 empty + +Vtable for QBluetoothTransferReply +QBluetoothTransferReply::_ZTV23QBluetoothTransferReply: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI23QBluetoothTransferReply) +16 (int (*)(...))QBluetoothTransferReply::metaObject +24 (int (*)(...))QBluetoothTransferReply::qt_metacast +32 (int (*)(...))QBluetoothTransferReply::qt_metacall +40 (int (*)(...))QBluetoothTransferReply::~QBluetoothTransferReply +48 (int (*)(...))QBluetoothTransferReply::~QBluetoothTransferReply +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 + +Class QBluetoothTransferReply + size=24 align=8 + base size=24 base align=8 +QBluetoothTransferReply (0x0x7fd1f4b5e6e8) 0 + vptr=((& QBluetoothTransferReply::_ZTV23QBluetoothTransferReply) + 16u) + QObject (0x0x7fd1f4b5fd20) 0 + primary-for QBluetoothTransferReply (0x0x7fd1f4b5e6e8) + diff --git a/tests/auto/bic/data/QtBluetooth.5.3.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtBluetooth.5.3.0.linux-gcc-amd64.txt new file mode 100644 index 0000000..66fbef0 --- /dev/null +++ b/tests/auto/bic/data/QtBluetooth.5.3.0.linux-gcc-amd64.txt @@ -0,0 +1,3942 @@ +Class std::__true_type + size=1 align=1 + base size=0 base align=1 +std::__true_type (0x0x7ffecb16ef00) 0 empty + +Class std::__false_type + size=1 align=1 + base size=0 base align=1 +std::__false_type (0x0x7ffecb16ef60) 0 empty + +Class std::input_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::input_iterator_tag (0x0x7ffeca113b40) 0 empty + +Class std::output_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::output_iterator_tag (0x0x7ffeca113ba0) 0 empty + +Class std::forward_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::forward_iterator_tag (0x0x7ffeca09c5b0) 0 empty + std::input_iterator_tag (0x0x7ffeca113c00) 0 empty + +Class std::bidirectional_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::bidirectional_iterator_tag (0x0x7ffeca09c618) 0 empty + std::forward_iterator_tag (0x0x7ffeca09c680) 0 empty + std::input_iterator_tag (0x0x7ffeca113c60) 0 empty + +Class std::random_access_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::random_access_iterator_tag (0x0x7ffeca09c6e8) 0 empty + std::bidirectional_iterator_tag (0x0x7ffeca09c750) 0 empty + std::forward_iterator_tag (0x0x7ffeca09c7b8) 0 empty + std::input_iterator_tag (0x0x7ffeca113cc0) 0 empty + +Class wait + size=4 align=4 + base size=4 base align=4 +wait (0x0x7ffeca16d840) 0 + +Class __locale_struct + size=232 align=8 + base size=232 base align=8 +__locale_struct (0x0x7ffeca16da80) 0 + +Class timespec + size=16 align=8 + base size=16 base align=8 +timespec (0x0x7ffeca16db40) 0 + +Class timeval + size=16 align=8 + base size=16 base align=8 +timeval (0x0x7ffeca16dba0) 0 + +Class pthread_attr_t + size=56 align=8 + base size=56 base align=8 +pthread_attr_t (0x0x7ffeca16dc60) 0 + +Class __pthread_internal_list + size=16 align=8 + base size=16 base align=8 +__pthread_internal_list (0x0x7ffeca16dcc0) 0 + +Class random_data + size=48 align=8 + base size=48 base align=8 +random_data (0x0x7ffeca22e180) 0 + +Class drand48_data + size=24 align=8 + base size=24 base align=8 +drand48_data (0x0x7ffeca22e1e0) 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 (0x0x7ffeca22e240) 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 (0x0x7ffeca09caf8) 0 nearly-empty + vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16u) + std::exception (0x0x7ffeca22e2a0) 0 nearly-empty + primary-for std::bad_exception (0x0x7ffeca09caf8) + +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 (0x0x7ffeca09cb60) 0 nearly-empty + vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16u) + std::exception (0x0x7ffeca22e300) 0 nearly-empty + primary-for std::bad_alloc (0x0x7ffeca09cb60) + +Class std::nothrow_t + size=1 align=1 + base size=0 base align=1 +std::nothrow_t (0x0x7ffeca22e360) 0 empty + +Class qIsNull(double)::U + size=8 align=8 + base size=8 base align=8 +qIsNull(double)::U (0x0x7ffec90386c0) 0 + +Class qIsNull(float)::U + size=4 align=4 + base size=4 base align=4 +qIsNull(float)::U (0x0x7ffec9038720) 0 + +Class QtPrivate::big_ + size=2 align=1 + base size=2 base align=1 +QtPrivate::big_ (0x0x7ffec9038900) 0 + +Class QSysInfo + size=1 align=1 + base size=0 base align=1 +QSysInfo (0x0x7ffec8d9d060) 0 empty + +Class QMessageLogContext + size=32 align=8 + base size=32 base align=8 +QMessageLogContext (0x0x7ffec8d9d0c0) 0 + +Class QMessageLogger + size=32 align=8 + base size=32 base align=8 +QMessageLogger (0x0x7ffec8d9d120) 0 + +Class QFlag + size=4 align=4 + base size=4 base align=4 +QFlag (0x0x7ffec8d9d180) 0 + +Class QIncompatibleFlag + size=4 align=4 + base size=4 base align=4 +QIncompatibleFlag (0x0x7ffec8d9d2a0) 0 + +Class QAtomicInt + size=4 align=4 + base size=4 base align=4 +QAtomicInt (0x0x7ffec8bc5138) 0 + QAtomicInteger (0x0x7ffec8bc51a0) 0 + QBasicAtomicInteger (0x0x7ffec8d9dd80) 0 + +Class QInternal + size=1 align=1 + base size=0 base align=1 +QInternal (0x0x7ffec887aea0) 0 empty + +Class QGenericArgument + size=16 align=8 + base size=16 base align=8 +QGenericArgument (0x0x7ffec8a24de0) 0 + +Class QGenericReturnArgument + size=16 align=8 + base size=16 base align=8 +QGenericReturnArgument (0x0x7ffec89872d8) 0 + QGenericArgument (0x0x7ffec8a24e40) 0 + +Class QMetaObject + size=48 align=8 + base size=48 base align=8 +QMetaObject (0x0x7ffec8688000) 0 + +Class QMetaObject::Connection + size=8 align=8 + base size=8 base align=8 +QMetaObject::Connection (0x0x7ffec8688120) 0 + +Class QLatin1Char + size=1 align=1 + base size=1 base align=1 +QLatin1Char (0x0x7ffec8688360) 0 + +Class QChar + size=2 align=2 + base size=2 base align=2 +QChar (0x0x7ffec86883c0) 0 + +Class QtPrivate::RefCount + size=4 align=4 + base size=4 base align=4 +QtPrivate::RefCount (0x0x7ffec86884e0) 0 + +Class QArrayData + size=24 align=8 + base size=24 base align=8 +QArrayData (0x0x7ffec8688540) 0 + +Class QByteArrayDataPtr + size=8 align=8 + base size=8 base align=8 +QByteArrayDataPtr (0x0x7ffec86888a0) 0 + +Class QByteArray + size=8 align=8 + base size=8 base align=8 +QByteArray (0x0x7ffec8688900) 0 + +Class QByteRef + size=16 align=8 + base size=12 base align=8 +QByteRef (0x0x7ffec8688a80) 0 + +Class lconv + size=96 align=8 + base size=96 base align=8 +lconv (0x0x7ffec8688ea0) 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 (0x0x7ffec8688f00) 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 (0x0x7ffec85869c0) 0 + +Class __sched_param + size=4 align=4 + base size=4 base align=4 +__sched_param (0x0x7ffec8586a20) 0 + +Class timex + size=208 align=8 + base size=208 base align=8 +timex (0x0x7ffec8586ae0) 0 + +Class tm + size=56 align=8 + base size=56 base align=8 +tm (0x0x7ffec8586b40) 0 + +Class itimerspec + size=32 align=8 + base size=32 base align=8 +itimerspec (0x0x7ffec8586ba0) 0 + +Class _pthread_cleanup_buffer + size=32 align=8 + base size=32 base align=8 +_pthread_cleanup_buffer (0x0x7ffec8586c00) 0 + +Class __pthread_cleanup_frame + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_frame (0x0x7ffec8586d20) 0 + +Class __pthread_cleanup_class + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_class (0x0x7ffec8586d80) 0 + +Class QLatin1String + size=16 align=8 + base size=16 base align=8 +QLatin1String (0x0x7ffec828d4e0) 0 + +Class QStringDataPtr + size=8 align=8 + base size=8 base align=8 +QStringDataPtr (0x0x7ffec828d660) 0 + +Class QString::Null + size=1 align=1 + base size=0 base align=1 +QString::Null (0x0x7ffec828d720) 0 empty + +Class QString + size=8 align=8 + base size=8 base align=8 +QString (0x0x7ffec828d6c0) 0 + +Class QCharRef + size=16 align=8 + base size=12 base align=8 +QCharRef (0x0x7ffec828d8a0) 0 + +Class QStringRef + size=16 align=8 + base size=16 base align=8 +QStringRef (0x0x7ffec828db40) 0 + +Class std::locale + size=8 align=8 + base size=8 base align=8 +std::locale (0x0x7ffec828dd20) 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 (0x0x7ffec828dd80) 0 + vptr=((& std::locale::facet::_ZTVNSt6locale5facetE) + 16u) + +Class std::locale::id + size=8 align=8 + base size=8 base align=8 +std::locale::id (0x0x7ffec828dde0) 0 + +Class std::locale::_Impl + size=40 align=8 + base size=40 base align=8 +std::locale::_Impl (0x0x7ffec828de40) 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 (0x0x7ffec841bbc8) 0 + vptr=((& std::ios_base::failure::_ZTVNSt8ios_base7failureE) + 16u) + std::exception (0x0x7ffec7f4e2a0) 0 nearly-empty + primary-for std::ios_base::failure (0x0x7ffec841bbc8) + +Class std::ios_base::_Callback_list + size=24 align=8 + base size=24 base align=8 +std::ios_base::_Callback_list (0x0x7ffec7f4e300) 0 + +Class std::ios_base::_Words + size=16 align=8 + base size=16 base align=8 +std::ios_base::_Words (0x0x7ffec7f4e360) 0 + +Class std::ios_base::Init + size=1 align=1 + base size=0 base align=1 +std::ios_base::Init (0x0x7ffec7f4e3c0) 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 (0x0x7ffec7f4e240) 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 (0x0x7ffec7f4e540) 0 empty + +Class std::__num_base + size=1 align=1 + base size=0 base align=1 +std::__num_base (0x0x7ffec7f4ec00) 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 (0x0x7ffec7bab6e8 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 (0x0x7ffec7bab7b8 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 (0x0x7ffec7baba90 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 (0x0x7ffec7babb60 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 (0x0x7ffec7c36000) 0 + +Class QListData::Data + size=24 align=8 + base size=24 base align=8 +QListData::Data (0x0x7ffec7c36300) 0 + +Class QListData + size=8 align=8 + base size=8 base align=8 +QListData (0x0x7ffec7c362a0) 0 + +Class QScopedPointerPodDeleter + size=1 align=1 + base size=0 base align=1 +QScopedPointerPodDeleter (0x0x7ffec7c366c0) 0 empty + +Class std::_Bit_reference + size=16 align=8 + base size=16 base align=8 +std::_Bit_reference (0x0x7ffec7a28420) 0 + +Class std::_Bit_iterator_base + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator_base (0x0x7ffec7bab9c0) 0 + std::iterator (0x0x7ffec7a284e0) 0 empty + +Class std::_Bit_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator (0x0x7ffec7babc98) 0 + std::_Bit_iterator_base (0x0x7ffec7babd00) 0 + std::iterator (0x0x7ffec7a28540) 0 empty + +Class std::_Bit_const_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_const_iterator (0x0x7ffec7babd68) 0 + std::_Bit_iterator_base (0x0x7ffec76ea000) 0 + std::iterator (0x0x7ffec7a285a0) 0 empty + +Class std::_Rb_tree_node_base + size=32 align=8 + base size=32 base align=8 +std::_Rb_tree_node_base (0x0x7ffec7a28960) 0 + +Class QtPrivate::AbstractDebugStreamFunction + size=16 align=8 + base size=16 base align=8 +QtPrivate::AbstractDebugStreamFunction (0x0x7ffec7a28d80) 0 + +Class QtPrivate::AbstractComparatorFunction + size=24 align=8 + base size=24 base align=8 +QtPrivate::AbstractComparatorFunction (0x0x7ffec7a28e40) 0 + +Class QtPrivate::AbstractConverterFunction + size=8 align=8 + base size=8 base align=8 +QtPrivate::AbstractConverterFunction (0x0x7ffec7a28f00) 0 + +Class QMetaType + size=80 align=8 + base size=80 base align=8 +QMetaType (0x0x7ffec7504360) 0 + +Class QtMetaTypePrivate::VariantData + size=24 align=8 + base size=20 base align=8 +QtMetaTypePrivate::VariantData (0x0x7ffec75046c0) 0 + +Class QtMetaTypePrivate::QSequentialIterableImpl + size=104 align=8 + base size=104 base align=8 +QtMetaTypePrivate::QSequentialIterableImpl (0x0x7ffec7504ae0) 0 + +Class QtMetaTypePrivate::QAssociativeIterableImpl + size=112 align=8 + base size=112 base align=8 +QtMetaTypePrivate::QAssociativeIterableImpl (0x0x7ffec7504cc0) 0 + +Class QtMetaTypePrivate::QPairVariantInterfaceImpl + size=40 align=8 + base size=40 base align=8 +QtMetaTypePrivate::QPairVariantInterfaceImpl (0x0x7ffec7504d80) 0 + +Class QtPrivate::QSlotObjectBase + size=16 align=8 + base size=16 base align=8 +QtPrivate::QSlotObjectBase (0x0x7ffec7377060) 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 (0x0x7ffec73771e0) 0 + vptr=((& QObjectData::_ZTV11QObjectData) + 16u) + +Class QObject::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObject::QPrivateSignal (0x0x7ffec7377360) 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 (0x0x7ffec7377300) 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 (0x0x7ffec7377660) 0 nearly-empty + vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16u) + +Class QSignalBlocker + size=16 align=8 + base size=10 base align=8 +QSignalBlocker (0x0x7ffec73776c0) 0 + +Class QAbstractAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractAnimation::QPrivateSignal (0x0x7ffec7377780) 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 (0x0x7ffec75fbb60) 0 + vptr=((& QAbstractAnimation::_ZTV18QAbstractAnimation) + 16u) + QObject (0x0x7ffec7377720) 0 + primary-for QAbstractAnimation (0x0x7ffec75fbb60) + +Class QAnimationDriver::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationDriver::QPrivateSignal (0x0x7ffec7377840) 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 (0x0x7ffec75fbbc8) 0 + vptr=((& QAnimationDriver::_ZTV16QAnimationDriver) + 16u) + QObject (0x0x7ffec73777e0) 0 + primary-for QAnimationDriver (0x0x7ffec75fbbc8) + +Class QAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationGroup::QPrivateSignal (0x0x7ffec7377900) 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 (0x0x7ffec75fbc30) 0 + vptr=((& QAnimationGroup::_ZTV15QAnimationGroup) + 16u) + QAbstractAnimation (0x0x7ffec75fbc98) 0 + primary-for QAnimationGroup (0x0x7ffec75fbc30) + QObject (0x0x7ffec73778a0) 0 + primary-for QAbstractAnimation (0x0x7ffec75fbc98) + +Class QParallelAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QParallelAnimationGroup::QPrivateSignal (0x0x7ffec73779c0) 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 (0x0x7ffec75fbd00) 0 + vptr=((& QParallelAnimationGroup::_ZTV23QParallelAnimationGroup) + 16u) + QAnimationGroup (0x0x7ffec75fbd68) 0 + primary-for QParallelAnimationGroup (0x0x7ffec75fbd00) + QAbstractAnimation (0x0x7ffec75fbdd0) 0 + primary-for QAnimationGroup (0x0x7ffec75fbd68) + QObject (0x0x7ffec7377960) 0 + primary-for QAbstractAnimation (0x0x7ffec75fbdd0) + +Class QPauseAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPauseAnimation::QPrivateSignal (0x0x7ffec7377a80) 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 (0x0x7ffec75fbe38) 0 + vptr=((& QPauseAnimation::_ZTV15QPauseAnimation) + 16u) + QAbstractAnimation (0x0x7ffec75fbea0) 0 + primary-for QPauseAnimation (0x0x7ffec75fbe38) + QObject (0x0x7ffec7377a20) 0 + primary-for QAbstractAnimation (0x0x7ffec75fbea0) + +Class QEasingCurve + size=8 align=8 + base size=8 base align=8 +QEasingCurve (0x0x7ffec7377c60) 0 + +Class QMapNodeBase + size=24 align=8 + base size=24 base align=8 +QMapNodeBase (0x0x7ffec7377e40) 0 + +Class QMapDataBase + size=40 align=8 + base size=40 base align=8 +QMapDataBase (0x0x7ffec7377f00) 0 + +Class QHashData::Node + size=16 align=8 + base size=16 base align=8 +QHashData::Node (0x0x7ffec71a72a0) 0 + +Class QHashData + size=48 align=8 + base size=48 base align=8 +QHashData (0x0x7ffec71a7240) 0 + +Class QHashDummyValue + size=1 align=1 + base size=0 base align=1 +QHashDummyValue (0x0x7ffec71a7300) 0 empty + +Class QIODevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIODevice::QPrivateSignal (0x0x7ffec71a77e0) 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 (0x0x7ffec71077b8) 0 + vptr=((& QIODevice::_ZTV9QIODevice) + 16u) + QObject (0x0x7ffec71a7780) 0 + primary-for QIODevice (0x0x7ffec71077b8) + +Class QDataStream + size=32 align=8 + base size=32 base align=8 +QDataStream (0x0x7ffec71a7900) 0 + +Class QRegExp + size=8 align=8 + base size=8 base align=8 +QRegExp (0x0x7ffec71a79c0) 0 + +Class QStringMatcher::Data + size=272 align=8 + base size=272 base align=8 +QStringMatcher::Data (0x0x7ffec71a7b40) 0 + +Class QStringMatcher + size=1048 align=8 + base size=1048 base align=8 +QStringMatcher (0x0x7ffec71a7ae0) 0 + +Class QStringList + size=8 align=8 + base size=8 base align=8 +QStringList (0x0x7ffec7107958) 0 + QList (0x0x7ffec71a7cc0) 0 + +Class QVariant::PrivateShared + size=16 align=8 + base size=12 base align=8 +QVariant::PrivateShared (0x0x7ffec6c83000) 0 + +Class QVariant::Private::Data + size=8 align=8 + base size=8 base align=8 +QVariant::Private::Data (0x0x7ffec6c830c0) 0 + +Class QVariant::Private + size=16 align=8 + base size=12 base align=8 +QVariant::Private (0x0x7ffec6c83060) 0 + +Class QVariant::Handler + size=72 align=8 + base size=72 base align=8 +QVariant::Handler (0x0x7ffec6c83120) 0 + +Class QVariant + size=16 align=8 + base size=16 base align=8 +QVariant (0x0x7ffec71a7f60) 0 + +Class QVariantComparisonHelper + size=8 align=8 + base size=8 base align=8 +QVariantComparisonHelper (0x0x7ffec6c833c0) 0 + +Class QSequentialIterable::const_iterator + size=112 align=8 + base size=112 base align=8 +QSequentialIterable::const_iterator (0x0x7ffec6c83480) 0 + +Class QSequentialIterable + size=104 align=8 + base size=104 base align=8 +QSequentialIterable (0x0x7ffec6c83420) 0 + +Class QAssociativeIterable::const_iterator + size=120 align=8 + base size=120 base align=8 +QAssociativeIterable::const_iterator (0x0x7ffec6c83540) 0 + +Class QAssociativeIterable + size=112 align=8 + base size=112 base align=8 +QAssociativeIterable (0x0x7ffec6c834e0) 0 + +Class QVariantAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QVariantAnimation::QPrivateSignal (0x0x7ffec6d96120) 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 (0x0x7ffec6d78340) 0 + vptr=((& QVariantAnimation::_ZTV17QVariantAnimation) + 16u) + QAbstractAnimation (0x0x7ffec6d783a8) 0 + primary-for QVariantAnimation (0x0x7ffec6d78340) + QObject (0x0x7ffec6d960c0) 0 + primary-for QAbstractAnimation (0x0x7ffec6d783a8) + +Class QPropertyAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPropertyAnimation::QPrivateSignal (0x0x7ffec6d961e0) 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 (0x0x7ffec6d78478) 0 + vptr=((& QPropertyAnimation::_ZTV18QPropertyAnimation) + 16u) + QVariantAnimation (0x0x7ffec6d784e0) 0 + primary-for QPropertyAnimation (0x0x7ffec6d78478) + QAbstractAnimation (0x0x7ffec6d78548) 0 + primary-for QVariantAnimation (0x0x7ffec6d784e0) + QObject (0x0x7ffec6d96180) 0 + primary-for QAbstractAnimation (0x0x7ffec6d78548) + +Class QSequentialAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSequentialAnimationGroup::QPrivateSignal (0x0x7ffec6d962a0) 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 (0x0x7ffec6d785b0) 0 + vptr=((& QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup) + 16u) + QAnimationGroup (0x0x7ffec6d78618) 0 + primary-for QSequentialAnimationGroup (0x0x7ffec6d785b0) + QAbstractAnimation (0x0x7ffec6d78680) 0 + primary-for QAnimationGroup (0x0x7ffec6d78618) + QObject (0x0x7ffec6d96240) 0 + primary-for QAbstractAnimation (0x0x7ffec6d78680) + +Class QTextCodec::ConverterState + size=32 align=8 + base size=32 base align=8 +QTextCodec::ConverterState (0x0x7ffec6d96360) 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 (0x0x7ffec6d96300) 0 nearly-empty + vptr=((& QTextCodec::_ZTV10QTextCodec) + 16u) + +Class QTextEncoder + size=40 align=8 + base size=40 base align=8 +QTextEncoder (0x0x7ffec6d96480) 0 + +Class QTextDecoder + size=40 align=8 + base size=40 base align=8 +QTextDecoder (0x0x7ffec6d964e0) 0 + +Class QSharedData + size=4 align=4 + base size=4 base align=4 +QSharedData (0x0x7ffec6d96540) 0 + +Class QtSharedPointer::NormalDeleter + size=1 align=1 + base size=0 base align=1 +QtSharedPointer::NormalDeleter (0x0x7ffec6d967e0) 0 empty + +Class QtSharedPointer::ExternalRefCountData + size=16 align=8 + base size=16 base align=8 +QtSharedPointer::ExternalRefCountData (0x0x7ffec6d96960) 0 + +Class std::__numeric_limits_base + size=1 align=1 + base size=0 base align=1 +std::__numeric_limits_base (0x0x7ffec6d96de0) 0 empty + +Class QDate + size=8 align=8 + base size=8 base align=8 +QDate (0x0x7ffec6b515a0) 0 + +Class QTime + size=4 align=4 + base size=4 base align=4 +QTime (0x0x7ffec6b516c0) 0 + +Class QDateTime + size=8 align=8 + base size=8 base align=8 +QDateTime (0x0x7ffec6b517e0) 0 + +Class QLibraryInfo + size=1 align=1 + base size=0 base align=1 +QLibraryInfo (0x0x7ffec6b51960) 0 empty + +Class QBuffer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBuffer::QPrivateSignal (0x0x7ffec6b51a20) 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 (0x0x7ffec6d78c98) 0 + vptr=((& QBuffer::_ZTV7QBuffer) + 16u) + QIODevice (0x0x7ffec6d78d00) 0 + primary-for QBuffer (0x0x7ffec6d78c98) + QObject (0x0x7ffec6b519c0) 0 + primary-for QIODevice (0x0x7ffec6d78d00) + +Class QLocale + size=8 align=8 + base size=8 base align=8 +QLocale (0x0x7ffec6b51a80) 0 + +Class _IO_marker + size=24 align=8 + base size=24 base align=8 +_IO_marker (0x0x7ffec6b51d80) 0 + +Class _IO_FILE + size=216 align=8 + base size=216 base align=8 +_IO_FILE (0x0x7ffec6b51de0) 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 (0x0x7ffec6b51ea0) 0 + vptr=((& QTextStream::_ZTV11QTextStream) + 16u) + +Class QTextStreamManipulator + size=40 align=8 + base size=38 base align=8 +QTextStreamManipulator (0x0x7ffec6924180) 0 + +Class QContiguousCacheData + size=24 align=4 + base size=24 base align=4 +QContiguousCacheData (0x0x7ffec69243c0) 0 + +Class QDebug::Stream + size=72 align=8 + base size=72 base align=8 +QDebug::Stream (0x0x7ffec6924a20) 0 + +Class QDebug + size=8 align=8 + base size=8 base align=8 +QDebug (0x0x7ffec69249c0) 0 + +Class QDebugStateSaver + size=8 align=8 + base size=8 base align=8 +QDebugStateSaver (0x0x7ffec6924b40) 0 + +Class QNoDebug + size=1 align=1 + base size=0 base align=1 +QNoDebug (0x0x7ffec6924c00) 0 empty + +Class QFileDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileDevice::QPrivateSignal (0x0x7ffec6924cc0) 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 (0x0x7ffec6d78a90) 0 + vptr=((& QFileDevice::_ZTV11QFileDevice) + 16u) + QIODevice (0x0x7ffec6d789c0) 0 + primary-for QFileDevice (0x0x7ffec6d78a90) + QObject (0x0x7ffec6924c60) 0 + primary-for QIODevice (0x0x7ffec6d789c0) + +Class QFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFile::QPrivateSignal (0x0x7ffec6924e40) 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 (0x0x7ffec66a80d0) 0 + vptr=((& QFile::_ZTV5QFile) + 16u) + QFileDevice (0x0x7ffec66a8138) 0 + primary-for QFile (0x0x7ffec66a80d0) + QIODevice (0x0x7ffec66a81a0) 0 + primary-for QFileDevice (0x0x7ffec66a8138) + QObject (0x0x7ffec6924de0) 0 + primary-for QIODevice (0x0x7ffec66a81a0) + +Class QFileInfo + size=8 align=8 + base size=8 base align=8 +QFileInfo (0x0x7ffec6924f60) 0 + +Class QDir + size=8 align=8 + base size=8 base align=8 +QDir (0x0x7ffec66f4240) 0 + +Class QDirIterator + size=8 align=8 + base size=8 base align=8 +QDirIterator (0x0x7ffec66f4540) 0 + +Class QFileSelector::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSelector::QPrivateSignal (0x0x7ffec66f4720) 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 (0x0x7ffec66a8680) 0 + vptr=((& QFileSelector::_ZTV13QFileSelector) + 16u) + QObject (0x0x7ffec66f46c0) 0 + primary-for QFileSelector (0x0x7ffec66a8680) + +Class QFileSystemWatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSystemWatcher::QPrivateSignal (0x0x7ffec66f47e0) 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 (0x0x7ffec66a86e8) 0 + vptr=((& QFileSystemWatcher::_ZTV18QFileSystemWatcher) + 16u) + QObject (0x0x7ffec66f4780) 0 + primary-for QFileSystemWatcher (0x0x7ffec66a86e8) + +Class QLockFile + size=8 align=8 + base size=8 base align=8 +QLockFile (0x0x7ffec66f4840) 0 + +Class QLoggingCategory + size=24 align=8 + base size=24 base align=8 +QLoggingCategory (0x0x7ffec66f4960) 0 + +Class QProcessEnvironment + size=8 align=8 + base size=8 base align=8 +QProcessEnvironment (0x0x7ffec66f49c0) 0 + +Class QProcess::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QProcess::QPrivateSignal (0x0x7ffec66f4ba0) 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 (0x0x7ffec66a87b8) 0 + vptr=((& QProcess::_ZTV8QProcess) + 16u) + QIODevice (0x0x7ffec66a8820) 0 + primary-for QProcess (0x0x7ffec66a87b8) + QObject (0x0x7ffec66f4b40) 0 + primary-for QIODevice (0x0x7ffec66a8820) + +Class QResource + size=8 align=8 + base size=8 base align=8 +QResource (0x0x7ffec66f4c00) 0 + +Class QSaveFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSaveFile::QPrivateSignal (0x0x7ffec66f4d80) 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 (0x0x7ffec66a8888) 0 + vptr=((& QSaveFile::_ZTV9QSaveFile) + 16u) + QFileDevice (0x0x7ffec66a88f0) 0 + primary-for QSaveFile (0x0x7ffec66a8888) + QIODevice (0x0x7ffec66a8958) 0 + primary-for QFileDevice (0x0x7ffec66a88f0) + QObject (0x0x7ffec66f4d20) 0 + primary-for QIODevice (0x0x7ffec66a8958) + +Class QSettings::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSettings::QPrivateSignal (0x0x7ffec66f4e40) 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 (0x0x7ffec66a89c0) 0 + vptr=((& QSettings::_ZTV9QSettings) + 16u) + QObject (0x0x7ffec66f4de0) 0 + primary-for QSettings (0x0x7ffec66a89c0) + +Class QStandardPaths + size=1 align=1 + base size=0 base align=1 +QStandardPaths (0x0x7ffec66f4ea0) 0 empty + +Class QTemporaryDir + size=8 align=8 + base size=8 base align=8 +QTemporaryDir (0x0x7ffec6476000) 0 + +Class QTemporaryFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTemporaryFile::QPrivateSignal (0x0x7ffec6476120) 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 (0x0x7ffec66a8af8) 0 + vptr=((& QTemporaryFile::_ZTV14QTemporaryFile) + 16u) + QFile (0x0x7ffec66a8b60) 0 + primary-for QTemporaryFile (0x0x7ffec66a8af8) + QFileDevice (0x0x7ffec66a8bc8) 0 + primary-for QFile (0x0x7ffec66a8b60) + QIODevice (0x0x7ffec66a8c30) 0 + primary-for QFileDevice (0x0x7ffec66a8bc8) + QObject (0x0x7ffec64760c0) 0 + primary-for QIODevice (0x0x7ffec66a8c30) + +Class QUrl + size=8 align=8 + base size=8 base align=8 +QUrl (0x0x7ffec6476240) 0 + +Class QUrlQuery + size=8 align=8 + base size=8 base align=8 +QUrlQuery (0x0x7ffec6476660) 0 + +Class QModelIndex + size=24 align=8 + base size=24 base align=8 +QModelIndex (0x0x7ffec64767e0) 0 + +Class QPersistentModelIndex + size=8 align=8 + base size=8 base align=8 +QPersistentModelIndex (0x0x7ffec6476900) 0 + +Class QAbstractItemModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractItemModel::QPrivateSignal (0x0x7ffec6476a80) 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 (0x0x7ffec658a068) 0 + vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16u) + QObject (0x0x7ffec6476a20) 0 + primary-for QAbstractItemModel (0x0x7ffec658a068) + +Class QAbstractTableModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTableModel::QPrivateSignal (0x0x7ffec6476d80) 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 (0x0x7ffec658a1a0) 0 + vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16u) + QAbstractItemModel (0x0x7ffec658a208) 0 + primary-for QAbstractTableModel (0x0x7ffec658a1a0) + QObject (0x0x7ffec6476d20) 0 + primary-for QAbstractItemModel (0x0x7ffec658a208) + +Class QAbstractListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractListModel::QPrivateSignal (0x0x7ffec6476e40) 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 (0x0x7ffec658a270) 0 + vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16u) + QAbstractItemModel (0x0x7ffec658a2d8) 0 + primary-for QAbstractListModel (0x0x7ffec658a270) + QObject (0x0x7ffec6476de0) 0 + primary-for QAbstractItemModel (0x0x7ffec658a2d8) + +Class QAbstractProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractProxyModel::QPrivateSignal (0x0x7ffec6476f00) 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 (0x0x7ffec658a340) 0 + vptr=((& QAbstractProxyModel::_ZTV19QAbstractProxyModel) + 16u) + QAbstractItemModel (0x0x7ffec658a3a8) 0 + primary-for QAbstractProxyModel (0x0x7ffec658a340) + QObject (0x0x7ffec6476ea0) 0 + primary-for QAbstractItemModel (0x0x7ffec658a3a8) + +Class QIdentityProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIdentityProxyModel::QPrivateSignal (0x0x7ffec626d000) 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 (0x0x7ffec658a410) 0 + vptr=((& QIdentityProxyModel::_ZTV19QIdentityProxyModel) + 16u) + QAbstractProxyModel (0x0x7ffec658a478) 0 + primary-for QIdentityProxyModel (0x0x7ffec658a410) + QAbstractItemModel (0x0x7ffec658a4e0) 0 + primary-for QAbstractProxyModel (0x0x7ffec658a478) + QObject (0x0x7ffec6476f60) 0 + primary-for QAbstractItemModel (0x0x7ffec658a4e0) + +Class QItemSelectionRange + size=16 align=8 + base size=16 base align=8 +QItemSelectionRange (0x0x7ffec626d060) 0 + +Class QItemSelectionModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QItemSelectionModel::QPrivateSignal (0x0x7ffec626d1e0) 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 (0x0x7ffec658a5b0) 0 + vptr=((& QItemSelectionModel::_ZTV19QItemSelectionModel) + 16u) + QObject (0x0x7ffec626d180) 0 + primary-for QItemSelectionModel (0x0x7ffec658a5b0) + +Class QItemSelection + size=8 align=8 + base size=8 base align=8 +QItemSelection (0x0x7ffec658a6e8) 0 + QList (0x0x7ffec626d3c0) 0 + +Class QSortFilterProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSortFilterProxyModel::QPrivateSignal (0x0x7ffec626d480) 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 (0x0x7ffec658a750) 0 + vptr=((& QSortFilterProxyModel::_ZTV21QSortFilterProxyModel) + 16u) + QAbstractProxyModel (0x0x7ffec658a7b8) 0 + primary-for QSortFilterProxyModel (0x0x7ffec658a750) + QAbstractItemModel (0x0x7ffec658a820) 0 + primary-for QAbstractProxyModel (0x0x7ffec658a7b8) + QObject (0x0x7ffec626d420) 0 + primary-for QAbstractItemModel (0x0x7ffec658a820) + +Class QStringListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStringListModel::QPrivateSignal (0x0x7ffec626d540) 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 (0x0x7ffec658a888) 0 + vptr=((& QStringListModel::_ZTV16QStringListModel) + 16u) + QAbstractListModel (0x0x7ffec658a8f0) 0 + primary-for QStringListModel (0x0x7ffec658a888) + QAbstractItemModel (0x0x7ffec658a958) 0 + primary-for QAbstractListModel (0x0x7ffec658a8f0) + QObject (0x0x7ffec626d4e0) 0 + primary-for QAbstractItemModel (0x0x7ffec658a958) + +Class QJsonValue + size=24 align=8 + base size=20 base align=8 +QJsonValue (0x0x7ffec626d5a0) 0 + +Class QJsonValueRef + size=16 align=8 + base size=12 base align=8 +QJsonValueRef (0x0x7ffec626d660) 0 + +Class QJsonArray::iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::iterator (0x0x7ffec626d780) 0 + +Class QJsonArray::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::const_iterator (0x0x7ffec626d7e0) 0 + +Class QJsonArray + size=16 align=8 + base size=16 base align=8 +QJsonArray (0x0x7ffec626d720) 0 + +Class QJsonParseError + size=8 align=4 + base size=8 base align=4 +QJsonParseError (0x0x7ffec626d840) 0 + +Class QJsonDocument + size=8 align=8 + base size=8 base align=8 +QJsonDocument (0x0x7ffec626d8a0) 0 + +Class QJsonObject::iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::iterator (0x0x7ffec626d960) 0 + +Class QJsonObject::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::const_iterator (0x0x7ffec626d9c0) 0 + +Class QJsonObject + size=16 align=8 + base size=16 base align=8 +QJsonObject (0x0x7ffec626d900) 0 + +Class QEventLoop::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventLoop::QPrivateSignal (0x0x7ffec626dae0) 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 (0x0x7ffec658a9c0) 0 + vptr=((& QEventLoop::_ZTV10QEventLoop) + 16u) + QObject (0x0x7ffec626da80) 0 + primary-for QEventLoop (0x0x7ffec658a9c0) + +Class QEventLoopLocker + size=8 align=8 + base size=8 base align=8 +QEventLoopLocker (0x0x7ffec626dc00) 0 + +Class QAbstractEventDispatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractEventDispatcher::QPrivateSignal (0x0x7ffec626dcc0) 0 empty + +Class QAbstractEventDispatcher::TimerInfo + size=12 align=4 + base size=12 base align=4 +QAbstractEventDispatcher::TimerInfo (0x0x7ffec626dd20) 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 (0x0x7ffec658aaf8) 0 + vptr=((& QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher) + 16u) + QObject (0x0x7ffec626dc60) 0 + primary-for QAbstractEventDispatcher (0x0x7ffec658aaf8) + +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 (0x0x7ffec626dd80) 0 + vptr=((& QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter) + 16u) + +Class QBasicTimer + size=4 align=4 + base size=4 base align=4 +QBasicTimer (0x0x7ffec626dde0) 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 (0x0x7ffec626df00) 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 (0x0x7ffec658abc8) 0 + vptr=((& QTimerEvent::_ZTV11QTimerEvent) + 16u) + QEvent (0x0x7ffec626df60) 0 + primary-for QTimerEvent (0x0x7ffec658abc8) + +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 (0x0x7ffec658ac30) 0 + vptr=((& QChildEvent::_ZTV11QChildEvent) + 16u) + QEvent (0x0x7ffec609c000) 0 + primary-for QChildEvent (0x0x7ffec658ac30) + +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 (0x0x7ffec658ac98) 0 + vptr=((& QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent) + 16u) + QEvent (0x0x7ffec609c060) 0 + primary-for QDynamicPropertyChangeEvent (0x0x7ffec658ac98) + +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 (0x0x7ffec658ad00) 0 + vptr=((& QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent) + 16u) + QEvent (0x0x7ffec609c0c0) 0 + primary-for QDeferredDeleteEvent (0x0x7ffec658ad00) + +Class QCoreApplication::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QCoreApplication::QPrivateSignal (0x0x7ffec609c180) 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 (0x0x7ffec658ad68) 0 + vptr=((& QCoreApplication::_ZTV16QCoreApplication) + 16u) + QObject (0x0x7ffec609c120) 0 + primary-for QCoreApplication (0x0x7ffec658ad68) + +Class __exception + size=40 align=8 + base size=40 base align=8 +__exception (0x0x7ffec609c1e0) 0 + +Class QMetaMethod + size=16 align=8 + base size=12 base align=8 +QMetaMethod (0x0x7ffec609c240) 0 + +Class QMetaEnum + size=16 align=8 + base size=12 base align=8 +QMetaEnum (0x0x7ffec609c360) 0 + +Class QMetaProperty + size=32 align=8 + base size=32 base align=8 +QMetaProperty (0x0x7ffec609c480) 0 + +Class QMetaClassInfo + size=16 align=8 + base size=12 base align=8 +QMetaClassInfo (0x0x7ffec609c4e0) 0 + +Class QMimeData::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QMimeData::QPrivateSignal (0x0x7ffec609c660) 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 (0x0x7ffec616c000) 0 + vptr=((& QMimeData::_ZTV9QMimeData) + 16u) + QObject (0x0x7ffec609c600) 0 + primary-for QMimeData (0x0x7ffec616c000) + +Class QObjectCleanupHandler::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObjectCleanupHandler::QPrivateSignal (0x0x7ffec609c720) 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 (0x0x7ffec616c068) 0 + vptr=((& QObjectCleanupHandler::_ZTV21QObjectCleanupHandler) + 16u) + QObject (0x0x7ffec609c6c0) 0 + primary-for QObjectCleanupHandler (0x0x7ffec616c068) + +Class QSharedMemory::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSharedMemory::QPrivateSignal (0x0x7ffec609c960) 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 (0x0x7ffec616c0d0) 0 + vptr=((& QSharedMemory::_ZTV13QSharedMemory) + 16u) + QObject (0x0x7ffec609c900) 0 + primary-for QSharedMemory (0x0x7ffec616c0d0) + +Class QSignalMapper::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalMapper::QPrivateSignal (0x0x7ffec609ca20) 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 (0x0x7ffec616c138) 0 + vptr=((& QSignalMapper::_ZTV13QSignalMapper) + 16u) + QObject (0x0x7ffec609c9c0) 0 + primary-for QSignalMapper (0x0x7ffec616c138) + +Class QSocketNotifier::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSocketNotifier::QPrivateSignal (0x0x7ffec609cae0) 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 (0x0x7ffec616c1a0) 0 + vptr=((& QSocketNotifier::_ZTV15QSocketNotifier) + 16u) + QObject (0x0x7ffec609ca80) 0 + primary-for QSocketNotifier (0x0x7ffec616c1a0) + +Class QSystemSemaphore + size=8 align=8 + base size=8 base align=8 +QSystemSemaphore (0x0x7ffec609cb40) 0 + +Class QTimer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimer::QPrivateSignal (0x0x7ffec609cc60) 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 (0x0x7ffec616c208) 0 + vptr=((& QTimer::_ZTV6QTimer) + 16u) + QObject (0x0x7ffec609cc00) 0 + primary-for QTimer (0x0x7ffec616c208) + +Class QTranslator::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTranslator::QPrivateSignal (0x0x7ffec609cd80) 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 (0x0x7ffec616c270) 0 + vptr=((& QTranslator::_ZTV11QTranslator) + 16u) + QObject (0x0x7ffec609cd20) 0 + primary-for QTranslator (0x0x7ffec616c270) + +Class QMimeType + size=8 align=8 + base size=8 base align=8 +QMimeType (0x0x7ffec609cde0) 0 + +Class QMimeDatabase + size=8 align=8 + base size=8 base align=8 +QMimeDatabase (0x0x7ffec609cf60) 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 (0x0x7ffec6233000) 0 nearly-empty + vptr=((& QFactoryInterface::_ZTV17QFactoryInterface) + 16u) + +Class QLibrary::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLibrary::QPrivateSignal (0x0x7ffec6233120) 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 (0x0x7ffec616c340) 0 + vptr=((& QLibrary::_ZTV8QLibrary) + 16u) + QObject (0x0x7ffec62330c0) 0 + primary-for QLibrary (0x0x7ffec616c340) + +Class QStaticPlugin + size=16 align=8 + base size=16 base align=8 +QStaticPlugin (0x0x7ffec6233240) 0 + +Class QPluginLoader::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPluginLoader::QPrivateSignal (0x0x7ffec62333c0) 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 (0x0x7ffec616c4e0) 0 + vptr=((& QPluginLoader::_ZTV13QPluginLoader) + 16u) + QObject (0x0x7ffec6233360) 0 + primary-for QPluginLoader (0x0x7ffec616c4e0) + +Class QUuid + size=16 align=4 + base size=16 base align=4 +QUuid (0x0x7ffec6233420) 0 + +Class QAbstractState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractState::QPrivateSignal (0x0x7ffec62335a0) 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 (0x0x7ffec616c5b0) 0 + vptr=((& QAbstractState::_ZTV14QAbstractState) + 16u) + QObject (0x0x7ffec6233540) 0 + primary-for QAbstractState (0x0x7ffec616c5b0) + +Class QAbstractTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTransition::QPrivateSignal (0x0x7ffec6233660) 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 (0x0x7ffec616c618) 0 + vptr=((& QAbstractTransition::_ZTV19QAbstractTransition) + 16u) + QObject (0x0x7ffec6233600) 0 + primary-for QAbstractTransition (0x0x7ffec616c618) + +Class QEventTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventTransition::QPrivateSignal (0x0x7ffec6233720) 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 (0x0x7ffec616c680) 0 + vptr=((& QEventTransition::_ZTV16QEventTransition) + 16u) + QAbstractTransition (0x0x7ffec616c6e8) 0 + primary-for QEventTransition (0x0x7ffec616c680) + QObject (0x0x7ffec62336c0) 0 + primary-for QAbstractTransition (0x0x7ffec616c6e8) + +Class QFinalState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFinalState::QPrivateSignal (0x0x7ffec62337e0) 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 (0x0x7ffec616c750) 0 + vptr=((& QFinalState::_ZTV11QFinalState) + 16u) + QAbstractState (0x0x7ffec616c7b8) 0 + primary-for QFinalState (0x0x7ffec616c750) + QObject (0x0x7ffec6233780) 0 + primary-for QAbstractState (0x0x7ffec616c7b8) + +Class QHistoryState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QHistoryState::QPrivateSignal (0x0x7ffec62338a0) 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 (0x0x7ffec616c820) 0 + vptr=((& QHistoryState::_ZTV13QHistoryState) + 16u) + QAbstractState (0x0x7ffec616c888) 0 + primary-for QHistoryState (0x0x7ffec616c820) + QObject (0x0x7ffec6233840) 0 + primary-for QAbstractState (0x0x7ffec616c888) + +Class QSignalTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalTransition::QPrivateSignal (0x0x7ffec6233960) 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 (0x0x7ffec616c8f0) 0 + vptr=((& QSignalTransition::_ZTV17QSignalTransition) + 16u) + QAbstractTransition (0x0x7ffec616c958) 0 + primary-for QSignalTransition (0x0x7ffec616c8f0) + QObject (0x0x7ffec6233900) 0 + primary-for QAbstractTransition (0x0x7ffec616c958) + +Class QState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QState::QPrivateSignal (0x0x7ffec6233a20) 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 (0x0x7ffec616c9c0) 0 + vptr=((& QState::_ZTV6QState) + 16u) + QAbstractState (0x0x7ffec616ca28) 0 + primary-for QState (0x0x7ffec616c9c0) + QObject (0x0x7ffec62339c0) 0 + primary-for QAbstractState (0x0x7ffec616ca28) + +Class QStateMachine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStateMachine::QPrivateSignal (0x0x7ffec6233b40) 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 (0x0x7ffec616cbc8) 0 + vptr=((& QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE) + 16u) + QEvent (0x0x7ffec6233ba0) 0 + primary-for QStateMachine::SignalEvent (0x0x7ffec616cbc8) + +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 (0x0x7ffec616cc30) 0 + vptr=((& QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE) + 16u) + QEvent (0x0x7ffec6233c00) 0 + primary-for QStateMachine::WrappedEvent (0x0x7ffec616cc30) + +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 (0x0x7ffec616ca90) 0 + vptr=((& QStateMachine::_ZTV13QStateMachine) + 16u) + QState (0x0x7ffec616caf8) 0 + primary-for QStateMachine (0x0x7ffec616ca90) + QAbstractState (0x0x7ffec616cb60) 0 + primary-for QState (0x0x7ffec616caf8) + QObject (0x0x7ffec6233ae0) 0 + primary-for QAbstractState (0x0x7ffec616cb60) + +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 (0x0x7ffec616cc98) 0 nearly-empty + vptr=((& QException::_ZTV10QException) + 16u) + std::exception (0x0x7ffec6233c60) 0 nearly-empty + primary-for QException (0x0x7ffec616cc98) + +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 (0x0x7ffec616cd00) 0 nearly-empty + vptr=((& QUnhandledException::_ZTV19QUnhandledException) + 16u) + QException (0x0x7ffec616cd68) 0 nearly-empty + primary-for QUnhandledException (0x0x7ffec616cd00) + std::exception (0x0x7ffec6233cc0) 0 nearly-empty + primary-for QException (0x0x7ffec616cd68) + +Class QtPrivate::ExceptionHolder + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionHolder (0x0x7ffec6233d20) 0 + +Class QtPrivate::ExceptionStore + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionStore (0x0x7ffec6233de0) 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 (0x0x7ffec6233e40) 0 + vptr=((& QRunnable::_ZTV9QRunnable) + 16u) + +Class QBasicMutex + size=8 align=8 + base size=8 base align=8 +QBasicMutex (0x0x7ffec6233ea0) 0 + +Class QMutex + size=8 align=8 + base size=8 base align=8 +QMutex (0x0x7ffec616cf08) 0 + QBasicMutex (0x0x7ffec5f6f000) 0 + +Class QMutexLocker + size=8 align=8 + base size=8 base align=8 +QMutexLocker (0x0x7ffec5f6f060) 0 + +Class QtPrivate::ResultItem + size=16 align=8 + base size=16 base align=8 +QtPrivate::ResultItem (0x0x7ffec5f6f0c0) 0 + +Class QtPrivate::ResultIteratorBase + size=16 align=8 + base size=12 base align=8 +QtPrivate::ResultIteratorBase (0x0x7ffec5f6f120) 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 (0x0x7ffec5f6f2a0) 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 (0x0x7ffec5f6f360) 0 + vptr=((& QFutureInterfaceBase::_ZTV20QFutureInterfaceBase) + 16u) + +Class QFutureWatcherBase::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFutureWatcherBase::QPrivateSignal (0x0x7ffec5f6f6c0) 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 (0x0x7ffec5fb3820) 0 + vptr=((& QFutureWatcherBase::_ZTV18QFutureWatcherBase) + 16u) + QObject (0x0x7ffec5f6f660) 0 + primary-for QFutureWatcherBase (0x0x7ffec5fb3820) + +Class QReadWriteLock + size=8 align=8 + base size=8 base align=8 +QReadWriteLock (0x0x7ffec5f6f7e0) 0 + +Class QReadLocker + size=8 align=8 + base size=8 base align=8 +QReadLocker (0x0x7ffec5f6f840) 0 + +Class QWriteLocker + size=8 align=8 + base size=8 base align=8 +QWriteLocker (0x0x7ffec5f6f8a0) 0 + +Class QSemaphore + size=8 align=8 + base size=8 base align=8 +QSemaphore (0x0x7ffec5f6f900) 0 + +Class QThread::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThread::QPrivateSignal (0x0x7ffec5f6f9c0) 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 (0x0x7ffec5fb3bc8) 0 + vptr=((& QThread::_ZTV7QThread) + 16u) + QObject (0x0x7ffec5f6f960) 0 + primary-for QThread (0x0x7ffec5fb3bc8) + +Class QThreadPool::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThreadPool::QPrivateSignal (0x0x7ffec5f6fa80) 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 (0x0x7ffec5fb3c30) 0 + vptr=((& QThreadPool::_ZTV11QThreadPool) + 16u) + QObject (0x0x7ffec5f6fa20) 0 + primary-for QThreadPool (0x0x7ffec5fb3c30) + +Class QThreadStorageData + size=4 align=4 + base size=4 base align=4 +QThreadStorageData (0x0x7ffec5f6fae0) 0 + +Class QWaitCondition + size=8 align=8 + base size=8 base align=8 +QWaitCondition (0x0x7ffec5f6fba0) 0 + +Class QBitArray + size=8 align=8 + base size=8 base align=8 +QBitArray (0x0x7ffec5d2b180) 0 + +Class QBitRef + size=16 align=8 + base size=12 base align=8 +QBitRef (0x0x7ffec5d2b1e0) 0 + +Class QByteArrayMatcher::Data + size=272 align=8 + base size=272 base align=8 +QByteArrayMatcher::Data (0x0x7ffec5d2b360) 0 + +Class QByteArrayMatcher + size=1040 align=8 + base size=1040 base align=8 +QByteArrayMatcher (0x0x7ffec5d2b300) 0 + +Class QCollatorSortKey + size=8 align=8 + base size=8 base align=8 +QCollatorSortKey (0x0x7ffec5d2b4e0) 0 + +Class QCollator + size=8 align=8 + base size=8 base align=8 +QCollator (0x0x7ffec5d2b5a0) 0 + +Class QCommandLineOption + size=8 align=8 + base size=8 base align=8 +QCommandLineOption (0x0x7ffec5d2b780) 0 + +Class QCommandLineParser + size=8 align=8 + base size=8 base align=8 +QCommandLineParser (0x0x7ffec5d2b900) 0 + +Class QCryptographicHash + size=8 align=8 + base size=8 base align=8 +QCryptographicHash (0x0x7ffec5d2b960) 0 + +Class QElapsedTimer + size=16 align=8 + base size=16 base align=8 +QElapsedTimer (0x0x7ffec5d2b9c0) 0 + +Class QPoint + size=8 align=4 + base size=8 base align=4 +QPoint (0x0x7ffec5d2ba20) 0 + +Class QPointF + size=16 align=8 + base size=16 base align=8 +QPointF (0x0x7ffec5d2bb40) 0 + +Class QLine + size=16 align=4 + base size=16 base align=4 +QLine (0x0x7ffec5d2bc60) 0 + +Class QLineF + size=32 align=8 + base size=32 base align=8 +QLineF (0x0x7ffec5d2bd80) 0 + +Class QLinkedListData + size=32 align=8 + base size=32 base align=8 +QLinkedListData (0x0x7ffec5d2bea0) 0 + +Class QMargins + size=16 align=4 + base size=16 base align=4 +QMargins (0x0x7ffec5add240) 0 + +Class QMarginsF + size=32 align=8 + base size=32 base align=8 +QMarginsF (0x0x7ffec5add360) 0 + +Class QMessageAuthenticationCode + size=8 align=8 + base size=8 base align=8 +QMessageAuthenticationCode (0x0x7ffec5add480) 0 + +Class QSize + size=8 align=4 + base size=8 base align=4 +QSize (0x0x7ffec5add540) 0 + +Class QSizeF + size=16 align=8 + base size=16 base align=8 +QSizeF (0x0x7ffec5add660) 0 + +Class QRect + size=16 align=4 + base size=16 base align=4 +QRect (0x0x7ffec5add780) 0 + +Class QRectF + size=32 align=8 + base size=32 base align=8 +QRectF (0x0x7ffec5add8a0) 0 + +Class QRegularExpression + size=8 align=8 + base size=8 base align=8 +QRegularExpression (0x0x7ffec5add9c0) 0 + +Class QRegularExpressionMatch + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatch (0x0x7ffec5addcc0) 0 + +Class QRegularExpressionMatchIterator + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatchIterator (0x0x7ffec5adde40) 0 + +Class QAbstractConcatenable + size=1 align=1 + base size=0 base align=1 +QAbstractConcatenable (0x0x7ffec59c20c0) 0 empty + +Class QTextBoundaryFinder + size=48 align=8 + base size=48 base align=8 +QTextBoundaryFinder (0x0x7ffec59c2ae0) 0 + +Class QTimeLine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimeLine::QPrivateSignal (0x0x7ffec59c2c60) 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 (0x0x7ffec5a14548) 0 + vptr=((& QTimeLine::_ZTV9QTimeLine) + 16u) + QObject (0x0x7ffec59c2c00) 0 + primary-for QTimeLine (0x0x7ffec5a14548) + +Class QTimeZone::OffsetData + size=32 align=8 + base size=28 base align=8 +QTimeZone::OffsetData (0x0x7ffec59c2d20) 0 + +Class QTimeZone + size=8 align=8 + base size=8 base align=8 +QTimeZone (0x0x7ffec59c2cc0) 0 + +Class QXmlStreamStringRef + size=16 align=8 + base size=16 base align=8 +QXmlStreamStringRef (0x0x7ffec59c2f60) 0 + +Class QXmlStreamAttribute + size=80 align=8 + base size=73 base align=8 +QXmlStreamAttribute (0x0x7ffec56bc000) 0 + +Class QXmlStreamAttributes + size=8 align=8 + base size=8 base align=8 +QXmlStreamAttributes (0x0x7ffec5a147b8) 0 + QVector (0x0x7ffec56bc1e0) 0 + +Class QXmlStreamNamespaceDeclaration + size=40 align=8 + base size=40 base align=8 +QXmlStreamNamespaceDeclaration (0x0x7ffec56bc240) 0 + +Class QXmlStreamNotationDeclaration + size=56 align=8 + base size=56 base align=8 +QXmlStreamNotationDeclaration (0x0x7ffec56bc360) 0 + +Class QXmlStreamEntityDeclaration + size=88 align=8 + base size=88 base align=8 +QXmlStreamEntityDeclaration (0x0x7ffec56bc480) 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 (0x0x7ffec56bc5a0) 0 nearly-empty + vptr=((& QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver) + 16u) + +Class QXmlStreamReader + size=8 align=8 + base size=8 base align=8 +QXmlStreamReader (0x0x7ffec56bc600) 0 + +Class QXmlStreamWriter + size=8 align=8 + base size=8 base align=8 +QXmlStreamWriter (0x0x7ffec56bc720) 0 + +Class QBluetoothAddress + size=8 align=8 + base size=8 base align=8 +QBluetoothAddress (0x0x7ffec56bc900) 0 + +Class QBluetoothDeviceInfo + size=8 align=8 + base size=8 base align=8 +QBluetoothDeviceInfo (0x0x7ffec56bca80) 0 + +Class QBluetoothDeviceDiscoveryAgent::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothDeviceDiscoveryAgent::QPrivateSignal (0x0x7ffec56bcb40) 0 empty + +Vtable for QBluetoothDeviceDiscoveryAgent +QBluetoothDeviceDiscoveryAgent::_ZTV30QBluetoothDeviceDiscoveryAgent: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI30QBluetoothDeviceDiscoveryAgent) +16 (int (*)(...))QBluetoothDeviceDiscoveryAgent::metaObject +24 (int (*)(...))QBluetoothDeviceDiscoveryAgent::qt_metacast +32 (int (*)(...))QBluetoothDeviceDiscoveryAgent::qt_metacall +40 (int (*)(...))QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent +48 (int (*)(...))QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent +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 QBluetoothDeviceDiscoveryAgent + size=24 align=8 + base size=24 base align=8 +QBluetoothDeviceDiscoveryAgent (0x0x7ffec5a14a28) 0 + vptr=((& QBluetoothDeviceDiscoveryAgent::_ZTV30QBluetoothDeviceDiscoveryAgent) + 16u) + QObject (0x0x7ffec56bcae0) 0 + primary-for QBluetoothDeviceDiscoveryAgent (0x0x7ffec5a14a28) + +Class QBluetoothHostInfo + size=8 align=8 + base size=8 base align=8 +QBluetoothHostInfo (0x0x7ffec56bcba0) 0 + +Class QBluetoothLocalDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothLocalDevice::QPrivateSignal (0x0x7ffec56bcc60) 0 empty + +Vtable for QBluetoothLocalDevice +QBluetoothLocalDevice::_ZTV21QBluetoothLocalDevice: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QBluetoothLocalDevice) +16 (int (*)(...))QBluetoothLocalDevice::metaObject +24 (int (*)(...))QBluetoothLocalDevice::qt_metacast +32 (int (*)(...))QBluetoothLocalDevice::qt_metacall +40 (int (*)(...))QBluetoothLocalDevice::~QBluetoothLocalDevice +48 (int (*)(...))QBluetoothLocalDevice::~QBluetoothLocalDevice +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 QBluetoothLocalDevice + size=24 align=8 + base size=24 base align=8 +QBluetoothLocalDevice (0x0x7ffec5a14a90) 0 + vptr=((& QBluetoothLocalDevice::_ZTV21QBluetoothLocalDevice) + 16u) + QObject (0x0x7ffec56bcc00) 0 + primary-for QBluetoothLocalDevice (0x0x7ffec5a14a90) + +Class quint128 + size=16 align=1 + base size=16 base align=1 +quint128 (0x0x7ffec5800060) 0 + +Class QBluetoothUuid + size=16 align=4 + base size=16 base align=4 +QBluetoothUuid (0x0x7ffec5a14af8) 0 + QUuid (0x0x7ffec58000c0) 0 + +Class QBluetoothServiceInfo::Sequence + size=8 align=8 + base size=8 base align=8 +QBluetoothServiceInfo::Sequence (0x0x7ffec5a14b60) 0 + QList (0x0x7ffec58002a0) 0 + +Class QBluetoothServiceInfo::Alternative + size=8 align=8 + base size=8 base align=8 +QBluetoothServiceInfo::Alternative (0x0x7ffec5a14bc8) 0 + QList (0x0x7ffec5800300) 0 + +Class QBluetoothServiceInfo + size=16 align=8 + base size=16 base align=8 +QBluetoothServiceInfo (0x0x7ffec5800240) 0 + +Class QAbstractSocket::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractSocket::QPrivateSignal (0x0x7ffec58007e0) 0 empty + +Vtable for QAbstractSocket +QAbstractSocket::_ZTV15QAbstractSocket: 41u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QAbstractSocket) +16 (int (*)(...))QAbstractSocket::metaObject +24 (int (*)(...))QAbstractSocket::qt_metacast +32 (int (*)(...))QAbstractSocket::qt_metacall +40 (int (*)(...))QAbstractSocket::~QAbstractSocket +48 (int (*)(...))QAbstractSocket::~QAbstractSocket +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 (*)(...))QAbstractSocket::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QAbstractSocket::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QAbstractSocket::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QAbstractSocket::bytesAvailable +184 (int (*)(...))QAbstractSocket::bytesToWrite +192 (int (*)(...))QAbstractSocket::canReadLine +200 (int (*)(...))QAbstractSocket::waitForReadyRead +208 (int (*)(...))QAbstractSocket::waitForBytesWritten +216 (int (*)(...))QAbstractSocket::readData +224 (int (*)(...))QAbstractSocket::readLineData +232 (int (*)(...))QAbstractSocket::writeData +240 (int (*)(...))QAbstractSocket::resume +248 (int (*)(...))QAbstractSocket::connectToHost +256 (int (*)(...))QAbstractSocket::connectToHost +264 (int (*)(...))QAbstractSocket::disconnectFromHost +272 (int (*)(...))QAbstractSocket::setReadBufferSize +280 (int (*)(...))QAbstractSocket::socketDescriptor +288 (int (*)(...))QAbstractSocket::setSocketDescriptor +296 (int (*)(...))QAbstractSocket::setSocketOption +304 (int (*)(...))QAbstractSocket::socketOption +312 (int (*)(...))QAbstractSocket::waitForConnected +320 (int (*)(...))QAbstractSocket::waitForDisconnected + +Class QAbstractSocket + size=16 align=8 + base size=16 base align=8 +QAbstractSocket (0x0x7ffec5a14e38) 0 + vptr=((& QAbstractSocket::_ZTV15QAbstractSocket) + 16u) + QIODevice (0x0x7ffec5a14ea0) 0 + primary-for QAbstractSocket (0x0x7ffec5a14e38) + QObject (0x0x7ffec5800780) 0 + primary-for QIODevice (0x0x7ffec5a14ea0) + +Class QBluetoothSocket::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothSocket::QPrivateSignal (0x0x7ffec5800c60) 0 empty + +Vtable for QBluetoothSocket +QBluetoothSocket::_ZTV16QBluetoothSocket: 30u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QBluetoothSocket) +16 (int (*)(...))QBluetoothSocket::metaObject +24 (int (*)(...))QBluetoothSocket::qt_metacast +32 (int (*)(...))QBluetoothSocket::qt_metacall +40 (int (*)(...))QBluetoothSocket::~QBluetoothSocket +48 (int (*)(...))QBluetoothSocket::~QBluetoothSocket +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 (*)(...))QBluetoothSocket::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QBluetoothSocket::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QIODevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QBluetoothSocket::bytesAvailable +184 (int (*)(...))QBluetoothSocket::bytesToWrite +192 (int (*)(...))QBluetoothSocket::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QBluetoothSocket::readData +224 (int (*)(...))QIODevice::readLineData +232 (int (*)(...))QBluetoothSocket::writeData + +Class QBluetoothSocket + size=24 align=8 + base size=24 base align=8 +QBluetoothSocket (0x0x7ffec54830d0) 0 + vptr=((& QBluetoothSocket::_ZTV16QBluetoothSocket) + 16u) + QIODevice (0x0x7ffec5483138) 0 + primary-for QBluetoothSocket (0x0x7ffec54830d0) + QObject (0x0x7ffec5800c00) 0 + primary-for QIODevice (0x0x7ffec5483138) + +Class QBluetoothServer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothServer::QPrivateSignal (0x0x7ffec5800d20) 0 empty + +Vtable for QBluetoothServer +QBluetoothServer::_ZTV16QBluetoothServer: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QBluetoothServer) +16 (int (*)(...))QBluetoothServer::metaObject +24 (int (*)(...))QBluetoothServer::qt_metacast +32 (int (*)(...))QBluetoothServer::qt_metacall +40 (int (*)(...))QBluetoothServer::~QBluetoothServer +48 (int (*)(...))QBluetoothServer::~QBluetoothServer +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 QBluetoothServer + size=24 align=8 + base size=24 base align=8 +QBluetoothServer (0x0x7ffec54831a0) 0 + vptr=((& QBluetoothServer::_ZTV16QBluetoothServer) + 16u) + QObject (0x0x7ffec5800cc0) 0 + primary-for QBluetoothServer (0x0x7ffec54831a0) + +Class QBluetoothServiceDiscoveryAgent::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothServiceDiscoveryAgent::QPrivateSignal (0x0x7ffec5800de0) 0 empty + +Vtable for QBluetoothServiceDiscoveryAgent +QBluetoothServiceDiscoveryAgent::_ZTV31QBluetoothServiceDiscoveryAgent: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI31QBluetoothServiceDiscoveryAgent) +16 (int (*)(...))QBluetoothServiceDiscoveryAgent::metaObject +24 (int (*)(...))QBluetoothServiceDiscoveryAgent::qt_metacast +32 (int (*)(...))QBluetoothServiceDiscoveryAgent::qt_metacall +40 (int (*)(...))QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent +48 (int (*)(...))QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent +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 QBluetoothServiceDiscoveryAgent + size=24 align=8 + base size=24 base align=8 +QBluetoothServiceDiscoveryAgent (0x0x7ffec5483208) 0 + vptr=((& QBluetoothServiceDiscoveryAgent::_ZTV31QBluetoothServiceDiscoveryAgent) + 16u) + QObject (0x0x7ffec5800d80) 0 + primary-for QBluetoothServiceDiscoveryAgent (0x0x7ffec5483208) + +Class QBluetoothTransferManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothTransferManager::QPrivateSignal (0x0x7ffec5800ea0) 0 empty + +Vtable for QBluetoothTransferManager +QBluetoothTransferManager::_ZTV25QBluetoothTransferManager: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI25QBluetoothTransferManager) +16 (int (*)(...))QBluetoothTransferManager::metaObject +24 (int (*)(...))QBluetoothTransferManager::qt_metacast +32 (int (*)(...))QBluetoothTransferManager::qt_metacall +40 (int (*)(...))QBluetoothTransferManager::~QBluetoothTransferManager +48 (int (*)(...))QBluetoothTransferManager::~QBluetoothTransferManager +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 QBluetoothTransferManager + size=16 align=8 + base size=16 base align=8 +QBluetoothTransferManager (0x0x7ffec5483270) 0 + vptr=((& QBluetoothTransferManager::_ZTV25QBluetoothTransferManager) + 16u) + QObject (0x0x7ffec5800e40) 0 + primary-for QBluetoothTransferManager (0x0x7ffec5483270) + +Class QBluetoothTransferRequest + size=8 align=8 + base size=8 base align=8 +QBluetoothTransferRequest (0x0x7ffec5800f00) 0 + +Class QBluetoothTransferReply::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothTransferReply::QPrivateSignal (0x0x7ffec5504000) 0 empty + +Vtable for QBluetoothTransferReply +QBluetoothTransferReply::_ZTV23QBluetoothTransferReply: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI23QBluetoothTransferReply) +16 (int (*)(...))QBluetoothTransferReply::metaObject +24 (int (*)(...))QBluetoothTransferReply::qt_metacast +32 (int (*)(...))QBluetoothTransferReply::qt_metacall +40 (int (*)(...))QBluetoothTransferReply::~QBluetoothTransferReply +48 (int (*)(...))QBluetoothTransferReply::~QBluetoothTransferReply +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 + +Class QBluetoothTransferReply + size=24 align=8 + base size=24 base align=8 +QBluetoothTransferReply (0x0x7ffec54832d8) 0 + vptr=((& QBluetoothTransferReply::_ZTV23QBluetoothTransferReply) + 16u) + QObject (0x0x7ffec5800f60) 0 + primary-for QBluetoothTransferReply (0x0x7ffec54832d8) + diff --git a/tests/auto/bic/data/QtBluetooth.5.4.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtBluetooth.5.4.0.linux-gcc-amd64.txt new file mode 100644 index 0000000..dfdde04 --- /dev/null +++ b/tests/auto/bic/data/QtBluetooth.5.4.0.linux-gcc-amd64.txt @@ -0,0 +1,4046 @@ +Class std::__true_type + size=1 align=1 + base size=0 base align=1 +std::__true_type (0x0x7fa3dc6f8060) 0 empty + +Class std::__false_type + size=1 align=1 + base size=0 base align=1 +std::__false_type (0x0x7fa3dc6f80c0) 0 empty + +Class std::input_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::input_iterator_tag (0x0x7fa3dc737c60) 0 empty + +Class std::output_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::output_iterator_tag (0x0x7fa3dc737cc0) 0 empty + +Class std::forward_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::forward_iterator_tag (0x0x7fa3dc6b66e8) 0 empty + std::input_iterator_tag (0x0x7fa3dc737d20) 0 empty + +Class std::bidirectional_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::bidirectional_iterator_tag (0x0x7fa3dc6b6750) 0 empty + std::forward_iterator_tag (0x0x7fa3dc6b67b8) 0 empty + std::input_iterator_tag (0x0x7fa3dc737d80) 0 empty + +Class std::random_access_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::random_access_iterator_tag (0x0x7fa3dc6b6820) 0 empty + std::bidirectional_iterator_tag (0x0x7fa3dc6b6888) 0 empty + std::forward_iterator_tag (0x0x7fa3dc6b68f0) 0 empty + std::input_iterator_tag (0x0x7fa3dc737de0) 0 empty + +Class wait + size=4 align=4 + base size=4 base align=4 +wait (0x0x7fa3dc76c960) 0 + +Class __locale_struct + size=232 align=8 + base size=232 base align=8 +__locale_struct (0x0x7fa3dc76cba0) 0 + +Class timespec + size=16 align=8 + base size=16 base align=8 +timespec (0x0x7fa3dc76cc60) 0 + +Class timeval + size=16 align=8 + base size=16 base align=8 +timeval (0x0x7fa3dc76ccc0) 0 + +Class pthread_attr_t + size=56 align=8 + base size=56 base align=8 +pthread_attr_t (0x0x7fa3dc76cd80) 0 + +Class __pthread_internal_list + size=16 align=8 + base size=16 base align=8 +__pthread_internal_list (0x0x7fa3dc76cde0) 0 + +Class random_data + size=48 align=8 + base size=48 base align=8 +random_data (0x0x7fa3db4562a0) 0 + +Class drand48_data + size=24 align=8 + base size=24 base align=8 +drand48_data (0x0x7fa3db456300) 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 (0x0x7fa3db456360) 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 (0x0x7fa3dc6b6c30) 0 nearly-empty + vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16u) + std::exception (0x0x7fa3db4563c0) 0 nearly-empty + primary-for std::bad_exception (0x0x7fa3dc6b6c30) + +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 (0x0x7fa3dc6b6c98) 0 nearly-empty + vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16u) + std::exception (0x0x7fa3db456420) 0 nearly-empty + primary-for std::bad_alloc (0x0x7fa3dc6b6c98) + +Class std::nothrow_t + size=1 align=1 + base size=0 base align=1 +std::nothrow_t (0x0x7fa3db456480) 0 empty + +Class qIsNull(double)::U + size=8 align=8 + base size=8 base align=8 +qIsNull(double)::U (0x0x7fa3db64a7e0) 0 + +Class qIsNull(float)::U + size=4 align=4 + base size=4 base align=4 +qIsNull(float)::U (0x0x7fa3db64a840) 0 + +Class QtPrivate::big_ + size=2 align=1 + base size=2 base align=1 +QtPrivate::big_ (0x0x7fa3db64aa20) 0 + +Class QSysInfo + size=1 align=1 + base size=0 base align=1 +QSysInfo (0x0x7fa3db3b9300) 0 empty + +Class QMessageLogContext + size=32 align=8 + base size=32 base align=8 +QMessageLogContext (0x0x7fa3db3b9360) 0 + +Class QMessageLogger + size=32 align=8 + base size=32 base align=8 +QMessageLogger (0x0x7fa3db3b93c0) 0 + +Class QFlag + size=4 align=4 + base size=4 base align=4 +QFlag (0x0x7fa3db3b9420) 0 + +Class QIncompatibleFlag + size=4 align=4 + base size=4 base align=4 +QIncompatibleFlag (0x0x7fa3db3b9540) 0 + +Class QAtomicInt + size=4 align=4 + base size=4 base align=4 +QAtomicInt (0x0x7fa3db05b410) 0 + QAtomicInteger (0x0x7fa3db05b478) 0 + QBasicAtomicInteger (0x0x7fa3db200060) 0 + +Class QInternal + size=1 align=1 + base size=0 base align=1 +QInternal (0x0x7fa3dafd5180) 0 empty + +Class QGenericArgument + size=16 align=8 + base size=16 base align=8 +QGenericArgument (0x0x7fa3daca10c0) 0 + +Class QGenericReturnArgument + size=16 align=8 + base size=16 base align=8 +QGenericReturnArgument (0x0x7fa3daf795b0) 0 + QGenericArgument (0x0x7fa3daca1120) 0 + +Class QMetaObject + size=48 align=8 + base size=48 base align=8 +QMetaObject (0x0x7fa3daca12a0) 0 + +Class QMetaObject::Connection + size=8 align=8 + base size=8 base align=8 +QMetaObject::Connection (0x0x7fa3daca13c0) 0 + +Class QLatin1Char + size=1 align=1 + base size=1 base align=1 +QLatin1Char (0x0x7fa3daca1600) 0 + +Class QChar + size=2 align=2 + base size=2 base align=2 +QChar (0x0x7fa3daca1660) 0 + +Class QtPrivate::RefCount + size=4 align=4 + base size=4 base align=4 +QtPrivate::RefCount (0x0x7fa3daca1780) 0 + +Class QArrayData + size=24 align=8 + base size=24 base align=8 +QArrayData (0x0x7fa3daca17e0) 0 + +Class QtPrivate::QContainerImplHelper + size=1 align=1 + base size=0 base align=1 +QtPrivate::QContainerImplHelper (0x0x7fa3daca1ae0) 0 empty + +Class lconv + size=96 align=8 + base size=96 base align=8 +lconv (0x0x7fa3daca1e40) 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 (0x0x7fa3daca1ea0) 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 (0x0x7fa3daad5960) 0 + +Class __sched_param + size=4 align=4 + base size=4 base align=4 +__sched_param (0x0x7fa3daad59c0) 0 + +Class timex + size=208 align=8 + base size=208 base align=8 +timex (0x0x7fa3daad5a80) 0 + +Class tm + size=56 align=8 + base size=56 base align=8 +tm (0x0x7fa3daad5ae0) 0 + +Class itimerspec + size=32 align=8 + base size=32 base align=8 +itimerspec (0x0x7fa3daad5b40) 0 + +Class _pthread_cleanup_buffer + size=32 align=8 + base size=32 base align=8 +_pthread_cleanup_buffer (0x0x7fa3daad5ba0) 0 + +Class __pthread_cleanup_frame + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_frame (0x0x7fa3daad5cc0) 0 + +Class __pthread_cleanup_class + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_class (0x0x7fa3daad5d20) 0 + +Class QByteArrayDataPtr + size=8 align=8 + base size=8 base align=8 +QByteArrayDataPtr (0x0x7fa3dabde4e0) 0 + +Class QByteArray + size=8 align=8 + base size=8 base align=8 +QByteArray (0x0x7fa3dabde540) 0 + +Class QByteRef + size=16 align=8 + base size=12 base align=8 +QByteRef (0x0x7fa3dabde6c0) 0 + +Class QLatin1String + size=16 align=8 + base size=16 base align=8 +QLatin1String (0x0x7fa3dabde7e0) 0 + +Class QStringDataPtr + size=8 align=8 + base size=8 base align=8 +QStringDataPtr (0x0x7fa3dabde960) 0 + +Class QString::Null + size=1 align=1 + base size=0 base align=1 +QString::Null (0x0x7fa3dabdea20) 0 empty + +Class QString + size=8 align=8 + base size=8 base align=8 +QString (0x0x7fa3dabde9c0) 0 + +Class QCharRef + size=16 align=8 + base size=12 base align=8 +QCharRef (0x0x7fa3dabdeba0) 0 + +Class QStringRef + size=16 align=8 + base size=16 base align=8 +QStringRef (0x0x7fa3dabdee40) 0 + +Class std::locale + size=8 align=8 + base size=8 base align=8 +std::locale (0x0x7fa3da508060) 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 (0x0x7fa3da5080c0) 0 + vptr=((& std::locale::facet::_ZTVNSt6locale5facetE) + 16u) + +Class std::locale::id + size=8 align=8 + base size=8 base align=8 +std::locale::id (0x0x7fa3da508120) 0 + +Class std::locale::_Impl + size=40 align=8 + base size=40 base align=8 +std::locale::_Impl (0x0x7fa3da508180) 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 (0x0x7fa3da905f08) 0 + vptr=((& std::ios_base::failure::_ZTVNSt8ios_base7failureE) + 16u) + std::exception (0x0x7fa3da5085a0) 0 nearly-empty + primary-for std::ios_base::failure (0x0x7fa3da905f08) + +Class std::ios_base::_Callback_list + size=24 align=8 + base size=24 base align=8 +std::ios_base::_Callback_list (0x0x7fa3da508600) 0 + +Class std::ios_base::_Words + size=16 align=8 + base size=16 base align=8 +std::ios_base::_Words (0x0x7fa3da508660) 0 + +Class std::ios_base::Init + size=1 align=1 + base size=0 base align=1 +std::ios_base::Init (0x0x7fa3da5086c0) 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 (0x0x7fa3da508540) 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 (0x0x7fa3da508840) 0 empty + +Class std::__num_base + size=1 align=1 + base size=0 base align=1 +std::__num_base (0x0x7fa3da508f00) 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 (0x0x7fa3da1d0af8 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 (0x0x7fa3da1d0bc8 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 (0x0x7fa3da1d0ea0 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 (0x0x7fa3da1d0f70 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 (0x0x7fa3da1d2300) 0 + +Class QListData::Data + size=24 align=8 + base size=24 base align=8 +QListData::Data (0x0x7fa3da1d2660) 0 + +Class QListData + size=8 align=8 + base size=8 base align=8 +QListData (0x0x7fa3da1d2600) 0 + +Class QScopedPointerPodDeleter + size=1 align=1 + base size=0 base align=1 +QScopedPointerPodDeleter (0x0x7fa3da1d2b40) 0 empty + +Class std::_Bit_reference + size=16 align=8 + base size=16 base align=8 +std::_Bit_reference (0x0x7fa3d9c578a0) 0 + +Class std::_Bit_iterator_base + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator_base (0x0x7fa3d9f0b3a8) 0 + std::iterator (0x0x7fa3d9c57960) 0 empty + +Class std::_Bit_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator (0x0x7fa3d9f0b410) 0 + std::_Bit_iterator_base (0x0x7fa3d9f0b478) 0 + std::iterator (0x0x7fa3d9c579c0) 0 empty + +Class std::_Bit_const_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_const_iterator (0x0x7fa3d9f0b4e0) 0 + std::_Bit_iterator_base (0x0x7fa3d9f0b548) 0 + std::iterator (0x0x7fa3d9c57a20) 0 empty + +Class std::_Rb_tree_node_base + size=32 align=8 + base size=32 base align=8 +std::_Rb_tree_node_base (0x0x7fa3d9c57de0) 0 + +Class QtPrivate::AbstractDebugStreamFunction + size=16 align=8 + base size=16 base align=8 +QtPrivate::AbstractDebugStreamFunction (0x0x7fa3d9e3e240) 0 + +Class QtPrivate::AbstractComparatorFunction + size=24 align=8 + base size=24 base align=8 +QtPrivate::AbstractComparatorFunction (0x0x7fa3d9e3e300) 0 + +Class QtPrivate::AbstractConverterFunction + size=8 align=8 + base size=8 base align=8 +QtPrivate::AbstractConverterFunction (0x0x7fa3d9e3e3c0) 0 + +Class QMetaType + size=80 align=8 + base size=80 base align=8 +QMetaType (0x0x7fa3d9e3e7e0) 0 + +Class QtMetaTypePrivate::VariantData + size=24 align=8 + base size=20 base align=8 +QtMetaTypePrivate::VariantData (0x0x7fa3d9e3eb40) 0 + +Class QtMetaTypePrivate::VectorBoolElements + size=1 align=1 + base size=0 base align=1 +QtMetaTypePrivate::VectorBoolElements (0x0x7fa3d9e3ec60) 0 empty + +Class QtMetaTypePrivate::QSequentialIterableImpl + size=104 align=8 + base size=104 base align=8 +QtMetaTypePrivate::QSequentialIterableImpl (0x0x7fa3d9c37480) 0 + +Class QtMetaTypePrivate::QAssociativeIterableImpl + size=112 align=8 + base size=112 base align=8 +QtMetaTypePrivate::QAssociativeIterableImpl (0x0x7fa3d9c37660) 0 + +Class QtMetaTypePrivate::QPairVariantInterfaceImpl + size=40 align=8 + base size=40 base align=8 +QtMetaTypePrivate::QPairVariantInterfaceImpl (0x0x7fa3d9c37720) 0 + +Class QtPrivate::QSlotObjectBase + size=16 align=8 + base size=16 base align=8 +QtPrivate::QSlotObjectBase (0x0x7fa3d99fca80) 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 (0x0x7fa3d99fcc00) 0 + vptr=((& QObjectData::_ZTV11QObjectData) + 16u) + +Class QObject::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObject::QPrivateSignal (0x0x7fa3d99fcde0) 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 (0x0x7fa3d99fcd80) 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 (0x0x7fa3d96d9120) 0 nearly-empty + vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16u) + +Class QSignalBlocker + size=16 align=8 + base size=10 base align=8 +QSignalBlocker (0x0x7fa3d96d9180) 0 + +Class QAbstractAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractAnimation::QPrivateSignal (0x0x7fa3d96d9240) 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 (0x0x7fa3d9657340) 0 + vptr=((& QAbstractAnimation::_ZTV18QAbstractAnimation) + 16u) + QObject (0x0x7fa3d96d91e0) 0 + primary-for QAbstractAnimation (0x0x7fa3d9657340) + +Class QAnimationDriver::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationDriver::QPrivateSignal (0x0x7fa3d96d9300) 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 (0x0x7fa3d96573a8) 0 + vptr=((& QAnimationDriver::_ZTV16QAnimationDriver) + 16u) + QObject (0x0x7fa3d96d92a0) 0 + primary-for QAnimationDriver (0x0x7fa3d96573a8) + +Class QAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationGroup::QPrivateSignal (0x0x7fa3d96d93c0) 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 (0x0x7fa3d9657410) 0 + vptr=((& QAnimationGroup::_ZTV15QAnimationGroup) + 16u) + QAbstractAnimation (0x0x7fa3d9657478) 0 + primary-for QAnimationGroup (0x0x7fa3d9657410) + QObject (0x0x7fa3d96d9360) 0 + primary-for QAbstractAnimation (0x0x7fa3d9657478) + +Class QParallelAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QParallelAnimationGroup::QPrivateSignal (0x0x7fa3d96d9480) 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 (0x0x7fa3d96574e0) 0 + vptr=((& QParallelAnimationGroup::_ZTV23QParallelAnimationGroup) + 16u) + QAnimationGroup (0x0x7fa3d9657548) 0 + primary-for QParallelAnimationGroup (0x0x7fa3d96574e0) + QAbstractAnimation (0x0x7fa3d96575b0) 0 + primary-for QAnimationGroup (0x0x7fa3d9657548) + QObject (0x0x7fa3d96d9420) 0 + primary-for QAbstractAnimation (0x0x7fa3d96575b0) + +Class QPauseAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPauseAnimation::QPrivateSignal (0x0x7fa3d96d9540) 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 (0x0x7fa3d9657618) 0 + vptr=((& QPauseAnimation::_ZTV15QPauseAnimation) + 16u) + QAbstractAnimation (0x0x7fa3d9657680) 0 + primary-for QPauseAnimation (0x0x7fa3d9657618) + QObject (0x0x7fa3d96d94e0) 0 + primary-for QAbstractAnimation (0x0x7fa3d9657680) + +Class QEasingCurve + size=8 align=8 + base size=8 base align=8 +QEasingCurve (0x0x7fa3d96d9720) 0 + +Class QMapNodeBase + size=24 align=8 + base size=24 base align=8 +QMapNodeBase (0x0x7fa3d96d9900) 0 + +Class QMapDataBase + size=40 align=8 + base size=40 base align=8 +QMapDataBase (0x0x7fa3d96d99c0) 0 + +Class QHashData::Node + size=16 align=8 + base size=16 base align=8 +QHashData::Node (0x0x7fa3d96d9d20) 0 + +Class QHashData + size=48 align=8 + base size=48 base align=8 +QHashData (0x0x7fa3d96d9cc0) 0 + +Class QHashDummyValue + size=1 align=1 + base size=0 base align=1 +QHashDummyValue (0x0x7fa3d96d9d80) 0 empty + +Class QIODevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIODevice::QPrivateSignal (0x0x7fa3d9562300) 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 (0x0x7fa3d9657ea0) 0 + vptr=((& QIODevice::_ZTV9QIODevice) + 16u) + QObject (0x0x7fa3d95622a0) 0 + primary-for QIODevice (0x0x7fa3d9657ea0) + +Class QDataStream + size=32 align=8 + base size=32 base align=8 +QDataStream (0x0x7fa3d9562420) 0 + +Class QRegExp + size=8 align=8 + base size=8 base align=8 +QRegExp (0x0x7fa3d95624e0) 0 + +Class QStringMatcher::Data + size=272 align=8 + base size=272 base align=8 +QStringMatcher::Data (0x0x7fa3d9562660) 0 + +Class QStringMatcher + size=1048 align=8 + base size=1048 base align=8 +QStringMatcher (0x0x7fa3d9562600) 0 + +Class QStringList + size=8 align=8 + base size=8 base align=8 +QStringList (0x0x7fa3d92bf068) 0 + QList (0x0x7fa3d92bf0d0) 0 + QListSpecialMethods (0x0x7fa3d9562840) 0 empty + +Class QVariant::PrivateShared + size=16 align=8 + base size=12 base align=8 +QVariant::PrivateShared (0x0x7fa3d9562b40) 0 + +Class QVariant::Private::Data + size=8 align=8 + base size=8 base align=8 +QVariant::Private::Data (0x0x7fa3d9562c00) 0 + +Class QVariant::Private + size=16 align=8 + base size=12 base align=8 +QVariant::Private (0x0x7fa3d9562ba0) 0 + +Class QVariant::Handler + size=72 align=8 + base size=72 base align=8 +QVariant::Handler (0x0x7fa3d9562c60) 0 + +Class QVariant + size=16 align=8 + base size=16 base align=8 +QVariant (0x0x7fa3d9562ae0) 0 + +Class QVariantComparisonHelper + size=8 align=8 + base size=8 base align=8 +QVariantComparisonHelper (0x0x7fa3d9562f60) 0 + +Class QSequentialIterable::const_iterator + size=112 align=8 + base size=112 base align=8 +QSequentialIterable::const_iterator (0x0x7fa3d93e8060) 0 + +Class QSequentialIterable + size=104 align=8 + base size=104 base align=8 +QSequentialIterable (0x0x7fa3d93e8000) 0 + +Class QAssociativeIterable::const_iterator + size=120 align=8 + base size=120 base align=8 +QAssociativeIterable::const_iterator (0x0x7fa3d93e8120) 0 + +Class QAssociativeIterable + size=112 align=8 + base size=112 base align=8 +QAssociativeIterable (0x0x7fa3d93e80c0) 0 + +Class QVariantAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QVariantAnimation::QPrivateSignal (0x0x7fa3d93e8cc0) 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 (0x0x7fa3d92bfb60) 0 + vptr=((& QVariantAnimation::_ZTV17QVariantAnimation) + 16u) + QAbstractAnimation (0x0x7fa3d92bfbc8) 0 + primary-for QVariantAnimation (0x0x7fa3d92bfb60) + QObject (0x0x7fa3d93e8c60) 0 + primary-for QAbstractAnimation (0x0x7fa3d92bfbc8) + +Class QPropertyAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPropertyAnimation::QPrivateSignal (0x0x7fa3d93e8d80) 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 (0x0x7fa3d92bfc98) 0 + vptr=((& QPropertyAnimation::_ZTV18QPropertyAnimation) + 16u) + QVariantAnimation (0x0x7fa3d92bfd00) 0 + primary-for QPropertyAnimation (0x0x7fa3d92bfc98) + QAbstractAnimation (0x0x7fa3d92bfd68) 0 + primary-for QVariantAnimation (0x0x7fa3d92bfd00) + QObject (0x0x7fa3d93e8d20) 0 + primary-for QAbstractAnimation (0x0x7fa3d92bfd68) + +Class QSequentialAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSequentialAnimationGroup::QPrivateSignal (0x0x7fa3d93e8e40) 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 (0x0x7fa3d92bfdd0) 0 + vptr=((& QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup) + 16u) + QAnimationGroup (0x0x7fa3d92bfe38) 0 + primary-for QSequentialAnimationGroup (0x0x7fa3d92bfdd0) + QAbstractAnimation (0x0x7fa3d92bfea0) 0 + primary-for QAnimationGroup (0x0x7fa3d92bfe38) + QObject (0x0x7fa3d93e8de0) 0 + primary-for QAbstractAnimation (0x0x7fa3d92bfea0) + +Class QTextCodec::ConverterState + size=32 align=8 + base size=32 base align=8 +QTextCodec::ConverterState (0x0x7fa3d93e8f00) 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 (0x0x7fa3d93e8ea0) 0 nearly-empty + vptr=((& QTextCodec::_ZTV10QTextCodec) + 16u) + +Class QTextEncoder + size=40 align=8 + base size=40 base align=8 +QTextEncoder (0x0x7fa3d90b3060) 0 + +Class QTextDecoder + size=40 align=8 + base size=40 base align=8 +QTextDecoder (0x0x7fa3d90b30c0) 0 + +Class QSharedData + size=4 align=4 + base size=4 base align=4 +QSharedData (0x0x7fa3d90b3120) 0 + +Class std::__numeric_limits_base + size=1 align=1 + base size=0 base align=1 +std::__numeric_limits_base (0x0x7fa3d90b3300) 0 empty + +Class QDate + size=8 align=8 + base size=8 base align=8 +QDate (0x0x7fa3d90b3a80) 0 + +Class QTime + size=4 align=4 + base size=4 base align=4 +QTime (0x0x7fa3d90b3ba0) 0 + +Class QDateTime + size=8 align=8 + base size=8 base align=8 +QDateTime (0x0x7fa3d90b3cc0) 0 + +Class QLibraryInfo + size=1 align=1 + base size=0 base align=1 +QLibraryInfo (0x0x7fa3d90b3e40) 0 empty + +Class QBuffer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBuffer::QPrivateSignal (0x0x7fa3d90b3f00) 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 (0x0x7fa3d923a068) 0 + vptr=((& QBuffer::_ZTV7QBuffer) + 16u) + QIODevice (0x0x7fa3d923a0d0) 0 + primary-for QBuffer (0x0x7fa3d923a068) + QObject (0x0x7fa3d90b3ea0) 0 + primary-for QIODevice (0x0x7fa3d923a0d0) + +Class QLocale + size=8 align=8 + base size=8 base align=8 +QLocale (0x0x7fa3d90b3f60) 0 + +Class _IO_marker + size=24 align=8 + base size=24 base align=8 +_IO_marker (0x0x7fa3d8eba2a0) 0 + +Class _IO_FILE + size=216 align=8 + base size=216 base align=8 +_IO_FILE (0x0x7fa3d8eba300) 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 (0x0x7fa3d8eba3c0) 0 + vptr=((& QTextStream::_ZTV11QTextStream) + 16u) + +Class QTextStreamManipulator + size=40 align=8 + base size=38 base align=8 +QTextStreamManipulator (0x0x7fa3d8eba660) 0 + +Class QContiguousCacheData + size=24 align=4 + base size=24 base align=4 +QContiguousCacheData (0x0x7fa3d8eba8a0) 0 + +Class QDebug::Stream + size=80 align=8 + base size=76 base align=8 +QDebug::Stream (0x0x7fa3d8ebaf00) 0 + +Class QDebug + size=8 align=8 + base size=8 base align=8 +QDebug (0x0x7fa3d8ebaea0) 0 + +Class QDebugStateSaver + size=8 align=8 + base size=8 base align=8 +QDebugStateSaver (0x0x7fa3d8c7d060) 0 + +Class QNoDebug + size=1 align=1 + base size=0 base align=1 +QNoDebug (0x0x7fa3d8c7d120) 0 empty + +Class QFileDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileDevice::QPrivateSignal (0x0x7fa3d8c7d1e0) 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 (0x0x7fa3d923a548) 0 + vptr=((& QFileDevice::_ZTV11QFileDevice) + 16u) + QIODevice (0x0x7fa3d923a5b0) 0 + primary-for QFileDevice (0x0x7fa3d923a548) + QObject (0x0x7fa3d8c7d180) 0 + primary-for QIODevice (0x0x7fa3d923a5b0) + +Class QFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFile::QPrivateSignal (0x0x7fa3d8c7d360) 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 (0x0x7fa3d923a6e8) 0 + vptr=((& QFile::_ZTV5QFile) + 16u) + QFileDevice (0x0x7fa3d923a750) 0 + primary-for QFile (0x0x7fa3d923a6e8) + QIODevice (0x0x7fa3d923a7b8) 0 + primary-for QFileDevice (0x0x7fa3d923a750) + QObject (0x0x7fa3d8c7d300) 0 + primary-for QIODevice (0x0x7fa3d923a7b8) + +Class QFileInfo + size=8 align=8 + base size=8 base align=8 +QFileInfo (0x0x7fa3d8c7d480) 0 + +Class QDir + size=8 align=8 + base size=8 base align=8 +QDir (0x0x7fa3d8c7d720) 0 + +Class QDirIterator + size=8 align=8 + base size=8 base align=8 +QDirIterator (0x0x7fa3d8c7da20) 0 + +Class QFileSelector::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSelector::QPrivateSignal (0x0x7fa3d8c7dc00) 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 (0x0x7fa3d923ac98) 0 + vptr=((& QFileSelector::_ZTV13QFileSelector) + 16u) + QObject (0x0x7fa3d8c7dba0) 0 + primary-for QFileSelector (0x0x7fa3d923ac98) + +Class QFileSystemWatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSystemWatcher::QPrivateSignal (0x0x7fa3d8c7dcc0) 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 (0x0x7fa3d923ad00) 0 + vptr=((& QFileSystemWatcher::_ZTV18QFileSystemWatcher) + 16u) + QObject (0x0x7fa3d8c7dc60) 0 + primary-for QFileSystemWatcher (0x0x7fa3d923ad00) + +Class QLockFile + size=8 align=8 + base size=8 base align=8 +QLockFile (0x0x7fa3d8c7dd20) 0 + +Class QLoggingCategory::AtomicBools + size=3 align=1 + base size=3 base align=1 +QLoggingCategory::AtomicBools (0x0x7fa3d8c7dea0) 0 + +Class QLoggingCategory + size=24 align=8 + base size=24 base align=8 +QLoggingCategory (0x0x7fa3d8c7de40) 0 + +Class QProcessEnvironment + size=8 align=8 + base size=8 base align=8 +QProcessEnvironment (0x0x7fa3d8e08060) 0 + +Class QProcess::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QProcess::QPrivateSignal (0x0x7fa3d8e08240) 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 (0x0x7fa3d923af08) 0 + vptr=((& QProcess::_ZTV8QProcess) + 16u) + QIODevice (0x0x7fa3d923af70) 0 + primary-for QProcess (0x0x7fa3d923af08) + QObject (0x0x7fa3d8e081e0) 0 + primary-for QIODevice (0x0x7fa3d923af70) + +Class QResource + size=8 align=8 + base size=8 base align=8 +QResource (0x0x7fa3d8e082a0) 0 + +Class QSaveFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSaveFile::QPrivateSignal (0x0x7fa3d8e08420) 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 (0x0x7fa3d923a410) 0 + vptr=((& QSaveFile::_ZTV9QSaveFile) + 16u) + QFileDevice (0x0x7fa3d8a69000) 0 + primary-for QSaveFile (0x0x7fa3d923a410) + QIODevice (0x0x7fa3d8a69068) 0 + primary-for QFileDevice (0x0x7fa3d8a69000) + QObject (0x0x7fa3d8e083c0) 0 + primary-for QIODevice (0x0x7fa3d8a69068) + +Class QSettings::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSettings::QPrivateSignal (0x0x7fa3d8e084e0) 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 (0x0x7fa3d8a690d0) 0 + vptr=((& QSettings::_ZTV9QSettings) + 16u) + QObject (0x0x7fa3d8e08480) 0 + primary-for QSettings (0x0x7fa3d8a690d0) + +Class QStandardPaths + size=1 align=1 + base size=0 base align=1 +QStandardPaths (0x0x7fa3d8e08540) 0 empty + +Class QStorageInfo + size=8 align=8 + base size=8 base align=8 +QStorageInfo (0x0x7fa3d8e08660) 0 + +Class QTemporaryDir + size=8 align=8 + base size=8 base align=8 +QTemporaryDir (0x0x7fa3d8e08900) 0 + +Class QTemporaryFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTemporaryFile::QPrivateSignal (0x0x7fa3d8e08a20) 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 (0x0x7fa3d8a69270) 0 + vptr=((& QTemporaryFile::_ZTV14QTemporaryFile) + 16u) + QFile (0x0x7fa3d8a692d8) 0 + primary-for QTemporaryFile (0x0x7fa3d8a69270) + QFileDevice (0x0x7fa3d8a69340) 0 + primary-for QFile (0x0x7fa3d8a692d8) + QIODevice (0x0x7fa3d8a693a8) 0 + primary-for QFileDevice (0x0x7fa3d8a69340) + QObject (0x0x7fa3d8e089c0) 0 + primary-for QIODevice (0x0x7fa3d8a693a8) + +Class QUrl + size=8 align=8 + base size=8 base align=8 +QUrl (0x0x7fa3d8e08b40) 0 + +Class QUrlQuery + size=8 align=8 + base size=8 base align=8 +QUrlQuery (0x0x7fa3d8baf060) 0 + +Class QModelIndex + size=24 align=8 + base size=24 base align=8 +QModelIndex (0x0x7fa3d8baf1e0) 0 + +Class QPersistentModelIndex + size=8 align=8 + base size=8 base align=8 +QPersistentModelIndex (0x0x7fa3d8baf300) 0 + +Class QAbstractItemModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractItemModel::QPrivateSignal (0x0x7fa3d8baf480) 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 (0x0x7fa3d8a69888) 0 + vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16u) + QObject (0x0x7fa3d8baf420) 0 + primary-for QAbstractItemModel (0x0x7fa3d8a69888) + +Class QAbstractTableModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTableModel::QPrivateSignal (0x0x7fa3d8baf7e0) 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 (0x0x7fa3d8a69a28) 0 + vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16u) + QAbstractItemModel (0x0x7fa3d8a69a90) 0 + primary-for QAbstractTableModel (0x0x7fa3d8a69a28) + QObject (0x0x7fa3d8baf780) 0 + primary-for QAbstractItemModel (0x0x7fa3d8a69a90) + +Class QAbstractListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractListModel::QPrivateSignal (0x0x7fa3d8baf8a0) 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 (0x0x7fa3d8a69af8) 0 + vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16u) + QAbstractItemModel (0x0x7fa3d8a69b60) 0 + primary-for QAbstractListModel (0x0x7fa3d8a69af8) + QObject (0x0x7fa3d8baf840) 0 + primary-for QAbstractItemModel (0x0x7fa3d8a69b60) + +Class QAbstractProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractProxyModel::QPrivateSignal (0x0x7fa3d8baf960) 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 (0x0x7fa3d8a69bc8) 0 + vptr=((& QAbstractProxyModel::_ZTV19QAbstractProxyModel) + 16u) + QAbstractItemModel (0x0x7fa3d8a69c30) 0 + primary-for QAbstractProxyModel (0x0x7fa3d8a69bc8) + QObject (0x0x7fa3d8baf900) 0 + primary-for QAbstractItemModel (0x0x7fa3d8a69c30) + +Class QIdentityProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIdentityProxyModel::QPrivateSignal (0x0x7fa3d8bafa20) 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 (0x0x7fa3d8a69c98) 0 + vptr=((& QIdentityProxyModel::_ZTV19QIdentityProxyModel) + 16u) + QAbstractProxyModel (0x0x7fa3d8a69d00) 0 + primary-for QIdentityProxyModel (0x0x7fa3d8a69c98) + QAbstractItemModel (0x0x7fa3d8a69d68) 0 + primary-for QAbstractProxyModel (0x0x7fa3d8a69d00) + QObject (0x0x7fa3d8baf9c0) 0 + primary-for QAbstractItemModel (0x0x7fa3d8a69d68) + +Class QItemSelectionRange + size=16 align=8 + base size=16 base align=8 +QItemSelectionRange (0x0x7fa3d8bafa80) 0 + +Class QItemSelectionModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QItemSelectionModel::QPrivateSignal (0x0x7fa3d8bafc00) 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 (0x0x7fa3d8a69e38) 0 + vptr=((& QItemSelectionModel::_ZTV19QItemSelectionModel) + 16u) + QObject (0x0x7fa3d8bafba0) 0 + primary-for QItemSelectionModel (0x0x7fa3d8a69e38) + +Class QItemSelection + size=8 align=8 + base size=8 base align=8 +QItemSelection (0x0x7fa3d8977000) 0 + QList (0x0x7fa3d8977068) 0 + QListSpecialMethods (0x0x7fa3d8bafe40) 0 empty + +Class QSortFilterProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSortFilterProxyModel::QPrivateSignal (0x0x7fa3d8baff00) 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 (0x0x7fa3d89770d0) 0 + vptr=((& QSortFilterProxyModel::_ZTV21QSortFilterProxyModel) + 16u) + QAbstractProxyModel (0x0x7fa3d8977138) 0 + primary-for QSortFilterProxyModel (0x0x7fa3d89770d0) + QAbstractItemModel (0x0x7fa3d89771a0) 0 + primary-for QAbstractProxyModel (0x0x7fa3d8977138) + QObject (0x0x7fa3d8bafea0) 0 + primary-for QAbstractItemModel (0x0x7fa3d89771a0) + +Class QStringListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStringListModel::QPrivateSignal (0x0x7fa3d89a8000) 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 (0x0x7fa3d8977208) 0 + vptr=((& QStringListModel::_ZTV16QStringListModel) + 16u) + QAbstractListModel (0x0x7fa3d8977270) 0 + primary-for QStringListModel (0x0x7fa3d8977208) + QAbstractItemModel (0x0x7fa3d89772d8) 0 + primary-for QAbstractListModel (0x0x7fa3d8977270) + QObject (0x0x7fa3d8baff60) 0 + primary-for QAbstractItemModel (0x0x7fa3d89772d8) + +Class QJsonValue + size=24 align=8 + base size=20 base align=8 +QJsonValue (0x0x7fa3d89a8060) 0 + +Class QJsonValueRef + size=16 align=8 + base size=12 base align=8 +QJsonValueRef (0x0x7fa3d89a8120) 0 + +Class QJsonValuePtr + size=24 align=8 + base size=24 base align=8 +QJsonValuePtr (0x0x7fa3d89a81e0) 0 + +Class QJsonValueRefPtr + size=16 align=8 + base size=16 base align=8 +QJsonValueRefPtr (0x0x7fa3d89a8240) 0 + +Class QJsonArray::iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::iterator (0x0x7fa3d89a8300) 0 + +Class QJsonArray::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::const_iterator (0x0x7fa3d89a8360) 0 + +Class QJsonArray + size=16 align=8 + base size=16 base align=8 +QJsonArray (0x0x7fa3d89a82a0) 0 + +Class QJsonParseError + size=8 align=4 + base size=8 base align=4 +QJsonParseError (0x0x7fa3d89a83c0) 0 + +Class QJsonDocument + size=8 align=8 + base size=8 base align=8 +QJsonDocument (0x0x7fa3d89a8420) 0 + +Class QJsonObject::iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::iterator (0x0x7fa3d89a84e0) 0 + +Class QJsonObject::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::const_iterator (0x0x7fa3d89a8540) 0 + +Class QJsonObject + size=16 align=8 + base size=16 base align=8 +QJsonObject (0x0x7fa3d89a8480) 0 + +Class QEventLoop::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventLoop::QPrivateSignal (0x0x7fa3d89a8660) 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 (0x0x7fa3d8977340) 0 + vptr=((& QEventLoop::_ZTV10QEventLoop) + 16u) + QObject (0x0x7fa3d89a8600) 0 + primary-for QEventLoop (0x0x7fa3d8977340) + +Class QEventLoopLocker + size=8 align=8 + base size=8 base align=8 +QEventLoopLocker (0x0x7fa3d89a8780) 0 + +Class QAbstractEventDispatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractEventDispatcher::QPrivateSignal (0x0x7fa3d89a8840) 0 empty + +Class QAbstractEventDispatcher::TimerInfo + size=12 align=4 + base size=12 base align=4 +QAbstractEventDispatcher::TimerInfo (0x0x7fa3d89a88a0) 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 (0x0x7fa3d8977478) 0 + vptr=((& QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher) + 16u) + QObject (0x0x7fa3d89a87e0) 0 + primary-for QAbstractEventDispatcher (0x0x7fa3d8977478) + +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 (0x0x7fa3d89a8900) 0 + vptr=((& QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter) + 16u) + +Class QBasicTimer + size=4 align=4 + base size=4 base align=4 +QBasicTimer (0x0x7fa3d89a8960) 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 (0x0x7fa3d89a8a80) 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 (0x0x7fa3d8977548) 0 + vptr=((& QTimerEvent::_ZTV11QTimerEvent) + 16u) + QEvent (0x0x7fa3d89a8ae0) 0 + primary-for QTimerEvent (0x0x7fa3d8977548) + +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 (0x0x7fa3d89775b0) 0 + vptr=((& QChildEvent::_ZTV11QChildEvent) + 16u) + QEvent (0x0x7fa3d89a8b40) 0 + primary-for QChildEvent (0x0x7fa3d89775b0) + +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 (0x0x7fa3d8977618) 0 + vptr=((& QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent) + 16u) + QEvent (0x0x7fa3d89a8ba0) 0 + primary-for QDynamicPropertyChangeEvent (0x0x7fa3d8977618) + +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 (0x0x7fa3d8977680) 0 + vptr=((& QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent) + 16u) + QEvent (0x0x7fa3d89a8c00) 0 + primary-for QDeferredDeleteEvent (0x0x7fa3d8977680) + +Class QCoreApplication::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QCoreApplication::QPrivateSignal (0x0x7fa3d89a8cc0) 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 (0x0x7fa3d89776e8) 0 + vptr=((& QCoreApplication::_ZTV16QCoreApplication) + 16u) + QObject (0x0x7fa3d89a8c60) 0 + primary-for QCoreApplication (0x0x7fa3d89776e8) + +Class __exception + size=40 align=8 + base size=40 base align=8 +__exception (0x0x7fa3d89a8d20) 0 + +Class QMetaMethod + size=16 align=8 + base size=12 base align=8 +QMetaMethod (0x0x7fa3d89a8d80) 0 + +Class QMetaEnum + size=16 align=8 + base size=12 base align=8 +QMetaEnum (0x0x7fa3d89a8ea0) 0 + +Class QMetaProperty + size=32 align=8 + base size=32 base align=8 +QMetaProperty (0x0x7fa3d87f0000) 0 + +Class QMetaClassInfo + size=16 align=8 + base size=12 base align=8 +QMetaClassInfo (0x0x7fa3d87f0060) 0 + +Class QMimeData::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QMimeData::QPrivateSignal (0x0x7fa3d87f01e0) 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 (0x0x7fa3d8977958) 0 + vptr=((& QMimeData::_ZTV9QMimeData) + 16u) + QObject (0x0x7fa3d87f0180) 0 + primary-for QMimeData (0x0x7fa3d8977958) + +Class QObjectCleanupHandler::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObjectCleanupHandler::QPrivateSignal (0x0x7fa3d87f02a0) 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 (0x0x7fa3d89779c0) 0 + vptr=((& QObjectCleanupHandler::_ZTV21QObjectCleanupHandler) + 16u) + QObject (0x0x7fa3d87f0240) 0 + primary-for QObjectCleanupHandler (0x0x7fa3d89779c0) + +Class QtSharedPointer::NormalDeleter + size=1 align=1 + base size=0 base align=1 +QtSharedPointer::NormalDeleter (0x0x7fa3d87f03c0) 0 empty + +Class QtSharedPointer::ExternalRefCountData + size=16 align=8 + base size=16 base align=8 +QtSharedPointer::ExternalRefCountData (0x0x7fa3d87f0540) 0 + +Class QSharedMemory::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSharedMemory::QPrivateSignal (0x0x7fa3d87f0c00) 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 (0x0x7fa3d8977d68) 0 + vptr=((& QSharedMemory::_ZTV13QSharedMemory) + 16u) + QObject (0x0x7fa3d87f0ba0) 0 + primary-for QSharedMemory (0x0x7fa3d8977d68) + +Class QSignalMapper::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalMapper::QPrivateSignal (0x0x7fa3d87f0cc0) 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 (0x0x7fa3d8977dd0) 0 + vptr=((& QSignalMapper::_ZTV13QSignalMapper) + 16u) + QObject (0x0x7fa3d87f0c60) 0 + primary-for QSignalMapper (0x0x7fa3d8977dd0) + +Class QSocketNotifier::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSocketNotifier::QPrivateSignal (0x0x7fa3d87f0d80) 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 (0x0x7fa3d8977e38) 0 + vptr=((& QSocketNotifier::_ZTV15QSocketNotifier) + 16u) + QObject (0x0x7fa3d87f0d20) 0 + primary-for QSocketNotifier (0x0x7fa3d8977e38) + +Class QSystemSemaphore + size=8 align=8 + base size=8 base align=8 +QSystemSemaphore (0x0x7fa3d87f0de0) 0 + +Class QTimer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimer::QPrivateSignal (0x0x7fa3d87f0f00) 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 (0x0x7fa3d8977ea0) 0 + vptr=((& QTimer::_ZTV6QTimer) + 16u) + QObject (0x0x7fa3d87f0ea0) 0 + primary-for QTimer (0x0x7fa3d8977ea0) + +Class QTranslator::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTranslator::QPrivateSignal (0x0x7fa3d85500c0) 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 (0x0x7fa3d8977f70) 0 + vptr=((& QTranslator::_ZTV11QTranslator) + 16u) + QObject (0x0x7fa3d8550060) 0 + primary-for QTranslator (0x0x7fa3d8977f70) + +Class QMimeType + size=8 align=8 + base size=8 base align=8 +QMimeType (0x0x7fa3d8550120) 0 + +Class QMimeDatabase + size=8 align=8 + base size=8 base align=8 +QMimeDatabase (0x0x7fa3d85502a0) 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 (0x0x7fa3d8550300) 0 nearly-empty + vptr=((& QFactoryInterface::_ZTV17QFactoryInterface) + 16u) + +Class QLibrary::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLibrary::QPrivateSignal (0x0x7fa3d8550420) 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 (0x0x7fa3d8977c30) 0 + vptr=((& QLibrary::_ZTV8QLibrary) + 16u) + QObject (0x0x7fa3d85503c0) 0 + primary-for QLibrary (0x0x7fa3d8977c30) + +Class QStaticPlugin + size=16 align=8 + base size=16 base align=8 +QStaticPlugin (0x0x7fa3d8550540) 0 + +Class QPluginLoader::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPluginLoader::QPrivateSignal (0x0x7fa3d85506c0) 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 (0x0x7fa3d85c5068) 0 + vptr=((& QPluginLoader::_ZTV13QPluginLoader) + 16u) + QObject (0x0x7fa3d8550660) 0 + primary-for QPluginLoader (0x0x7fa3d85c5068) + +Class QUuid + size=16 align=4 + base size=16 base align=4 +QUuid (0x0x7fa3d8550720) 0 + +Class QAbstractState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractState::QPrivateSignal (0x0x7fa3d85508a0) 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 (0x0x7fa3d85c5138) 0 + vptr=((& QAbstractState::_ZTV14QAbstractState) + 16u) + QObject (0x0x7fa3d8550840) 0 + primary-for QAbstractState (0x0x7fa3d85c5138) + +Class QAbstractTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTransition::QPrivateSignal (0x0x7fa3d8550960) 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 (0x0x7fa3d85c51a0) 0 + vptr=((& QAbstractTransition::_ZTV19QAbstractTransition) + 16u) + QObject (0x0x7fa3d8550900) 0 + primary-for QAbstractTransition (0x0x7fa3d85c51a0) + +Class QEventTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventTransition::QPrivateSignal (0x0x7fa3d8550a20) 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 (0x0x7fa3d85c5208) 0 + vptr=((& QEventTransition::_ZTV16QEventTransition) + 16u) + QAbstractTransition (0x0x7fa3d85c5270) 0 + primary-for QEventTransition (0x0x7fa3d85c5208) + QObject (0x0x7fa3d85509c0) 0 + primary-for QAbstractTransition (0x0x7fa3d85c5270) + +Class QFinalState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFinalState::QPrivateSignal (0x0x7fa3d8550ae0) 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 (0x0x7fa3d85c52d8) 0 + vptr=((& QFinalState::_ZTV11QFinalState) + 16u) + QAbstractState (0x0x7fa3d85c5340) 0 + primary-for QFinalState (0x0x7fa3d85c52d8) + QObject (0x0x7fa3d8550a80) 0 + primary-for QAbstractState (0x0x7fa3d85c5340) + +Class QHistoryState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QHistoryState::QPrivateSignal (0x0x7fa3d8550ba0) 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 (0x0x7fa3d85c53a8) 0 + vptr=((& QHistoryState::_ZTV13QHistoryState) + 16u) + QAbstractState (0x0x7fa3d85c5410) 0 + primary-for QHistoryState (0x0x7fa3d85c53a8) + QObject (0x0x7fa3d8550b40) 0 + primary-for QAbstractState (0x0x7fa3d85c5410) + +Class QSignalTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalTransition::QPrivateSignal (0x0x7fa3d8550c60) 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 (0x0x7fa3d85c5478) 0 + vptr=((& QSignalTransition::_ZTV17QSignalTransition) + 16u) + QAbstractTransition (0x0x7fa3d85c54e0) 0 + primary-for QSignalTransition (0x0x7fa3d85c5478) + QObject (0x0x7fa3d8550c00) 0 + primary-for QAbstractTransition (0x0x7fa3d85c54e0) + +Class QState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QState::QPrivateSignal (0x0x7fa3d8550d20) 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 (0x0x7fa3d85c5548) 0 + vptr=((& QState::_ZTV6QState) + 16u) + QAbstractState (0x0x7fa3d85c55b0) 0 + primary-for QState (0x0x7fa3d85c5548) + QObject (0x0x7fa3d8550cc0) 0 + primary-for QAbstractState (0x0x7fa3d85c55b0) + +Class QStateMachine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStateMachine::QPrivateSignal (0x0x7fa3d8550e40) 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 (0x0x7fa3d85c5750) 0 + vptr=((& QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE) + 16u) + QEvent (0x0x7fa3d8550ea0) 0 + primary-for QStateMachine::SignalEvent (0x0x7fa3d85c5750) + +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 (0x0x7fa3d85c57b8) 0 + vptr=((& QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE) + 16u) + QEvent (0x0x7fa3d8550f00) 0 + primary-for QStateMachine::WrappedEvent (0x0x7fa3d85c57b8) + +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 (0x0x7fa3d85c5618) 0 + vptr=((& QStateMachine::_ZTV13QStateMachine) + 16u) + QState (0x0x7fa3d85c5680) 0 + primary-for QStateMachine (0x0x7fa3d85c5618) + QAbstractState (0x0x7fa3d85c56e8) 0 + primary-for QState (0x0x7fa3d85c5680) + QObject (0x0x7fa3d8550de0) 0 + primary-for QAbstractState (0x0x7fa3d85c56e8) + +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 (0x0x7fa3d85c5820) 0 nearly-empty + vptr=((& QException::_ZTV10QException) + 16u) + std::exception (0x0x7fa3d8550f60) 0 nearly-empty + primary-for QException (0x0x7fa3d85c5820) + +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 (0x0x7fa3d85c5888) 0 nearly-empty + vptr=((& QUnhandledException::_ZTV19QUnhandledException) + 16u) + QException (0x0x7fa3d85c58f0) 0 nearly-empty + primary-for QUnhandledException (0x0x7fa3d85c5888) + std::exception (0x0x7fa3d829a000) 0 nearly-empty + primary-for QException (0x0x7fa3d85c58f0) + +Class QtPrivate::ExceptionHolder + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionHolder (0x0x7fa3d829a060) 0 + +Class QtPrivate::ExceptionStore + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionStore (0x0x7fa3d829a120) 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 (0x0x7fa3d829a180) 0 + vptr=((& QRunnable::_ZTV9QRunnable) + 16u) + +Class QBasicMutex + size=8 align=8 + base size=8 base align=8 +QBasicMutex (0x0x7fa3d829a1e0) 0 + +Class QMutex + size=8 align=8 + base size=8 base align=8 +QMutex (0x0x7fa3d85c5a90) 0 + QBasicMutex (0x0x7fa3d829a300) 0 + +Class QMutexLocker + size=8 align=8 + base size=8 base align=8 +QMutexLocker (0x0x7fa3d829a360) 0 + +Class QtPrivate::ResultItem + size=16 align=8 + base size=16 base align=8 +QtPrivate::ResultItem (0x0x7fa3d829a3c0) 0 + +Class QtPrivate::ResultIteratorBase + size=16 align=8 + base size=12 base align=8 +QtPrivate::ResultIteratorBase (0x0x7fa3d829a420) 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 (0x0x7fa3d829a5a0) 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 (0x0x7fa3d829a660) 0 + vptr=((& QFutureInterfaceBase::_ZTV20QFutureInterfaceBase) + 16u) + +Class QFutureWatcherBase::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFutureWatcherBase::QPrivateSignal (0x0x7fa3d829a9c0) 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 (0x0x7fa3d83293a8) 0 + vptr=((& QFutureWatcherBase::_ZTV18QFutureWatcherBase) + 16u) + QObject (0x0x7fa3d829a960) 0 + primary-for QFutureWatcherBase (0x0x7fa3d83293a8) + +Class QReadWriteLock + size=8 align=8 + base size=8 base align=8 +QReadWriteLock (0x0x7fa3d829aae0) 0 + +Class QReadLocker + size=8 align=8 + base size=8 base align=8 +QReadLocker (0x0x7fa3d829ab40) 0 + +Class QWriteLocker + size=8 align=8 + base size=8 base align=8 +QWriteLocker (0x0x7fa3d829aba0) 0 + +Class QSemaphore + size=8 align=8 + base size=8 base align=8 +QSemaphore (0x0x7fa3d829ac00) 0 + +Class QThread::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThread::QPrivateSignal (0x0x7fa3d829acc0) 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 (0x0x7fa3d8329750) 0 + vptr=((& QThread::_ZTV7QThread) + 16u) + QObject (0x0x7fa3d829ac60) 0 + primary-for QThread (0x0x7fa3d8329750) + +Class QThreadPool::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThreadPool::QPrivateSignal (0x0x7fa3d829ad80) 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 (0x0x7fa3d83297b8) 0 + vptr=((& QThreadPool::_ZTV11QThreadPool) + 16u) + QObject (0x0x7fa3d829ad20) 0 + primary-for QThreadPool (0x0x7fa3d83297b8) + +Class QThreadStorageData + size=4 align=4 + base size=4 base align=4 +QThreadStorageData (0x0x7fa3d829ade0) 0 + +Class QWaitCondition + size=8 align=8 + base size=8 base align=8 +QWaitCondition (0x0x7fa3d829aea0) 0 + +Class QBitArray + size=8 align=8 + base size=8 base align=8 +QBitArray (0x0x7fa3d8073480) 0 + +Class QBitRef + size=16 align=8 + base size=12 base align=8 +QBitRef (0x0x7fa3d80734e0) 0 + +Class QByteArrayMatcher::Data + size=272 align=8 + base size=272 base align=8 +QByteArrayMatcher::Data (0x0x7fa3d8073660) 0 + +Class QByteArrayMatcher + size=1040 align=8 + base size=1040 base align=8 +QByteArrayMatcher (0x0x7fa3d8073600) 0 + +Class QCollatorSortKey + size=8 align=8 + base size=8 base align=8 +QCollatorSortKey (0x0x7fa3d80737e0) 0 + +Class QCollator + size=8 align=8 + base size=8 base align=8 +QCollator (0x0x7fa3d80738a0) 0 + +Class QCommandLineOption + size=8 align=8 + base size=8 base align=8 +QCommandLineOption (0x0x7fa3d8073a80) 0 + +Class QCommandLineParser + size=8 align=8 + base size=8 base align=8 +QCommandLineParser (0x0x7fa3d8073c00) 0 + +Class QCryptographicHash + size=8 align=8 + base size=8 base align=8 +QCryptographicHash (0x0x7fa3d8073c60) 0 + +Class QElapsedTimer + size=16 align=8 + base size=16 base align=8 +QElapsedTimer (0x0x7fa3d8073cc0) 0 + +Class QPoint + size=8 align=4 + base size=8 base align=4 +QPoint (0x0x7fa3d8073d20) 0 + +Class QPointF + size=16 align=8 + base size=16 base align=8 +QPointF (0x0x7fa3d8073e40) 0 + +Class QLine + size=16 align=4 + base size=16 base align=4 +QLine (0x0x7fa3d8073f60) 0 + +Class QLineF + size=32 align=8 + base size=32 base align=8 +QLineF (0x0x7fa3d81ea0c0) 0 + +Class QLinkedListData + size=32 align=8 + base size=32 base align=8 +QLinkedListData (0x0x7fa3d81ea1e0) 0 + +Class QMargins + size=16 align=4 + base size=16 base align=4 +QMargins (0x0x7fa3d81ea540) 0 + +Class QMarginsF + size=32 align=8 + base size=32 base align=8 +QMarginsF (0x0x7fa3d81ea660) 0 + +Class QMessageAuthenticationCode + size=8 align=8 + base size=8 base align=8 +QMessageAuthenticationCode (0x0x7fa3d81ea780) 0 + +Class QSize + size=8 align=4 + base size=8 base align=4 +QSize (0x0x7fa3d81ea840) 0 + +Class QSizeF + size=16 align=8 + base size=16 base align=8 +QSizeF (0x0x7fa3d81ea960) 0 + +Class QRect + size=16 align=4 + base size=16 base align=4 +QRect (0x0x7fa3d81eaa80) 0 + +Class QRectF + size=32 align=8 + base size=32 base align=8 +QRectF (0x0x7fa3d81eaba0) 0 + +Class QRegularExpression + size=8 align=8 + base size=8 base align=8 +QRegularExpression (0x0x7fa3d81eacc0) 0 + +Class QRegularExpressionMatch + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatch (0x0x7fa3d7cfc000) 0 + +Class QRegularExpressionMatchIterator + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatchIterator (0x0x7fa3d7cfc180) 0 + +Class QAbstractConcatenable + size=1 align=1 + base size=0 base align=1 +QAbstractConcatenable (0x0x7fa3d7cfc3c0) 0 empty + +Class QTextBoundaryFinder + size=48 align=8 + base size=48 base align=8 +QTextBoundaryFinder (0x0x7fa3d7cfcde0) 0 + +Class QTimeLine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimeLine::QPrivateSignal (0x0x7fa3d7cfcf60) 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 (0x0x7fa3d7dbe0d0) 0 + vptr=((& QTimeLine::_ZTV9QTimeLine) + 16u) + QObject (0x0x7fa3d7cfcf00) 0 + primary-for QTimeLine (0x0x7fa3d7dbe0d0) + +Class QTimeZone::OffsetData + size=32 align=8 + base size=28 base align=8 +QTimeZone::OffsetData (0x0x7fa3d7ded060) 0 + +Class QTimeZone + size=8 align=8 + base size=8 base align=8 +QTimeZone (0x0x7fa3d7ded000) 0 + +Class QXmlStreamStringRef + size=16 align=8 + base size=16 base align=8 +QXmlStreamStringRef (0x0x7fa3d7ded2a0) 0 + +Class QXmlStreamAttribute + size=80 align=8 + base size=73 base align=8 +QXmlStreamAttribute (0x0x7fa3d7ded300) 0 + +Class QXmlStreamAttributes + size=8 align=8 + base size=8 base align=8 +QXmlStreamAttributes (0x0x7fa3d7dbe340) 0 + QVector (0x0x7fa3d7ded4e0) 0 + +Class QXmlStreamNamespaceDeclaration + size=40 align=8 + base size=40 base align=8 +QXmlStreamNamespaceDeclaration (0x0x7fa3d7ded540) 0 + +Class QXmlStreamNotationDeclaration + size=56 align=8 + base size=56 base align=8 +QXmlStreamNotationDeclaration (0x0x7fa3d7ded660) 0 + +Class QXmlStreamEntityDeclaration + size=88 align=8 + base size=88 base align=8 +QXmlStreamEntityDeclaration (0x0x7fa3d7ded780) 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 (0x0x7fa3d7ded8a0) 0 nearly-empty + vptr=((& QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver) + 16u) + +Class QXmlStreamReader + size=8 align=8 + base size=8 base align=8 +QXmlStreamReader (0x0x7fa3d7ded900) 0 + +Class QXmlStreamWriter + size=8 align=8 + base size=8 base align=8 +QXmlStreamWriter (0x0x7fa3d7deda20) 0 + +Class QBluetoothAddress + size=8 align=8 + base size=8 base align=8 +QBluetoothAddress (0x0x7fa3d7dedc00) 0 + +Class QBluetoothDeviceInfo + size=8 align=8 + base size=8 base align=8 +QBluetoothDeviceInfo (0x0x7fa3d7dedd80) 0 + +Class QBluetoothDeviceDiscoveryAgent::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothDeviceDiscoveryAgent::QPrivateSignal (0x0x7fa3d7dede40) 0 empty + +Vtable for QBluetoothDeviceDiscoveryAgent +QBluetoothDeviceDiscoveryAgent::_ZTV30QBluetoothDeviceDiscoveryAgent: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI30QBluetoothDeviceDiscoveryAgent) +16 (int (*)(...))QBluetoothDeviceDiscoveryAgent::metaObject +24 (int (*)(...))QBluetoothDeviceDiscoveryAgent::qt_metacast +32 (int (*)(...))QBluetoothDeviceDiscoveryAgent::qt_metacall +40 (int (*)(...))QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent +48 (int (*)(...))QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent +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 QBluetoothDeviceDiscoveryAgent + size=24 align=8 + base size=24 base align=8 +QBluetoothDeviceDiscoveryAgent (0x0x7fa3d7dbe5b0) 0 + vptr=((& QBluetoothDeviceDiscoveryAgent::_ZTV30QBluetoothDeviceDiscoveryAgent) + 16u) + QObject (0x0x7fa3d7dedde0) 0 + primary-for QBluetoothDeviceDiscoveryAgent (0x0x7fa3d7dbe5b0) + +Class QBluetoothHostInfo + size=8 align=8 + base size=8 base align=8 +QBluetoothHostInfo (0x0x7fa3d7dedea0) 0 + +Class QBluetoothLocalDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothLocalDevice::QPrivateSignal (0x0x7fa3d7dedf60) 0 empty + +Vtable for QBluetoothLocalDevice +QBluetoothLocalDevice::_ZTV21QBluetoothLocalDevice: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QBluetoothLocalDevice) +16 (int (*)(...))QBluetoothLocalDevice::metaObject +24 (int (*)(...))QBluetoothLocalDevice::qt_metacast +32 (int (*)(...))QBluetoothLocalDevice::qt_metacall +40 (int (*)(...))QBluetoothLocalDevice::~QBluetoothLocalDevice +48 (int (*)(...))QBluetoothLocalDevice::~QBluetoothLocalDevice +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 QBluetoothLocalDevice + size=24 align=8 + base size=24 base align=8 +QBluetoothLocalDevice (0x0x7fa3d7dbe618) 0 + vptr=((& QBluetoothLocalDevice::_ZTV21QBluetoothLocalDevice) + 16u) + QObject (0x0x7fa3d7dedf00) 0 + primary-for QBluetoothLocalDevice (0x0x7fa3d7dbe618) + +Class quint128 + size=16 align=1 + base size=16 base align=1 +quint128 (0x0x7fa3d7adc360) 0 + +Class QBluetoothUuid + size=16 align=4 + base size=16 base align=4 +QBluetoothUuid (0x0x7fa3d7dbe680) 0 + QUuid (0x0x7fa3d7adc3c0) 0 + +Class QBluetoothServiceInfo::Sequence + size=8 align=8 + base size=8 base align=8 +QBluetoothServiceInfo::Sequence (0x0x7fa3d7dbe6e8) 0 + QList (0x0x7fa3d7dbe750) 0 + QListSpecialMethods (0x0x7fa3d7adc5a0) 0 empty + +Class QBluetoothServiceInfo::Alternative + size=8 align=8 + base size=8 base align=8 +QBluetoothServiceInfo::Alternative (0x0x7fa3d7dbe7b8) 0 + QList (0x0x7fa3d7dbe820) 0 + QListSpecialMethods (0x0x7fa3d7adc600) 0 empty + +Class QBluetoothServiceInfo + size=16 align=8 + base size=16 base align=8 +QBluetoothServiceInfo (0x0x7fa3d7adc540) 0 + +Class QAbstractSocket::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractSocket::QPrivateSignal (0x0x7fa3d7adcae0) 0 empty + +Vtable for QAbstractSocket +QAbstractSocket::_ZTV15QAbstractSocket: 41u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QAbstractSocket) +16 (int (*)(...))QAbstractSocket::metaObject +24 (int (*)(...))QAbstractSocket::qt_metacast +32 (int (*)(...))QAbstractSocket::qt_metacall +40 (int (*)(...))QAbstractSocket::~QAbstractSocket +48 (int (*)(...))QAbstractSocket::~QAbstractSocket +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 (*)(...))QAbstractSocket::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QAbstractSocket::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QAbstractSocket::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QAbstractSocket::bytesAvailable +184 (int (*)(...))QAbstractSocket::bytesToWrite +192 (int (*)(...))QAbstractSocket::canReadLine +200 (int (*)(...))QAbstractSocket::waitForReadyRead +208 (int (*)(...))QAbstractSocket::waitForBytesWritten +216 (int (*)(...))QAbstractSocket::readData +224 (int (*)(...))QAbstractSocket::readLineData +232 (int (*)(...))QAbstractSocket::writeData +240 (int (*)(...))QAbstractSocket::resume +248 (int (*)(...))QAbstractSocket::connectToHost +256 (int (*)(...))QAbstractSocket::connectToHost +264 (int (*)(...))QAbstractSocket::disconnectFromHost +272 (int (*)(...))QAbstractSocket::setReadBufferSize +280 (int (*)(...))QAbstractSocket::socketDescriptor +288 (int (*)(...))QAbstractSocket::setSocketDescriptor +296 (int (*)(...))QAbstractSocket::setSocketOption +304 (int (*)(...))QAbstractSocket::socketOption +312 (int (*)(...))QAbstractSocket::waitForConnected +320 (int (*)(...))QAbstractSocket::waitForDisconnected + +Class QAbstractSocket + size=16 align=8 + base size=16 base align=8 +QAbstractSocket (0x0x7fa3d7dbea90) 0 + vptr=((& QAbstractSocket::_ZTV15QAbstractSocket) + 16u) + QIODevice (0x0x7fa3d7dbeaf8) 0 + primary-for QAbstractSocket (0x0x7fa3d7dbea90) + QObject (0x0x7fa3d7adca80) 0 + primary-for QIODevice (0x0x7fa3d7dbeaf8) + +Class QBluetoothSocket::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothSocket::QPrivateSignal (0x0x7fa3d7adcf60) 0 empty + +Vtable for QBluetoothSocket +QBluetoothSocket::_ZTV16QBluetoothSocket: 30u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QBluetoothSocket) +16 (int (*)(...))QBluetoothSocket::metaObject +24 (int (*)(...))QBluetoothSocket::qt_metacast +32 (int (*)(...))QBluetoothSocket::qt_metacall +40 (int (*)(...))QBluetoothSocket::~QBluetoothSocket +48 (int (*)(...))QBluetoothSocket::~QBluetoothSocket +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 (*)(...))QBluetoothSocket::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QBluetoothSocket::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QIODevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QBluetoothSocket::bytesAvailable +184 (int (*)(...))QBluetoothSocket::bytesToWrite +192 (int (*)(...))QBluetoothSocket::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QBluetoothSocket::readData +224 (int (*)(...))QIODevice::readLineData +232 (int (*)(...))QBluetoothSocket::writeData + +Class QBluetoothSocket + size=24 align=8 + base size=24 base align=8 +QBluetoothSocket (0x0x7fa3d7dbed00) 0 + vptr=((& QBluetoothSocket::_ZTV16QBluetoothSocket) + 16u) + QIODevice (0x0x7fa3d7dbed68) 0 + primary-for QBluetoothSocket (0x0x7fa3d7dbed00) + QObject (0x0x7fa3d7adcf00) 0 + primary-for QIODevice (0x0x7fa3d7dbed68) + +Class QBluetoothServer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothServer::QPrivateSignal (0x0x7fa3d7805060) 0 empty + +Vtable for QBluetoothServer +QBluetoothServer::_ZTV16QBluetoothServer: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QBluetoothServer) +16 (int (*)(...))QBluetoothServer::metaObject +24 (int (*)(...))QBluetoothServer::qt_metacast +32 (int (*)(...))QBluetoothServer::qt_metacall +40 (int (*)(...))QBluetoothServer::~QBluetoothServer +48 (int (*)(...))QBluetoothServer::~QBluetoothServer +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 QBluetoothServer + size=24 align=8 + base size=24 base align=8 +QBluetoothServer (0x0x7fa3d7dbedd0) 0 + vptr=((& QBluetoothServer::_ZTV16QBluetoothServer) + 16u) + QObject (0x0x7fa3d7805000) 0 + primary-for QBluetoothServer (0x0x7fa3d7dbedd0) + +Class QBluetoothServiceDiscoveryAgent::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothServiceDiscoveryAgent::QPrivateSignal (0x0x7fa3d7805120) 0 empty + +Vtable for QBluetoothServiceDiscoveryAgent +QBluetoothServiceDiscoveryAgent::_ZTV31QBluetoothServiceDiscoveryAgent: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI31QBluetoothServiceDiscoveryAgent) +16 (int (*)(...))QBluetoothServiceDiscoveryAgent::metaObject +24 (int (*)(...))QBluetoothServiceDiscoveryAgent::qt_metacast +32 (int (*)(...))QBluetoothServiceDiscoveryAgent::qt_metacall +40 (int (*)(...))QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent +48 (int (*)(...))QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent +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 QBluetoothServiceDiscoveryAgent + size=24 align=8 + base size=24 base align=8 +QBluetoothServiceDiscoveryAgent (0x0x7fa3d7dbee38) 0 + vptr=((& QBluetoothServiceDiscoveryAgent::_ZTV31QBluetoothServiceDiscoveryAgent) + 16u) + QObject (0x0x7fa3d78050c0) 0 + primary-for QBluetoothServiceDiscoveryAgent (0x0x7fa3d7dbee38) + +Class QBluetoothTransferManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothTransferManager::QPrivateSignal (0x0x7fa3d78051e0) 0 empty + +Vtable for QBluetoothTransferManager +QBluetoothTransferManager::_ZTV25QBluetoothTransferManager: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI25QBluetoothTransferManager) +16 (int (*)(...))QBluetoothTransferManager::metaObject +24 (int (*)(...))QBluetoothTransferManager::qt_metacast +32 (int (*)(...))QBluetoothTransferManager::qt_metacall +40 (int (*)(...))QBluetoothTransferManager::~QBluetoothTransferManager +48 (int (*)(...))QBluetoothTransferManager::~QBluetoothTransferManager +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 QBluetoothTransferManager + size=16 align=8 + base size=16 base align=8 +QBluetoothTransferManager (0x0x7fa3d7dbeea0) 0 + vptr=((& QBluetoothTransferManager::_ZTV25QBluetoothTransferManager) + 16u) + QObject (0x0x7fa3d7805180) 0 + primary-for QBluetoothTransferManager (0x0x7fa3d7dbeea0) + +Class QBluetoothTransferRequest + size=8 align=8 + base size=8 base align=8 +QBluetoothTransferRequest (0x0x7fa3d7805240) 0 + +Class QBluetoothTransferReply::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothTransferReply::QPrivateSignal (0x0x7fa3d7805300) 0 empty + +Vtable for QBluetoothTransferReply +QBluetoothTransferReply::_ZTV23QBluetoothTransferReply: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI23QBluetoothTransferReply) +16 (int (*)(...))QBluetoothTransferReply::metaObject +24 (int (*)(...))QBluetoothTransferReply::qt_metacast +32 (int (*)(...))QBluetoothTransferReply::qt_metacall +40 (int (*)(...))QBluetoothTransferReply::~QBluetoothTransferReply +48 (int (*)(...))QBluetoothTransferReply::~QBluetoothTransferReply +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 + +Class QBluetoothTransferReply + size=24 align=8 + base size=24 base align=8 +QBluetoothTransferReply (0x0x7fa3d7dbef08) 0 + vptr=((& QBluetoothTransferReply::_ZTV23QBluetoothTransferReply) + 16u) + QObject (0x0x7fa3d78052a0) 0 + primary-for QBluetoothTransferReply (0x0x7fa3d7dbef08) + +Class QLowEnergyDescriptor + size=24 align=8 + base size=24 base align=8 +QLowEnergyDescriptor (0x0x7fa3d78054e0) 0 + +Class QLowEnergyCharacteristic + size=24 align=8 + base size=24 base align=8 +QLowEnergyCharacteristic (0x0x7fa3d78055a0) 0 + +Class QLowEnergyService::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLowEnergyService::QPrivateSignal (0x0x7fa3d7805720) 0 empty + +Vtable for QLowEnergyService +QLowEnergyService::_ZTV17QLowEnergyService: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QLowEnergyService) +16 (int (*)(...))QLowEnergyService::metaObject +24 (int (*)(...))QLowEnergyService::qt_metacast +32 (int (*)(...))QLowEnergyService::qt_metacall +40 (int (*)(...))QLowEnergyService::~QLowEnergyService +48 (int (*)(...))QLowEnergyService::~QLowEnergyService +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 QLowEnergyService + size=32 align=8 + base size=32 base align=8 +QLowEnergyService (0x0x7fa3d7886068) 0 + vptr=((& QLowEnergyService::_ZTV17QLowEnergyService) + 16u) + QObject (0x0x7fa3d78056c0) 0 + primary-for QLowEnergyService (0x0x7fa3d7886068) + +Class QLowEnergyController::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLowEnergyController::QPrivateSignal (0x0x7fa3d78057e0) 0 empty + +Vtable for QLowEnergyController +QLowEnergyController::_ZTV20QLowEnergyController: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI20QLowEnergyController) +16 (int (*)(...))QLowEnergyController::metaObject +24 (int (*)(...))QLowEnergyController::qt_metacast +32 (int (*)(...))QLowEnergyController::qt_metacall +40 (int (*)(...))QLowEnergyController::~QLowEnergyController +48 (int (*)(...))QLowEnergyController::~QLowEnergyController +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 QLowEnergyController + size=24 align=8 + base size=24 base align=8 +QLowEnergyController (0x0x7fa3d78860d0) 0 + vptr=((& QLowEnergyController::_ZTV20QLowEnergyController) + 16u) + QObject (0x0x7fa3d7805780) 0 + primary-for QLowEnergyController (0x0x7fa3d78860d0) + diff --git a/tests/auto/bic/data/QtBluetooth.5.6.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtBluetooth.5.6.0.linux-gcc-amd64.txt new file mode 100644 index 0000000..ddb2eed --- /dev/null +++ b/tests/auto/bic/data/QtBluetooth.5.6.0.linux-gcc-amd64.txt @@ -0,0 +1,4310 @@ +Class std::__true_type + size=1 align=1 + base size=0 base align=1 +std::__true_type (0x0x7efe9d614ae0) 0 empty + +Class std::__false_type + size=1 align=1 + base size=0 base align=1 +std::__false_type (0x0x7efe9d614b40) 0 empty + +Class std::input_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::input_iterator_tag (0x0x7efe9d6f0780) 0 empty + +Class std::output_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::output_iterator_tag (0x0x7efe9d6f07e0) 0 empty + +Class std::forward_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::forward_iterator_tag (0x0x7efe9d64f6e8) 0 empty + std::input_iterator_tag (0x0x7efe9d6f0840) 0 empty + +Class std::bidirectional_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::bidirectional_iterator_tag (0x0x7efe9d64f750) 0 empty + std::forward_iterator_tag (0x0x7efe9d64f7b8) 0 empty + std::input_iterator_tag (0x0x7efe9d6f08a0) 0 empty + +Class std::random_access_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::random_access_iterator_tag (0x0x7efe9d64f820) 0 empty + std::bidirectional_iterator_tag (0x0x7efe9d64f888) 0 empty + std::forward_iterator_tag (0x0x7efe9d64f8f0) 0 empty + std::input_iterator_tag (0x0x7efe9d6f0900) 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 (0x0x7efe9d6f0de0) 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 (0x0x7efe9d6f0e40) 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 (0x0x7efe9d6f0ea0) 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 (0x0x7efe9d6f0f00) 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 (0x0x7efe9d6f0f60) 0 empty + +Class wait + size=4 align=4 + base size=4 base align=4 +wait (0x0x7efe9d7839c0) 0 + +Class __locale_struct + size=232 align=8 + base size=232 base align=8 +__locale_struct (0x0x7efe9d783c00) 0 + +Class timespec + size=16 align=8 + base size=16 base align=8 +timespec (0x0x7efe9d783cc0) 0 + +Class timeval + size=16 align=8 + base size=16 base align=8 +timeval (0x0x7efe9d783d20) 0 + +Class pthread_attr_t + size=56 align=8 + base size=56 base align=8 +pthread_attr_t (0x0x7efe9d783de0) 0 + +Class __pthread_internal_list + size=16 align=8 + base size=16 base align=8 +__pthread_internal_list (0x0x7efe9d783e40) 0 + +Class random_data + size=48 align=8 + base size=48 base align=8 +random_data (0x0x7efe9c433300) 0 + +Class drand48_data + size=24 align=8 + base size=24 base align=8 +drand48_data (0x0x7efe9c433360) 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 (0x0x7efe9c4333c0) 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 (0x0x7efe9d64fbc8) 0 nearly-empty + vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16u) + std::exception (0x0x7efe9c433420) 0 nearly-empty + primary-for std::bad_exception (0x0x7efe9d64fbc8) + +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 (0x0x7efe9d64fc30) 0 nearly-empty + vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16u) + std::exception (0x0x7efe9c433480) 0 nearly-empty + primary-for std::bad_alloc (0x0x7efe9d64fc30) + +Class std::nothrow_t + size=1 align=1 + base size=0 base align=1 +std::nothrow_t (0x0x7efe9c4334e0) 0 empty + +Class qIsNull(double)::U + size=8 align=8 + base size=8 base align=8 +qIsNull(double)::U (0x0x7efe9c1c8c00) 0 + +Class qIsNull(float)::U + size=4 align=4 + base size=4 base align=4 +qIsNull(float)::U (0x0x7efe9c1c8c60) 0 + +Class QtPrivate::big_ + size=2 align=1 + base size=2 base align=1 +QtPrivate::big_ (0x0x7efe9c1c8e40) 0 + +Class QSysInfo + size=1 align=1 + base size=0 base align=1 +QSysInfo (0x0x7efe9c2edea0) 0 empty + +Class QMessageLogContext + size=32 align=8 + base size=32 base align=8 +QMessageLogContext (0x0x7efe9c2edf00) 0 + +Class QMessageLogger + size=32 align=8 + base size=32 base align=8 +QMessageLogger (0x0x7efe9c2edf60) 0 + +Class QFlag + size=4 align=4 + base size=4 base align=4 +QFlag (0x0x7efe9c354000) 0 + +Class QIncompatibleFlag + size=4 align=4 + base size=4 base align=4 +QIncompatibleFlag (0x0x7efe9c354180) 0 + +Class QAtomicInt + size=4 align=4 + base size=4 base align=4 +QAtomicInt (0x0x7efe9c0003a8) 0 + QAtomicInteger (0x0x7efe9c000410) 0 + QBasicAtomicInteger (0x0x7efe9c354cc0) 0 + +Class QInternal + size=1 align=1 + base size=0 base align=1 +QInternal (0x0x7efe9be1bde0) 0 empty + +Class QGenericArgument + size=16 align=8 + base size=16 base align=8 +QGenericArgument (0x0x7efe9bc5a2a0) 0 + +Class QGenericReturnArgument + size=16 align=8 + base size=16 base align=8 +QGenericReturnArgument (0x0x7efe9beb6618) 0 + QGenericArgument (0x0x7efe9bc5a300) 0 + +Class QMetaObject + size=48 align=8 + base size=48 base align=8 +QMetaObject (0x0x7efe9bc5a480) 0 + +Class QMetaObject::Connection + size=8 align=8 + base size=8 base align=8 +QMetaObject::Connection (0x0x7efe9bc5a540) 0 + +Class QLatin1Char + size=1 align=1 + base size=1 base align=1 +QLatin1Char (0x0x7efe9bc5a600) 0 + +Class QChar + size=2 align=2 + base size=2 base align=2 +QChar (0x0x7efe9bc5a660) 0 + +Class QtPrivate::RefCount + size=4 align=4 + base size=4 base align=4 +QtPrivate::RefCount (0x0x7efe9bc5a7e0) 0 + +Class QArrayData + size=24 align=8 + base size=24 base align=8 +QArrayData (0x0x7efe9bc5a8a0) 0 + +Class QtPrivate::QContainerImplHelper + size=1 align=1 + base size=0 base align=1 +QtPrivate::QContainerImplHelper (0x0x7efe9bc5acc0) 0 empty + +Class lconv + size=96 align=8 + base size=96 base align=8 +lconv (0x0x7efe9b9e7060) 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 (0x0x7efe9b9e70c0) 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 (0x0x7efe9b9e7f60) 0 + +Class __sched_param + size=4 align=4 + base size=4 base align=4 +__sched_param (0x0x7efe9baac000) 0 + +Class timex + size=208 align=8 + base size=208 base align=8 +timex (0x0x7efe9baac0c0) 0 + +Class tm + size=56 align=8 + base size=56 base align=8 +tm (0x0x7efe9baac120) 0 + +Class itimerspec + size=32 align=8 + base size=32 base align=8 +itimerspec (0x0x7efe9baac180) 0 + +Class _pthread_cleanup_buffer + size=32 align=8 + base size=32 base align=8 +_pthread_cleanup_buffer (0x0x7efe9baac1e0) 0 + +Class __pthread_cleanup_frame + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_frame (0x0x7efe9baac300) 0 + +Class __pthread_cleanup_class + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_class (0x0x7efe9baac360) 0 + +Class std::locale + size=8 align=8 + base size=8 base align=8 +std::locale (0x0x7efe9baacc00) 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 (0x0x7efe9baacc60) 0 + vptr=((& std::locale::facet::_ZTVNSt6locale5facetE) + 16u) + +Class std::locale::id + size=8 align=8 + base size=8 base align=8 +std::locale::id (0x0x7efe9baaccc0) 0 + +Class std::locale::_Impl + size=40 align=8 + base size=40 base align=8 +std::locale::_Impl (0x0x7efe9baacd20) 0 + +Class std::__cow_string + size=8 align=8 + base size=8 base align=8 +std::__cow_string (0x0x7efe9b969120) 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 (0x0x7efe9b83b7b8) 0 + vptr=((& std::logic_error::_ZTVSt11logic_error) + 16u) + std::exception (0x0x7efe9b9691e0) 0 nearly-empty + primary-for std::logic_error (0x0x7efe9b83b7b8) + +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 (0x0x7efe9b83b820) 0 + vptr=((& std::domain_error::_ZTVSt12domain_error) + 16u) + std::logic_error (0x0x7efe9b83b888) 0 + primary-for std::domain_error (0x0x7efe9b83b820) + std::exception (0x0x7efe9b969240) 0 nearly-empty + primary-for std::logic_error (0x0x7efe9b83b888) + +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 (0x0x7efe9b83b8f0) 0 + vptr=((& std::invalid_argument::_ZTVSt16invalid_argument) + 16u) + std::logic_error (0x0x7efe9b83b958) 0 + primary-for std::invalid_argument (0x0x7efe9b83b8f0) + std::exception (0x0x7efe9b9692a0) 0 nearly-empty + primary-for std::logic_error (0x0x7efe9b83b958) + +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 (0x0x7efe9b83b9c0) 0 + vptr=((& std::length_error::_ZTVSt12length_error) + 16u) + std::logic_error (0x0x7efe9b83ba28) 0 + primary-for std::length_error (0x0x7efe9b83b9c0) + std::exception (0x0x7efe9b969300) 0 nearly-empty + primary-for std::logic_error (0x0x7efe9b83ba28) + +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 (0x0x7efe9b83ba90) 0 + vptr=((& std::out_of_range::_ZTVSt12out_of_range) + 16u) + std::logic_error (0x0x7efe9b83baf8) 0 + primary-for std::out_of_range (0x0x7efe9b83ba90) + std::exception (0x0x7efe9b969360) 0 nearly-empty + primary-for std::logic_error (0x0x7efe9b83baf8) + +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 (0x0x7efe9b83bb60) 0 + vptr=((& std::runtime_error::_ZTVSt13runtime_error) + 16u) + std::exception (0x0x7efe9b9693c0) 0 nearly-empty + primary-for std::runtime_error (0x0x7efe9b83bb60) + +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 (0x0x7efe9b83bbc8) 0 + vptr=((& std::range_error::_ZTVSt11range_error) + 16u) + std::runtime_error (0x0x7efe9b83bc30) 0 + primary-for std::range_error (0x0x7efe9b83bbc8) + std::exception (0x0x7efe9b969420) 0 nearly-empty + primary-for std::runtime_error (0x0x7efe9b83bc30) + +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 (0x0x7efe9b83bc98) 0 + vptr=((& std::overflow_error::_ZTVSt14overflow_error) + 16u) + std::runtime_error (0x0x7efe9b83bd00) 0 + primary-for std::overflow_error (0x0x7efe9b83bc98) + std::exception (0x0x7efe9b969480) 0 nearly-empty + primary-for std::runtime_error (0x0x7efe9b83bd00) + +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 (0x0x7efe9b83bd68) 0 + vptr=((& std::underflow_error::_ZTVSt15underflow_error) + 16u) + std::runtime_error (0x0x7efe9b83bdd0) 0 + primary-for std::underflow_error (0x0x7efe9b83bd68) + std::exception (0x0x7efe9b9694e0) 0 nearly-empty + primary-for std::runtime_error (0x0x7efe9b83bdd0) + +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 (0x0x7efe9b969600) 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 (0x0x7efe9b83be38) 0 + vptr=((& std::ios_base::system_error::_ZTVNSt8ios_base12system_errorE) + 16u) + std::runtime_error (0x0x7efe9b83bea0) 0 + primary-for std::ios_base::system_error (0x0x7efe9b83be38) + std::exception (0x0x7efe9b9695a0) 0 nearly-empty + primary-for std::runtime_error (0x0x7efe9b83bea0) + +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 (0x0x7efe9b83bf08) 0 + vptr=((& std::ios_base::failure::_ZTVNSt8ios_base7failureB5cxx11E) + 16u) + std::ios_base::system_error (0x0x7efe9b83bf70) 0 + primary-for std::ios_base::failure (0x0x7efe9b83bf08) + std::runtime_error (0x0x7efe9b83b068) 0 + primary-for std::ios_base::system_error (0x0x7efe9b83bf70) + std::exception (0x0x7efe9b969660) 0 nearly-empty + primary-for std::runtime_error (0x0x7efe9b83b068) + +Class std::ios_base::_Callback_list + size=24 align=8 + base size=24 base align=8 +std::ios_base::_Callback_list (0x0x7efe9b9696c0) 0 + +Class std::ios_base::_Words + size=16 align=8 + base size=16 base align=8 +std::ios_base::_Words (0x0x7efe9b969720) 0 + +Class std::ios_base::Init + size=1 align=1 + base size=0 base align=1 +std::ios_base::Init (0x0x7efe9b969780) 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 (0x0x7efe9b969540) 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 (0x0x7efe9b969ea0) 0 empty + +Class std::__num_base + size=1 align=1 + base size=0 base align=1 +std::__num_base (0x0x7efe9b6ba5a0) 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 (0x0x7efe9b1e14e0 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 (0x0x7efe9b1e15b0 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 (0x0x7efe9b1e1958 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 (0x0x7efe9b1e1a28 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 (0x0x7efe9b442cc0) 0 + +Class QByteArray + size=8 align=8 + base size=8 base align=8 +QByteArray (0x0x7efe9b442d20) 0 + +Class QByteRef + size=16 align=8 + base size=12 base align=8 +QByteRef (0x0x7efe9b2cb360) 0 + +Class QLatin1String + size=16 align=8 + base size=16 base align=8 +QLatin1String (0x0x7efe9b2cb540) 0 + +Class QStringDataPtr + size=8 align=8 + base size=8 base align=8 +QStringDataPtr (0x0x7efe9b2cb780) 0 + +Class QString::Null + size=1 align=1 + base size=0 base align=1 +QString::Null (0x0x7efe9b2cb840) 0 empty + +Class QString + size=8 align=8 + base size=8 base align=8 +QString (0x0x7efe9b2cb7e0) 0 + +Class QCharRef + size=16 align=8 + base size=12 base align=8 +QCharRef (0x0x7efe9b2cbea0) 0 + +Class QStringRef + size=16 align=8 + base size=16 base align=8 +QStringRef (0x0x7efe9b1232a0) 0 + +Class QtPrivate::QHashCombine + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombine (0x0x7efe9b123660) 0 empty + +Class QtPrivate::QHashCombineCommutative + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombineCommutative (0x0x7efe9b1236c0) 0 empty + +Class std::__detail::_List_node_base + size=16 align=8 + base size=16 base align=8 +std::__detail::_List_node_base (0x0x7efe9b123720) 0 + +Class QListData::NotArrayCompatibleLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotArrayCompatibleLayout (0x0x7efe9b123ae0) 0 empty + +Class QListData::NotIndirectLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotIndirectLayout (0x0x7efe9b123b40) 0 empty + +Class QListData::ArrayCompatibleLayout + size=1 align=1 + base size=1 base align=1 +QListData::ArrayCompatibleLayout (0x0x7efe9b360a28) 0 empty + QListData::NotIndirectLayout (0x0x7efe9b123ba0) 0 empty + +Class QListData::InlineWithPaddingLayout + size=1 align=1 + base size=1 base align=1 +QListData::InlineWithPaddingLayout (0x0x7efe9af45310) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7efe9b123c00) 0 empty + QListData::NotIndirectLayout (0x0x7efe9b123c60) 0 empty + +Class QListData::IndirectLayout + size=1 align=1 + base size=1 base align=1 +QListData::IndirectLayout (0x0x7efe9b360a90) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7efe9b123cc0) 0 empty + +Class QListData::Data + size=24 align=8 + base size=24 base align=8 +QListData::Data (0x0x7efe9b123d20) 0 + +Class QListData + size=8 align=8 + base size=8 base align=8 +QListData (0x0x7efe9b123a80) 0 + +Class QRegExp + size=8 align=8 + base size=8 base align=8 +QRegExp (0x0x7efe9abb6900) 0 + +Class QStringMatcher::Data + size=272 align=8 + base size=272 base align=8 +QStringMatcher::Data (0x0x7efe9abb6ae0) 0 + +Class QStringMatcher + size=1048 align=8 + base size=1048 base align=8 +QStringMatcher (0x0x7efe9abb6a80) 0 + +Class QStringList + size=8 align=8 + base size=8 base align=8 +QStringList (0x0x7efe9b360ea0) 0 + QList (0x0x7efe9b360f08) 0 + QListSpecialMethods (0x0x7efe9abb6cc0) 0 empty + +Class QScopedPointerPodDeleter + size=1 align=1 + base size=0 base align=1 +QScopedPointerPodDeleter (0x0x7efe9abb6f00) 0 empty + +Class std::_Bit_reference + size=16 align=8 + base size=16 base align=8 +std::_Bit_reference (0x0x7efe9acf8600) 0 + +Class std::_Bit_iterator_base + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator_base (0x0x7efe9ad00a90) 0 + std::iterator (0x0x7efe9acf86c0) 0 empty + +Class std::_Bit_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator (0x0x7efe9ad00af8) 0 + std::_Bit_iterator_base (0x0x7efe9ad00b60) 0 + std::iterator (0x0x7efe9acf8720) 0 empty + +Class std::_Bit_const_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_const_iterator (0x0x7efe9ad00bc8) 0 + std::_Bit_iterator_base (0x0x7efe9ad00c30) 0 + std::iterator (0x0x7efe9acf8780) 0 empty + +Class std::_Rb_tree_node_base + size=32 align=8 + base size=32 base align=8 +std::_Rb_tree_node_base (0x0x7efe9acf8b40) 0 + +Class QtPrivate::AbstractDebugStreamFunction + size=16 align=8 + base size=16 base align=8 +QtPrivate::AbstractDebugStreamFunction (0x0x7efe9a80c060) 0 + +Class QtPrivate::AbstractComparatorFunction + size=24 align=8 + base size=24 base align=8 +QtPrivate::AbstractComparatorFunction (0x0x7efe9a80c120) 0 + +Class QtPrivate::AbstractConverterFunction + size=8 align=8 + base size=8 base align=8 +QtPrivate::AbstractConverterFunction (0x0x7efe9a80c240) 0 + +Class QMetaType + size=80 align=8 + base size=80 base align=8 +QMetaType (0x0x7efe9a80c3c0) 0 + +Class QtMetaTypePrivate::VariantData + size=24 align=8 + base size=20 base align=8 +QtMetaTypePrivate::VariantData (0x0x7efe9a80c660) 0 + +Class QtMetaTypePrivate::VectorBoolElements + size=1 align=1 + base size=0 base align=1 +QtMetaTypePrivate::VectorBoolElements (0x0x7efe9a80c780) 0 empty + +Class QtMetaTypePrivate::QSequentialIterableImpl + size=104 align=8 + base size=104 base align=8 +QtMetaTypePrivate::QSequentialIterableImpl (0x0x7efe9a93d180) 0 + +Class QtMetaTypePrivate::QAssociativeIterableImpl + size=112 align=8 + base size=112 base align=8 +QtMetaTypePrivate::QAssociativeIterableImpl (0x0x7efe9a93d540) 0 + +Class QtMetaTypePrivate::QPairVariantInterfaceImpl + size=40 align=8 + base size=40 base align=8 +QtMetaTypePrivate::QPairVariantInterfaceImpl (0x0x7efe9a93d780) 0 + +Class QtPrivate::QSlotObjectBase + size=16 align=8 + base size=16 base align=8 +QtPrivate::QSlotObjectBase (0x0x7efe9a7177e0) 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 (0x0x7efe9a717960) 0 + vptr=((& QObjectData::_ZTV11QObjectData) + 16u) + +Class QObject::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObject::QPrivateSignal (0x0x7efe9a717b40) 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 (0x0x7efe9a717ae0) 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 (0x0x7efe9a717ea0) 0 nearly-empty + vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16u) + +Class QSignalBlocker + size=16 align=8 + base size=10 base align=8 +QSignalBlocker (0x0x7efe9a717f00) 0 + +Class QAbstractAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractAnimation::QPrivateSignal (0x0x7efe9a412000) 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 (0x0x7efe9a963d68) 0 + vptr=((& QAbstractAnimation::_ZTV18QAbstractAnimation) + 16u) + QObject (0x0x7efe9a717f60) 0 + primary-for QAbstractAnimation (0x0x7efe9a963d68) + +Class QAnimationDriver::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationDriver::QPrivateSignal (0x0x7efe9a4120c0) 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 (0x0x7efe9a963dd0) 0 + vptr=((& QAnimationDriver::_ZTV16QAnimationDriver) + 16u) + QObject (0x0x7efe9a412060) 0 + primary-for QAnimationDriver (0x0x7efe9a963dd0) + +Class QAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationGroup::QPrivateSignal (0x0x7efe9a412180) 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 (0x0x7efe9a963e38) 0 + vptr=((& QAnimationGroup::_ZTV15QAnimationGroup) + 16u) + QAbstractAnimation (0x0x7efe9a963ea0) 0 + primary-for QAnimationGroup (0x0x7efe9a963e38) + QObject (0x0x7efe9a412120) 0 + primary-for QAbstractAnimation (0x0x7efe9a963ea0) + +Class QParallelAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QParallelAnimationGroup::QPrivateSignal (0x0x7efe9a412240) 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 (0x0x7efe9a963f08) 0 + vptr=((& QParallelAnimationGroup::_ZTV23QParallelAnimationGroup) + 16u) + QAnimationGroup (0x0x7efe9a963f70) 0 + primary-for QParallelAnimationGroup (0x0x7efe9a963f08) + QAbstractAnimation (0x0x7efe9a44c000) 0 + primary-for QAnimationGroup (0x0x7efe9a963f70) + QObject (0x0x7efe9a4121e0) 0 + primary-for QAbstractAnimation (0x0x7efe9a44c000) + +Class QPauseAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPauseAnimation::QPrivateSignal (0x0x7efe9a412300) 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 (0x0x7efe9a44c068) 0 + vptr=((& QPauseAnimation::_ZTV15QPauseAnimation) + 16u) + QAbstractAnimation (0x0x7efe9a44c0d0) 0 + primary-for QPauseAnimation (0x0x7efe9a44c068) + QObject (0x0x7efe9a4122a0) 0 + primary-for QAbstractAnimation (0x0x7efe9a44c0d0) + +Class QEasingCurve + size=8 align=8 + base size=8 base align=8 +QEasingCurve (0x0x7efe9a4e4660) 0 + +Class QMapNodeBase + size=24 align=8 + base size=24 base align=8 +QMapNodeBase (0x0x7efe9a4e47e0) 0 + +Class QMapDataBase + size=40 align=8 + base size=40 base align=8 +QMapDataBase (0x0x7efe9a4e48a0) 0 + +Class QHashData::Node + size=16 align=8 + base size=16 base align=8 +QHashData::Node (0x0x7efe9a4e4c60) 0 + +Class QHashData + size=48 align=8 + base size=48 base align=8 +QHashData (0x0x7efe9a4e4c00) 0 + +Class QHashDummyValue + size=1 align=1 + base size=0 base align=1 +QHashDummyValue (0x0x7efe9a4e4cc0) 0 empty + +Class QVariant::PrivateShared + size=16 align=8 + base size=12 base align=8 +QVariant::PrivateShared (0x0x7efe9a268720) 0 + +Class QVariant::Private::Data + size=8 align=8 + base size=8 base align=8 +QVariant::Private::Data (0x0x7efe9a2687e0) 0 + +Class QVariant::Private + size=16 align=8 + base size=12 base align=8 +QVariant::Private (0x0x7efe9a268780) 0 + +Class QVariant::Handler + size=72 align=8 + base size=72 base align=8 +QVariant::Handler (0x0x7efe9a268840) 0 + +Class QVariant + size=16 align=8 + base size=16 base align=8 +QVariant (0x0x7efe9a2686c0) 0 + +Class QVariantComparisonHelper + size=8 align=8 + base size=8 base align=8 +QVariantComparisonHelper (0x0x7efe9a268b40) 0 + +Class QSequentialIterable::const_iterator + size=112 align=8 + base size=112 base align=8 +QSequentialIterable::const_iterator (0x0x7efe9a268c00) 0 + +Class QSequentialIterable + size=104 align=8 + base size=104 base align=8 +QSequentialIterable (0x0x7efe9a268ba0) 0 + +Class QAssociativeIterable::const_iterator + size=120 align=8 + base size=120 base align=8 +QAssociativeIterable::const_iterator (0x0x7efe9a268cc0) 0 + +Class QAssociativeIterable + size=112 align=8 + base size=112 base align=8 +QAssociativeIterable (0x0x7efe9a268c60) 0 + +Class QVariantAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QVariantAnimation::QPrivateSignal (0x0x7efe9a034900) 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 (0x0x7efe9a085000) 0 + vptr=((& QVariantAnimation::_ZTV17QVariantAnimation) + 16u) + QAbstractAnimation (0x0x7efe9a085068) 0 + primary-for QVariantAnimation (0x0x7efe9a085000) + QObject (0x0x7efe9a0348a0) 0 + primary-for QAbstractAnimation (0x0x7efe9a085068) + +Class QPropertyAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPropertyAnimation::QPrivateSignal (0x0x7efe9a0349c0) 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 (0x0x7efe9a085138) 0 + vptr=((& QPropertyAnimation::_ZTV18QPropertyAnimation) + 16u) + QVariantAnimation (0x0x7efe9a0851a0) 0 + primary-for QPropertyAnimation (0x0x7efe9a085138) + QAbstractAnimation (0x0x7efe9a085208) 0 + primary-for QVariantAnimation (0x0x7efe9a0851a0) + QObject (0x0x7efe9a034960) 0 + primary-for QAbstractAnimation (0x0x7efe9a085208) + +Class QSequentialAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSequentialAnimationGroup::QPrivateSignal (0x0x7efe9a034a80) 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 (0x0x7efe9a085270) 0 + vptr=((& QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup) + 16u) + QAnimationGroup (0x0x7efe9a0852d8) 0 + primary-for QSequentialAnimationGroup (0x0x7efe9a085270) + QAbstractAnimation (0x0x7efe9a085340) 0 + primary-for QAnimationGroup (0x0x7efe9a0852d8) + QObject (0x0x7efe9a034a20) 0 + primary-for QAbstractAnimation (0x0x7efe9a085340) + +Class QTextCodec::ConverterState + size=32 align=8 + base size=32 base align=8 +QTextCodec::ConverterState (0x0x7efe9a034b40) 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 (0x0x7efe9a034ae0) 0 nearly-empty + vptr=((& QTextCodec::_ZTV10QTextCodec) + 16u) + +Class QTextEncoder + size=40 align=8 + base size=40 base align=8 +QTextEncoder (0x0x7efe9a034c60) 0 + +Class QTextDecoder + size=40 align=8 + base size=40 base align=8 +QTextDecoder (0x0x7efe9a034cc0) 0 + +Class QSharedData + size=4 align=4 + base size=4 base align=4 +QSharedData (0x0x7efe9a034d20) 0 + +Class std::__numeric_limits_base + size=1 align=1 + base size=0 base align=1 +std::__numeric_limits_base (0x0x7efe9a034f00) 0 empty + +Class QDate + size=8 align=8 + base size=8 base align=8 +QDate (0x0x7efe9a1726c0) 0 + +Class QTime + size=4 align=4 + base size=4 base align=4 +QTime (0x0x7efe9a172840) 0 + +Class QDateTime + size=8 align=8 + base size=8 base align=8 +QDateTime (0x0x7efe9a1729c0) 0 + +Class QLibraryInfo + size=1 align=1 + base size=0 base align=1 +QLibraryInfo (0x0x7efe9a172ba0) 0 empty + +Class QIODevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIODevice::QPrivateSignal (0x0x7efe9a172c60) 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 (0x0x7efe9a085618) 0 + vptr=((& QIODevice::_ZTV9QIODevice) + 16u) + QObject (0x0x7efe9a172c00) 0 + primary-for QIODevice (0x0x7efe9a085618) + +Class QBuffer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBuffer::QPrivateSignal (0x0x7efe9a172de0) 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 (0x0x7efe9a085750) 0 + vptr=((& QBuffer::_ZTV7QBuffer) + 16u) + QIODevice (0x0x7efe9a0857b8) 0 + primary-for QBuffer (0x0x7efe9a085750) + QObject (0x0x7efe9a172d80) 0 + primary-for QIODevice (0x0x7efe9a0857b8) + +Class QDataStream + size=32 align=8 + base size=32 base align=8 +QDataStream (0x0x7efe9a172e40) 0 + +Class QLocale + size=8 align=8 + base size=8 base align=8 +QLocale (0x0x7efe9a172f00) 0 + +Class _IO_marker + size=24 align=8 + base size=24 base align=8 +_IO_marker (0x0x7efe99f632a0) 0 + +Class _IO_FILE + size=216 align=8 + base size=216 base align=8 +_IO_FILE (0x0x7efe99f63300) 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 (0x0x7efe99f633c0) 0 + vptr=((& QTextStream::_ZTV11QTextStream) + 16u) + +Class QTextStreamManipulator + size=40 align=8 + base size=38 base align=8 +QTextStreamManipulator (0x0x7efe99f635a0) 0 + +Class QContiguousCacheData + size=24 align=4 + base size=24 base align=4 +QContiguousCacheData (0x0x7efe99f637e0) 0 + +Class QDebug::Stream + size=80 align=8 + base size=76 base align=8 +QDebug::Stream (0x0x7efe99f63ae0) 0 + +Class QDebug + size=8 align=8 + base size=8 base align=8 +QDebug (0x0x7efe99f63a80) 0 + +Class QDebugStateSaver + size=8 align=8 + base size=8 base align=8 +QDebugStateSaver (0x0x7efe99f63c60) 0 + +Class QNoDebug + size=1 align=1 + base size=0 base align=1 +QNoDebug (0x0x7efe99f63d20) 0 empty + +Class QFileDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileDevice::QPrivateSignal (0x0x7efe99f63f00) 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 (0x0x7efe99d750d0) 0 + vptr=((& QFileDevice::_ZTV11QFileDevice) + 16u) + QIODevice (0x0x7efe99d75138) 0 + primary-for QFileDevice (0x0x7efe99d750d0) + QObject (0x0x7efe99f63ea0) 0 + primary-for QIODevice (0x0x7efe99d75138) + +Class QFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFile::QPrivateSignal (0x0x7efe99d9e0c0) 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 (0x0x7efe99d75270) 0 + vptr=((& QFile::_ZTV5QFile) + 16u) + QFileDevice (0x0x7efe99d752d8) 0 + primary-for QFile (0x0x7efe99d75270) + QIODevice (0x0x7efe99d75340) 0 + primary-for QFileDevice (0x0x7efe99d752d8) + QObject (0x0x7efe99d9e060) 0 + primary-for QIODevice (0x0x7efe99d75340) + +Class QFileInfo + size=8 align=8 + base size=8 base align=8 +QFileInfo (0x0x7efe99d9e1e0) 0 + +Class QDir + size=8 align=8 + base size=8 base align=8 +QDir (0x0x7efe99d9e4e0) 0 + +Class QDirIterator + size=8 align=8 + base size=8 base align=8 +QDirIterator (0x0x7efe99d9e840) 0 + +Class QFileSelector::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSelector::QPrivateSignal (0x0x7efe99d9ea20) 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 (0x0x7efe99d75820) 0 + vptr=((& QFileSelector::_ZTV13QFileSelector) + 16u) + QObject (0x0x7efe99d9e9c0) 0 + primary-for QFileSelector (0x0x7efe99d75820) + +Class QFileSystemWatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSystemWatcher::QPrivateSignal (0x0x7efe99d9eae0) 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 (0x0x7efe99d75888) 0 + vptr=((& QFileSystemWatcher::_ZTV18QFileSystemWatcher) + 16u) + QObject (0x0x7efe99d9ea80) 0 + primary-for QFileSystemWatcher (0x0x7efe99d75888) + +Class QLockFile + size=8 align=8 + base size=8 base align=8 +QLockFile (0x0x7efe99d9eb40) 0 + +Class QLoggingCategory::AtomicBools + size=4 align=1 + base size=4 base align=1 +QLoggingCategory::AtomicBools (0x0x7efe99d9ecc0) 0 + +Class QLoggingCategory + size=24 align=8 + base size=24 base align=8 +QLoggingCategory (0x0x7efe99d9ec60) 0 + +Class QProcessEnvironment + size=8 align=8 + base size=8 base align=8 +QProcessEnvironment (0x0x7efe99d9ee40) 0 + +Class QProcess::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QProcess::QPrivateSignal (0x0x7efe99af30c0) 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 (0x0x7efe99d75a90) 0 + vptr=((& QProcess::_ZTV8QProcess) + 16u) + QIODevice (0x0x7efe99d75af8) 0 + primary-for QProcess (0x0x7efe99d75a90) + QObject (0x0x7efe99af3060) 0 + primary-for QIODevice (0x0x7efe99d75af8) + +Class QResource + size=8 align=8 + base size=8 base align=8 +QResource (0x0x7efe99af3120) 0 + +Class QSaveFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSaveFile::QPrivateSignal (0x0x7efe99af32a0) 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 (0x0x7efe99d75b60) 0 + vptr=((& QSaveFile::_ZTV9QSaveFile) + 16u) + QFileDevice (0x0x7efe99d75bc8) 0 + primary-for QSaveFile (0x0x7efe99d75b60) + QIODevice (0x0x7efe99d75c30) 0 + primary-for QFileDevice (0x0x7efe99d75bc8) + QObject (0x0x7efe99af3240) 0 + primary-for QIODevice (0x0x7efe99d75c30) + +Class QSettings::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSettings::QPrivateSignal (0x0x7efe99af3360) 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 (0x0x7efe99d75c98) 0 + vptr=((& QSettings::_ZTV9QSettings) + 16u) + QObject (0x0x7efe99af3300) 0 + primary-for QSettings (0x0x7efe99d75c98) + +Class QStandardPaths + size=1 align=1 + base size=0 base align=1 +QStandardPaths (0x0x7efe99af33c0) 0 empty + +Class QStorageInfo + size=8 align=8 + base size=8 base align=8 +QStorageInfo (0x0x7efe99af34e0) 0 + +Class QTemporaryDir + size=8 align=8 + base size=8 base align=8 +QTemporaryDir (0x0x7efe99af37e0) 0 + +Class QTemporaryFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTemporaryFile::QPrivateSignal (0x0x7efe99af3900) 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 (0x0x7efe99d75e38) 0 + vptr=((& QTemporaryFile::_ZTV14QTemporaryFile) + 16u) + QFile (0x0x7efe99d75ea0) 0 + primary-for QTemporaryFile (0x0x7efe99d75e38) + QFileDevice (0x0x7efe99d75f08) 0 + primary-for QFile (0x0x7efe99d75ea0) + QIODevice (0x0x7efe99d75f70) 0 + primary-for QFileDevice (0x0x7efe99d75f08) + QObject (0x0x7efe99af38a0) 0 + primary-for QIODevice (0x0x7efe99d75f70) + +Class QUrl + size=8 align=8 + base size=8 base align=8 +QUrl (0x0x7efe99af3a20) 0 + +Class QUrlQuery + size=8 align=8 + base size=8 base align=8 +QUrlQuery (0x0x7efe99af3e40) 0 + +Class QModelIndex + size=24 align=8 + base size=24 base align=8 +QModelIndex (0x0x7efe998a5060) 0 + +Class QPersistentModelIndex + size=8 align=8 + base size=8 base align=8 +QPersistentModelIndex (0x0x7efe998a51e0) 0 + +Class QAbstractItemModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractItemModel::QPrivateSignal (0x0x7efe998a53c0) 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 (0x0x7efe99816410) 0 + vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16u) + QObject (0x0x7efe998a5360) 0 + primary-for QAbstractItemModel (0x0x7efe99816410) + +Class QAbstractTableModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTableModel::QPrivateSignal (0x0x7efe998a5720) 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 (0x0x7efe99816618) 0 + vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16u) + QAbstractItemModel (0x0x7efe99816680) 0 + primary-for QAbstractTableModel (0x0x7efe99816618) + QObject (0x0x7efe998a56c0) 0 + primary-for QAbstractItemModel (0x0x7efe99816680) + +Class QAbstractListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractListModel::QPrivateSignal (0x0x7efe998a57e0) 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 (0x0x7efe998166e8) 0 + vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16u) + QAbstractItemModel (0x0x7efe99816750) 0 + primary-for QAbstractListModel (0x0x7efe998166e8) + QObject (0x0x7efe998a5780) 0 + primary-for QAbstractItemModel (0x0x7efe99816750) + +Class QAbstractProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractProxyModel::QPrivateSignal (0x0x7efe998a5ae0) 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 (0x0x7efe99816888) 0 + vptr=((& QAbstractProxyModel::_ZTV19QAbstractProxyModel) + 16u) + QAbstractItemModel (0x0x7efe998168f0) 0 + primary-for QAbstractProxyModel (0x0x7efe99816888) + QObject (0x0x7efe998a5a80) 0 + primary-for QAbstractItemModel (0x0x7efe998168f0) + +Class QIdentityProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIdentityProxyModel::QPrivateSignal (0x0x7efe998a5ba0) 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 (0x0x7efe99816958) 0 + vptr=((& QIdentityProxyModel::_ZTV19QIdentityProxyModel) + 16u) + QAbstractProxyModel (0x0x7efe998169c0) 0 + primary-for QIdentityProxyModel (0x0x7efe99816958) + QAbstractItemModel (0x0x7efe99816a28) 0 + primary-for QAbstractProxyModel (0x0x7efe998169c0) + QObject (0x0x7efe998a5b40) 0 + primary-for QAbstractItemModel (0x0x7efe99816a28) + +Class QItemSelectionRange + size=16 align=8 + base size=16 base align=8 +QItemSelectionRange (0x0x7efe998a5c00) 0 + +Class QItemSelectionModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QItemSelectionModel::QPrivateSignal (0x0x7efe998a5de0) 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 (0x0x7efe99816b60) 0 + vptr=((& QItemSelectionModel::_ZTV19QItemSelectionModel) + 16u) + QObject (0x0x7efe998a5d80) 0 + primary-for QItemSelectionModel (0x0x7efe99816b60) + +Class QItemSelection + size=8 align=8 + base size=8 base align=8 +QItemSelection (0x0x7efe99816d68) 0 + QList (0x0x7efe99816dd0) 0 + QListSpecialMethods (0x0x7efe9965d060) 0 empty + +Class QSortFilterProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSortFilterProxyModel::QPrivateSignal (0x0x7efe9965d480) 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 (0x0x7efe99816ea0) 0 + vptr=((& QSortFilterProxyModel::_ZTV21QSortFilterProxyModel) + 16u) + QAbstractProxyModel (0x0x7efe99816f08) 0 + primary-for QSortFilterProxyModel (0x0x7efe99816ea0) + QAbstractItemModel (0x0x7efe99816f70) 0 + primary-for QAbstractProxyModel (0x0x7efe99816f08) + QObject (0x0x7efe9965d420) 0 + primary-for QAbstractItemModel (0x0x7efe99816f70) + +Class QStringListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStringListModel::QPrivateSignal (0x0x7efe9965d540) 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 (0x0x7efe996c2000) 0 + vptr=((& QStringListModel::_ZTV16QStringListModel) + 16u) + QAbstractListModel (0x0x7efe996c2068) 0 + primary-for QStringListModel (0x0x7efe996c2000) + QAbstractItemModel (0x0x7efe996c20d0) 0 + primary-for QAbstractListModel (0x0x7efe996c2068) + QObject (0x0x7efe9965d4e0) 0 + primary-for QAbstractItemModel (0x0x7efe996c20d0) + +Class QJsonValue + size=24 align=8 + base size=20 base align=8 +QJsonValue (0x0x7efe9965d5a0) 0 + +Class QJsonValueRef + size=16 align=8 + base size=12 base align=8 +QJsonValueRef (0x0x7efe9965d660) 0 + +Class QJsonValuePtr + size=24 align=8 + base size=24 base align=8 +QJsonValuePtr (0x0x7efe9965d720) 0 + +Class QJsonValueRefPtr + size=16 align=8 + base size=16 base align=8 +QJsonValueRefPtr (0x0x7efe9965d780) 0 + +Class QJsonArray::iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::iterator (0x0x7efe9965d840) 0 + +Class QJsonArray::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::const_iterator (0x0x7efe9965d8a0) 0 + +Class QJsonArray + size=16 align=8 + base size=16 base align=8 +QJsonArray (0x0x7efe9965d7e0) 0 + +Class QJsonParseError + size=8 align=4 + base size=8 base align=4 +QJsonParseError (0x0x7efe9965d900) 0 + +Class QJsonDocument + size=8 align=8 + base size=8 base align=8 +QJsonDocument (0x0x7efe9965d960) 0 + +Class QJsonObject::iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::iterator (0x0x7efe9965da20) 0 + +Class QJsonObject::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::const_iterator (0x0x7efe9965da80) 0 + +Class QJsonObject + size=16 align=8 + base size=16 base align=8 +QJsonObject (0x0x7efe9965d9c0) 0 + +Class QEventLoop::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventLoop::QPrivateSignal (0x0x7efe9965dba0) 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 (0x0x7efe996c2138) 0 + vptr=((& QEventLoop::_ZTV10QEventLoop) + 16u) + QObject (0x0x7efe9965db40) 0 + primary-for QEventLoop (0x0x7efe996c2138) + +Class QEventLoopLocker + size=8 align=8 + base size=8 base align=8 +QEventLoopLocker (0x0x7efe9965dcc0) 0 + +Class QAbstractEventDispatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractEventDispatcher::QPrivateSignal (0x0x7efe9965dd80) 0 empty + +Class QAbstractEventDispatcher::TimerInfo + size=12 align=4 + base size=12 base align=4 +QAbstractEventDispatcher::TimerInfo (0x0x7efe9965dde0) 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 (0x0x7efe996c2270) 0 + vptr=((& QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher) + 16u) + QObject (0x0x7efe9965dd20) 0 + primary-for QAbstractEventDispatcher (0x0x7efe996c2270) + +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 (0x0x7efe9965de40) 0 + vptr=((& QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter) + 16u) + +Class QBasicTimer + size=4 align=4 + base size=4 base align=4 +QBasicTimer (0x0x7efe9965dea0) 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 (0x0x7efe99431060) 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 (0x0x7efe996c2340) 0 + vptr=((& QTimerEvent::_ZTV11QTimerEvent) + 16u) + QEvent (0x0x7efe994310c0) 0 + primary-for QTimerEvent (0x0x7efe996c2340) + +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 (0x0x7efe996c23a8) 0 + vptr=((& QChildEvent::_ZTV11QChildEvent) + 16u) + QEvent (0x0x7efe99431120) 0 + primary-for QChildEvent (0x0x7efe996c23a8) + +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 (0x0x7efe996c2410) 0 + vptr=((& QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent) + 16u) + QEvent (0x0x7efe99431180) 0 + primary-for QDynamicPropertyChangeEvent (0x0x7efe996c2410) + +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 (0x0x7efe996c2478) 0 + vptr=((& QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent) + 16u) + QEvent (0x0x7efe994311e0) 0 + primary-for QDeferredDeleteEvent (0x0x7efe996c2478) + +Class QCoreApplication::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QCoreApplication::QPrivateSignal (0x0x7efe994312a0) 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 (0x0x7efe996c24e0) 0 + vptr=((& QCoreApplication::_ZTV16QCoreApplication) + 16u) + QObject (0x0x7efe99431240) 0 + primary-for QCoreApplication (0x0x7efe996c24e0) + +Class __exception + size=40 align=8 + base size=40 base align=8 +__exception (0x0x7efe99431300) 0 + +Class QMetaMethod + size=16 align=8 + base size=12 base align=8 +QMetaMethod (0x0x7efe99431480) 0 + +Class QMetaEnum + size=16 align=8 + base size=12 base align=8 +QMetaEnum (0x0x7efe99431600) 0 + +Class QMetaProperty + size=32 align=8 + base size=32 base align=8 +QMetaProperty (0x0x7efe99431780) 0 + +Class QMetaClassInfo + size=16 align=8 + base size=12 base align=8 +QMetaClassInfo (0x0x7efe994317e0) 0 + +Class QMimeData::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QMimeData::QPrivateSignal (0x0x7efe994319c0) 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 (0x0x7efe996c2680) 0 + vptr=((& QMimeData::_ZTV9QMimeData) + 16u) + QObject (0x0x7efe99431960) 0 + primary-for QMimeData (0x0x7efe996c2680) + +Class QObjectCleanupHandler::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObjectCleanupHandler::QPrivateSignal (0x0x7efe99431a80) 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 (0x0x7efe996c26e8) 0 + vptr=((& QObjectCleanupHandler::_ZTV21QObjectCleanupHandler) + 16u) + QObject (0x0x7efe99431a20) 0 + primary-for QObjectCleanupHandler (0x0x7efe996c26e8) + +Class QtSharedPointer::NormalDeleter + size=1 align=1 + base size=0 base align=1 +QtSharedPointer::NormalDeleter (0x0x7efe99431ae0) 0 empty + +Class QtSharedPointer::ExternalRefCountData + size=16 align=8 + base size=16 base align=8 +QtSharedPointer::ExternalRefCountData (0x0x7efe99431c60) 0 + +Class QSharedMemory::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSharedMemory::QPrivateSignal (0x0x7efe9923d2a0) 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 (0x0x7efe996c2af8) 0 + vptr=((& QSharedMemory::_ZTV13QSharedMemory) + 16u) + QObject (0x0x7efe9923d240) 0 + primary-for QSharedMemory (0x0x7efe996c2af8) + +Class QSignalMapper::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalMapper::QPrivateSignal (0x0x7efe9923d360) 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 (0x0x7efe996c2b60) 0 + vptr=((& QSignalMapper::_ZTV13QSignalMapper) + 16u) + QObject (0x0x7efe9923d300) 0 + primary-for QSignalMapper (0x0x7efe996c2b60) + +Class QSocketNotifier::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSocketNotifier::QPrivateSignal (0x0x7efe9923d420) 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 (0x0x7efe996c2bc8) 0 + vptr=((& QSocketNotifier::_ZTV15QSocketNotifier) + 16u) + QObject (0x0x7efe9923d3c0) 0 + primary-for QSocketNotifier (0x0x7efe996c2bc8) + +Class QSystemSemaphore + size=8 align=8 + base size=8 base align=8 +QSystemSemaphore (0x0x7efe9923d480) 0 + +Class QTimer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimer::QPrivateSignal (0x0x7efe9923d5a0) 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 (0x0x7efe996c2c30) 0 + vptr=((& QTimer::_ZTV6QTimer) + 16u) + QObject (0x0x7efe9923d540) 0 + primary-for QTimer (0x0x7efe996c2c30) + +Class QTranslator::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTranslator::QPrivateSignal (0x0x7efe9923d720) 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 (0x0x7efe996c2d00) 0 + vptr=((& QTranslator::_ZTV11QTranslator) + 16u) + QObject (0x0x7efe9923d6c0) 0 + primary-for QTranslator (0x0x7efe996c2d00) + +Class QMimeType + size=8 align=8 + base size=8 base align=8 +QMimeType (0x0x7efe9923d780) 0 + +Class QMimeDatabase + size=8 align=8 + base size=8 base align=8 +QMimeDatabase (0x0x7efe9923d960) 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 (0x0x7efe9923d9c0) 0 nearly-empty + vptr=((& QFactoryInterface::_ZTV17QFactoryInterface) + 16u) + +Class QLibrary::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLibrary::QPrivateSignal (0x0x7efe9923dae0) 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 (0x0x7efe996c2dd0) 0 + vptr=((& QLibrary::_ZTV8QLibrary) + 16u) + QObject (0x0x7efe9923da80) 0 + primary-for QLibrary (0x0x7efe996c2dd0) + +Class QStaticPlugin + size=16 align=8 + base size=16 base align=8 +QStaticPlugin (0x0x7efe9923dc00) 0 + +Class QPluginLoader::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPluginLoader::QPrivateSignal (0x0x7efe9923dde0) 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 (0x0x7efe996c2f70) 0 + vptr=((& QPluginLoader::_ZTV13QPluginLoader) + 16u) + QObject (0x0x7efe9923dd80) 0 + primary-for QPluginLoader (0x0x7efe996c2f70) + +Class QUuid + size=16 align=4 + base size=16 base align=4 +QUuid (0x0x7efe9923de40) 0 + +Class QAbstractState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractState::QPrivateSignal (0x0x7efe99361060) 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 (0x0x7efe996c2a28) 0 + vptr=((& QAbstractState::_ZTV14QAbstractState) + 16u) + QObject (0x0x7efe99361000) 0 + primary-for QAbstractState (0x0x7efe996c2a28) + +Class QAbstractTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTransition::QPrivateSignal (0x0x7efe99361120) 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 (0x0x7efe996c2a90) 0 + vptr=((& QAbstractTransition::_ZTV19QAbstractTransition) + 16u) + QObject (0x0x7efe993610c0) 0 + primary-for QAbstractTransition (0x0x7efe996c2a90) + +Class QEventTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventTransition::QPrivateSignal (0x0x7efe993611e0) 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 (0x0x7efe98f8d000) 0 + vptr=((& QEventTransition::_ZTV16QEventTransition) + 16u) + QAbstractTransition (0x0x7efe98f8d068) 0 + primary-for QEventTransition (0x0x7efe98f8d000) + QObject (0x0x7efe99361180) 0 + primary-for QAbstractTransition (0x0x7efe98f8d068) + +Class QFinalState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFinalState::QPrivateSignal (0x0x7efe993612a0) 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 (0x0x7efe98f8d0d0) 0 + vptr=((& QFinalState::_ZTV11QFinalState) + 16u) + QAbstractState (0x0x7efe98f8d138) 0 + primary-for QFinalState (0x0x7efe98f8d0d0) + QObject (0x0x7efe99361240) 0 + primary-for QAbstractState (0x0x7efe98f8d138) + +Class QHistoryState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QHistoryState::QPrivateSignal (0x0x7efe99361360) 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 (0x0x7efe98f8d1a0) 0 + vptr=((& QHistoryState::_ZTV13QHistoryState) + 16u) + QAbstractState (0x0x7efe98f8d208) 0 + primary-for QHistoryState (0x0x7efe98f8d1a0) + QObject (0x0x7efe99361300) 0 + primary-for QAbstractState (0x0x7efe98f8d208) + +Class QSignalTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalTransition::QPrivateSignal (0x0x7efe99361420) 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 (0x0x7efe98f8d270) 0 + vptr=((& QSignalTransition::_ZTV17QSignalTransition) + 16u) + QAbstractTransition (0x0x7efe98f8d2d8) 0 + primary-for QSignalTransition (0x0x7efe98f8d270) + QObject (0x0x7efe993613c0) 0 + primary-for QAbstractTransition (0x0x7efe98f8d2d8) + +Class QState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QState::QPrivateSignal (0x0x7efe993614e0) 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 (0x0x7efe98f8d340) 0 + vptr=((& QState::_ZTV6QState) + 16u) + QAbstractState (0x0x7efe98f8d3a8) 0 + primary-for QState (0x0x7efe98f8d340) + QObject (0x0x7efe99361480) 0 + primary-for QAbstractState (0x0x7efe98f8d3a8) + +Class QStateMachine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStateMachine::QPrivateSignal (0x0x7efe99361600) 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 (0x0x7efe98f8d548) 0 + vptr=((& QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE) + 16u) + QEvent (0x0x7efe99361660) 0 + primary-for QStateMachine::SignalEvent (0x0x7efe98f8d548) + +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 (0x0x7efe98f8d5b0) 0 + vptr=((& QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE) + 16u) + QEvent (0x0x7efe993616c0) 0 + primary-for QStateMachine::WrappedEvent (0x0x7efe98f8d5b0) + +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 (0x0x7efe98f8d410) 0 + vptr=((& QStateMachine::_ZTV13QStateMachine) + 16u) + QState (0x0x7efe98f8d478) 0 + primary-for QStateMachine (0x0x7efe98f8d410) + QAbstractState (0x0x7efe98f8d4e0) 0 + primary-for QState (0x0x7efe98f8d478) + QObject (0x0x7efe993615a0) 0 + primary-for QAbstractState (0x0x7efe98f8d4e0) + +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 (0x0x7efe98f8d618) 0 nearly-empty + vptr=((& QException::_ZTV10QException) + 16u) + std::exception (0x0x7efe99361720) 0 nearly-empty + primary-for QException (0x0x7efe98f8d618) + +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 (0x0x7efe98f8d680) 0 nearly-empty + vptr=((& QUnhandledException::_ZTV19QUnhandledException) + 16u) + QException (0x0x7efe98f8d6e8) 0 nearly-empty + primary-for QUnhandledException (0x0x7efe98f8d680) + std::exception (0x0x7efe99361780) 0 nearly-empty + primary-for QException (0x0x7efe98f8d6e8) + +Class QtPrivate::ExceptionHolder + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionHolder (0x0x7efe993617e0) 0 + +Class QtPrivate::ExceptionStore + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionStore (0x0x7efe993618a0) 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 (0x0x7efe99361900) 0 + vptr=((& QRunnable::_ZTV9QRunnable) + 16u) + +Class QBasicMutex + size=8 align=8 + base size=8 base align=8 +QBasicMutex (0x0x7efe99361960) 0 + +Class QMutex + size=8 align=8 + base size=8 base align=8 +QMutex (0x0x7efe98f8d888) 0 + QBasicMutex (0x0x7efe99361ae0) 0 + +Class QMutexLocker + size=8 align=8 + base size=8 base align=8 +QMutexLocker (0x0x7efe99361b40) 0 + +Class QtPrivate::ResultItem + size=16 align=8 + base size=16 base align=8 +QtPrivate::ResultItem (0x0x7efe99361c00) 0 + +Class QtPrivate::ResultIteratorBase + size=16 align=8 + base size=12 base align=8 +QtPrivate::ResultIteratorBase (0x0x7efe99361c60) 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 (0x0x7efe99361de0) 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 (0x0x7efe99361ea0) 0 + vptr=((& QFutureInterfaceBase::_ZTV20QFutureInterfaceBase) + 16u) + +Class QFutureWatcherBase::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFutureWatcherBase::QPrivateSignal (0x0x7efe990e4240) 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 (0x0x7efe990cd138) 0 + vptr=((& QFutureWatcherBase::_ZTV18QFutureWatcherBase) + 16u) + QObject (0x0x7efe990e41e0) 0 + primary-for QFutureWatcherBase (0x0x7efe990cd138) + +Class QReadWriteLock + size=8 align=8 + base size=8 base align=8 +QReadWriteLock (0x0x7efe990e4360) 0 + +Class QReadLocker + size=8 align=8 + base size=8 base align=8 +QReadLocker (0x0x7efe990e43c0) 0 + +Class QWriteLocker + size=8 align=8 + base size=8 base align=8 +QWriteLocker (0x0x7efe990e4420) 0 + +Class QSemaphore + size=8 align=8 + base size=8 base align=8 +QSemaphore (0x0x7efe990e4480) 0 + +Class QThread::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThread::QPrivateSignal (0x0x7efe990e4540) 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 (0x0x7efe990cd5b0) 0 + vptr=((& QThread::_ZTV7QThread) + 16u) + QObject (0x0x7efe990e44e0) 0 + primary-for QThread (0x0x7efe990cd5b0) + +Class QThreadPool::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThreadPool::QPrivateSignal (0x0x7efe990e4600) 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 (0x0x7efe990cd618) 0 + vptr=((& QThreadPool::_ZTV11QThreadPool) + 16u) + QObject (0x0x7efe990e45a0) 0 + primary-for QThreadPool (0x0x7efe990cd618) + +Class QThreadStorageData + size=4 align=4 + base size=4 base align=4 +QThreadStorageData (0x0x7efe990e4660) 0 + +Class QWaitCondition + size=8 align=8 + base size=8 base align=8 +QWaitCondition (0x0x7efe990e4720) 0 + +Class QBitArray + size=8 align=8 + base size=8 base align=8 +QBitArray (0x0x7efe990e4c00) 0 + +Class QBitRef + size=16 align=8 + base size=12 base align=8 +QBitRef (0x0x7efe990e4de0) 0 + +Class QByteArrayMatcher::Data + size=272 align=8 + base size=272 base align=8 +QByteArrayMatcher::Data (0x0x7efe98e67060) 0 + +Class QByteArrayMatcher + size=1040 align=8 + base size=1040 base align=8 +QByteArrayMatcher (0x0x7efe98e67000) 0 + +Class QCollatorSortKey + size=8 align=8 + base size=8 base align=8 +QCollatorSortKey (0x0x7efe98e671e0) 0 + +Class QCollator + size=8 align=8 + base size=8 base align=8 +QCollator (0x0x7efe98e672a0) 0 + +Class QCommandLineOption + size=8 align=8 + base size=8 base align=8 +QCommandLineOption (0x0x7efe98e67540) 0 + +Class QCommandLineParser + size=8 align=8 + base size=8 base align=8 +QCommandLineParser (0x0x7efe98e67720) 0 + +Class QCryptographicHash + size=8 align=8 + base size=8 base align=8 +QCryptographicHash (0x0x7efe98e67780) 0 + +Class QElapsedTimer + size=16 align=8 + base size=16 base align=8 +QElapsedTimer (0x0x7efe98e677e0) 0 + +Class QPoint + size=8 align=4 + base size=8 base align=4 +QPoint (0x0x7efe98e67840) 0 + +Class QPointF + size=16 align=8 + base size=16 base align=8 +QPointF (0x0x7efe98e679c0) 0 + +Class QLine + size=16 align=4 + base size=16 base align=4 +QLine (0x0x7efe98e67b40) 0 + +Class QLineF + size=32 align=8 + base size=32 base align=8 +QLineF (0x0x7efe98e67cc0) 0 + +Class QLinkedListData + size=32 align=8 + base size=32 base align=8 +QLinkedListData (0x0x7efe98e67e40) 0 + +Class QMargins + size=16 align=4 + base size=16 base align=4 +QMargins (0x0x7efe98bba600) 0 + +Class QMarginsF + size=32 align=8 + base size=32 base align=8 +QMarginsF (0x0x7efe98bba780) 0 + +Class QMessageAuthenticationCode + size=8 align=8 + base size=8 base align=8 +QMessageAuthenticationCode (0x0x7efe98bba900) 0 + +Class QSize + size=8 align=4 + base size=8 base align=4 +QSize (0x0x7efe98bba9c0) 0 + +Class QSizeF + size=16 align=8 + base size=16 base align=8 +QSizeF (0x0x7efe98bbac00) 0 + +Class QRect + size=16 align=4 + base size=16 base align=4 +QRect (0x0x7efe98bbae40) 0 + +Class QRectF + size=32 align=8 + base size=32 base align=8 +QRectF (0x0x7efe9891d000) 0 + +Class QRegularExpression + size=8 align=8 + base size=8 base align=8 +QRegularExpression (0x0x7efe9891d180) 0 + +Class QRegularExpressionMatch + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatch (0x0x7efe9891d4e0) 0 + +Class QRegularExpressionMatchIterator + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatchIterator (0x0x7efe9891d6c0) 0 + +Class QAbstractConcatenable + size=1 align=1 + base size=0 base align=1 +QAbstractConcatenable (0x0x7efe9891da80) 0 empty + +Class QTextBoundaryFinder + size=48 align=8 + base size=48 base align=8 +QTextBoundaryFinder (0x0x7efe98a614e0) 0 + +Class QTimeLine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimeLine::QPrivateSignal (0x0x7efe98a61660) 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 (0x0x7efe98a31958) 0 + vptr=((& QTimeLine::_ZTV9QTimeLine) + 16u) + QObject (0x0x7efe98a61600) 0 + primary-for QTimeLine (0x0x7efe98a31958) + +Class QTimeZone::OffsetData + size=32 align=8 + base size=28 base align=8 +QTimeZone::OffsetData (0x0x7efe98a61720) 0 + +Class QTimeZone + size=8 align=8 + base size=8 base align=8 +QTimeZone (0x0x7efe98a616c0) 0 + +Class QVersionNumber::SegmentStorage + size=8 align=8 + base size=8 base align=8 +QVersionNumber::SegmentStorage (0x0x7efe98a61a80) 0 + +Class QVersionNumber + size=8 align=8 + base size=8 base align=8 +QVersionNumber (0x0x7efe98a61a20) 0 + +Class QXmlStreamStringRef + size=16 align=8 + base size=16 base align=8 +QXmlStreamStringRef (0x0x7efe98a61d80) 0 + +Class QXmlStreamAttribute + size=80 align=8 + base size=73 base align=8 +QXmlStreamAttribute (0x0x7efe98a61f00) 0 + +Class QXmlStreamAttributes + size=8 align=8 + base size=8 base align=8 +QXmlStreamAttributes (0x0x7efe98a31dd0) 0 + QVector (0x0x7efe98782180) 0 + +Class QXmlStreamNamespaceDeclaration + size=40 align=8 + base size=40 base align=8 +QXmlStreamNamespaceDeclaration (0x0x7efe987821e0) 0 + +Class QXmlStreamNotationDeclaration + size=56 align=8 + base size=56 base align=8 +QXmlStreamNotationDeclaration (0x0x7efe98782360) 0 + +Class QXmlStreamEntityDeclaration + size=88 align=8 + base size=88 base align=8 +QXmlStreamEntityDeclaration (0x0x7efe987824e0) 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 (0x0x7efe98782660) 0 nearly-empty + vptr=((& QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver) + 16u) + +Class QXmlStreamReader + size=8 align=8 + base size=8 base align=8 +QXmlStreamReader (0x0x7efe987826c0) 0 + +Class QXmlStreamWriter + size=8 align=8 + base size=8 base align=8 +QXmlStreamWriter (0x0x7efe987827e0) 0 + +Class QBluetoothAddress + size=8 align=8 + base size=8 base align=8 +QBluetoothAddress (0x0x7efe987829c0) 0 + +Class QBluetoothDeviceInfo + size=8 align=8 + base size=8 base align=8 +QBluetoothDeviceInfo (0x0x7efe98782b40) 0 + +Class QBluetoothDeviceDiscoveryAgent::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothDeviceDiscoveryAgent::QPrivateSignal (0x0x7efe98782ea0) 0 empty + +Vtable for QBluetoothDeviceDiscoveryAgent +QBluetoothDeviceDiscoveryAgent::_ZTV30QBluetoothDeviceDiscoveryAgent: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI30QBluetoothDeviceDiscoveryAgent) +16 (int (*)(...))QBluetoothDeviceDiscoveryAgent::metaObject +24 (int (*)(...))QBluetoothDeviceDiscoveryAgent::qt_metacast +32 (int (*)(...))QBluetoothDeviceDiscoveryAgent::qt_metacall +40 (int (*)(...))QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent +48 (int (*)(...))QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent +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 QBluetoothDeviceDiscoveryAgent + size=24 align=8 + base size=24 base align=8 +QBluetoothDeviceDiscoveryAgent (0x0x7efe9883c208) 0 + vptr=((& QBluetoothDeviceDiscoveryAgent::_ZTV30QBluetoothDeviceDiscoveryAgent) + 16u) + QObject (0x0x7efe98782e40) 0 + primary-for QBluetoothDeviceDiscoveryAgent (0x0x7efe9883c208) + +Class QBluetoothHostInfo + size=8 align=8 + base size=8 base align=8 +QBluetoothHostInfo (0x0x7efe98782f00) 0 + +Class QBluetoothLocalDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothLocalDevice::QPrivateSignal (0x0x7efe988e3120) 0 empty + +Vtable for QBluetoothLocalDevice +QBluetoothLocalDevice::_ZTV21QBluetoothLocalDevice: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QBluetoothLocalDevice) +16 (int (*)(...))QBluetoothLocalDevice::metaObject +24 (int (*)(...))QBluetoothLocalDevice::qt_metacast +32 (int (*)(...))QBluetoothLocalDevice::qt_metacall +40 (int (*)(...))QBluetoothLocalDevice::~QBluetoothLocalDevice +48 (int (*)(...))QBluetoothLocalDevice::~QBluetoothLocalDevice +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 QBluetoothLocalDevice + size=24 align=8 + base size=24 base align=8 +QBluetoothLocalDevice (0x0x7efe9883c270) 0 + vptr=((& QBluetoothLocalDevice::_ZTV21QBluetoothLocalDevice) + 16u) + QObject (0x0x7efe988e30c0) 0 + primary-for QBluetoothLocalDevice (0x0x7efe9883c270) + +Class quint128 + size=16 align=1 + base size=16 base align=1 +quint128 (0x0x7efe988e34e0) 0 + +Class QBluetoothUuid + size=16 align=4 + base size=16 base align=4 +QBluetoothUuid (0x0x7efe9883c2d8) 0 + QUuid (0x0x7efe988e3540) 0 + +Class QBluetoothServiceInfo::Sequence + size=8 align=8 + base size=8 base align=8 +QBluetoothServiceInfo::Sequence (0x0x7efe9883c340) 0 + QList (0x0x7efe9883c3a8) 0 + QListSpecialMethods (0x0x7efe988e3780) 0 empty + +Class QBluetoothServiceInfo::Alternative + size=8 align=8 + base size=8 base align=8 +QBluetoothServiceInfo::Alternative (0x0x7efe9883c410) 0 + QList (0x0x7efe9883c478) 0 + QListSpecialMethods (0x0x7efe988e37e0) 0 empty + +Class QBluetoothServiceInfo + size=16 align=8 + base size=16 base align=8 +QBluetoothServiceInfo (0x0x7efe988e3720) 0 + +Class QAbstractSocket::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractSocket::QPrivateSignal (0x0x7efe988e3c60) 0 empty + +Vtable for QAbstractSocket +QAbstractSocket::_ZTV15QAbstractSocket: 41u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QAbstractSocket) +16 (int (*)(...))QAbstractSocket::metaObject +24 (int (*)(...))QAbstractSocket::qt_metacast +32 (int (*)(...))QAbstractSocket::qt_metacall +40 (int (*)(...))QAbstractSocket::~QAbstractSocket +48 (int (*)(...))QAbstractSocket::~QAbstractSocket +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 (*)(...))QAbstractSocket::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QAbstractSocket::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QAbstractSocket::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QAbstractSocket::bytesAvailable +184 (int (*)(...))QAbstractSocket::bytesToWrite +192 (int (*)(...))QAbstractSocket::canReadLine +200 (int (*)(...))QAbstractSocket::waitForReadyRead +208 (int (*)(...))QAbstractSocket::waitForBytesWritten +216 (int (*)(...))QAbstractSocket::readData +224 (int (*)(...))QAbstractSocket::readLineData +232 (int (*)(...))QAbstractSocket::writeData +240 (int (*)(...))QAbstractSocket::resume +248 (int (*)(...))QAbstractSocket::connectToHost +256 (int (*)(...))QAbstractSocket::connectToHost +264 (int (*)(...))QAbstractSocket::disconnectFromHost +272 (int (*)(...))QAbstractSocket::setReadBufferSize +280 (int (*)(...))QAbstractSocket::socketDescriptor +288 (int (*)(...))QAbstractSocket::setSocketDescriptor +296 (int (*)(...))QAbstractSocket::setSocketOption +304 (int (*)(...))QAbstractSocket::socketOption +312 (int (*)(...))QAbstractSocket::waitForConnected +320 (int (*)(...))QAbstractSocket::waitForDisconnected + +Class QAbstractSocket + size=16 align=8 + base size=16 base align=8 +QAbstractSocket (0x0x7efe9883c6e8) 0 + vptr=((& QAbstractSocket::_ZTV15QAbstractSocket) + 16u) + QIODevice (0x0x7efe9883c750) 0 + primary-for QAbstractSocket (0x0x7efe9883c6e8) + QObject (0x0x7efe988e3c00) 0 + primary-for QIODevice (0x0x7efe9883c750) + +Class QBluetoothSocket::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothSocket::QPrivateSignal (0x0x7efe9861d120) 0 empty + +Vtable for QBluetoothSocket +QBluetoothSocket::_ZTV16QBluetoothSocket: 30u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QBluetoothSocket) +16 (int (*)(...))QBluetoothSocket::metaObject +24 (int (*)(...))QBluetoothSocket::qt_metacast +32 (int (*)(...))QBluetoothSocket::qt_metacall +40 (int (*)(...))QBluetoothSocket::~QBluetoothSocket +48 (int (*)(...))QBluetoothSocket::~QBluetoothSocket +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 (*)(...))QBluetoothSocket::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QBluetoothSocket::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QIODevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QBluetoothSocket::bytesAvailable +184 (int (*)(...))QBluetoothSocket::bytesToWrite +192 (int (*)(...))QBluetoothSocket::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QBluetoothSocket::readData +224 (int (*)(...))QIODevice::readLineData +232 (int (*)(...))QBluetoothSocket::writeData + +Class QBluetoothSocket + size=24 align=8 + base size=24 base align=8 +QBluetoothSocket (0x0x7efe9883c958) 0 + vptr=((& QBluetoothSocket::_ZTV16QBluetoothSocket) + 16u) + QIODevice (0x0x7efe9883c9c0) 0 + primary-for QBluetoothSocket (0x0x7efe9883c958) + QObject (0x0x7efe9861d0c0) 0 + primary-for QIODevice (0x0x7efe9883c9c0) + +Class QBluetoothServer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothServer::QPrivateSignal (0x0x7efe9861d1e0) 0 empty + +Vtable for QBluetoothServer +QBluetoothServer::_ZTV16QBluetoothServer: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QBluetoothServer) +16 (int (*)(...))QBluetoothServer::metaObject +24 (int (*)(...))QBluetoothServer::qt_metacast +32 (int (*)(...))QBluetoothServer::qt_metacall +40 (int (*)(...))QBluetoothServer::~QBluetoothServer +48 (int (*)(...))QBluetoothServer::~QBluetoothServer +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 QBluetoothServer + size=24 align=8 + base size=24 base align=8 +QBluetoothServer (0x0x7efe9883ca28) 0 + vptr=((& QBluetoothServer::_ZTV16QBluetoothServer) + 16u) + QObject (0x0x7efe9861d180) 0 + primary-for QBluetoothServer (0x0x7efe9883ca28) + +Class QBluetoothServiceDiscoveryAgent::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothServiceDiscoveryAgent::QPrivateSignal (0x0x7efe9861d2a0) 0 empty + +Vtable for QBluetoothServiceDiscoveryAgent +QBluetoothServiceDiscoveryAgent::_ZTV31QBluetoothServiceDiscoveryAgent: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI31QBluetoothServiceDiscoveryAgent) +16 (int (*)(...))QBluetoothServiceDiscoveryAgent::metaObject +24 (int (*)(...))QBluetoothServiceDiscoveryAgent::qt_metacast +32 (int (*)(...))QBluetoothServiceDiscoveryAgent::qt_metacall +40 (int (*)(...))QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent +48 (int (*)(...))QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent +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 QBluetoothServiceDiscoveryAgent + size=24 align=8 + base size=24 base align=8 +QBluetoothServiceDiscoveryAgent (0x0x7efe9883ca90) 0 + vptr=((& QBluetoothServiceDiscoveryAgent::_ZTV31QBluetoothServiceDiscoveryAgent) + 16u) + QObject (0x0x7efe9861d240) 0 + primary-for QBluetoothServiceDiscoveryAgent (0x0x7efe9883ca90) + +Class QBluetoothTransferManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothTransferManager::QPrivateSignal (0x0x7efe9861d360) 0 empty + +Vtable for QBluetoothTransferManager +QBluetoothTransferManager::_ZTV25QBluetoothTransferManager: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI25QBluetoothTransferManager) +16 (int (*)(...))QBluetoothTransferManager::metaObject +24 (int (*)(...))QBluetoothTransferManager::qt_metacast +32 (int (*)(...))QBluetoothTransferManager::qt_metacall +40 (int (*)(...))QBluetoothTransferManager::~QBluetoothTransferManager +48 (int (*)(...))QBluetoothTransferManager::~QBluetoothTransferManager +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 QBluetoothTransferManager + size=16 align=8 + base size=16 base align=8 +QBluetoothTransferManager (0x0x7efe9883caf8) 0 + vptr=((& QBluetoothTransferManager::_ZTV25QBluetoothTransferManager) + 16u) + QObject (0x0x7efe9861d300) 0 + primary-for QBluetoothTransferManager (0x0x7efe9883caf8) + +Class QBluetoothTransferRequest + size=8 align=8 + base size=8 base align=8 +QBluetoothTransferRequest (0x0x7efe9861d3c0) 0 + +Class QBluetoothTransferReply::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothTransferReply::QPrivateSignal (0x0x7efe9861d480) 0 empty + +Vtable for QBluetoothTransferReply +QBluetoothTransferReply::_ZTV23QBluetoothTransferReply: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI23QBluetoothTransferReply) +16 (int (*)(...))QBluetoothTransferReply::metaObject +24 (int (*)(...))QBluetoothTransferReply::qt_metacast +32 (int (*)(...))QBluetoothTransferReply::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 + +Class QBluetoothTransferReply + size=24 align=8 + base size=24 base align=8 +QBluetoothTransferReply (0x0x7efe9883cb60) 0 + vptr=((& QBluetoothTransferReply::_ZTV23QBluetoothTransferReply) + 16u) + QObject (0x0x7efe9861d420) 0 + primary-for QBluetoothTransferReply (0x0x7efe9883cb60) + +Class QLowEnergyDescriptor + size=24 align=8 + base size=24 base align=8 +QLowEnergyDescriptor (0x0x7efe9861d600) 0 + +Class QLowEnergyCharacteristic + size=24 align=8 + base size=24 base align=8 +QLowEnergyCharacteristic (0x0x7efe9861d6c0) 0 + +Class QLowEnergyService::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLowEnergyService::QPrivateSignal (0x0x7efe9861d840) 0 empty + +Vtable for QLowEnergyService +QLowEnergyService::_ZTV17QLowEnergyService: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QLowEnergyService) +16 (int (*)(...))QLowEnergyService::metaObject +24 (int (*)(...))QLowEnergyService::qt_metacast +32 (int (*)(...))QLowEnergyService::qt_metacall +40 (int (*)(...))QLowEnergyService::~QLowEnergyService +48 (int (*)(...))QLowEnergyService::~QLowEnergyService +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 QLowEnergyService + size=32 align=8 + base size=32 base align=8 +QLowEnergyService (0x0x7efe9883cc98) 0 + vptr=((& QLowEnergyService::_ZTV17QLowEnergyService) + 16u) + QObject (0x0x7efe9861d7e0) 0 + primary-for QLowEnergyService (0x0x7efe9883cc98) + +Class QLowEnergyController::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLowEnergyController::QPrivateSignal (0x0x7efe9861de40) 0 empty + +Vtable for QLowEnergyController +QLowEnergyController::_ZTV20QLowEnergyController: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI20QLowEnergyController) +16 (int (*)(...))QLowEnergyController::metaObject +24 (int (*)(...))QLowEnergyController::qt_metacast +32 (int (*)(...))QLowEnergyController::qt_metacall +40 (int (*)(...))QLowEnergyController::~QLowEnergyController +48 (int (*)(...))QLowEnergyController::~QLowEnergyController +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 QLowEnergyController + size=24 align=8 + base size=24 base align=8 +QLowEnergyController (0x0x7efe9883cdd0) 0 + vptr=((& QLowEnergyController::_ZTV20QLowEnergyController) + 16u) + QObject (0x0x7efe9861dde0) 0 + primary-for QLowEnergyController (0x0x7efe9883cdd0) + diff --git a/tests/auto/bic/data/QtBluetooth.5.7.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtBluetooth.5.7.0.linux-gcc-amd64.txt new file mode 100644 index 0000000..ab85793 --- /dev/null +++ b/tests/auto/bic/data/QtBluetooth.5.7.0.linux-gcc-amd64.txt @@ -0,0 +1,4627 @@ +Class std::__failure_type + size=1 align=1 + base size=0 base align=1 +std::__failure_type (0x0x7fcf671b16c0) 0 empty + +Class std::__do_is_destructible_impl + size=1 align=1 + base size=0 base align=1 +std::__do_is_destructible_impl (0x0x7fcf67208e40) 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 (0x0x7fcf672320c0) 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 (0x0x7fcf67232300) 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 (0x0x7fcf67232540) 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 (0x0x7fcf672326c0) 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 (0x0x7fcf67232a80) 0 empty + +Class std::__do_common_type_impl + size=1 align=1 + base size=0 base align=1 +std::__do_common_type_impl (0x0x7fcf64eee240) 0 empty + +Class std::__do_member_type_wrapper + size=1 align=1 + base size=0 base align=1 +std::__do_member_type_wrapper (0x0x7fcf64eee300) 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 (0x0x7fcf64eee660) 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 (0x0x7fcf64eee720) 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 (0x0x7fcf64eee7e0) 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 (0x0x7fcf64eee8a0) 0 empty + +Class std::__result_of_other_impl + size=1 align=1 + base size=0 base align=1 +std::__result_of_other_impl (0x0x7fcf64eeeb40) 0 empty + +Class std::piecewise_construct_t + size=1 align=1 + base size=0 base align=1 +std::piecewise_construct_t (0x0x7fcf64eeecc0) 0 empty + +Class std::__true_type + size=1 align=1 + base size=0 base align=1 +std::__true_type (0x0x7fcf64f67180) 0 empty + +Class std::__false_type + size=1 align=1 + base size=0 base align=1 +std::__false_type (0x0x7fcf64f671e0) 0 empty + +Class std::input_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::input_iterator_tag (0x0x7fcf64fa1e40) 0 empty + +Class std::output_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::output_iterator_tag (0x0x7fcf64fa1ea0) 0 empty + +Class std::forward_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::forward_iterator_tag (0x0x7fcf64f5f1a0) 0 empty + std::input_iterator_tag (0x0x7fcf64fa1f00) 0 empty + +Class std::bidirectional_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::bidirectional_iterator_tag (0x0x7fcf64f5f208) 0 empty + std::forward_iterator_tag (0x0x7fcf64f5f270) 0 empty + std::input_iterator_tag (0x0x7fcf64fa1f60) 0 empty + +Class std::random_access_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::random_access_iterator_tag (0x0x7fcf64f5f2d8) 0 empty + std::bidirectional_iterator_tag (0x0x7fcf64f5f340) 0 empty + std::forward_iterator_tag (0x0x7fcf64f5f3a8) 0 empty + std::input_iterator_tag (0x0x7fcf64fcf000) 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 (0x0x7fcf64fcfc60) 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 (0x0x7fcf64fcfcc0) 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 (0x0x7fcf64fcfd20) 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 (0x0x7fcf64fcfd80) 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 (0x0x7fcf64fcfde0) 0 empty + +Class wait + size=4 align=4 + base size=4 base align=4 +wait (0x0x7fcf64c9d900) 0 + +Class __locale_struct + size=232 align=8 + base size=232 base align=8 +__locale_struct (0x0x7fcf64c9db40) 0 + +Class timespec + size=16 align=8 + base size=16 base align=8 +timespec (0x0x7fcf64c9dc00) 0 + +Class timeval + size=16 align=8 + base size=16 base align=8 +timeval (0x0x7fcf64c9dc60) 0 + +Class pthread_attr_t + size=56 align=8 + base size=56 base align=8 +pthread_attr_t (0x0x7fcf64c9dd20) 0 + +Class __pthread_internal_list + size=16 align=8 + base size=16 base align=8 +__pthread_internal_list (0x0x7fcf64c9dd80) 0 + +Class random_data + size=48 align=8 + base size=48 base align=8 +random_data (0x0x7fcf64d40240) 0 + +Class drand48_data + size=24 align=8 + base size=24 base align=8 +drand48_data (0x0x7fcf64d402a0) 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 (0x0x7fcf64d40300) 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 (0x0x7fcf64f5f8f0) 0 nearly-empty + vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16u) + std::exception (0x0x7fcf64d40360) 0 nearly-empty + primary-for std::bad_exception (0x0x7fcf64f5f8f0) + +Class std::__exception_ptr::exception_ptr + size=8 align=8 + base size=8 base align=8 +std::__exception_ptr::exception_ptr (0x0x7fcf64d403c0) 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 (0x0x7fcf64d40420) 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 (0x0x7fcf64f5faf8) 0 nearly-empty + vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16u) + std::exception (0x0x7fcf64d40840) 0 nearly-empty + primary-for std::bad_alloc (0x0x7fcf64f5faf8) + +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 (0x0x7fcf64f5fb60) 0 nearly-empty + vptr=((& std::bad_array_new_length::_ZTVSt20bad_array_new_length) + 16u) + std::bad_alloc (0x0x7fcf64f5fbc8) 0 nearly-empty + primary-for std::bad_array_new_length (0x0x7fcf64f5fb60) + std::exception (0x0x7fcf64d408a0) 0 nearly-empty + primary-for std::bad_alloc (0x0x7fcf64f5fbc8) + +Class std::nothrow_t + size=1 align=1 + base size=0 base align=1 +std::nothrow_t (0x0x7fcf64d40900) 0 empty + +Class __exception + size=40 align=8 + base size=40 base align=8 +__exception (0x0x7fcf64ab7540) 0 + +Class lconv + size=96 align=8 + base size=96 base align=8 +lconv (0x0x7fcf648ce240) 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 (0x0x7fcf648ce2a0) 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 (0x0x7fcf6496f180) 0 + +Class __sched_param + size=4 align=4 + base size=4 base align=4 +__sched_param (0x0x7fcf6496f1e0) 0 + +Class timex + size=208 align=8 + base size=208 base align=8 +timex (0x0x7fcf6496f2a0) 0 + +Class tm + size=56 align=8 + base size=56 base align=8 +tm (0x0x7fcf6496f300) 0 + +Class itimerspec + size=32 align=8 + base size=32 base align=8 +itimerspec (0x0x7fcf6496f360) 0 + +Class _pthread_cleanup_buffer + size=32 align=8 + base size=32 base align=8 +_pthread_cleanup_buffer (0x0x7fcf6496f3c0) 0 + +Class __pthread_cleanup_frame + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_frame (0x0x7fcf6496f4e0) 0 + +Class __pthread_cleanup_class + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_class (0x0x7fcf6496f540) 0 + +Class _IO_marker + size=24 align=8 + base size=24 base align=8 +_IO_marker (0x0x7fcf6496f960) 0 + +Class _IO_FILE + size=216 align=8 + base size=216 base align=8 +_IO_FILE (0x0x7fcf6496f9c0) 0 + +Class std::_Hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Hash_impl (0x0x7fcf6449d1e0) 0 empty + +Class std::_Fnv_hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Fnv_hash_impl (0x0x7fcf6449d240) 0 empty + +Class std::__numeric_limits_base + size=1 align=1 + base size=0 base align=1 +std::__numeric_limits_base (0x0x7fcf645781e0) 0 empty + +Class std::_Bit_reference + size=16 align=8 + base size=16 base align=8 +std::_Bit_reference (0x0x7fcf64384000) 0 + +Class std::_Bit_iterator_base + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator_base (0x0x7fcf644b9958) 0 + std::iterator (0x0x7fcf643840c0) 0 empty + +Class std::_Bit_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator (0x0x7fcf644b99c0) 0 + std::_Bit_iterator_base (0x0x7fcf644b9a28) 0 + std::iterator (0x0x7fcf64384120) 0 empty + +Class std::_Bit_const_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_const_iterator (0x0x7fcf644b9a90) 0 + std::_Bit_iterator_base (0x0x7fcf644b9af8) 0 + std::iterator (0x0x7fcf64384180) 0 empty + +Class std::random_device + size=5000 align=8 + base size=5000 base align=8 +std::random_device (0x0x7fcf64384f60) 0 + +Class std::bernoulli_distribution::param_type + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution::param_type (0x0x7fcf64160d20) 0 + +Class std::bernoulli_distribution + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution (0x0x7fcf64160cc0) 0 + +Class std::seed_seq + size=24 align=8 + base size=24 base align=8 +std::seed_seq (0x0x7fcf63e91cc0) 0 + +Class qIsNull(double)::U + size=8 align=8 + base size=8 base align=8 +qIsNull(double)::U (0x0x7fcf62aaa780) 0 + +Class qIsNull(float)::U + size=4 align=4 + base size=4 base align=4 +qIsNull(float)::U (0x0x7fcf62aaa7e0) 0 + +Class QtPrivate::big_ + size=2 align=1 + base size=2 base align=1 +QtPrivate::big_ (0x0x7fcf62aaaba0) 0 + +Class QSysInfo + size=1 align=1 + base size=0 base align=1 +QSysInfo (0x0x7fcf62bc50c0) 0 empty + +Class QMessageLogContext + size=32 align=8 + base size=32 base align=8 +QMessageLogContext (0x0x7fcf62bc5120) 0 + +Class QMessageLogger + size=32 align=8 + base size=32 base align=8 +QMessageLogger (0x0x7fcf62bc5180) 0 + +Class QFlag + size=4 align=4 + base size=4 base align=4 +QFlag (0x0x7fcf62bc51e0) 0 + +Class QIncompatibleFlag + size=4 align=4 + base size=4 base align=4 +QIncompatibleFlag (0x0x7fcf62bc5360) 0 + +Class std::__atomic_flag_base + size=1 align=1 + base size=1 base align=1 +std::__atomic_flag_base (0x0x7fcf62bc5780) 0 + +Class std::atomic_flag + size=1 align=1 + base size=1 base align=1 +std::atomic_flag (0x0x7fcf62b68b60) 0 + std::__atomic_flag_base (0x0x7fcf62bc57e0) 0 + +Class QAtomicInt + size=4 align=4 + base size=4 base align=4 +QAtomicInt (0x0x7fcf626af2d8) 0 + QAtomicInteger (0x0x7fcf626af340) 0 + QBasicAtomicInteger (0x0x7fcf62984d20) 0 + +Class QInternal + size=1 align=1 + base size=0 base align=1 +QInternal (0x0x7fcf62600600) 0 empty + +Class QGenericArgument + size=16 align=8 + base size=16 base align=8 +QGenericArgument (0x0x7fcf624054e0) 0 + +Class QGenericReturnArgument + size=16 align=8 + base size=16 base align=8 +QGenericReturnArgument (0x0x7fcf625df5b0) 0 + QGenericArgument (0x0x7fcf62405540) 0 + +Class QMetaObject + size=48 align=8 + base size=48 base align=8 +QMetaObject (0x0x7fcf624056c0) 0 + +Class QMetaObject::Connection + size=8 align=8 + base size=8 base align=8 +QMetaObject::Connection (0x0x7fcf62405780) 0 + +Class QLatin1Char + size=1 align=1 + base size=1 base align=1 +QLatin1Char (0x0x7fcf620c67e0) 0 + +Class QChar + size=2 align=2 + base size=2 base align=2 +QChar (0x0x7fcf620c6840) 0 + +Class QtPrivate::RefCount + size=4 align=4 + base size=4 base align=4 +QtPrivate::RefCount (0x0x7fcf620c69c0) 0 + +Class QArrayData + size=24 align=8 + base size=24 base align=8 +QArrayData (0x0x7fcf620c6a80) 0 + +Class QtPrivate::QContainerImplHelper + size=1 align=1 + base size=0 base align=1 +QtPrivate::QContainerImplHelper (0x0x7fcf620c6ea0) 0 empty + +Class std::locale + size=8 align=8 + base size=8 base align=8 +std::locale (0x0x7fcf620c6f00) 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 (0x0x7fcf620c6f60) 0 + vptr=((& std::locale::facet::_ZTVNSt6locale5facetE) + 16u) + +Class std::locale::id + size=8 align=8 + base size=8 base align=8 +std::locale::id (0x0x7fcf621fa000) 0 + +Class std::locale::_Impl + size=40 align=8 + base size=40 base align=8 +std::locale::_Impl (0x0x7fcf621fa060) 0 + +Class std::__cow_string + size=8 align=8 + base size=8 base align=8 +std::__cow_string (0x0x7fcf621fa420) 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 (0x0x7fcf6218fa28) 0 + vptr=((& std::logic_error::_ZTVSt11logic_error) + 16u) + std::exception (0x0x7fcf621fa4e0) 0 nearly-empty + primary-for std::logic_error (0x0x7fcf6218fa28) + +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 (0x0x7fcf6218fa90) 0 + vptr=((& std::domain_error::_ZTVSt12domain_error) + 16u) + std::logic_error (0x0x7fcf6218faf8) 0 + primary-for std::domain_error (0x0x7fcf6218fa90) + std::exception (0x0x7fcf621fa540) 0 nearly-empty + primary-for std::logic_error (0x0x7fcf6218faf8) + +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 (0x0x7fcf6218fb60) 0 + vptr=((& std::invalid_argument::_ZTVSt16invalid_argument) + 16u) + std::logic_error (0x0x7fcf6218fbc8) 0 + primary-for std::invalid_argument (0x0x7fcf6218fb60) + std::exception (0x0x7fcf621fa5a0) 0 nearly-empty + primary-for std::logic_error (0x0x7fcf6218fbc8) + +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 (0x0x7fcf6218fc30) 0 + vptr=((& std::length_error::_ZTVSt12length_error) + 16u) + std::logic_error (0x0x7fcf6218fc98) 0 + primary-for std::length_error (0x0x7fcf6218fc30) + std::exception (0x0x7fcf621fa600) 0 nearly-empty + primary-for std::logic_error (0x0x7fcf6218fc98) + +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 (0x0x7fcf6218fd00) 0 + vptr=((& std::out_of_range::_ZTVSt12out_of_range) + 16u) + std::logic_error (0x0x7fcf6218fd68) 0 + primary-for std::out_of_range (0x0x7fcf6218fd00) + std::exception (0x0x7fcf621fa660) 0 nearly-empty + primary-for std::logic_error (0x0x7fcf6218fd68) + +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 (0x0x7fcf6218fdd0) 0 + vptr=((& std::runtime_error::_ZTVSt13runtime_error) + 16u) + std::exception (0x0x7fcf621fa6c0) 0 nearly-empty + primary-for std::runtime_error (0x0x7fcf6218fdd0) + +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 (0x0x7fcf6218fe38) 0 + vptr=((& std::range_error::_ZTVSt11range_error) + 16u) + std::runtime_error (0x0x7fcf6218fea0) 0 + primary-for std::range_error (0x0x7fcf6218fe38) + std::exception (0x0x7fcf621fa720) 0 nearly-empty + primary-for std::runtime_error (0x0x7fcf6218fea0) + +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 (0x0x7fcf6218ff08) 0 + vptr=((& std::overflow_error::_ZTVSt14overflow_error) + 16u) + std::runtime_error (0x0x7fcf6218ff70) 0 + primary-for std::overflow_error (0x0x7fcf6218ff08) + std::exception (0x0x7fcf621fa780) 0 nearly-empty + primary-for std::runtime_error (0x0x7fcf6218ff70) + +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 (0x0x7fcf6218f750) 0 + vptr=((& std::underflow_error::_ZTVSt15underflow_error) + 16u) + std::runtime_error (0x0x7fcf6218f820) 0 + primary-for std::underflow_error (0x0x7fcf6218f750) + std::exception (0x0x7fcf621fa7e0) 0 nearly-empty + primary-for std::runtime_error (0x0x7fcf6218f820) + +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 (0x0x7fcf621fa960) 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 (0x0x7fcf621faba0) 0 + +Class std::error_condition + size=16 align=8 + base size=16 base align=8 +std::error_condition (0x0x7fcf621fad20) 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 (0x0x7fcf61e88478) 0 + vptr=((& std::system_error::_ZTVSt12system_error) + 16u) + std::runtime_error (0x0x7fcf61e884e0) 0 + primary-for std::system_error (0x0x7fcf61e88478) + std::exception (0x0x7fcf621faf60) 0 nearly-empty + primary-for std::runtime_error (0x0x7fcf61e884e0) + +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 (0x0x7fcf61eff0d0) 0 + vptr=((& std::ios_base::failure::_ZTVNSt8ios_base7failureB5cxx11E) + 16u) + std::system_error (0x0x7fcf61eff138) 0 + primary-for std::ios_base::failure (0x0x7fcf61eff0d0) + std::runtime_error (0x0x7fcf61eff1a0) 0 + primary-for std::system_error (0x0x7fcf61eff138) + std::exception (0x0x7fcf61ee82a0) 0 nearly-empty + primary-for std::runtime_error (0x0x7fcf61eff1a0) + +Class std::ios_base::_Callback_list + size=24 align=8 + base size=24 base align=8 +std::ios_base::_Callback_list (0x0x7fcf61ee8300) 0 + +Class std::ios_base::_Words + size=16 align=8 + base size=16 base align=8 +std::ios_base::_Words (0x0x7fcf61ee8360) 0 + +Class std::ios_base::Init + size=1 align=1 + base size=0 base align=1 +std::ios_base::Init (0x0x7fcf61ee83c0) 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 (0x0x7fcf61ee8240) 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 (0x0x7fcf61ee8b40) 0 empty + +Class std::__num_base + size=1 align=1 + base size=0 base align=1 +std::__num_base (0x0x7fcf61c75240) 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 (0x0x7fcf61b65c30 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 (0x0x7fcf61b65d00 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 (0x0x7fcf61b651a0 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 (0x0x7fcf61b652d8 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 (0x0x7fcf61e2bae0) 0 + +Class QByteArray + size=8 align=8 + base size=8 base align=8 +QByteArray (0x0x7fcf61e2bb40) 0 + +Class QByteRef + size=16 align=8 + base size=12 base align=8 +QByteRef (0x0x7fcf618e3f60) 0 + +Class QLatin1String + size=16 align=8 + base size=16 base align=8 +QLatin1String (0x0x7fcf61979180) 0 + +Class QStringDataPtr + size=8 align=8 + base size=8 base align=8 +QStringDataPtr (0x0x7fcf619793c0) 0 + +Class QString::Null + size=1 align=1 + base size=0 base align=1 +QString::Null (0x0x7fcf61979480) 0 empty + +Class QString + size=8 align=8 + base size=8 base align=8 +QString (0x0x7fcf61979420) 0 + +Class QCharRef + size=16 align=8 + base size=12 base align=8 +QCharRef (0x0x7fcf61778420) 0 + +Class QStringRef + size=16 align=8 + base size=16 base align=8 +QStringRef (0x0x7fcf61778f60) 0 + +Class QtPrivate::QHashCombine + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombine (0x0x7fcf615223c0) 0 empty + +Class QtPrivate::QHashCombineCommutative + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombineCommutative (0x0x7fcf61522420) 0 empty + +Class std::__detail::_List_node_base + size=16 align=8 + base size=16 base align=8 +std::__detail::_List_node_base (0x0x7fcf61522480) 0 + +Class QListData::NotArrayCompatibleLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotArrayCompatibleLayout (0x0x7fcf61522840) 0 empty + +Class QListData::NotIndirectLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotIndirectLayout (0x0x7fcf615228a0) 0 empty + +Class QListData::ArrayCompatibleLayout + size=1 align=1 + base size=1 base align=1 +QListData::ArrayCompatibleLayout (0x0x7fcf612b1000) 0 empty + QListData::NotIndirectLayout (0x0x7fcf61522900) 0 empty + +Class QListData::InlineWithPaddingLayout + size=1 align=1 + base size=1 base align=1 +QListData::InlineWithPaddingLayout (0x0x7fcf612a9af0) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7fcf61522960) 0 empty + QListData::NotIndirectLayout (0x0x7fcf615229c0) 0 empty + +Class QListData::IndirectLayout + size=1 align=1 + base size=1 base align=1 +QListData::IndirectLayout (0x0x7fcf612b1068) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7fcf61522a20) 0 empty + +Class QListData::Data + size=24 align=8 + base size=24 base align=8 +QListData::Data (0x0x7fcf61522a80) 0 + +Class QListData + size=8 align=8 + base size=8 base align=8 +QListData (0x0x7fcf615227e0) 0 + +Class QRegExp + size=8 align=8 + base size=8 base align=8 +QRegExp (0x0x7fcf6133b660) 0 + +Class QStringMatcher::Data + size=272 align=8 + base size=272 base align=8 +QStringMatcher::Data (0x0x7fcf61459780) 0 + +Class QStringMatcher + size=1048 align=8 + base size=1048 base align=8 +QStringMatcher (0x0x7fcf61459720) 0 + +Class QStringList + size=8 align=8 + base size=8 base align=8 +QStringList (0x0x7fcf61458958) 0 + QList (0x0x7fcf614589c0) 0 + QListSpecialMethods (0x0x7fcf61459960) 0 empty + +Class QScopedPointerPodDeleter + size=1 align=1 + base size=0 base align=1 +QScopedPointerPodDeleter (0x0x7fcf61459c60) 0 empty + +Class std::_Rb_tree_node_base + size=32 align=8 + base size=32 base align=8 +std::_Rb_tree_node_base (0x0x7fcf6117b0c0) 0 + +Class std::allocator_arg_t + size=1 align=1 + base size=0 base align=1 +std::allocator_arg_t (0x0x7fcf6117b720) 0 empty + +Class std::__uses_alloc_base + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc_base (0x0x7fcf6117b8a0) 0 empty + +Class std::__uses_alloc0::_Sink + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc0::_Sink (0x0x7fcf6117b960) 0 empty + +Class std::__uses_alloc0 + size=1 align=1 + base size=1 base align=1 +std::__uses_alloc0 (0x0x7fcf611379c0) 0 + std::__uses_alloc_base (0x0x7fcf6117b900) 0 empty + +Class std::_Swallow_assign + size=1 align=1 + base size=0 base align=1 +std::_Swallow_assign (0x0x7fcf60fb29c0) 0 empty + +Class QtPrivate::AbstractDebugStreamFunction + size=16 align=8 + base size=16 base align=8 +QtPrivate::AbstractDebugStreamFunction (0x0x7fcf60fb2c00) 0 + +Class QtPrivate::AbstractComparatorFunction + size=24 align=8 + base size=24 base align=8 +QtPrivate::AbstractComparatorFunction (0x0x7fcf60fb2cc0) 0 + +Class QtPrivate::AbstractConverterFunction + size=8 align=8 + base size=8 base align=8 +QtPrivate::AbstractConverterFunction (0x0x7fcf60fb2de0) 0 + +Class QMetaType + size=80 align=8 + base size=80 base align=8 +QMetaType (0x0x7fcf60fb2f60) 0 + +Class QtMetaTypePrivate::VariantData + size=24 align=8 + base size=20 base align=8 +QtMetaTypePrivate::VariantData (0x0x7fcf60ce4360) 0 + +Class QtMetaTypePrivate::VectorBoolElements + size=1 align=1 + base size=0 base align=1 +QtMetaTypePrivate::VectorBoolElements (0x0x7fcf60ce4480) 0 empty + +Class QtMetaTypePrivate::QSequentialIterableImpl + size=104 align=8 + base size=104 base align=8 +QtMetaTypePrivate::QSequentialIterableImpl (0x0x7fcf60ce4de0) 0 + +Class QtMetaTypePrivate::QAssociativeIterableImpl + size=112 align=8 + base size=112 base align=8 +QtMetaTypePrivate::QAssociativeIterableImpl (0x0x7fcf60de71e0) 0 + +Class QtMetaTypePrivate::QPairVariantInterfaceImpl + size=40 align=8 + base size=40 base align=8 +QtMetaTypePrivate::QPairVariantInterfaceImpl (0x0x7fcf60de7420) 0 + +Class QtPrivate::QSlotObjectBase + size=16 align=8 + base size=16 base align=8 +QtPrivate::QSlotObjectBase (0x0x7fcf60bc0180) 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 (0x0x7fcf60bc0300) 0 + vptr=((& QObjectData::_ZTV11QObjectData) + 16u) + +Class QObject::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObject::QPrivateSignal (0x0x7fcf60bc04e0) 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 (0x0x7fcf60bc0480) 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 (0x0x7fcf60bc0840) 0 nearly-empty + vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16u) + +Class QSignalBlocker + size=16 align=8 + base size=10 base align=8 +QSignalBlocker (0x0x7fcf60bc08a0) 0 + +Class QAbstractAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractAnimation::QPrivateSignal (0x0x7fcf60bc0960) 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 (0x0x7fcf60be9340) 0 + vptr=((& QAbstractAnimation::_ZTV18QAbstractAnimation) + 16u) + QObject (0x0x7fcf60bc0900) 0 + primary-for QAbstractAnimation (0x0x7fcf60be9340) + +Class QAnimationDriver::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationDriver::QPrivateSignal (0x0x7fcf60bc0a20) 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 (0x0x7fcf60be93a8) 0 + vptr=((& QAnimationDriver::_ZTV16QAnimationDriver) + 16u) + QObject (0x0x7fcf60bc09c0) 0 + primary-for QAnimationDriver (0x0x7fcf60be93a8) + +Class QAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationGroup::QPrivateSignal (0x0x7fcf60bc0ae0) 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 (0x0x7fcf60be9410) 0 + vptr=((& QAnimationGroup::_ZTV15QAnimationGroup) + 16u) + QAbstractAnimation (0x0x7fcf60be9478) 0 + primary-for QAnimationGroup (0x0x7fcf60be9410) + QObject (0x0x7fcf60bc0a80) 0 + primary-for QAbstractAnimation (0x0x7fcf60be9478) + +Class QParallelAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QParallelAnimationGroup::QPrivateSignal (0x0x7fcf60bc0ba0) 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 (0x0x7fcf60be94e0) 0 + vptr=((& QParallelAnimationGroup::_ZTV23QParallelAnimationGroup) + 16u) + QAnimationGroup (0x0x7fcf60be9548) 0 + primary-for QParallelAnimationGroup (0x0x7fcf60be94e0) + QAbstractAnimation (0x0x7fcf60be95b0) 0 + primary-for QAnimationGroup (0x0x7fcf60be9548) + QObject (0x0x7fcf60bc0b40) 0 + primary-for QAbstractAnimation (0x0x7fcf60be95b0) + +Class QPauseAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPauseAnimation::QPrivateSignal (0x0x7fcf60bc0c60) 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 (0x0x7fcf60be9618) 0 + vptr=((& QPauseAnimation::_ZTV15QPauseAnimation) + 16u) + QAbstractAnimation (0x0x7fcf60be9680) 0 + primary-for QPauseAnimation (0x0x7fcf60be9618) + QObject (0x0x7fcf60bc0c00) 0 + primary-for QAbstractAnimation (0x0x7fcf60be9680) + +Class QEasingCurve + size=8 align=8 + base size=8 base align=8 +QEasingCurve (0x0x7fcf609be000) 0 + +Class QMapNodeBase + size=24 align=8 + base size=24 base align=8 +QMapNodeBase (0x0x7fcf60a4d0c0) 0 + +Class QMapDataBase + size=40 align=8 + base size=40 base align=8 +QMapDataBase (0x0x7fcf60a4d180) 0 + +Class QHashData::Node + size=16 align=8 + base size=16 base align=8 +QHashData::Node (0x0x7fcf60a4d540) 0 + +Class QHashData + size=48 align=8 + base size=44 base align=8 +QHashData (0x0x7fcf60a4d4e0) 0 + +Class QHashDummyValue + size=1 align=1 + base size=0 base align=1 +QHashDummyValue (0x0x7fcf60a4d5a0) 0 empty + +Class QVariant::PrivateShared + size=16 align=8 + base size=12 base align=8 +QVariant::PrivateShared (0x0x7fcf6046c000) 0 + +Class QVariant::Private::Data + size=8 align=8 + base size=8 base align=8 +QVariant::Private::Data (0x0x7fcf6046c0c0) 0 + +Class QVariant::Private + size=16 align=8 + base size=12 base align=8 +QVariant::Private (0x0x7fcf6046c060) 0 + +Class QVariant::Handler + size=72 align=8 + base size=72 base align=8 +QVariant::Handler (0x0x7fcf6046c120) 0 + +Class QVariant + size=16 align=8 + base size=16 base align=8 +QVariant (0x0x7fcf60a4df60) 0 + +Class QVariantComparisonHelper + size=8 align=8 + base size=8 base align=8 +QVariantComparisonHelper (0x0x7fcf60511420) 0 + +Class QSequentialIterable::const_iterator + size=112 align=8 + base size=112 base align=8 +QSequentialIterable::const_iterator (0x0x7fcf60511600) 0 + +Class QSequentialIterable + size=104 align=8 + base size=104 base align=8 +QSequentialIterable (0x0x7fcf605115a0) 0 + +Class QAssociativeIterable::const_iterator + size=120 align=8 + base size=120 base align=8 +QAssociativeIterable::const_iterator (0x0x7fcf605116c0) 0 + +Class QAssociativeIterable + size=112 align=8 + base size=112 base align=8 +QAssociativeIterable (0x0x7fcf60511660) 0 + +Class QVariantAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QVariantAnimation::QPrivateSignal (0x0x7fcf602a2060) 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 (0x0x7fcf60288c30) 0 + vptr=((& QVariantAnimation::_ZTV17QVariantAnimation) + 16u) + QAbstractAnimation (0x0x7fcf60288c98) 0 + primary-for QVariantAnimation (0x0x7fcf60288c30) + QObject (0x0x7fcf602a2000) 0 + primary-for QAbstractAnimation (0x0x7fcf60288c98) + +Class QPropertyAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPropertyAnimation::QPrivateSignal (0x0x7fcf602a2120) 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 (0x0x7fcf60288d68) 0 + vptr=((& QPropertyAnimation::_ZTV18QPropertyAnimation) + 16u) + QVariantAnimation (0x0x7fcf60288dd0) 0 + primary-for QPropertyAnimation (0x0x7fcf60288d68) + QAbstractAnimation (0x0x7fcf60288e38) 0 + primary-for QVariantAnimation (0x0x7fcf60288dd0) + QObject (0x0x7fcf602a20c0) 0 + primary-for QAbstractAnimation (0x0x7fcf60288e38) + +Class QSequentialAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSequentialAnimationGroup::QPrivateSignal (0x0x7fcf602a21e0) 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 (0x0x7fcf60288ea0) 0 + vptr=((& QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup) + 16u) + QAnimationGroup (0x0x7fcf60288f08) 0 + primary-for QSequentialAnimationGroup (0x0x7fcf60288ea0) + QAbstractAnimation (0x0x7fcf60288f70) 0 + primary-for QAnimationGroup (0x0x7fcf60288f08) + QObject (0x0x7fcf602a2180) 0 + primary-for QAbstractAnimation (0x0x7fcf60288f70) + +Class QTextCodec::ConverterState + size=32 align=8 + base size=32 base align=8 +QTextCodec::ConverterState (0x0x7fcf602a22a0) 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 (0x0x7fcf602a2240) 0 nearly-empty + vptr=((& QTextCodec::_ZTV10QTextCodec) + 16u) + +Class QTextEncoder + size=40 align=8 + base size=40 base align=8 +QTextEncoder (0x0x7fcf602a2420) 0 + +Class QTextDecoder + size=40 align=8 + base size=40 base align=8 +QTextDecoder (0x0x7fcf602a2480) 0 + +Class QSharedData + size=4 align=4 + base size=4 base align=4 +QSharedData (0x0x7fcf602a24e0) 0 + +Class QDate + size=8 align=8 + base size=8 base align=8 +QDate (0x0x7fcf602a26c0) 0 + +Class QTime + size=4 align=4 + base size=4 base align=4 +QTime (0x0x7fcf602a2840) 0 + +Class QDateTime + size=8 align=8 + base size=8 base align=8 +QDateTime (0x0x7fcf602a29c0) 0 + +Class QLibraryInfo + size=1 align=1 + base size=0 base align=1 +QLibraryInfo (0x0x7fcf602a2ba0) 0 empty + +Class QIODevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIODevice::QPrivateSignal (0x0x7fcf602a2c60) 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 (0x0x7fcf602e7208) 0 + vptr=((& QIODevice::_ZTV9QIODevice) + 16u) + QObject (0x0x7fcf602a2c00) 0 + primary-for QIODevice (0x0x7fcf602e7208) + +Class QBuffer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBuffer::QPrivateSignal (0x0x7fcf602a2e40) 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 (0x0x7fcf602e7340) 0 + vptr=((& QBuffer::_ZTV7QBuffer) + 16u) + QIODevice (0x0x7fcf602e73a8) 0 + primary-for QBuffer (0x0x7fcf602e7340) + QObject (0x0x7fcf602a2de0) 0 + primary-for QIODevice (0x0x7fcf602e73a8) + +Class QDataStream + size=32 align=8 + base size=32 base align=8 +QDataStream (0x0x7fcf602a2ea0) 0 + +Class QLocale + size=8 align=8 + base size=8 base align=8 +QLocale (0x0x7fcf602a2f60) 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 (0x0x7fcf601222a0) 0 + vptr=((& QTextStream::_ZTV11QTextStream) + 16u) + +Class QTextStreamManipulator + size=40 align=8 + base size=38 base align=8 +QTextStreamManipulator (0x0x7fcf601224e0) 0 + +Class QContiguousCacheData + size=24 align=4 + base size=24 base align=4 +QContiguousCacheData (0x0x7fcf60122720) 0 + +Class QtSharedPointer::NormalDeleter + size=1 align=1 + base size=0 base align=1 +QtSharedPointer::NormalDeleter (0x0x7fcf601229c0) 0 empty + +Class QtSharedPointer::ExternalRefCountData + size=16 align=8 + base size=16 base align=8 +QtSharedPointer::ExternalRefCountData (0x0x7fcf60122b40) 0 + +Class QDebug::Stream + size=80 align=8 + base size=76 base align=8 +QDebug::Stream (0x0x7fcf5ff27000) 0 + +Class QDebug + size=8 align=8 + base size=8 base align=8 +QDebug (0x0x7fcf60122f60) 0 + +Class QDebugStateSaver + size=8 align=8 + base size=8 base align=8 +QDebugStateSaver (0x0x7fcf5fc020c0) 0 + +Class QNoDebug + size=1 align=1 + base size=0 base align=1 +QNoDebug (0x0x7fcf5fc02180) 0 empty + +Class QFileDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileDevice::QPrivateSignal (0x0x7fcf5fc02240) 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 (0x0x7fcf5ffd12d8) 0 + vptr=((& QFileDevice::_ZTV11QFileDevice) + 16u) + QIODevice (0x0x7fcf5ffd1340) 0 + primary-for QFileDevice (0x0x7fcf5ffd12d8) + QObject (0x0x7fcf5fc021e0) 0 + primary-for QIODevice (0x0x7fcf5ffd1340) + +Class QFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFile::QPrivateSignal (0x0x7fcf5fc02420) 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 (0x0x7fcf5ffd1478) 0 + vptr=((& QFile::_ZTV5QFile) + 16u) + QFileDevice (0x0x7fcf5ffd14e0) 0 + primary-for QFile (0x0x7fcf5ffd1478) + QIODevice (0x0x7fcf5ffd1548) 0 + primary-for QFileDevice (0x0x7fcf5ffd14e0) + QObject (0x0x7fcf5fc023c0) 0 + primary-for QIODevice (0x0x7fcf5ffd1548) + +Class QFileInfo + size=8 align=8 + base size=8 base align=8 +QFileInfo (0x0x7fcf5fc025a0) 0 + +Class QDir + size=8 align=8 + base size=8 base align=8 +QDir (0x0x7fcf5fc028a0) 0 + +Class QDirIterator + size=8 align=8 + base size=8 base align=8 +QDirIterator (0x0x7fcf5fc02cc0) 0 + +Class QFileSelector::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSelector::QPrivateSignal (0x0x7fcf5fc02f00) 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 (0x0x7fcf5ffd1a28) 0 + vptr=((& QFileSelector::_ZTV13QFileSelector) + 16u) + QObject (0x0x7fcf5fc02ea0) 0 + primary-for QFileSelector (0x0x7fcf5ffd1a28) + +Class QFileSystemWatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSystemWatcher::QPrivateSignal (0x0x7fcf5fdc3000) 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 (0x0x7fcf5ffd1a90) 0 + vptr=((& QFileSystemWatcher::_ZTV18QFileSystemWatcher) + 16u) + QObject (0x0x7fcf5fc02f60) 0 + primary-for QFileSystemWatcher (0x0x7fcf5ffd1a90) + +Class QLockFile + size=8 align=8 + base size=8 base align=8 +QLockFile (0x0x7fcf5fdc3060) 0 + +Class QLoggingCategory::AtomicBools + size=4 align=1 + base size=4 base align=1 +QLoggingCategory::AtomicBools (0x0x7fcf5fdc31e0) 0 + +Class QLoggingCategory + size=24 align=8 + base size=24 base align=8 +QLoggingCategory (0x0x7fcf5fdc3180) 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 (0x0x7fcf5fdc3360) 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 (0x0x7fcf5ffd1b60) 0 nearly-empty + vptr=((& std::bad_cast::_ZTVSt8bad_cast) + 16u) + std::exception (0x0x7fcf5fdc33c0) 0 nearly-empty + primary-for std::bad_cast (0x0x7fcf5ffd1b60) + +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 (0x0x7fcf5ffd1bc8) 0 nearly-empty + vptr=((& std::bad_typeid::_ZTVSt10bad_typeid) + 16u) + std::exception (0x0x7fcf5fdc3420) 0 nearly-empty + primary-for std::bad_typeid (0x0x7fcf5ffd1bc8) + +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 (0x0x7fcf5fac1e38) 0 nearly-empty + vptr=((& std::bad_function_call::_ZTVSt17bad_function_call) + 16u) + std::exception (0x0x7fcf5fb964e0) 0 nearly-empty + primary-for std::bad_function_call (0x0x7fcf5fac1e38) + +Class std::_Nocopy_types + size=16 align=8 + base size=16 base align=8 +std::_Nocopy_types (0x0x7fcf5fb965a0) 0 + +Class std::_Any_data + size=16 align=8 + base size=16 base align=8 +std::_Any_data (0x0x7fcf5fb96600) 0 + +Class std::_Function_base + size=24 align=8 + base size=24 base align=8 +std::_Function_base (0x0x7fcf5fb96720) 0 + +Class QProcessEnvironment + size=8 align=8 + base size=8 base align=8 +QProcessEnvironment (0x0x7fcf5fb96c00) 0 + +Class QProcess::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QProcess::QPrivateSignal (0x0x7fcf5fb96e40) 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 (0x0x7fcf5fbe0680) 0 + vptr=((& QProcess::_ZTV8QProcess) + 16u) + QIODevice (0x0x7fcf5fbe06e8) 0 + primary-for QProcess (0x0x7fcf5fbe0680) + QObject (0x0x7fcf5fb96de0) 0 + primary-for QIODevice (0x0x7fcf5fbe06e8) + +Class QResource + size=8 align=8 + base size=8 base align=8 +QResource (0x0x7fcf5fb96ea0) 0 + +Class QSaveFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSaveFile::QPrivateSignal (0x0x7fcf5f89b060) 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 (0x0x7fcf5fbe0750) 0 + vptr=((& QSaveFile::_ZTV9QSaveFile) + 16u) + QFileDevice (0x0x7fcf5fbe07b8) 0 + primary-for QSaveFile (0x0x7fcf5fbe0750) + QIODevice (0x0x7fcf5fbe0820) 0 + primary-for QFileDevice (0x0x7fcf5fbe07b8) + QObject (0x0x7fcf5f89b000) 0 + primary-for QIODevice (0x0x7fcf5fbe0820) + +Class QSettings::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSettings::QPrivateSignal (0x0x7fcf5f89b120) 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 (0x0x7fcf5fbe0888) 0 + vptr=((& QSettings::_ZTV9QSettings) + 16u) + QObject (0x0x7fcf5f89b0c0) 0 + primary-for QSettings (0x0x7fcf5fbe0888) + +Class QStandardPaths + size=1 align=1 + base size=0 base align=1 +QStandardPaths (0x0x7fcf5f89b180) 0 empty + +Class QStorageInfo + size=8 align=8 + base size=8 base align=8 +QStorageInfo (0x0x7fcf5f89b300) 0 + +Class QTemporaryDir + size=8 align=8 + base size=8 base align=8 +QTemporaryDir (0x0x7fcf5f89b600) 0 + +Class QTemporaryFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTemporaryFile::QPrivateSignal (0x0x7fcf5f89b720) 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 (0x0x7fcf5fbe0a28) 0 + vptr=((& QTemporaryFile::_ZTV14QTemporaryFile) + 16u) + QFile (0x0x7fcf5fbe0a90) 0 + primary-for QTemporaryFile (0x0x7fcf5fbe0a28) + QFileDevice (0x0x7fcf5fbe0af8) 0 + primary-for QFile (0x0x7fcf5fbe0a90) + QIODevice (0x0x7fcf5fbe0b60) 0 + primary-for QFileDevice (0x0x7fcf5fbe0af8) + QObject (0x0x7fcf5f89b6c0) 0 + primary-for QIODevice (0x0x7fcf5fbe0b60) + +Class QUrl + size=8 align=8 + base size=8 base align=8 +QUrl (0x0x7fcf5f89b840) 0 + +Class QUrlQuery + size=8 align=8 + base size=8 base align=8 +QUrlQuery (0x0x7fcf5f624cc0) 0 + +Class QModelIndex + size=24 align=8 + base size=24 base align=8 +QModelIndex (0x0x7fcf5f624ea0) 0 + +Class QPersistentModelIndex + size=8 align=8 + base size=8 base align=8 +QPersistentModelIndex (0x0x7fcf5f6dc060) 0 + +Class QAbstractItemModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractItemModel::QPrivateSignal (0x0x7fcf5f73ff00) 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 (0x0x7fcf5f7579c0) 0 + vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16u) + QObject (0x0x7fcf5f73fea0) 0 + primary-for QAbstractItemModel (0x0x7fcf5f7579c0) + +Class QAbstractTableModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTableModel::QPrivateSignal (0x0x7fcf5f7b52a0) 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 (0x0x7fcf5f757bc8) 0 + vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16u) + QAbstractItemModel (0x0x7fcf5f757c30) 0 + primary-for QAbstractTableModel (0x0x7fcf5f757bc8) + QObject (0x0x7fcf5f7b5240) 0 + primary-for QAbstractItemModel (0x0x7fcf5f757c30) + +Class QAbstractListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractListModel::QPrivateSignal (0x0x7fcf5f7b5360) 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 (0x0x7fcf5f757c98) 0 + vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16u) + QAbstractItemModel (0x0x7fcf5f757d00) 0 + primary-for QAbstractListModel (0x0x7fcf5f757c98) + QObject (0x0x7fcf5f7b5300) 0 + primary-for QAbstractItemModel (0x0x7fcf5f757d00) + +Class QAbstractProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractProxyModel::QPrivateSignal (0x0x7fcf5f7b5660) 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 (0x0x7fcf5f757e38) 0 + vptr=((& QAbstractProxyModel::_ZTV19QAbstractProxyModel) + 16u) + QAbstractItemModel (0x0x7fcf5f757ea0) 0 + primary-for QAbstractProxyModel (0x0x7fcf5f757e38) + QObject (0x0x7fcf5f7b5600) 0 + primary-for QAbstractItemModel (0x0x7fcf5f757ea0) + +Class QIdentityProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIdentityProxyModel::QPrivateSignal (0x0x7fcf5f7b5720) 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 (0x0x7fcf5f757f08) 0 + vptr=((& QIdentityProxyModel::_ZTV19QIdentityProxyModel) + 16u) + QAbstractProxyModel (0x0x7fcf5f757f70) 0 + primary-for QIdentityProxyModel (0x0x7fcf5f757f08) + QAbstractItemModel (0x0x7fcf5f485000) 0 + primary-for QAbstractProxyModel (0x0x7fcf5f757f70) + QObject (0x0x7fcf5f7b56c0) 0 + primary-for QAbstractItemModel (0x0x7fcf5f485000) + +Class QItemSelectionRange + size=16 align=8 + base size=16 base align=8 +QItemSelectionRange (0x0x7fcf5f7b5780) 0 + +Class QItemSelectionModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QItemSelectionModel::QPrivateSignal (0x0x7fcf5f7b59c0) 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 (0x0x7fcf5f485270) 0 + vptr=((& QItemSelectionModel::_ZTV19QItemSelectionModel) + 16u) + QObject (0x0x7fcf5f7b5960) 0 + primary-for QItemSelectionModel (0x0x7fcf5f485270) + +Class QItemSelection + size=8 align=8 + base size=8 base align=8 +QItemSelection (0x0x7fcf5f485478) 0 + QList (0x0x7fcf5f4854e0) 0 + QListSpecialMethods (0x0x7fcf5f7b5c60) 0 empty + +Class QSortFilterProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSortFilterProxyModel::QPrivateSignal (0x0x7fcf5f5640c0) 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 (0x0x7fcf5f4855b0) 0 + vptr=((& QSortFilterProxyModel::_ZTV21QSortFilterProxyModel) + 16u) + QAbstractProxyModel (0x0x7fcf5f485618) 0 + primary-for QSortFilterProxyModel (0x0x7fcf5f4855b0) + QAbstractItemModel (0x0x7fcf5f485680) 0 + primary-for QAbstractProxyModel (0x0x7fcf5f485618) + QObject (0x0x7fcf5f564060) 0 + primary-for QAbstractItemModel (0x0x7fcf5f485680) + +Class QStringListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStringListModel::QPrivateSignal (0x0x7fcf5f564180) 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 (0x0x7fcf5f4856e8) 0 + vptr=((& QStringListModel::_ZTV16QStringListModel) + 16u) + QAbstractListModel (0x0x7fcf5f485750) 0 + primary-for QStringListModel (0x0x7fcf5f4856e8) + QAbstractItemModel (0x0x7fcf5f4857b8) 0 + primary-for QAbstractListModel (0x0x7fcf5f485750) + QObject (0x0x7fcf5f564120) 0 + primary-for QAbstractItemModel (0x0x7fcf5f4857b8) + +Class QJsonValue + size=24 align=8 + base size=20 base align=8 +QJsonValue (0x0x7fcf5f5641e0) 0 + +Class QJsonValueRef + size=16 align=8 + base size=12 base align=8 +QJsonValueRef (0x0x7fcf5f5642a0) 0 + +Class QJsonValuePtr + size=24 align=8 + base size=24 base align=8 +QJsonValuePtr (0x0x7fcf5f564360) 0 + +Class QJsonValueRefPtr + size=16 align=8 + base size=16 base align=8 +QJsonValueRefPtr (0x0x7fcf5f5643c0) 0 + +Class QJsonArray::iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::iterator (0x0x7fcf5f564480) 0 + +Class QJsonArray::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::const_iterator (0x0x7fcf5f5644e0) 0 + +Class QJsonArray + size=16 align=8 + base size=16 base align=8 +QJsonArray (0x0x7fcf5f564420) 0 + +Class QJsonParseError + size=8 align=4 + base size=8 base align=4 +QJsonParseError (0x0x7fcf5f5645a0) 0 + +Class QJsonDocument + size=8 align=8 + base size=8 base align=8 +QJsonDocument (0x0x7fcf5f564600) 0 + +Class QJsonObject::iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::iterator (0x0x7fcf5f5646c0) 0 + +Class QJsonObject::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::const_iterator (0x0x7fcf5f564720) 0 + +Class QJsonObject + size=16 align=8 + base size=16 base align=8 +QJsonObject (0x0x7fcf5f564660) 0 + +Class QEventLoop::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventLoop::QPrivateSignal (0x0x7fcf5f564900) 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 (0x0x7fcf5f4859c0) 0 + vptr=((& QEventLoop::_ZTV10QEventLoop) + 16u) + QObject (0x0x7fcf5f5648a0) 0 + primary-for QEventLoop (0x0x7fcf5f4859c0) + +Class QEventLoopLocker + size=8 align=8 + base size=8 base align=8 +QEventLoopLocker (0x0x7fcf5f564a80) 0 + +Class QAbstractEventDispatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractEventDispatcher::QPrivateSignal (0x0x7fcf5f564b40) 0 empty + +Class QAbstractEventDispatcher::TimerInfo + size=12 align=4 + base size=12 base align=4 +QAbstractEventDispatcher::TimerInfo (0x0x7fcf5f564ba0) 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 (0x0x7fcf5f485af8) 0 + vptr=((& QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher) + 16u) + QObject (0x0x7fcf5f564ae0) 0 + primary-for QAbstractEventDispatcher (0x0x7fcf5f485af8) + +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 (0x0x7fcf5f564c00) 0 + vptr=((& QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter) + 16u) + +Class QBasicTimer + size=4 align=4 + base size=4 base align=4 +QBasicTimer (0x0x7fcf5f564c60) 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 (0x0x7fcf5f564de0) 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 (0x0x7fcf5f485bc8) 0 + vptr=((& QTimerEvent::_ZTV11QTimerEvent) + 16u) + QEvent (0x0x7fcf5f564e40) 0 + primary-for QTimerEvent (0x0x7fcf5f485bc8) + +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 (0x0x7fcf5f485c30) 0 + vptr=((& QChildEvent::_ZTV11QChildEvent) + 16u) + QEvent (0x0x7fcf5f564ea0) 0 + primary-for QChildEvent (0x0x7fcf5f485c30) + +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 (0x0x7fcf5f485c98) 0 + vptr=((& QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent) + 16u) + QEvent (0x0x7fcf5f564f00) 0 + primary-for QDynamicPropertyChangeEvent (0x0x7fcf5f485c98) + +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 (0x0x7fcf5f485d00) 0 + vptr=((& QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent) + 16u) + QEvent (0x0x7fcf5f564f60) 0 + primary-for QDeferredDeleteEvent (0x0x7fcf5f485d00) + +Class QCoreApplication::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QCoreApplication::QPrivateSignal (0x0x7fcf5f37a060) 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 (0x0x7fcf5f485d68) 0 + vptr=((& QCoreApplication::_ZTV16QCoreApplication) + 16u) + QObject (0x0x7fcf5f37a000) 0 + primary-for QCoreApplication (0x0x7fcf5f485d68) + +Class QMetaMethod + size=16 align=8 + base size=12 base align=8 +QMetaMethod (0x0x7fcf5f37a120) 0 + +Class QMetaEnum + size=16 align=8 + base size=12 base align=8 +QMetaEnum (0x0x7fcf5f37a2a0) 0 + +Class QMetaProperty + size=32 align=8 + base size=32 base align=8 +QMetaProperty (0x0x7fcf5f37a480) 0 + +Class QMetaClassInfo + size=16 align=8 + base size=12 base align=8 +QMetaClassInfo (0x0x7fcf5f37a4e0) 0 + +Class QMimeData::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QMimeData::QPrivateSignal (0x0x7fcf5f37a6c0) 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 (0x0x7fcf5f485f08) 0 + vptr=((& QMimeData::_ZTV9QMimeData) + 16u) + QObject (0x0x7fcf5f37a660) 0 + primary-for QMimeData (0x0x7fcf5f485f08) + +Class QObjectCleanupHandler::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObjectCleanupHandler::QPrivateSignal (0x0x7fcf5f37a780) 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 (0x0x7fcf5f485f70) 0 + vptr=((& QObjectCleanupHandler::_ZTV21QObjectCleanupHandler) + 16u) + QObject (0x0x7fcf5f37a720) 0 + primary-for QObjectCleanupHandler (0x0x7fcf5f485f70) + +Class QSharedMemory::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSharedMemory::QPrivateSignal (0x0x7fcf5f37a9c0) 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 (0x0x7fcf5f036000) 0 + vptr=((& QSharedMemory::_ZTV13QSharedMemory) + 16u) + QObject (0x0x7fcf5f37a960) 0 + primary-for QSharedMemory (0x0x7fcf5f036000) + +Class QSignalMapper::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalMapper::QPrivateSignal (0x0x7fcf5f37aa80) 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 (0x0x7fcf5f036068) 0 + vptr=((& QSignalMapper::_ZTV13QSignalMapper) + 16u) + QObject (0x0x7fcf5f37aa20) 0 + primary-for QSignalMapper (0x0x7fcf5f036068) + +Class QSocketNotifier::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSocketNotifier::QPrivateSignal (0x0x7fcf5f37ab40) 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 (0x0x7fcf5f0360d0) 0 + vptr=((& QSocketNotifier::_ZTV15QSocketNotifier) + 16u) + QObject (0x0x7fcf5f37aae0) 0 + primary-for QSocketNotifier (0x0x7fcf5f0360d0) + +Class QSystemSemaphore + size=8 align=8 + base size=8 base align=8 +QSystemSemaphore (0x0x7fcf5f37aba0) 0 + +Class QTimer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimer::QPrivateSignal (0x0x7fcf5f37acc0) 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 (0x0x7fcf5f036138) 0 + vptr=((& QTimer::_ZTV6QTimer) + 16u) + QObject (0x0x7fcf5f37ac60) 0 + primary-for QTimer (0x0x7fcf5f036138) + +Class QTranslator::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTranslator::QPrivateSignal (0x0x7fcf5f37ae40) 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 (0x0x7fcf5f036208) 0 + vptr=((& QTranslator::_ZTV11QTranslator) + 16u) + QObject (0x0x7fcf5f37ade0) 0 + primary-for QTranslator (0x0x7fcf5f036208) + +Class QMimeType + size=8 align=8 + base size=8 base align=8 +QMimeType (0x0x7fcf5f37aea0) 0 + +Class QMimeDatabase + size=8 align=8 + base size=8 base align=8 +QMimeDatabase (0x0x7fcf5f0c80c0) 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 (0x0x7fcf5f0c8120) 0 nearly-empty + vptr=((& QFactoryInterface::_ZTV17QFactoryInterface) + 16u) + +Class QLibrary::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLibrary::QPrivateSignal (0x0x7fcf5f0c8240) 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 (0x0x7fcf5f0362d8) 0 + vptr=((& QLibrary::_ZTV8QLibrary) + 16u) + QObject (0x0x7fcf5f0c81e0) 0 + primary-for QLibrary (0x0x7fcf5f0362d8) + +Class QStaticPlugin + size=16 align=8 + base size=16 base align=8 +QStaticPlugin (0x0x7fcf5f0c83c0) 0 + +Class QPluginLoader::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPluginLoader::QPrivateSignal (0x0x7fcf5f0c85a0) 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 (0x0x7fcf5f036478) 0 + vptr=((& QPluginLoader::_ZTV13QPluginLoader) + 16u) + QObject (0x0x7fcf5f0c8540) 0 + primary-for QPluginLoader (0x0x7fcf5f036478) + +Class QUuid + size=16 align=4 + base size=16 base align=4 +QUuid (0x0x7fcf5f0c8600) 0 + +Class QAbstractState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractState::QPrivateSignal (0x0x7fcf5f0c87e0) 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 (0x0x7fcf5f036548) 0 + vptr=((& QAbstractState::_ZTV14QAbstractState) + 16u) + QObject (0x0x7fcf5f0c8780) 0 + primary-for QAbstractState (0x0x7fcf5f036548) + +Class QAbstractTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTransition::QPrivateSignal (0x0x7fcf5f0c88a0) 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 (0x0x7fcf5f0365b0) 0 + vptr=((& QAbstractTransition::_ZTV19QAbstractTransition) + 16u) + QObject (0x0x7fcf5f0c8840) 0 + primary-for QAbstractTransition (0x0x7fcf5f0365b0) + +Class QEventTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventTransition::QPrivateSignal (0x0x7fcf5f0c8960) 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 (0x0x7fcf5f036618) 0 + vptr=((& QEventTransition::_ZTV16QEventTransition) + 16u) + QAbstractTransition (0x0x7fcf5f036680) 0 + primary-for QEventTransition (0x0x7fcf5f036618) + QObject (0x0x7fcf5f0c8900) 0 + primary-for QAbstractTransition (0x0x7fcf5f036680) + +Class QFinalState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFinalState::QPrivateSignal (0x0x7fcf5f0c8a20) 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 (0x0x7fcf5f0366e8) 0 + vptr=((& QFinalState::_ZTV11QFinalState) + 16u) + QAbstractState (0x0x7fcf5f036750) 0 + primary-for QFinalState (0x0x7fcf5f0366e8) + QObject (0x0x7fcf5f0c89c0) 0 + primary-for QAbstractState (0x0x7fcf5f036750) + +Class QHistoryState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QHistoryState::QPrivateSignal (0x0x7fcf5f0c8ae0) 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 (0x0x7fcf5f0367b8) 0 + vptr=((& QHistoryState::_ZTV13QHistoryState) + 16u) + QAbstractState (0x0x7fcf5f036820) 0 + primary-for QHistoryState (0x0x7fcf5f0367b8) + QObject (0x0x7fcf5f0c8a80) 0 + primary-for QAbstractState (0x0x7fcf5f036820) + +Class QSignalTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalTransition::QPrivateSignal (0x0x7fcf5f0c8ba0) 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 (0x0x7fcf5f036888) 0 + vptr=((& QSignalTransition::_ZTV17QSignalTransition) + 16u) + QAbstractTransition (0x0x7fcf5f0368f0) 0 + primary-for QSignalTransition (0x0x7fcf5f036888) + QObject (0x0x7fcf5f0c8b40) 0 + primary-for QAbstractTransition (0x0x7fcf5f0368f0) + +Class QState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QState::QPrivateSignal (0x0x7fcf5f0c8c60) 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 (0x0x7fcf5f036958) 0 + vptr=((& QState::_ZTV6QState) + 16u) + QAbstractState (0x0x7fcf5f0369c0) 0 + primary-for QState (0x0x7fcf5f036958) + QObject (0x0x7fcf5f0c8c00) 0 + primary-for QAbstractState (0x0x7fcf5f0369c0) + +Class QStateMachine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStateMachine::QPrivateSignal (0x0x7fcf5f0c8d80) 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 (0x0x7fcf5f036b60) 0 + vptr=((& QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE) + 16u) + QEvent (0x0x7fcf5f0c8de0) 0 + primary-for QStateMachine::SignalEvent (0x0x7fcf5f036b60) + +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 (0x0x7fcf5f036bc8) 0 + vptr=((& QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE) + 16u) + QEvent (0x0x7fcf5f0c8e40) 0 + primary-for QStateMachine::WrappedEvent (0x0x7fcf5f036bc8) + +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 (0x0x7fcf5f036a28) 0 + vptr=((& QStateMachine::_ZTV13QStateMachine) + 16u) + QState (0x0x7fcf5f036a90) 0 + primary-for QStateMachine (0x0x7fcf5f036a28) + QAbstractState (0x0x7fcf5f036af8) 0 + primary-for QState (0x0x7fcf5f036a90) + QObject (0x0x7fcf5f0c8d20) 0 + primary-for QAbstractState (0x0x7fcf5f036af8) + +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 (0x0x7fcf5f036c30) 0 nearly-empty + vptr=((& QException::_ZTV10QException) + 16u) + std::exception (0x0x7fcf5f0c8ea0) 0 nearly-empty + primary-for QException (0x0x7fcf5f036c30) + +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 (0x0x7fcf5f036c98) 0 nearly-empty + vptr=((& QUnhandledException::_ZTV19QUnhandledException) + 16u) + QException (0x0x7fcf5f036d00) 0 nearly-empty + primary-for QUnhandledException (0x0x7fcf5f036c98) + std::exception (0x0x7fcf5f0c8f00) 0 nearly-empty + primary-for QException (0x0x7fcf5f036d00) + +Class QtPrivate::ExceptionHolder + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionHolder (0x0x7fcf5f0c8f60) 0 + +Class QtPrivate::ExceptionStore + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionStore (0x0x7fcf5ee12060) 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 (0x0x7fcf5ee120c0) 0 + vptr=((& QRunnable::_ZTV9QRunnable) + 16u) + +Class QBasicMutex + size=8 align=8 + base size=8 base align=8 +QBasicMutex (0x0x7fcf5ee12120) 0 + +Class QMutex + size=8 align=8 + base size=8 base align=8 +QMutex (0x0x7fcf5f036e38) 0 + QBasicMutex (0x0x7fcf5ee12360) 0 + +Class QMutexLocker + size=8 align=8 + base size=8 base align=8 +QMutexLocker (0x0x7fcf5ee123c0) 0 + +Class QtPrivate::ResultItem + size=16 align=8 + base size=16 base align=8 +QtPrivate::ResultItem (0x0x7fcf5ee12480) 0 + +Class QtPrivate::ResultIteratorBase + size=16 align=8 + base size=12 base align=8 +QtPrivate::ResultIteratorBase (0x0x7fcf5ee124e0) 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 (0x0x7fcf5ee12660) 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 (0x0x7fcf5ee12720) 0 + vptr=((& QFutureInterfaceBase::_ZTV20QFutureInterfaceBase) + 16u) + +Class QFutureWatcherBase::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFutureWatcherBase::QPrivateSignal (0x0x7fcf5ee12a80) 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 (0x0x7fcf5eeec6e8) 0 + vptr=((& QFutureWatcherBase::_ZTV18QFutureWatcherBase) + 16u) + QObject (0x0x7fcf5ee12a20) 0 + primary-for QFutureWatcherBase (0x0x7fcf5eeec6e8) + +Class QReadWriteLock + size=8 align=8 + base size=8 base align=8 +QReadWriteLock (0x0x7fcf5ee12ba0) 0 + +Class QReadLocker + size=8 align=8 + base size=8 base align=8 +QReadLocker (0x0x7fcf5ee12e40) 0 + +Class QWriteLocker + size=8 align=8 + base size=8 base align=8 +QWriteLocker (0x0x7fcf5ee12ea0) 0 + +Class QSemaphore + size=8 align=8 + base size=8 base align=8 +QSemaphore (0x0x7fcf5ee12f00) 0 + +Class QThread::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThread::QPrivateSignal (0x0x7fcf5ec54000) 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 (0x0x7fcf5eeecc98) 0 + vptr=((& QThread::_ZTV7QThread) + 16u) + QObject (0x0x7fcf5ee12f60) 0 + primary-for QThread (0x0x7fcf5eeecc98) + +Class QThreadPool::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThreadPool::QPrivateSignal (0x0x7fcf5ec540c0) 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 (0x0x7fcf5eeecd00) 0 + vptr=((& QThreadPool::_ZTV11QThreadPool) + 16u) + QObject (0x0x7fcf5ec54060) 0 + primary-for QThreadPool (0x0x7fcf5eeecd00) + +Class QThreadStorageData + size=4 align=4 + base size=4 base align=4 +QThreadStorageData (0x0x7fcf5ec54120) 0 + +Class QWaitCondition + size=8 align=8 + base size=8 base align=8 +QWaitCondition (0x0x7fcf5ec541e0) 0 + +Class QBitArray + size=8 align=8 + base size=8 base align=8 +QBitArray (0x0x7fcf5ec546c0) 0 + +Class QBitRef + size=16 align=8 + base size=12 base align=8 +QBitRef (0x0x7fcf5ec54900) 0 + +Class QByteArrayMatcher::Data + size=272 align=8 + base size=272 base align=8 +QByteArrayMatcher::Data (0x0x7fcf5ec54b40) 0 + +Class QByteArrayMatcher + size=1040 align=8 + base size=1040 base align=8 +QByteArrayMatcher (0x0x7fcf5ec54ae0) 0 + +Class QCollatorSortKey + size=8 align=8 + base size=8 base align=8 +QCollatorSortKey (0x0x7fcf5ec54cc0) 0 + +Class QCollator + size=8 align=8 + base size=8 base align=8 +QCollator (0x0x7fcf5ec54d80) 0 + +Class QCommandLineOption + size=8 align=8 + base size=8 base align=8 +QCommandLineOption (0x0x7fcf5eddbb40) 0 + +Class QCommandLineParser + size=8 align=8 + base size=8 base align=8 +QCommandLineParser (0x0x7fcf5eddbd20) 0 + +Class QCryptographicHash + size=8 align=8 + base size=8 base align=8 +QCryptographicHash (0x0x7fcf5eddbd80) 0 + +Class QElapsedTimer + size=16 align=8 + base size=16 base align=8 +QElapsedTimer (0x0x7fcf5eddbde0) 0 + +Class QPoint + size=8 align=4 + base size=8 base align=4 +QPoint (0x0x7fcf5eddbe40) 0 + +Class QPointF + size=16 align=8 + base size=16 base align=8 +QPointF (0x0x7fcf5ea67000) 0 + +Class QLine + size=16 align=4 + base size=16 base align=4 +QLine (0x0x7fcf5ea67180) 0 + +Class QLineF + size=32 align=8 + base size=32 base align=8 +QLineF (0x0x7fcf5ea67300) 0 + +Class QLinkedListData + size=32 align=8 + base size=25 base align=8 +QLinkedListData (0x0x7fcf5ea67480) 0 + +Class QMargins + size=16 align=4 + base size=16 base align=4 +QMargins (0x0x7fcf5ea67c00) 0 + +Class QMarginsF + size=32 align=8 + base size=32 base align=8 +QMarginsF (0x0x7fcf5ea67d80) 0 + +Class QMessageAuthenticationCode + size=8 align=8 + base size=8 base align=8 +QMessageAuthenticationCode (0x0x7fcf5ea67f00) 0 + +Class QSize + size=8 align=4 + base size=8 base align=4 +QSize (0x0x7fcf5e82f000) 0 + +Class QSizeF + size=16 align=8 + base size=16 base align=8 +QSizeF (0x0x7fcf5e82f240) 0 + +Class QRect + size=16 align=4 + base size=16 base align=4 +QRect (0x0x7fcf5e82f480) 0 + +Class QRectF + size=32 align=8 + base size=32 base align=8 +QRectF (0x0x7fcf5e82f600) 0 + +Class QRegularExpression + size=8 align=8 + base size=8 base align=8 +QRegularExpression (0x0x7fcf5e82f780) 0 + +Class QRegularExpressionMatch + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatch (0x0x7fcf5e82fba0) 0 + +Class QRegularExpressionMatchIterator + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatchIterator (0x0x7fcf5e82fd80) 0 + +Class QAbstractConcatenable + size=1 align=1 + base size=0 base align=1 +QAbstractConcatenable (0x0x7fcf5e66f180) 0 empty + +Class QTextBoundaryFinder + size=48 align=8 + base size=48 base align=8 +QTextBoundaryFinder (0x0x7fcf5e66fba0) 0 + +Class QTimeLine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimeLine::QPrivateSignal (0x0x7fcf5e66fd80) 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 (0x0x7fcf5e650af8) 0 + vptr=((& QTimeLine::_ZTV9QTimeLine) + 16u) + QObject (0x0x7fcf5e66fd20) 0 + primary-for QTimeLine (0x0x7fcf5e650af8) + +Class QTimeZone::OffsetData + size=32 align=8 + base size=28 base align=8 +QTimeZone::OffsetData (0x0x7fcf5e66fe40) 0 + +Class QTimeZone + size=8 align=8 + base size=8 base align=8 +QTimeZone (0x0x7fcf5e66fde0) 0 + +Class QVersionNumber::SegmentStorage + size=8 align=8 + base size=8 base align=8 +QVersionNumber::SegmentStorage (0x0x7fcf5e7641e0) 0 + +Class QVersionNumber + size=8 align=8 + base size=8 base align=8 +QVersionNumber (0x0x7fcf5e764180) 0 + +Class QXmlStreamStringRef + size=16 align=8 + base size=16 base align=8 +QXmlStreamStringRef (0x0x7fcf5e7e1f60) 0 + +Class QXmlStreamAttribute + size=80 align=8 + base size=73 base align=8 +QXmlStreamAttribute (0x0x7fcf5e4bcc60) 0 + +Class QXmlStreamAttributes + size=8 align=8 + base size=8 base align=8 +QXmlStreamAttributes (0x0x7fcf5e4e0340) 0 + QVector (0x0x7fcf5e4bcf00) 0 + +Class QXmlStreamNamespaceDeclaration + size=40 align=8 + base size=40 base align=8 +QXmlStreamNamespaceDeclaration (0x0x7fcf5e4bcf60) 0 + +Class QXmlStreamNotationDeclaration + size=56 align=8 + base size=56 base align=8 +QXmlStreamNotationDeclaration (0x0x7fcf5e542120) 0 + +Class QXmlStreamEntityDeclaration + size=88 align=8 + base size=88 base align=8 +QXmlStreamEntityDeclaration (0x0x7fcf5e5422a0) 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 (0x0x7fcf5e542420) 0 nearly-empty + vptr=((& QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver) + 16u) + +Class QXmlStreamReader + size=8 align=8 + base size=8 base align=8 +QXmlStreamReader (0x0x7fcf5e542480) 0 + +Class QXmlStreamWriter + size=8 align=8 + base size=8 base align=8 +QXmlStreamWriter (0x0x7fcf5e5425a0) 0 + +Class QBluetoothAddress + size=8 align=8 + base size=8 base align=8 +QBluetoothAddress (0x0x7fcf5e542900) 0 + +Class QBluetoothDeviceInfo + size=8 align=8 + base size=8 base align=8 +QBluetoothDeviceInfo (0x0x7fcf5e542a80) 0 + +Class QBluetoothDeviceDiscoveryAgent::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothDeviceDiscoveryAgent::QPrivateSignal (0x0x7fcf5e542ea0) 0 empty + +Vtable for QBluetoothDeviceDiscoveryAgent +QBluetoothDeviceDiscoveryAgent::_ZTV30QBluetoothDeviceDiscoveryAgent: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI30QBluetoothDeviceDiscoveryAgent) +16 (int (*)(...))QBluetoothDeviceDiscoveryAgent::metaObject +24 (int (*)(...))QBluetoothDeviceDiscoveryAgent::qt_metacast +32 (int (*)(...))QBluetoothDeviceDiscoveryAgent::qt_metacall +40 (int (*)(...))QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent +48 (int (*)(...))QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent +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 QBluetoothDeviceDiscoveryAgent + size=24 align=8 + base size=24 base align=8 +QBluetoothDeviceDiscoveryAgent (0x0x7fcf5e4e0bc8) 0 + vptr=((& QBluetoothDeviceDiscoveryAgent::_ZTV30QBluetoothDeviceDiscoveryAgent) + 16u) + QObject (0x0x7fcf5e542e40) 0 + primary-for QBluetoothDeviceDiscoveryAgent (0x0x7fcf5e4e0bc8) + +Class QBluetoothHostInfo + size=8 align=8 + base size=8 base align=8 +QBluetoothHostInfo (0x0x7fcf5e542f00) 0 + +Class QBluetoothLocalDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothLocalDevice::QPrivateSignal (0x0x7fcf5e2c4120) 0 empty + +Vtable for QBluetoothLocalDevice +QBluetoothLocalDevice::_ZTV21QBluetoothLocalDevice: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QBluetoothLocalDevice) +16 (int (*)(...))QBluetoothLocalDevice::metaObject +24 (int (*)(...))QBluetoothLocalDevice::qt_metacast +32 (int (*)(...))QBluetoothLocalDevice::qt_metacall +40 (int (*)(...))QBluetoothLocalDevice::~QBluetoothLocalDevice +48 (int (*)(...))QBluetoothLocalDevice::~QBluetoothLocalDevice +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 QBluetoothLocalDevice + size=24 align=8 + base size=24 base align=8 +QBluetoothLocalDevice (0x0x7fcf5e4e0c30) 0 + vptr=((& QBluetoothLocalDevice::_ZTV21QBluetoothLocalDevice) + 16u) + QObject (0x0x7fcf5e2c40c0) 0 + primary-for QBluetoothLocalDevice (0x0x7fcf5e4e0c30) + +Class quint128 + size=16 align=1 + base size=16 base align=1 +quint128 (0x0x7fcf5e2c44e0) 0 + +Class QBluetoothUuid + size=16 align=4 + base size=16 base align=4 +QBluetoothUuid (0x0x7fcf5e4e0c98) 0 + QUuid (0x0x7fcf5e2c4540) 0 + +Class QBluetoothServiceInfo::Sequence + size=8 align=8 + base size=8 base align=8 +QBluetoothServiceInfo::Sequence (0x0x7fcf5e4e0d00) 0 + QList (0x0x7fcf5e4e0d68) 0 + QListSpecialMethods (0x0x7fcf5e2c4780) 0 empty + +Class QBluetoothServiceInfo::Alternative + size=8 align=8 + base size=8 base align=8 +QBluetoothServiceInfo::Alternative (0x0x7fcf5e4e0dd0) 0 + QList (0x0x7fcf5e4e0e38) 0 + QListSpecialMethods (0x0x7fcf5e2c47e0) 0 empty + +Class QBluetoothServiceInfo + size=16 align=8 + base size=16 base align=8 +QBluetoothServiceInfo (0x0x7fcf5e2c4720) 0 + +Class QAbstractSocket::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractSocket::QPrivateSignal (0x0x7fcf5e2c4c60) 0 empty + +Vtable for QAbstractSocket +QAbstractSocket::_ZTV15QAbstractSocket: 41u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QAbstractSocket) +16 (int (*)(...))QAbstractSocket::metaObject +24 (int (*)(...))QAbstractSocket::qt_metacast +32 (int (*)(...))QAbstractSocket::qt_metacall +40 (int (*)(...))QAbstractSocket::~QAbstractSocket +48 (int (*)(...))QAbstractSocket::~QAbstractSocket +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 (*)(...))QAbstractSocket::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QAbstractSocket::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QAbstractSocket::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QAbstractSocket::bytesAvailable +184 (int (*)(...))QAbstractSocket::bytesToWrite +192 (int (*)(...))QAbstractSocket::canReadLine +200 (int (*)(...))QAbstractSocket::waitForReadyRead +208 (int (*)(...))QAbstractSocket::waitForBytesWritten +216 (int (*)(...))QAbstractSocket::readData +224 (int (*)(...))QAbstractSocket::readLineData +232 (int (*)(...))QAbstractSocket::writeData +240 (int (*)(...))QAbstractSocket::resume +248 (int (*)(...))QAbstractSocket::connectToHost +256 (int (*)(...))QAbstractSocket::connectToHost +264 (int (*)(...))QAbstractSocket::disconnectFromHost +272 (int (*)(...))QAbstractSocket::setReadBufferSize +280 (int (*)(...))QAbstractSocket::socketDescriptor +288 (int (*)(...))QAbstractSocket::setSocketDescriptor +296 (int (*)(...))QAbstractSocket::setSocketOption +304 (int (*)(...))QAbstractSocket::socketOption +312 (int (*)(...))QAbstractSocket::waitForConnected +320 (int (*)(...))QAbstractSocket::waitForDisconnected + +Class QAbstractSocket + size=16 align=8 + base size=16 base align=8 +QAbstractSocket (0x0x7fcf5e4e05b0) 0 + vptr=((& QAbstractSocket::_ZTV15QAbstractSocket) + 16u) + QIODevice (0x0x7fcf5e4e06e8) 0 + primary-for QAbstractSocket (0x0x7fcf5e4e05b0) + QObject (0x0x7fcf5e2c4c00) 0 + primary-for QIODevice (0x0x7fcf5e4e06e8) + +Class QBluetoothSocket::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothSocket::QPrivateSignal (0x0x7fcf5e02d1e0) 0 empty + +Vtable for QBluetoothSocket +QBluetoothSocket::_ZTV16QBluetoothSocket: 30u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QBluetoothSocket) +16 (int (*)(...))QBluetoothSocket::metaObject +24 (int (*)(...))QBluetoothSocket::qt_metacast +32 (int (*)(...))QBluetoothSocket::qt_metacall +40 (int (*)(...))QBluetoothSocket::~QBluetoothSocket +48 (int (*)(...))QBluetoothSocket::~QBluetoothSocket +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 (*)(...))QBluetoothSocket::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QBluetoothSocket::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QIODevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QBluetoothSocket::bytesAvailable +184 (int (*)(...))QBluetoothSocket::bytesToWrite +192 (int (*)(...))QBluetoothSocket::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QBluetoothSocket::readData +224 (int (*)(...))QIODevice::readLineData +232 (int (*)(...))QBluetoothSocket::writeData + +Class QBluetoothSocket + size=24 align=8 + base size=24 base align=8 +QBluetoothSocket (0x0x7fcf5e3cd138) 0 + vptr=((& QBluetoothSocket::_ZTV16QBluetoothSocket) + 16u) + QIODevice (0x0x7fcf5e3cd1a0) 0 + primary-for QBluetoothSocket (0x0x7fcf5e3cd138) + QObject (0x0x7fcf5e02d180) 0 + primary-for QIODevice (0x0x7fcf5e3cd1a0) + +Class QBluetoothServer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothServer::QPrivateSignal (0x0x7fcf5e02d2a0) 0 empty + +Vtable for QBluetoothServer +QBluetoothServer::_ZTV16QBluetoothServer: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QBluetoothServer) +16 (int (*)(...))QBluetoothServer::metaObject +24 (int (*)(...))QBluetoothServer::qt_metacast +32 (int (*)(...))QBluetoothServer::qt_metacall +40 (int (*)(...))QBluetoothServer::~QBluetoothServer +48 (int (*)(...))QBluetoothServer::~QBluetoothServer +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 QBluetoothServer + size=24 align=8 + base size=24 base align=8 +QBluetoothServer (0x0x7fcf5e3cd208) 0 + vptr=((& QBluetoothServer::_ZTV16QBluetoothServer) + 16u) + QObject (0x0x7fcf5e02d240) 0 + primary-for QBluetoothServer (0x0x7fcf5e3cd208) + +Class QBluetoothServiceDiscoveryAgent::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothServiceDiscoveryAgent::QPrivateSignal (0x0x7fcf5e02d360) 0 empty + +Vtable for QBluetoothServiceDiscoveryAgent +QBluetoothServiceDiscoveryAgent::_ZTV31QBluetoothServiceDiscoveryAgent: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI31QBluetoothServiceDiscoveryAgent) +16 (int (*)(...))QBluetoothServiceDiscoveryAgent::metaObject +24 (int (*)(...))QBluetoothServiceDiscoveryAgent::qt_metacast +32 (int (*)(...))QBluetoothServiceDiscoveryAgent::qt_metacall +40 (int (*)(...))QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent +48 (int (*)(...))QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent +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 QBluetoothServiceDiscoveryAgent + size=24 align=8 + base size=24 base align=8 +QBluetoothServiceDiscoveryAgent (0x0x7fcf5e3cd270) 0 + vptr=((& QBluetoothServiceDiscoveryAgent::_ZTV31QBluetoothServiceDiscoveryAgent) + 16u) + QObject (0x0x7fcf5e02d300) 0 + primary-for QBluetoothServiceDiscoveryAgent (0x0x7fcf5e3cd270) + +Class QBluetoothTransferManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothTransferManager::QPrivateSignal (0x0x7fcf5e02d420) 0 empty + +Vtable for QBluetoothTransferManager +QBluetoothTransferManager::_ZTV25QBluetoothTransferManager: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI25QBluetoothTransferManager) +16 (int (*)(...))QBluetoothTransferManager::metaObject +24 (int (*)(...))QBluetoothTransferManager::qt_metacast +32 (int (*)(...))QBluetoothTransferManager::qt_metacall +40 (int (*)(...))QBluetoothTransferManager::~QBluetoothTransferManager +48 (int (*)(...))QBluetoothTransferManager::~QBluetoothTransferManager +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 QBluetoothTransferManager + size=16 align=8 + base size=16 base align=8 +QBluetoothTransferManager (0x0x7fcf5e3cd2d8) 0 + vptr=((& QBluetoothTransferManager::_ZTV25QBluetoothTransferManager) + 16u) + QObject (0x0x7fcf5e02d3c0) 0 + primary-for QBluetoothTransferManager (0x0x7fcf5e3cd2d8) + +Class QBluetoothTransferRequest + size=8 align=8 + base size=8 base align=8 +QBluetoothTransferRequest (0x0x7fcf5e02d480) 0 + +Class QBluetoothTransferReply::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothTransferReply::QPrivateSignal (0x0x7fcf5e02d540) 0 empty + +Vtable for QBluetoothTransferReply +QBluetoothTransferReply::_ZTV23QBluetoothTransferReply: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI23QBluetoothTransferReply) +16 (int (*)(...))QBluetoothTransferReply::metaObject +24 (int (*)(...))QBluetoothTransferReply::qt_metacast +32 (int (*)(...))QBluetoothTransferReply::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 + +Class QBluetoothTransferReply + size=24 align=8 + base size=24 base align=8 +QBluetoothTransferReply (0x0x7fcf5e3cd340) 0 + vptr=((& QBluetoothTransferReply::_ZTV23QBluetoothTransferReply) + 16u) + QObject (0x0x7fcf5e02d4e0) 0 + primary-for QBluetoothTransferReply (0x0x7fcf5e3cd340) + +Class QLowEnergyAdvertisingData + size=8 align=8 + base size=8 base align=8 +QLowEnergyAdvertisingData (0x0x7fcf5e02d6c0) 0 + +Class QLowEnergyDescriptor + size=24 align=8 + base size=24 base align=8 +QLowEnergyDescriptor (0x0x7fcf5e02d8a0) 0 + +Class QLowEnergyCharacteristic + size=24 align=8 + base size=24 base align=8 +QLowEnergyCharacteristic (0x0x7fcf5e02d960) 0 + +Class QLowEnergyService::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLowEnergyService::QPrivateSignal (0x0x7fcf5e02db40) 0 empty + +Vtable for QLowEnergyService +QLowEnergyService::_ZTV17QLowEnergyService: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QLowEnergyService) +16 (int (*)(...))QLowEnergyService::metaObject +24 (int (*)(...))QLowEnergyService::qt_metacast +32 (int (*)(...))QLowEnergyService::qt_metacall +40 (int (*)(...))QLowEnergyService::~QLowEnergyService +48 (int (*)(...))QLowEnergyService::~QLowEnergyService +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 QLowEnergyService + size=32 align=8 + base size=32 base align=8 +QLowEnergyService (0x0x7fcf5e3cd4e0) 0 + vptr=((& QLowEnergyService::_ZTV17QLowEnergyService) + 16u) + QObject (0x0x7fcf5e02dae0) 0 + primary-for QLowEnergyService (0x0x7fcf5e3cd4e0) + +Class QLowEnergyController::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLowEnergyController::QPrivateSignal (0x0x7fcf5e1961e0) 0 empty + +Vtable for QLowEnergyController +QLowEnergyController::_ZTV20QLowEnergyController: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI20QLowEnergyController) +16 (int (*)(...))QLowEnergyController::metaObject +24 (int (*)(...))QLowEnergyController::qt_metacast +32 (int (*)(...))QLowEnergyController::qt_metacall +40 (int (*)(...))QLowEnergyController::~QLowEnergyController +48 (int (*)(...))QLowEnergyController::~QLowEnergyController +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 QLowEnergyController + size=24 align=8 + base size=24 base align=8 +QLowEnergyController (0x0x7fcf5e3cd618) 0 + vptr=((& QLowEnergyController::_ZTV20QLowEnergyController) + 16u) + QObject (0x0x7fcf5e196180) 0 + primary-for QLowEnergyController (0x0x7fcf5e3cd618) + +Class QLowEnergyAdvertisingParameters::AddressInfo + size=16 align=8 + base size=12 base align=8 +QLowEnergyAdvertisingParameters::AddressInfo (0x0x7fcf5e196720) 0 + +Class QLowEnergyAdvertisingParameters + size=8 align=8 + base size=8 base align=8 +QLowEnergyAdvertisingParameters (0x0x7fcf5e1966c0) 0 + +Class QLowEnergyCharacteristicData + size=8 align=8 + base size=8 base align=8 +QLowEnergyCharacteristicData (0x0x7fcf5e196900) 0 + +Class QLowEnergyConnectionParameters + size=8 align=8 + base size=8 base align=8 +QLowEnergyConnectionParameters (0x0x7fcf5e196ae0) 0 + +Class QLowEnergyDescriptorData + size=8 align=8 + base size=8 base align=8 +QLowEnergyDescriptorData (0x0x7fcf5e196de0) 0 + +Class QLowEnergyServiceData + size=8 align=8 + base size=8 base align=8 +QLowEnergyServiceData (0x0x7fcf5de6e000) 0 + diff --git a/tests/auto/bic/data/QtBluetooth.5.8.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtBluetooth.5.8.0.linux-gcc-amd64.txt new file mode 100644 index 0000000..34e7789 --- /dev/null +++ b/tests/auto/bic/data/QtBluetooth.5.8.0.linux-gcc-amd64.txt @@ -0,0 +1,4652 @@ +Class std::__failure_type + size=1 align=1 + base size=0 base align=1 +std::__failure_type (0x0x7fc2012b5c60) 0 empty + +Class std::__do_is_destructible_impl + size=1 align=1 + base size=0 base align=1 +std::__do_is_destructible_impl (0x0x7fc201344420) 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 (0x0x7fc201344660) 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 (0x0x7fc2013448a0) 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 (0x0x7fc201344ae0) 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 (0x0x7fc201344c60) 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 (0x0x7fc1fef7e060) 0 empty + +Class std::__do_common_type_impl + size=1 align=1 + base size=0 base align=1 +std::__do_common_type_impl (0x0x7fc1ff0017e0) 0 empty + +Class std::__do_member_type_wrapper + size=1 align=1 + base size=0 base align=1 +std::__do_member_type_wrapper (0x0x7fc1ff0018a0) 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 (0x0x7fc1ff001c00) 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 (0x0x7fc1ff001cc0) 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 (0x0x7fc1ff001d80) 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 (0x0x7fc1ff001e40) 0 empty + +Class std::__result_of_other_impl + size=1 align=1 + base size=0 base align=1 +std::__result_of_other_impl (0x0x7fc1ff03c120) 0 empty + +Class std::piecewise_construct_t + size=1 align=1 + base size=0 base align=1 +std::piecewise_construct_t (0x0x7fc1ff03c300) 0 empty + +Class std::__true_type + size=1 align=1 + base size=0 base align=1 +std::__true_type (0x0x7fc1ff03c780) 0 empty + +Class std::__false_type + size=1 align=1 + base size=0 base align=1 +std::__false_type (0x0x7fc1ff03c7e0) 0 empty + +Class std::input_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::input_iterator_tag (0x0x7fc1ff0e1480) 0 empty + +Class std::output_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::output_iterator_tag (0x0x7fc1ff0e14e0) 0 empty + +Class std::forward_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::forward_iterator_tag (0x0x7fc1ff02a4e0) 0 empty + std::input_iterator_tag (0x0x7fc1ff0e1540) 0 empty + +Class std::bidirectional_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::bidirectional_iterator_tag (0x0x7fc1ff02a548) 0 empty + std::forward_iterator_tag (0x0x7fc1ff02a5b0) 0 empty + std::input_iterator_tag (0x0x7fc1ff0e15a0) 0 empty + +Class std::random_access_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::random_access_iterator_tag (0x0x7fc1ff02a618) 0 empty + std::bidirectional_iterator_tag (0x0x7fc1ff02a680) 0 empty + std::forward_iterator_tag (0x0x7fc1ff02a6e8) 0 empty + std::input_iterator_tag (0x0x7fc1ff0e1600) 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 (0x0x7fc1ff1272a0) 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 (0x0x7fc1ff127300) 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 (0x0x7fc1ff127360) 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 (0x0x7fc1ff1273c0) 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 (0x0x7fc1ff127420) 0 empty + +Class wait + size=4 align=4 + base size=4 base align=4 +wait (0x0x7fc1ff127f00) 0 + +Class __locale_struct + size=232 align=8 + base size=232 base align=8 +__locale_struct (0x0x7fc1fee4e180) 0 + +Class timespec + size=16 align=8 + base size=16 base align=8 +timespec (0x0x7fc1fee4e240) 0 + +Class timeval + size=16 align=8 + base size=16 base align=8 +timeval (0x0x7fc1fee4e2a0) 0 + +Class pthread_attr_t + size=56 align=8 + base size=56 base align=8 +pthread_attr_t (0x0x7fc1fee4e360) 0 + +Class __pthread_internal_list + size=16 align=8 + base size=16 base align=8 +__pthread_internal_list (0x0x7fc1fee4e3c0) 0 + +Class random_data + size=48 align=8 + base size=48 base align=8 +random_data (0x0x7fc1fee4e840) 0 + +Class drand48_data + size=24 align=8 + base size=24 base align=8 +drand48_data (0x0x7fc1fee4e8a0) 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 (0x0x7fc1fee4e900) 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 (0x0x7fc1ff02ac30) 0 nearly-empty + vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16u) + std::exception (0x0x7fc1fee4e960) 0 nearly-empty + primary-for std::bad_exception (0x0x7fc1ff02ac30) + +Class std::__exception_ptr::exception_ptr + size=8 align=8 + base size=8 base align=8 +std::__exception_ptr::exception_ptr (0x0x7fc1fee4e9c0) 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 (0x0x7fc1fee4ea20) 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 (0x0x7fc1ff02ae38) 0 nearly-empty + vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16u) + std::exception (0x0x7fc1fee4ee40) 0 nearly-empty + primary-for std::bad_alloc (0x0x7fc1ff02ae38) + +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 (0x0x7fc1ff02aea0) 0 nearly-empty + vptr=((& std::bad_array_new_length::_ZTVSt20bad_array_new_length) + 16u) + std::bad_alloc (0x0x7fc1ff02af08) 0 nearly-empty + primary-for std::bad_array_new_length (0x0x7fc1ff02aea0) + std::exception (0x0x7fc1fee4eea0) 0 nearly-empty + primary-for std::bad_alloc (0x0x7fc1ff02af08) + +Class std::nothrow_t + size=1 align=1 + base size=0 base align=1 +std::nothrow_t (0x0x7fc1fee4ef00) 0 empty + +Class __exception + size=40 align=8 + base size=40 base align=8 +__exception (0x0x7fc1feb75b40) 0 + +Class lconv + size=96 align=8 + base size=96 base align=8 +lconv (0x0x7fc1fe98c840) 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 (0x0x7fc1fe98c8a0) 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 (0x0x7fc1fea62780) 0 + +Class __sched_param + size=4 align=4 + base size=4 base align=4 +__sched_param (0x0x7fc1fea627e0) 0 + +Class timex + size=208 align=8 + base size=208 base align=8 +timex (0x0x7fc1fea628a0) 0 + +Class tm + size=56 align=8 + base size=56 base align=8 +tm (0x0x7fc1fea62900) 0 + +Class itimerspec + size=32 align=8 + base size=32 base align=8 +itimerspec (0x0x7fc1fea62960) 0 + +Class _pthread_cleanup_buffer + size=32 align=8 + base size=32 base align=8 +_pthread_cleanup_buffer (0x0x7fc1fea629c0) 0 + +Class __pthread_cleanup_frame + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_frame (0x0x7fc1fea62ae0) 0 + +Class __pthread_cleanup_class + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_class (0x0x7fc1fea62b40) 0 + +Class _IO_marker + size=24 align=8 + base size=24 base align=8 +_IO_marker (0x0x7fc1fea62f60) 0 + +Class _IO_FILE + size=216 align=8 + base size=216 base align=8 +_IO_FILE (0x0x7fc1fe813000) 0 + +Class std::_Hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Hash_impl (0x0x7fc1fe5b57e0) 0 empty + +Class std::_Fnv_hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Fnv_hash_impl (0x0x7fc1fe5b5840) 0 empty + +Class std::__numeric_limits_base + size=1 align=1 + base size=0 base align=1 +std::__numeric_limits_base (0x0x7fc1fe5fc7e0) 0 empty + +Class std::_Bit_reference + size=16 align=8 + base size=16 base align=8 +std::_Bit_reference (0x0x7fc1fe3ef600) 0 + +Class std::_Bit_iterator_base + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator_base (0x0x7fc1fe5d4c98) 0 + std::iterator (0x0x7fc1fe3ef6c0) 0 empty + +Class std::_Bit_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator (0x0x7fc1fe5d4d00) 0 + std::_Bit_iterator_base (0x0x7fc1fe5d4d68) 0 + std::iterator (0x0x7fc1fe3ef720) 0 empty + +Class std::_Bit_const_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_const_iterator (0x0x7fc1fe5d4dd0) 0 + std::_Bit_iterator_base (0x0x7fc1fe5d4e38) 0 + std::iterator (0x0x7fc1fe3ef780) 0 empty + +Class std::random_device + size=5000 align=8 + base size=5000 base align=8 +std::random_device (0x0x7fc1fe20d5a0) 0 + +Class std::bernoulli_distribution::param_type + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution::param_type (0x0x7fc1fe322360) 0 + +Class std::bernoulli_distribution + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution (0x0x7fc1fe322300) 0 + +Class std::seed_seq + size=24 align=8 + base size=24 base align=8 +std::seed_seq (0x0x7fc1fe0ad300) 0 + +Class qIsNull(double)::U + size=8 align=8 + base size=8 base align=8 +qIsNull(double)::U (0x0x7fc1fcf26d80) 0 + +Class qIsNull(float)::U + size=4 align=4 + base size=4 base align=4 +qIsNull(float)::U (0x0x7fc1fcf26de0) 0 + +Class QSysInfo + size=1 align=1 + base size=0 base align=1 +QSysInfo (0x0x7fc1fccb9060) 0 empty + +Class QMessageLogContext + size=32 align=8 + base size=32 base align=8 +QMessageLogContext (0x0x7fc1fccb90c0) 0 + +Class QMessageLogger + size=32 align=8 + base size=32 base align=8 +QMessageLogger (0x0x7fc1fccb9120) 0 + +Class QFlag + size=4 align=4 + base size=4 base align=4 +QFlag (0x0x7fc1fccb9ba0) 0 + +Class QIncompatibleFlag + size=4 align=4 + base size=4 base align=4 +QIncompatibleFlag (0x0x7fc1fccb9ea0) 0 + +Class std::__atomic_flag_base + size=1 align=1 + base size=1 base align=1 +std::__atomic_flag_base (0x0x7fc1fcd1a480) 0 + +Class std::atomic_flag + size=1 align=1 + base size=1 base align=1 +std::atomic_flag (0x0x7fc1fcd1f0d0) 0 + std::__atomic_flag_base (0x0x7fc1fcd1a4e0) 0 + +Class QAtomicInt + size=4 align=4 + base size=4 base align=4 +QAtomicInt (0x0x7fc1fcd1f820) 0 + QAtomicInteger (0x0x7fc1fcd1f888) 0 + QBasicAtomicInteger (0x0x7fc1fcb1cc00) 0 + +Class QInternal + size=1 align=1 + base size=0 base align=1 +QInternal (0x0x7fc1fc72d4e0) 0 empty + +Class QGenericArgument + size=16 align=8 + base size=16 base align=8 +QGenericArgument (0x0x7fc1fc524540) 0 + +Class QGenericReturnArgument + size=16 align=8 + base size=16 base align=8 +QGenericReturnArgument (0x0x7fc1fc681c98) 0 + QGenericArgument (0x0x7fc1fc5245a0) 0 + +Class QMetaObject + size=48 align=8 + base size=48 base align=8 +QMetaObject (0x0x7fc1fc524720) 0 + +Class QMetaObject::Connection + size=8 align=8 + base size=8 base align=8 +QMetaObject::Connection (0x0x7fc1fc5247e0) 0 + +Class QLatin1Char + size=1 align=1 + base size=1 base align=1 +QLatin1Char (0x0x7fc1fc1e3840) 0 + +Class QChar + size=2 align=2 + base size=2 base align=2 +QChar (0x0x7fc1fc1e38a0) 0 + +Class QtPrivate::RefCount + size=4 align=4 + base size=4 base align=4 +QtPrivate::RefCount (0x0x7fc1fc1e3d20) 0 + +Class QArrayData + size=24 align=8 + base size=24 base align=8 +QArrayData (0x0x7fc1fc1e3de0) 0 + +Class QtPrivate::QContainerImplHelper + size=1 align=1 + base size=0 base align=1 +QtPrivate::QContainerImplHelper (0x0x7fc1fc2cd240) 0 empty + +Class std::locale + size=8 align=8 + base size=8 base align=8 +std::locale (0x0x7fc1fc2cd2a0) 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 (0x0x7fc1fc2cd300) 0 + vptr=((& std::locale::facet::_ZTVNSt6locale5facetE) + 16u) + +Class std::locale::id + size=8 align=8 + base size=8 base align=8 +std::locale::id (0x0x7fc1fc2cd360) 0 + +Class std::locale::_Impl + size=40 align=8 + base size=40 base align=8 +std::locale::_Impl (0x0x7fc1fc2cd3c0) 0 + +Class std::__cow_string + size=8 align=8 + base size=8 base align=8 +std::__cow_string (0x0x7fc1fc2cd780) 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 (0x0x7fc1fbf75208) 0 + vptr=((& std::logic_error::_ZTVSt11logic_error) + 16u) + std::exception (0x0x7fc1fc2cd840) 0 nearly-empty + primary-for std::logic_error (0x0x7fc1fbf75208) + +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 (0x0x7fc1fbf75270) 0 + vptr=((& std::domain_error::_ZTVSt12domain_error) + 16u) + std::logic_error (0x0x7fc1fbf752d8) 0 + primary-for std::domain_error (0x0x7fc1fbf75270) + std::exception (0x0x7fc1fc2cd8a0) 0 nearly-empty + primary-for std::logic_error (0x0x7fc1fbf752d8) + +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 (0x0x7fc1fbf75340) 0 + vptr=((& std::invalid_argument::_ZTVSt16invalid_argument) + 16u) + std::logic_error (0x0x7fc1fbf753a8) 0 + primary-for std::invalid_argument (0x0x7fc1fbf75340) + std::exception (0x0x7fc1fc2cd900) 0 nearly-empty + primary-for std::logic_error (0x0x7fc1fbf753a8) + +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 (0x0x7fc1fbf75410) 0 + vptr=((& std::length_error::_ZTVSt12length_error) + 16u) + std::logic_error (0x0x7fc1fbf75478) 0 + primary-for std::length_error (0x0x7fc1fbf75410) + std::exception (0x0x7fc1fc2cd960) 0 nearly-empty + primary-for std::logic_error (0x0x7fc1fbf75478) + +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 (0x0x7fc1fbf754e0) 0 + vptr=((& std::out_of_range::_ZTVSt12out_of_range) + 16u) + std::logic_error (0x0x7fc1fbf75548) 0 + primary-for std::out_of_range (0x0x7fc1fbf754e0) + std::exception (0x0x7fc1fc2cd9c0) 0 nearly-empty + primary-for std::logic_error (0x0x7fc1fbf75548) + +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 (0x0x7fc1fbf755b0) 0 + vptr=((& std::runtime_error::_ZTVSt13runtime_error) + 16u) + std::exception (0x0x7fc1fc2cda20) 0 nearly-empty + primary-for std::runtime_error (0x0x7fc1fbf755b0) + +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 (0x0x7fc1fbf75618) 0 + vptr=((& std::range_error::_ZTVSt11range_error) + 16u) + std::runtime_error (0x0x7fc1fbf75680) 0 + primary-for std::range_error (0x0x7fc1fbf75618) + std::exception (0x0x7fc1fc2cda80) 0 nearly-empty + primary-for std::runtime_error (0x0x7fc1fbf75680) + +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 (0x0x7fc1fbf756e8) 0 + vptr=((& std::overflow_error::_ZTVSt14overflow_error) + 16u) + std::runtime_error (0x0x7fc1fbf75750) 0 + primary-for std::overflow_error (0x0x7fc1fbf756e8) + std::exception (0x0x7fc1fc2cdae0) 0 nearly-empty + primary-for std::runtime_error (0x0x7fc1fbf75750) + +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 (0x0x7fc1fbf757b8) 0 + vptr=((& std::underflow_error::_ZTVSt15underflow_error) + 16u) + std::runtime_error (0x0x7fc1fbf75820) 0 + primary-for std::underflow_error (0x0x7fc1fbf757b8) + std::exception (0x0x7fc1fc2cdb40) 0 nearly-empty + primary-for std::runtime_error (0x0x7fc1fbf75820) + +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 (0x0x7fc1fc2cdcc0) 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 (0x0x7fc1fc2cdf00) 0 + +Class std::error_condition + size=16 align=8 + base size=16 base align=8 +std::error_condition (0x0x7fc1fbfd70c0) 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 (0x0x7fc1fbf75d00) 0 + vptr=((& std::system_error::_ZTVSt12system_error) + 16u) + std::runtime_error (0x0x7fc1fbf75d68) 0 + primary-for std::system_error (0x0x7fc1fbf75d00) + std::exception (0x0x7fc1fbfd7300) 0 nearly-empty + primary-for std::runtime_error (0x0x7fc1fbf75d68) + +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 (0x0x7fc1fc00d8f0) 0 + vptr=((& std::ios_base::failure::_ZTVNSt8ios_base7failureB5cxx11E) + 16u) + std::system_error (0x0x7fc1fc00d958) 0 + primary-for std::ios_base::failure (0x0x7fc1fc00d8f0) + std::runtime_error (0x0x7fc1fc00d9c0) 0 + primary-for std::system_error (0x0x7fc1fc00d958) + std::exception (0x0x7fc1fbfd7600) 0 nearly-empty + primary-for std::runtime_error (0x0x7fc1fc00d9c0) + +Class std::ios_base::_Callback_list + size=24 align=8 + base size=24 base align=8 +std::ios_base::_Callback_list (0x0x7fc1fbfd7660) 0 + +Class std::ios_base::_Words + size=16 align=8 + base size=16 base align=8 +std::ios_base::_Words (0x0x7fc1fbfd76c0) 0 + +Class std::ios_base::Init + size=1 align=1 + base size=0 base align=1 +std::ios_base::Init (0x0x7fc1fbfd7720) 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 (0x0x7fc1fbfd75a0) 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 (0x0x7fc1fbfd7ea0) 0 empty + +Class std::__num_base + size=1 align=1 + base size=0 base align=1 +std::__num_base (0x0x7fc1fc14f5a0) 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 (0x0x7fc1fbcd0270 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 (0x0x7fc1fbcd0340 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 (0x0x7fc1fbcd06e8 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 (0x0x7fc1fbcd07b8 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 (0x0x7fc1fbedfe40) 0 + +Class QByteArray + size=8 align=8 + base size=8 base align=8 +QByteArray (0x0x7fc1fbedfea0) 0 + +Class QByteRef + size=16 align=8 + base size=12 base align=8 +QByteRef (0x0x7fc1fba3c300) 0 + +Class QLatin1String + size=16 align=8 + base size=16 base align=8 +QLatin1String (0x0x7fc1fba3c660) 0 + +Class QStringDataPtr + size=8 align=8 + base size=8 base align=8 +QStringDataPtr (0x0x7fc1fba3ca20) 0 + +Class QString::Null + size=1 align=1 + base size=0 base align=1 +QString::Null (0x0x7fc1fba3cae0) 0 empty + +Class QString + size=8 align=8 + base size=8 base align=8 +QString (0x0x7fc1fba3ca80) 0 + +Class QCharRef + size=16 align=8 + base size=12 base align=8 +QCharRef (0x0x7fc1fb868a80) 0 + +Class QStringRef + size=16 align=8 + base size=16 base align=8 +QStringRef (0x0x7fc1fb5f7900) 0 + +Class QtPrivate::QHashCombine + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombine (0x0x7fc1fb39b000) 0 empty + +Class QtPrivate::QHashCombineCommutative + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombineCommutative (0x0x7fc1fb39b060) 0 empty + +Class std::__detail::_List_node_base + size=16 align=8 + base size=16 base align=8 +std::__detail::_List_node_base (0x0x7fc1fb39b0c0) 0 + +Class QListData::NotArrayCompatibleLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotArrayCompatibleLayout (0x0x7fc1fb39b480) 0 empty + +Class QListData::NotIndirectLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotIndirectLayout (0x0x7fc1fb39b4e0) 0 empty + +Class QListData::ArrayCompatibleLayout + size=1 align=1 + base size=1 base align=1 +QListData::ArrayCompatibleLayout (0x0x7fc1fb5f6dd0) 0 empty + QListData::NotIndirectLayout (0x0x7fc1fb39b540) 0 empty + +Class QListData::InlineWithPaddingLayout + size=1 align=1 + base size=1 base align=1 +QListData::InlineWithPaddingLayout (0x0x7fc1fb452d90) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7fc1fb39b5a0) 0 empty + QListData::NotIndirectLayout (0x0x7fc1fb39b600) 0 empty + +Class QListData::IndirectLayout + size=1 align=1 + base size=1 base align=1 +QListData::IndirectLayout (0x0x7fc1fb5f6e38) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7fc1fb39b660) 0 empty + +Class QListData::Data + size=24 align=8 + base size=24 base align=8 +QListData::Data (0x0x7fc1fb39b6c0) 0 + +Class QListData + size=8 align=8 + base size=8 base align=8 +QListData (0x0x7fc1fb39b420) 0 + +Class QRegExp + size=8 align=8 + base size=8 base align=8 +QRegExp (0x0x7fc1fb53d2a0) 0 + +Class QStringMatcher::Data + size=272 align=8 + base size=272 base align=8 +QStringMatcher::Data (0x0x7fc1fb20f540) 0 + +Class QStringMatcher + size=1048 align=8 + base size=1048 base align=8 +QStringMatcher (0x0x7fc1fb20f4e0) 0 + +Class QStringList + size=8 align=8 + base size=8 base align=8 +QStringList (0x0x7fc1fb20c7b8) 0 + QList (0x0x7fc1fb20c820) 0 + QListSpecialMethods (0x0x7fc1fb20f720) 0 empty + +Class QScopedPointerPodDeleter + size=1 align=1 + base size=0 base align=1 +QScopedPointerPodDeleter (0x0x7fc1fb20fba0) 0 empty + +Class std::_Rb_tree_node_base + size=32 align=8 + base size=32 base align=8 +std::_Rb_tree_node_base (0x0x7fc1fb33f000) 0 + +Class std::allocator_arg_t + size=1 align=1 + base size=0 base align=1 +std::allocator_arg_t (0x0x7fc1fb33f660) 0 empty + +Class std::__uses_alloc_base + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc_base (0x0x7fc1fb33f7e0) 0 empty + +Class std::__uses_alloc0::_Sink + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc0::_Sink (0x0x7fc1fb33f8a0) 0 empty + +Class std::__uses_alloc0 + size=1 align=1 + base size=1 base align=1 +std::__uses_alloc0 (0x0x7fc1fb30c7b8) 0 + std::__uses_alloc_base (0x0x7fc1fb33f840) 0 empty + +Class std::_Swallow_assign + size=1 align=1 + base size=0 base align=1 +std::_Swallow_assign (0x0x7fc1fb16f900) 0 empty + +Class QtPrivate::AbstractDebugStreamFunction + size=16 align=8 + base size=16 base align=8 +QtPrivate::AbstractDebugStreamFunction (0x0x7fc1fb16fb40) 0 + +Class QtPrivate::AbstractComparatorFunction + size=24 align=8 + base size=24 base align=8 +QtPrivate::AbstractComparatorFunction (0x0x7fc1fb16fc00) 0 + +Class QtPrivate::AbstractConverterFunction + size=8 align=8 + base size=8 base align=8 +QtPrivate::AbstractConverterFunction (0x0x7fc1fb16fd20) 0 + +Class QMetaType + size=80 align=8 + base size=80 base align=8 +QMetaType (0x0x7fc1fb16fea0) 0 + +Class QtMetaTypePrivate::VariantData + size=24 align=8 + base size=20 base align=8 +QtMetaTypePrivate::VariantData (0x0x7fc1faea82a0) 0 + +Class QtMetaTypePrivate::VectorBoolElements + size=1 align=1 + base size=0 base align=1 +QtMetaTypePrivate::VectorBoolElements (0x0x7fc1faea83c0) 0 empty + +Class QtMetaTypePrivate::QSequentialIterableImpl + size=104 align=8 + base size=104 base align=8 +QtMetaTypePrivate::QSequentialIterableImpl (0x0x7fc1faea8d20) 0 + +Class QtMetaTypePrivate::QAssociativeIterableImpl + size=112 align=8 + base size=112 base align=8 +QtMetaTypePrivate::QAssociativeIterableImpl (0x0x7fc1fab942a0) 0 + +Class QtMetaTypePrivate::QPairVariantInterfaceImpl + size=40 align=8 + base size=40 base align=8 +QtMetaTypePrivate::QPairVariantInterfaceImpl (0x0x7fc1fab94660) 0 + +Class QtPrivate::QSlotObjectBase + size=16 align=8 + base size=16 base align=8 +QtPrivate::QSlotObjectBase (0x0x7fc1fad48720) 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 (0x0x7fc1fad488a0) 0 + vptr=((& QObjectData::_ZTV11QObjectData) + 16u) + +Class QObject::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObject::QPrivateSignal (0x0x7fc1fad48a80) 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 (0x0x7fc1fad48a20) 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 (0x0x7fc1faa39060) 0 nearly-empty + vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16u) + +Class QSignalBlocker + size=16 align=8 + base size=10 base align=8 +QSignalBlocker (0x0x7fc1faa390c0) 0 + +Class QAbstractAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractAnimation::QPrivateSignal (0x0x7fc1faa39180) 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 (0x0x7fc1fa996820) 0 + vptr=((& QAbstractAnimation::_ZTV18QAbstractAnimation) + 16u) + QObject (0x0x7fc1faa39120) 0 + primary-for QAbstractAnimation (0x0x7fc1fa996820) + +Class QAnimationDriver::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationDriver::QPrivateSignal (0x0x7fc1faa39240) 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 (0x0x7fc1fa996888) 0 + vptr=((& QAnimationDriver::_ZTV16QAnimationDriver) + 16u) + QObject (0x0x7fc1faa391e0) 0 + primary-for QAnimationDriver (0x0x7fc1fa996888) + +Class QEventLoop::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventLoop::QPrivateSignal (0x0x7fc1faa39300) 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 (0x0x7fc1fa9968f0) 0 + vptr=((& QEventLoop::_ZTV10QEventLoop) + 16u) + QObject (0x0x7fc1faa392a0) 0 + primary-for QEventLoop (0x0x7fc1fa9968f0) + +Class QEventLoopLocker + size=8 align=8 + base size=8 base align=8 +QEventLoopLocker (0x0x7fc1faa39480) 0 + +Class QAbstractEventDispatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractEventDispatcher::QPrivateSignal (0x0x7fc1faa39540) 0 empty + +Class QAbstractEventDispatcher::TimerInfo + size=12 align=4 + base size=12 base align=4 +QAbstractEventDispatcher::TimerInfo (0x0x7fc1faa395a0) 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 (0x0x7fc1fa996a28) 0 + vptr=((& QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher) + 16u) + QObject (0x0x7fc1faa394e0) 0 + primary-for QAbstractEventDispatcher (0x0x7fc1fa996a28) + +Class QMapNodeBase + size=24 align=8 + base size=24 base align=8 +QMapNodeBase (0x0x7fc1faa39600) 0 + +Class QMapDataBase + size=40 align=8 + base size=40 base align=8 +QMapDataBase (0x0x7fc1faa39840) 0 + +Class QHashData::Node + size=16 align=8 + base size=16 base align=8 +QHashData::Node (0x0x7fc1faa39c00) 0 + +Class QHashData + size=48 align=8 + base size=44 base align=8 +QHashData (0x0x7fc1faa39ba0) 0 + +Class QHashDummyValue + size=1 align=1 + base size=0 base align=1 +QHashDummyValue (0x0x7fc1faa39c60) 0 empty + +Class QVariant::PrivateShared + size=16 align=8 + base size=12 base align=8 +QVariant::PrivateShared (0x0x7fc1fa7f5840) 0 + +Class QVariant::Private::Data + size=8 align=8 + base size=8 base align=8 +QVariant::Private::Data (0x0x7fc1fa7f5900) 0 + +Class QVariant::Private + size=16 align=8 + base size=12 base align=8 +QVariant::Private (0x0x7fc1fa7f58a0) 0 + +Class QVariant::Handler + size=72 align=8 + base size=72 base align=8 +QVariant::Handler (0x0x7fc1fa7f5960) 0 + +Class QVariant + size=16 align=8 + base size=16 base align=8 +QVariant (0x0x7fc1fa7f57e0) 0 + +Class QVariantComparisonHelper + size=8 align=8 + base size=8 base align=8 +QVariantComparisonHelper (0x0x7fc1fa57fde0) 0 + +Class QSequentialIterable::const_iterator + size=112 align=8 + base size=112 base align=8 +QSequentialIterable::const_iterator (0x0x7fc1fa627180) 0 + +Class QSequentialIterable + size=104 align=8 + base size=104 base align=8 +QSequentialIterable (0x0x7fc1fa627120) 0 + +Class QAssociativeIterable::const_iterator + size=120 align=8 + base size=120 base align=8 +QAssociativeIterable::const_iterator (0x0x7fc1fa627240) 0 + +Class QAssociativeIterable + size=112 align=8 + base size=112 base align=8 +QAssociativeIterable (0x0x7fc1fa6271e0) 0 + +Class QModelIndex + size=24 align=8 + base size=24 base align=8 +QModelIndex (0x0x7fc1fa39ac60) 0 + +Class QPersistentModelIndex + size=8 align=8 + base size=8 base align=8 +QPersistentModelIndex (0x0x7fc1fa39af60) 0 + +Class QAbstractItemModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractItemModel::QPrivateSignal (0x0x7fc1fa4bc000) 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 (0x0x7fc1fa4a72d8) 0 + vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16u) + QObject (0x0x7fc1fa48af60) 0 + primary-for QAbstractItemModel (0x0x7fc1fa4a72d8) + +Class QAbstractTableModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTableModel::QPrivateSignal (0x0x7fc1fa4bc360) 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 (0x0x7fc1fa4a74e0) 0 + vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16u) + QAbstractItemModel (0x0x7fc1fa4a7548) 0 + primary-for QAbstractTableModel (0x0x7fc1fa4a74e0) + QObject (0x0x7fc1fa4bc300) 0 + primary-for QAbstractItemModel (0x0x7fc1fa4a7548) + +Class QAbstractListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractListModel::QPrivateSignal (0x0x7fc1fa4bc420) 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 (0x0x7fc1fa4a75b0) 0 + vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16u) + QAbstractItemModel (0x0x7fc1fa4a7618) 0 + primary-for QAbstractListModel (0x0x7fc1fa4a75b0) + QObject (0x0x7fc1fa4bc3c0) 0 + primary-for QAbstractItemModel (0x0x7fc1fa4a7618) + +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 (0x0x7fc1fa4bc6c0) 0 + vptr=((& QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter) + 16u) + +Class QAbstractProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractProxyModel::QPrivateSignal (0x0x7fc1fa4bc780) 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 (0x0x7fc1fa4a7750) 0 + vptr=((& QAbstractProxyModel::_ZTV19QAbstractProxyModel) + 16u) + QAbstractItemModel (0x0x7fc1fa4a77b8) 0 + primary-for QAbstractProxyModel (0x0x7fc1fa4a7750) + QObject (0x0x7fc1fa4bc720) 0 + primary-for QAbstractItemModel (0x0x7fc1fa4a77b8) + +Class QAbstractState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractState::QPrivateSignal (0x0x7fc1fa4bc840) 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 (0x0x7fc1fa4a7820) 0 + vptr=((& QAbstractState::_ZTV14QAbstractState) + 16u) + QObject (0x0x7fc1fa4bc7e0) 0 + primary-for QAbstractState (0x0x7fc1fa4a7820) + +Class QAbstractTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTransition::QPrivateSignal (0x0x7fc1fa4bc900) 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 (0x0x7fc1fa4a7888) 0 + vptr=((& QAbstractTransition::_ZTV19QAbstractTransition) + 16u) + QObject (0x0x7fc1fa4bc8a0) 0 + primary-for QAbstractTransition (0x0x7fc1fa4a7888) + +Class QAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationGroup::QPrivateSignal (0x0x7fc1fa4bc9c0) 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 (0x0x7fc1fa4a78f0) 0 + vptr=((& QAnimationGroup::_ZTV15QAnimationGroup) + 16u) + QAbstractAnimation (0x0x7fc1fa4a7958) 0 + primary-for QAnimationGroup (0x0x7fc1fa4a78f0) + QObject (0x0x7fc1fa4bc960) 0 + primary-for QAbstractAnimation (0x0x7fc1fa4a7958) + +Class QBasicTimer + size=4 align=4 + base size=4 base align=4 +QBasicTimer (0x0x7fc1fa4bcea0) 0 + +Class QBitArray + size=8 align=8 + base size=8 base align=8 +QBitArray (0x0x7fc1fa26d1e0) 0 + +Class QBitRef + size=16 align=8 + base size=12 base align=8 +QBitRef (0x0x7fc1fa26d420) 0 + +Class QIODevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIODevice::QPrivateSignal (0x0x7fc1fa26d7e0) 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 (0x0x7fc1fa235958) 0 + vptr=((& QIODevice::_ZTV9QIODevice) + 16u) + QObject (0x0x7fc1fa26d780) 0 + primary-for QIODevice (0x0x7fc1fa235958) + +Class QBuffer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBuffer::QPrivateSignal (0x0x7fc1fa26d9c0) 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 (0x0x7fc1fa235a90) 0 + vptr=((& QBuffer::_ZTV7QBuffer) + 16u) + QIODevice (0x0x7fc1fa235af8) 0 + primary-for QBuffer (0x0x7fc1fa235a90) + QObject (0x0x7fc1fa26d960) 0 + primary-for QIODevice (0x0x7fc1fa235af8) + +Class QByteArrayMatcher::Data + size=272 align=8 + base size=272 base align=8 +QByteArrayMatcher::Data (0x0x7fc1fa26da80) 0 + +Class QByteArrayMatcher + size=1040 align=8 + base size=1040 base align=8 +QByteArrayMatcher (0x0x7fc1fa26da20) 0 + +Class QSharedData + size=4 align=4 + base size=4 base align=4 +QSharedData (0x0x7fc1fa26dc00) 0 + +Class QLocale + size=8 align=8 + base size=8 base align=8 +QLocale (0x0x7fc1fa26dde0) 0 + +Class QCollatorSortKey + size=8 align=8 + base size=8 base align=8 +QCollatorSortKey (0x0x7fc1fa00a2a0) 0 + +Class QCollator + size=8 align=8 + base size=8 base align=8 +QCollator (0x0x7fc1fa00a360) 0 + +Class QCommandLineOption + size=8 align=8 + base size=8 base align=8 +QCommandLineOption (0x0x7fc1fa0d8420) 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 (0x0x7fc1fa0d88a0) 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 (0x0x7fc1fa0cac30) 0 + vptr=((& QTimerEvent::_ZTV11QTimerEvent) + 16u) + QEvent (0x0x7fc1fa0d8900) 0 + primary-for QTimerEvent (0x0x7fc1fa0cac30) + +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 (0x0x7fc1fa0cac98) 0 + vptr=((& QChildEvent::_ZTV11QChildEvent) + 16u) + QEvent (0x0x7fc1fa0d8960) 0 + primary-for QChildEvent (0x0x7fc1fa0cac98) + +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 (0x0x7fc1fa0cadd0) 0 + vptr=((& QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent) + 16u) + QEvent (0x0x7fc1fa0d8b40) 0 + primary-for QDynamicPropertyChangeEvent (0x0x7fc1fa0cadd0) + +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 (0x0x7fc1fa0cae38) 0 + vptr=((& QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent) + 16u) + QEvent (0x0x7fc1fa0d8ba0) 0 + primary-for QDeferredDeleteEvent (0x0x7fc1fa0cae38) + +Class QCoreApplication::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QCoreApplication::QPrivateSignal (0x0x7fc1fa0d8c60) 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 (0x0x7fc1fa0caea0) 0 + vptr=((& QCoreApplication::_ZTV16QCoreApplication) + 16u) + QObject (0x0x7fc1fa0d8c00) 0 + primary-for QCoreApplication (0x0x7fc1fa0caea0) + +Class QCommandLineParser + size=8 align=8 + base size=8 base align=8 +QCommandLineParser (0x0x7fc1fa0d8cc0) 0 + +Class QContiguousCacheData + size=24 align=4 + base size=24 base align=4 +QContiguousCacheData (0x0x7fc1fa0d8d20) 0 + +Class QCryptographicHash + size=8 align=8 + base size=8 base align=8 +QCryptographicHash (0x0x7fc1f9da5000) 0 + +Class QDataStream + size=32 align=8 + base size=32 base align=8 +QDataStream (0x0x7fc1f9da5060) 0 + +Class QtPrivate::StreamStateSaver + size=16 align=8 + base size=12 base align=8 +QtPrivate::StreamStateSaver (0x0x7fc1f9da5120) 0 + +Class QDate + size=8 align=8 + base size=8 base align=8 +QDate (0x0x7fc1f9da5300) 0 + +Class QTime + size=4 align=4 + base size=4 base align=4 +QTime (0x0x7fc1f9da5600) 0 + +Class QDateTime::ShortData + size=8 align=8 + base size=8 base align=8 +QDateTime::ShortData (0x0x7fc1f9da5ae0) 0 + +Class QDateTime::Data + size=8 align=8 + base size=8 base align=8 +QDateTime::Data (0x0x7fc1f9da5b40) 0 + +Class QDateTime + size=8 align=8 + base size=8 base align=8 +QDateTime (0x0x7fc1f9da5a80) 0 + +Class QElapsedTimer + size=16 align=8 + base size=16 base align=8 +QElapsedTimer (0x0x7fc1f9eec960) 0 + +Class std::chrono::_V2::system_clock + size=1 align=1 + base size=0 base align=1 +std::chrono::_V2::system_clock (0x0x7fc1f9b3fd20) 0 empty + +Class std::chrono::_V2::steady_clock + size=1 align=1 + base size=0 base align=1 +std::chrono::_V2::steady_clock (0x0x7fc1f9ca7ba0) 0 empty + +Class QDeadlineTimer + size=16 align=8 + base size=16 base align=8 +QDeadlineTimer (0x0x7fc1f9ca7c00) 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 (0x0x7fc1f99d1a80) 0 + vptr=((& QTextStream::_ZTV11QTextStream) + 16u) + +Class QTextStreamManipulator + size=40 align=8 + base size=38 base align=8 +QTextStreamManipulator (0x0x7fc1f99d1cc0) 0 + +Class QtSharedPointer::NormalDeleter + size=1 align=1 + base size=0 base align=1 +QtSharedPointer::NormalDeleter (0x0x7fc1f99d1f00) 0 empty + +Class QtSharedPointer::ExternalRefCountData + size=16 align=8 + base size=16 base align=8 +QtSharedPointer::ExternalRefCountData (0x0x7fc1f9b040c0) 0 + +Class QDebug::Stream + size=80 align=8 + base size=76 base align=8 +QDebug::Stream (0x0x7fc1f9b04540) 0 + +Class QDebug + size=8 align=8 + base size=8 base align=8 +QDebug (0x0x7fc1f9b044e0) 0 + +Class QDebugStateSaver + size=8 align=8 + base size=8 base align=8 +QDebugStateSaver (0x0x7fc1f9864780) 0 + +Class QNoDebug + size=1 align=1 + base size=0 base align=1 +QNoDebug (0x0x7fc1f9864840) 0 empty + +Class QFileDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileDevice::QPrivateSignal (0x0x7fc1f9864900) 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 (0x0x7fc1f986c5b0) 0 + vptr=((& QFileDevice::_ZTV11QFileDevice) + 16u) + QIODevice (0x0x7fc1f986c618) 0 + primary-for QFileDevice (0x0x7fc1f986c5b0) + QObject (0x0x7fc1f98648a0) 0 + primary-for QIODevice (0x0x7fc1f986c618) + +Class QFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFile::QPrivateSignal (0x0x7fc1f9864ae0) 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 (0x0x7fc1f986c750) 0 + vptr=((& QFile::_ZTV5QFile) + 16u) + QFileDevice (0x0x7fc1f986c7b8) 0 + primary-for QFile (0x0x7fc1f986c750) + QIODevice (0x0x7fc1f986c820) 0 + primary-for QFileDevice (0x0x7fc1f986c7b8) + QObject (0x0x7fc1f9864a80) 0 + primary-for QIODevice (0x0x7fc1f986c820) + +Class QFileInfo + size=8 align=8 + base size=8 base align=8 +QFileInfo (0x0x7fc1f9864c60) 0 + +Class QDir + size=8 align=8 + base size=8 base align=8 +QDir (0x0x7fc1f9590120) 0 + +Class QDirIterator + size=8 align=8 + base size=8 base align=8 +QDirIterator (0x0x7fc1f95906c0) 0 + +Class QEasingCurve + size=8 align=8 + base size=8 base align=8 +QEasingCurve (0x0x7fc1f95908a0) 0 + +Class QEventTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventTransition::QPrivateSignal (0x0x7fc1f96dbb40) 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 (0x0x7fc1f96e6618) 0 + vptr=((& QEventTransition::_ZTV16QEventTransition) + 16u) + QAbstractTransition (0x0x7fc1f96e6680) 0 + primary-for QEventTransition (0x0x7fc1f96e6618) + QObject (0x0x7fc1f96dbae0) 0 + primary-for QAbstractTransition (0x0x7fc1f96e6680) + +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 (0x0x7fc1f96e66e8) 0 nearly-empty + vptr=((& QException::_ZTV10QException) + 16u) + std::exception (0x0x7fc1f96dbba0) 0 nearly-empty + primary-for QException (0x0x7fc1f96e66e8) + +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 (0x0x7fc1f96e6750) 0 nearly-empty + vptr=((& QUnhandledException::_ZTV19QUnhandledException) + 16u) + QException (0x0x7fc1f96e67b8) 0 nearly-empty + primary-for QUnhandledException (0x0x7fc1f96e6750) + std::exception (0x0x7fc1f96dbc00) 0 nearly-empty + primary-for QException (0x0x7fc1f96e67b8) + +Class QtPrivate::ExceptionHolder + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionHolder (0x0x7fc1f96dbc60) 0 + +Class QtPrivate::ExceptionStore + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionStore (0x0x7fc1f96dbd20) 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 (0x0x7fc1f96dbd80) 0 nearly-empty + vptr=((& QFactoryInterface::_ZTV17QFactoryInterface) + 16u) + +Class QFileSelector::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSelector::QPrivateSignal (0x0x7fc1f96dbea0) 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 (0x0x7fc1f96e6820) 0 + vptr=((& QFileSelector::_ZTV13QFileSelector) + 16u) + QObject (0x0x7fc1f96dbe40) 0 + primary-for QFileSelector (0x0x7fc1f96e6820) + +Class QFileSystemWatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSystemWatcher::QPrivateSignal (0x0x7fc1f96dbf60) 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 (0x0x7fc1f96e6888) 0 + vptr=((& QFileSystemWatcher::_ZTV18QFileSystemWatcher) + 16u) + QObject (0x0x7fc1f96dbf00) 0 + primary-for QFileSystemWatcher (0x0x7fc1f96e6888) + +Class QFinalState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFinalState::QPrivateSignal (0x0x7fc1f936b060) 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 (0x0x7fc1f96e68f0) 0 + vptr=((& QFinalState::_ZTV11QFinalState) + 16u) + QAbstractState (0x0x7fc1f96e6958) 0 + primary-for QFinalState (0x0x7fc1f96e68f0) + QObject (0x0x7fc1f936b000) 0 + primary-for QAbstractState (0x0x7fc1f96e6958) + +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 (0x0x7fc1f936b0c0) 0 + vptr=((& QRunnable::_ZTV9QRunnable) + 16u) + +Class QBasicMutex + size=8 align=8 + base size=8 base align=8 +QBasicMutex (0x0x7fc1f936b120) 0 + +Class QMutex + size=8 align=8 + base size=8 base align=8 +QMutex (0x0x7fc1f96e6a90) 0 + QBasicMutex (0x0x7fc1f936b360) 0 + +Class QMutexLocker + size=8 align=8 + base size=8 base align=8 +QMutexLocker (0x0x7fc1f936b720) 0 + +Class QtPrivate::ResultItem + size=16 align=8 + base size=16 base align=8 +QtPrivate::ResultItem (0x0x7fc1f936b7e0) 0 + +Class QtPrivate::ResultIteratorBase + size=16 align=8 + base size=12 base align=8 +QtPrivate::ResultIteratorBase (0x0x7fc1f936b840) 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 (0x0x7fc1f936b9c0) 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 (0x0x7fc1f936ba80) 0 + vptr=((& QFutureInterfaceBase::_ZTV20QFutureInterfaceBase) + 16u) + +Class QFutureWatcherBase::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFutureWatcherBase::QPrivateSignal (0x0x7fc1f936bde0) 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 (0x0x7fc1f9465680) 0 + vptr=((& QFutureWatcherBase::_ZTV18QFutureWatcherBase) + 16u) + QObject (0x0x7fc1f936bd80) 0 + primary-for QFutureWatcherBase (0x0x7fc1f9465680) + +Class QHistoryState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QHistoryState::QPrivateSignal (0x0x7fc1f936bf60) 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 (0x0x7fc1f9465a90) 0 + vptr=((& QHistoryState::_ZTV13QHistoryState) + 16u) + QAbstractState (0x0x7fc1f9465af8) 0 + primary-for QHistoryState (0x0x7fc1f9465a90) + QObject (0x0x7fc1f936bf00) 0 + primary-for QAbstractState (0x0x7fc1f9465af8) + +Class QIdentityProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIdentityProxyModel::QPrivateSignal (0x0x7fc1f9152060) 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 (0x0x7fc1f9465b60) 0 + vptr=((& QIdentityProxyModel::_ZTV19QIdentityProxyModel) + 16u) + QAbstractProxyModel (0x0x7fc1f9465bc8) 0 + primary-for QIdentityProxyModel (0x0x7fc1f9465b60) + QAbstractItemModel (0x0x7fc1f9465c30) 0 + primary-for QAbstractProxyModel (0x0x7fc1f9465bc8) + QObject (0x0x7fc1f9152000) 0 + primary-for QAbstractItemModel (0x0x7fc1f9465c30) + +Class QItemSelectionRange + size=16 align=8 + base size=16 base align=8 +QItemSelectionRange (0x0x7fc1f91520c0) 0 + +Class QItemSelectionModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QItemSelectionModel::QPrivateSignal (0x0x7fc1f9152480) 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 (0x0x7fc1f9465f70) 0 + vptr=((& QItemSelectionModel::_ZTV19QItemSelectionModel) + 16u) + QObject (0x0x7fc1f9152420) 0 + primary-for QItemSelectionModel (0x0x7fc1f9465f70) + +Class QItemSelection + size=8 align=8 + base size=8 base align=8 +QItemSelection (0x0x7fc1f91cd1a0) 0 + QList (0x0x7fc1f91cd208) 0 + QListSpecialMethods (0x0x7fc1f9152720) 0 empty + +Class QJsonValue + size=24 align=8 + base size=20 base align=8 +QJsonValue (0x0x7fc1f9152c60) 0 + +Class QJsonValueRef + size=16 align=8 + base size=12 base align=8 +QJsonValueRef (0x0x7fc1f9152ea0) 0 + +Class QJsonValuePtr + size=24 align=8 + base size=24 base align=8 +QJsonValuePtr (0x0x7fc1f9152f60) 0 + +Class QJsonValueRefPtr + size=16 align=8 + base size=16 base align=8 +QJsonValueRefPtr (0x0x7fc1f9291000) 0 + +Class QJsonArray::iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::iterator (0x0x7fc1f92910c0) 0 + +Class QJsonArray::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::const_iterator (0x0x7fc1f9291120) 0 + +Class QJsonArray + size=16 align=8 + base size=16 base align=8 +QJsonArray (0x0x7fc1f9291060) 0 + +Class QJsonParseError + size=8 align=4 + base size=8 base align=4 +QJsonParseError (0x0x7fc1f92911e0) 0 + +Class QJsonDocument + size=8 align=8 + base size=8 base align=8 +QJsonDocument (0x0x7fc1f9291240) 0 + +Class QJsonObject::iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::iterator (0x0x7fc1f9291300) 0 + +Class QJsonObject::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::const_iterator (0x0x7fc1f9291360) 0 + +Class QJsonObject + size=16 align=8 + base size=16 base align=8 +QJsonObject (0x0x7fc1f92912a0) 0 + +Class QLibrary::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLibrary::QPrivateSignal (0x0x7fc1f9291540) 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 (0x0x7fc1f91cd618) 0 + vptr=((& QLibrary::_ZTV8QLibrary) + 16u) + QObject (0x0x7fc1f92914e0) 0 + primary-for QLibrary (0x0x7fc1f91cd618) + +Class QVersionNumber::SegmentStorage + size=8 align=8 + base size=8 base align=8 +QVersionNumber::SegmentStorage (0x0x7fc1f9291720) 0 + +Class QVersionNumber + size=8 align=8 + base size=8 base align=8 +QVersionNumber (0x0x7fc1f92916c0) 0 + +Class QLibraryInfo + size=1 align=1 + base size=0 base align=1 +QLibraryInfo (0x0x7fc1f905f4e0) 0 empty + +Class QPoint + size=8 align=4 + base size=8 base align=4 +QPoint (0x0x7fc1f905f540) 0 + +Class QPointF + size=16 align=8 + base size=16 base align=8 +QPointF (0x0x7fc1f905f840) 0 + +Class QLine + size=16 align=4 + base size=16 base align=4 +QLine (0x0x7fc1f905fb40) 0 + +Class QLineF + size=32 align=8 + base size=32 base align=8 +QLineF (0x0x7fc1f905fe40) 0 + +Class QLinkedListData + size=32 align=8 + base size=25 base align=8 +QLinkedListData (0x0x7fc1f8d64180) 0 + +Class QLockFile + size=8 align=8 + base size=8 base align=8 +QLockFile (0x0x7fc1f8d64900) 0 + +Class QLoggingCategory::AtomicBools + size=4 align=1 + base size=4 base align=1 +QLoggingCategory::AtomicBools (0x0x7fc1f8d64a80) 0 + +Class QLoggingCategory + size=24 align=8 + base size=24 base align=8 +QLoggingCategory (0x0x7fc1f8d64a20) 0 + +Class QMargins + size=16 align=4 + base size=16 base align=4 +QMargins (0x0x7fc1f8d64c00) 0 + +Class QMarginsF + size=32 align=8 + base size=32 base align=8 +QMarginsF (0x0x7fc1f8d64f00) 0 + +Class QMessageAuthenticationCode + size=8 align=8 + base size=8 base align=8 +QMessageAuthenticationCode (0x0x7fc1f8ede2a0) 0 + +Class QMetaMethod + size=16 align=8 + base size=12 base align=8 +QMetaMethod (0x0x7fc1f8ede300) 0 + +Class QMetaEnum + size=16 align=8 + base size=12 base align=8 +QMetaEnum (0x0x7fc1f8ede600) 0 + +Class QMetaProperty + size=32 align=8 + base size=32 base align=8 +QMetaProperty (0x0x7fc1f8ede960) 0 + +Class QMetaClassInfo + size=16 align=8 + base size=12 base align=8 +QMetaClassInfo (0x0x7fc1f8ede9c0) 0 + +Class QMimeData::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QMimeData::QPrivateSignal (0x0x7fc1f8eded20) 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 (0x0x7fc1f8b64340) 0 + vptr=((& QMimeData::_ZTV9QMimeData) + 16u) + QObject (0x0x7fc1f8edecc0) 0 + primary-for QMimeData (0x0x7fc1f8b64340) + +Class QMimeType + size=8 align=8 + base size=8 base align=8 +QMimeType (0x0x7fc1f8eded80) 0 + +Class QMimeDatabase + size=8 align=8 + base size=8 base align=8 +QMimeDatabase (0x0x7fc1f8bbc120) 0 + +Class QObjectCleanupHandler::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObjectCleanupHandler::QPrivateSignal (0x0x7fc1f8bbc1e0) 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 (0x0x7fc1f8b644e0) 0 + vptr=((& QObjectCleanupHandler::_ZTV21QObjectCleanupHandler) + 16u) + QObject (0x0x7fc1f8bbc180) 0 + primary-for QObjectCleanupHandler (0x0x7fc1f8b644e0) + +Class QParallelAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QParallelAnimationGroup::QPrivateSignal (0x0x7fc1f8bbc2a0) 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 (0x0x7fc1f8b64548) 0 + vptr=((& QParallelAnimationGroup::_ZTV23QParallelAnimationGroup) + 16u) + QAnimationGroup (0x0x7fc1f8b645b0) 0 + primary-for QParallelAnimationGroup (0x0x7fc1f8b64548) + QAbstractAnimation (0x0x7fc1f8b64618) 0 + primary-for QAnimationGroup (0x0x7fc1f8b645b0) + QObject (0x0x7fc1f8bbc240) 0 + primary-for QAbstractAnimation (0x0x7fc1f8b64618) + +Class QPauseAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPauseAnimation::QPrivateSignal (0x0x7fc1f8bbc360) 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 (0x0x7fc1f8b64680) 0 + vptr=((& QPauseAnimation::_ZTV15QPauseAnimation) + 16u) + QAbstractAnimation (0x0x7fc1f8b646e8) 0 + primary-for QPauseAnimation (0x0x7fc1f8b64680) + QObject (0x0x7fc1f8bbc300) 0 + primary-for QAbstractAnimation (0x0x7fc1f8b646e8) + +Class QStaticPlugin + size=16 align=8 + base size=16 base align=8 +QStaticPlugin (0x0x7fc1f8bbc540) 0 + +Class QPluginLoader::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPluginLoader::QPrivateSignal (0x0x7fc1f8bbc8a0) 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 (0x0x7fc1f8b64888) 0 + vptr=((& QPluginLoader::_ZTV13QPluginLoader) + 16u) + QObject (0x0x7fc1f8bbc840) 0 + primary-for QPluginLoader (0x0x7fc1f8b64888) + +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 (0x0x7fc1f8bbc900) 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 (0x0x7fc1f8b648f0) 0 nearly-empty + vptr=((& std::bad_cast::_ZTVSt8bad_cast) + 16u) + std::exception (0x0x7fc1f8bbc960) 0 nearly-empty + primary-for std::bad_cast (0x0x7fc1f8b648f0) + +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 (0x0x7fc1f8b64958) 0 nearly-empty + vptr=((& std::bad_typeid::_ZTVSt10bad_typeid) + 16u) + std::exception (0x0x7fc1f8bbc9c0) 0 nearly-empty + primary-for std::bad_typeid (0x0x7fc1f8b64958) + +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 (0x0x7fc1f8cdcbc8) 0 nearly-empty + vptr=((& std::bad_function_call::_ZTVSt17bad_function_call) + 16u) + std::exception (0x0x7fc1f893fa80) 0 nearly-empty + primary-for std::bad_function_call (0x0x7fc1f8cdcbc8) + +Class std::_Nocopy_types + size=16 align=8 + base size=16 base align=8 +std::_Nocopy_types (0x0x7fc1f893fb40) 0 + +Class std::_Any_data + size=16 align=8 + base size=16 base align=8 +std::_Any_data (0x0x7fc1f893fba0) 0 + +Class std::_Function_base + size=24 align=8 + base size=24 base align=8 +std::_Function_base (0x0x7fc1f893fcc0) 0 + +Class QProcessEnvironment + size=8 align=8 + base size=8 base align=8 +QProcessEnvironment (0x0x7fc1f8a061e0) 0 + +Class QProcess::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QProcess::QPrivateSignal (0x0x7fc1f8a065a0) 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 (0x0x7fc1f8a034e0) 0 + vptr=((& QProcess::_ZTV8QProcess) + 16u) + QIODevice (0x0x7fc1f8a03548) 0 + primary-for QProcess (0x0x7fc1f8a034e0) + QObject (0x0x7fc1f8a06540) 0 + primary-for QIODevice (0x0x7fc1f8a03548) + +Class QVariantAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QVariantAnimation::QPrivateSignal (0x0x7fc1f8a06660) 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 (0x0x7fc1f8a035b0) 0 + vptr=((& QVariantAnimation::_ZTV17QVariantAnimation) + 16u) + QAbstractAnimation (0x0x7fc1f8a03618) 0 + primary-for QVariantAnimation (0x0x7fc1f8a035b0) + QObject (0x0x7fc1f8a06600) 0 + primary-for QAbstractAnimation (0x0x7fc1f8a03618) + +Class QPropertyAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPropertyAnimation::QPrivateSignal (0x0x7fc1f8a06720) 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 (0x0x7fc1f8a036e8) 0 + vptr=((& QPropertyAnimation::_ZTV18QPropertyAnimation) + 16u) + QVariantAnimation (0x0x7fc1f8a03750) 0 + primary-for QPropertyAnimation (0x0x7fc1f8a036e8) + QAbstractAnimation (0x0x7fc1f8a037b8) 0 + primary-for QVariantAnimation (0x0x7fc1f8a03750) + QObject (0x0x7fc1f8a066c0) 0 + primary-for QAbstractAnimation (0x0x7fc1f8a037b8) + +Class QReadWriteLock + size=8 align=8 + base size=8 base align=8 +QReadWriteLock (0x0x7fc1f8a067e0) 0 + +Class QReadLocker + size=8 align=8 + base size=8 base align=8 +QReadLocker (0x0x7fc1f8a06a80) 0 + +Class QWriteLocker + size=8 align=8 + base size=8 base align=8 +QWriteLocker (0x0x7fc1f8a06ae0) 0 + +Class QSize + size=8 align=4 + base size=8 base align=4 +QSize (0x0x7fc1f8a06b40) 0 + +Class QSizeF + size=16 align=8 + base size=16 base align=8 +QSizeF (0x0x7fc1f8a06f00) 0 + +Class QRect + size=16 align=4 + base size=16 base align=4 +QRect (0x0x7fc1f879c300) 0 + +Class QRectF + size=32 align=8 + base size=32 base align=8 +QRectF (0x0x7fc1f879c600) 0 + +Class QRegularExpression + size=8 align=8 + base size=8 base align=8 +QRegularExpression (0x0x7fc1f879c900) 0 + +Class QRegularExpressionMatch + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatch (0x0x7fc1f879cea0) 0 + +Class QRegularExpressionMatchIterator + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatchIterator (0x0x7fc1f8579240) 0 + +Class QResource + size=8 align=8 + base size=8 base align=8 +QResource (0x0x7fc1f85795a0) 0 + +Class QSaveFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSaveFile::QPrivateSignal (0x0x7fc1f8579720) 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 (0x0x7fc1f87ec7b8) 0 + vptr=((& QSaveFile::_ZTV9QSaveFile) + 16u) + QFileDevice (0x0x7fc1f87ec820) 0 + primary-for QSaveFile (0x0x7fc1f87ec7b8) + QIODevice (0x0x7fc1f87ec888) 0 + primary-for QFileDevice (0x0x7fc1f87ec820) + QObject (0x0x7fc1f85796c0) 0 + primary-for QIODevice (0x0x7fc1f87ec888) + +Class QSemaphore + size=8 align=8 + base size=8 base align=8 +QSemaphore (0x0x7fc1f85797e0) 0 + +Class QSequentialAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSequentialAnimationGroup::QPrivateSignal (0x0x7fc1f85798a0) 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 (0x0x7fc1f87ec8f0) 0 + vptr=((& QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup) + 16u) + QAnimationGroup (0x0x7fc1f87ec958) 0 + primary-for QSequentialAnimationGroup (0x0x7fc1f87ec8f0) + QAbstractAnimation (0x0x7fc1f87ec9c0) 0 + primary-for QAnimationGroup (0x0x7fc1f87ec958) + QObject (0x0x7fc1f8579840) 0 + primary-for QAbstractAnimation (0x0x7fc1f87ec9c0) + +Class QSettings::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSettings::QPrivateSignal (0x0x7fc1f8579960) 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 (0x0x7fc1f87eca28) 0 + vptr=((& QSettings::_ZTV9QSettings) + 16u) + QObject (0x0x7fc1f8579900) 0 + primary-for QSettings (0x0x7fc1f87eca28) + +Class QSharedMemory::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSharedMemory::QPrivateSignal (0x0x7fc1f8579a20) 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 (0x0x7fc1f87eca90) 0 + vptr=((& QSharedMemory::_ZTV13QSharedMemory) + 16u) + QObject (0x0x7fc1f85799c0) 0 + primary-for QSharedMemory (0x0x7fc1f87eca90) + +Class QSignalMapper::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalMapper::QPrivateSignal (0x0x7fc1f8579ae0) 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 (0x0x7fc1f87ecaf8) 0 + vptr=((& QSignalMapper::_ZTV13QSignalMapper) + 16u) + QObject (0x0x7fc1f8579a80) 0 + primary-for QSignalMapper (0x0x7fc1f87ecaf8) + +Class QSignalTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalTransition::QPrivateSignal (0x0x7fc1f8579ba0) 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 (0x0x7fc1f87ecb60) 0 + vptr=((& QSignalTransition::_ZTV17QSignalTransition) + 16u) + QAbstractTransition (0x0x7fc1f87ecbc8) 0 + primary-for QSignalTransition (0x0x7fc1f87ecb60) + QObject (0x0x7fc1f8579b40) 0 + primary-for QAbstractTransition (0x0x7fc1f87ecbc8) + +Class QSocketNotifier::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSocketNotifier::QPrivateSignal (0x0x7fc1f8579c60) 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 (0x0x7fc1f87ecc30) 0 + vptr=((& QSocketNotifier::_ZTV15QSocketNotifier) + 16u) + QObject (0x0x7fc1f8579c00) 0 + primary-for QSocketNotifier (0x0x7fc1f87ecc30) + +Class QSortFilterProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSortFilterProxyModel::QPrivateSignal (0x0x7fc1f8579d20) 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 (0x0x7fc1f87ecc98) 0 + vptr=((& QSortFilterProxyModel::_ZTV21QSortFilterProxyModel) + 16u) + QAbstractProxyModel (0x0x7fc1f87ecd00) 0 + primary-for QSortFilterProxyModel (0x0x7fc1f87ecc98) + QAbstractItemModel (0x0x7fc1f87ecd68) 0 + primary-for QAbstractProxyModel (0x0x7fc1f87ecd00) + QObject (0x0x7fc1f8579cc0) 0 + primary-for QAbstractItemModel (0x0x7fc1f87ecd68) + +Class QStandardPaths + size=1 align=1 + base size=0 base align=1 +QStandardPaths (0x0x7fc1f8579f00) 0 empty + +Class QState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QState::QPrivateSignal (0x0x7fc1f868b120) 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 (0x0x7fc1f87ecf08) 0 + vptr=((& QState::_ZTV6QState) + 16u) + QAbstractState (0x0x7fc1f87ecf70) 0 + primary-for QState (0x0x7fc1f87ecf08) + QObject (0x0x7fc1f868b0c0) 0 + primary-for QAbstractState (0x0x7fc1f87ecf70) + +Class QStateMachine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStateMachine::QPrivateSignal (0x0x7fc1f868b240) 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 (0x0x7fc1f86d1138) 0 + vptr=((& QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE) + 16u) + QEvent (0x0x7fc1f868b2a0) 0 + primary-for QStateMachine::SignalEvent (0x0x7fc1f86d1138) + +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 (0x0x7fc1f86d11a0) 0 + vptr=((& QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE) + 16u) + QEvent (0x0x7fc1f868b300) 0 + primary-for QStateMachine::WrappedEvent (0x0x7fc1f86d11a0) + +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 (0x0x7fc1f86d1000) 0 + vptr=((& QStateMachine::_ZTV13QStateMachine) + 16u) + QState (0x0x7fc1f86d1068) 0 + primary-for QStateMachine (0x0x7fc1f86d1000) + QAbstractState (0x0x7fc1f86d10d0) 0 + primary-for QState (0x0x7fc1f86d1068) + QObject (0x0x7fc1f868b1e0) 0 + primary-for QAbstractState (0x0x7fc1f86d10d0) + +Class QStorageInfo + size=8 align=8 + base size=8 base align=8 +QStorageInfo (0x0x7fc1f868b360) 0 + +Class QAbstractConcatenable + size=1 align=1 + base size=0 base align=1 +QAbstractConcatenable (0x0x7fc1f868b7e0) 0 empty + +Class QStringListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStringListModel::QPrivateSignal (0x0x7fc1f838a2a0) 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 (0x0x7fc1f86d1c30) 0 + vptr=((& QStringListModel::_ZTV16QStringListModel) + 16u) + QAbstractListModel (0x0x7fc1f86d1c98) 0 + primary-for QStringListModel (0x0x7fc1f86d1c30) + QAbstractItemModel (0x0x7fc1f86d1d00) 0 + primary-for QAbstractListModel (0x0x7fc1f86d1c98) + QObject (0x0x7fc1f838a240) 0 + primary-for QAbstractItemModel (0x0x7fc1f86d1d00) + +Class QSystemSemaphore + size=8 align=8 + base size=8 base align=8 +QSystemSemaphore (0x0x7fc1f838a300) 0 + +Class QTemporaryDir + size=8 align=8 + base size=8 base align=8 +QTemporaryDir (0x0x7fc1f838a3c0) 0 + +Class QTemporaryFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTemporaryFile::QPrivateSignal (0x0x7fc1f838a4e0) 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 (0x0x7fc1f86d1d68) 0 + vptr=((& QTemporaryFile::_ZTV14QTemporaryFile) + 16u) + QFile (0x0x7fc1f86d1dd0) 0 + primary-for QTemporaryFile (0x0x7fc1f86d1d68) + QFileDevice (0x0x7fc1f86d1e38) 0 + primary-for QFile (0x0x7fc1f86d1dd0) + QIODevice (0x0x7fc1f86d1ea0) 0 + primary-for QFileDevice (0x0x7fc1f86d1e38) + QObject (0x0x7fc1f838a480) 0 + primary-for QIODevice (0x0x7fc1f86d1ea0) + +Class QTextBoundaryFinder + size=48 align=8 + base size=48 base align=8 +QTextBoundaryFinder (0x0x7fc1f838a540) 0 + +Class QTextCodec::ConverterState + size=32 align=8 + base size=32 base align=8 +QTextCodec::ConverterState (0x0x7fc1f838a720) 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 (0x0x7fc1f838a6c0) 0 nearly-empty + vptr=((& QTextCodec::_ZTV10QTextCodec) + 16u) + +Class QTextEncoder + size=40 align=8 + base size=40 base align=8 +QTextEncoder (0x0x7fc1f838a8a0) 0 + +Class QTextDecoder + size=40 align=8 + base size=40 base align=8 +QTextDecoder (0x0x7fc1f838a900) 0 + +Class QThread::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThread::QPrivateSignal (0x0x7fc1f838a9c0) 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 (0x0x7fc1f84300d0) 0 + vptr=((& QThread::_ZTV7QThread) + 16u) + QObject (0x0x7fc1f838a960) 0 + primary-for QThread (0x0x7fc1f84300d0) + +Class QThreadPool::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThreadPool::QPrivateSignal (0x0x7fc1f838aa80) 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 (0x0x7fc1f8430138) 0 + vptr=((& QThreadPool::_ZTV11QThreadPool) + 16u) + QObject (0x0x7fc1f838aa20) 0 + primary-for QThreadPool (0x0x7fc1f8430138) + +Class QThreadStorageData + size=4 align=4 + base size=4 base align=4 +QThreadStorageData (0x0x7fc1f838aae0) 0 + +Class QTimeLine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimeLine::QPrivateSignal (0x0x7fc1f838ac00) 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 (0x0x7fc1f84301a0) 0 + vptr=((& QTimeLine::_ZTV9QTimeLine) + 16u) + QObject (0x0x7fc1f838aba0) 0 + primary-for QTimeLine (0x0x7fc1f84301a0) + +Class QTimer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimer::QPrivateSignal (0x0x7fc1f838acc0) 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 (0x0x7fc1f8430208) 0 + vptr=((& QTimer::_ZTV6QTimer) + 16u) + QObject (0x0x7fc1f838ac60) 0 + primary-for QTimer (0x0x7fc1f8430208) + +Class QTimeZone::OffsetData + size=32 align=8 + base size=28 base align=8 +QTimeZone::OffsetData (0x0x7fc1f84f8ae0) 0 + +Class QTimeZone + size=8 align=8 + base size=8 base align=8 +QTimeZone (0x0x7fc1f84f8a80) 0 + +Class QTranslator::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTranslator::QPrivateSignal (0x0x7fc1f8146180) 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 (0x0x7fc1f81103a8) 0 + vptr=((& QTranslator::_ZTV11QTranslator) + 16u) + QObject (0x0x7fc1f8146120) 0 + primary-for QTranslator (0x0x7fc1f81103a8) + +Class QUrl + size=8 align=8 + base size=8 base align=8 +QUrl (0x0x7fc1f81462a0) 0 + +Class QUrlQuery + size=8 align=8 + base size=8 base align=8 +QUrlQuery (0x0x7fc1f82598a0) 0 + +Class QUuid + size=16 align=4 + base size=16 base align=4 +QUuid (0x0x7fc1f8259c00) 0 + +Class QWaitCondition + size=8 align=8 + base size=8 base align=8 +QWaitCondition (0x0x7fc1f8259f00) 0 + +Class QXmlStreamStringRef + size=16 align=8 + base size=16 base align=8 +QXmlStreamStringRef (0x0x7fc1f8259f60) 0 + +Class QXmlStreamAttribute + size=80 align=8 + base size=73 base align=8 +QXmlStreamAttribute (0x0x7fc1f7f92540) 0 + +Class QXmlStreamAttributes + size=8 align=8 + base size=8 base align=8 +QXmlStreamAttributes (0x0x7fc1f7f8fc98) 0 + QVector (0x0x7fc1f7f92960) 0 + +Class QXmlStreamNamespaceDeclaration + size=40 align=8 + base size=40 base align=8 +QXmlStreamNamespaceDeclaration (0x0x7fc1f7f929c0) 0 + +Class QXmlStreamNotationDeclaration + size=56 align=8 + base size=56 base align=8 +QXmlStreamNotationDeclaration (0x0x7fc1f7f92cc0) 0 + +Class QXmlStreamEntityDeclaration + size=88 align=8 + base size=88 base align=8 +QXmlStreamEntityDeclaration (0x0x7fc1f8035000) 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 (0x0x7fc1f8035300) 0 nearly-empty + vptr=((& QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver) + 16u) + +Class QXmlStreamReader + size=8 align=8 + base size=8 base align=8 +QXmlStreamReader (0x0x7fc1f8035360) 0 + +Class QXmlStreamWriter + size=8 align=8 + base size=8 base align=8 +QXmlStreamWriter (0x0x7fc1f8035780) 0 + +Class QBluetoothAddress + size=8 align=8 + base size=8 base align=8 +QBluetoothAddress (0x0x7fc1f8035ae0) 0 + +Class QBluetoothDeviceInfo + size=8 align=8 + base size=8 base align=8 +QBluetoothDeviceInfo (0x0x7fc1f8035c60) 0 + +Class QBluetoothDeviceDiscoveryAgent::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothDeviceDiscoveryAgent::QPrivateSignal (0x0x7fc1f7d980c0) 0 empty + +Vtable for QBluetoothDeviceDiscoveryAgent +QBluetoothDeviceDiscoveryAgent::_ZTV30QBluetoothDeviceDiscoveryAgent: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI30QBluetoothDeviceDiscoveryAgent) +16 (int (*)(...))QBluetoothDeviceDiscoveryAgent::metaObject +24 (int (*)(...))QBluetoothDeviceDiscoveryAgent::qt_metacast +32 (int (*)(...))QBluetoothDeviceDiscoveryAgent::qt_metacall +40 (int (*)(...))QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent +48 (int (*)(...))QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent +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 QBluetoothDeviceDiscoveryAgent + size=24 align=8 + base size=24 base align=8 +QBluetoothDeviceDiscoveryAgent (0x0x7fc1f8031820) 0 + vptr=((& QBluetoothDeviceDiscoveryAgent::_ZTV30QBluetoothDeviceDiscoveryAgent) + 16u) + QObject (0x0x7fc1f7d98060) 0 + primary-for QBluetoothDeviceDiscoveryAgent (0x0x7fc1f8031820) + +Class QBluetoothHostInfo + size=8 align=8 + base size=8 base align=8 +QBluetoothHostInfo (0x0x7fc1f7d98240) 0 + +Class QBluetoothLocalDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothLocalDevice::QPrivateSignal (0x0x7fc1f7d98420) 0 empty + +Vtable for QBluetoothLocalDevice +QBluetoothLocalDevice::_ZTV21QBluetoothLocalDevice: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QBluetoothLocalDevice) +16 (int (*)(...))QBluetoothLocalDevice::metaObject +24 (int (*)(...))QBluetoothLocalDevice::qt_metacast +32 (int (*)(...))QBluetoothLocalDevice::qt_metacall +40 (int (*)(...))QBluetoothLocalDevice::~QBluetoothLocalDevice +48 (int (*)(...))QBluetoothLocalDevice::~QBluetoothLocalDevice +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 QBluetoothLocalDevice + size=24 align=8 + base size=24 base align=8 +QBluetoothLocalDevice (0x0x7fc1f8031958) 0 + vptr=((& QBluetoothLocalDevice::_ZTV21QBluetoothLocalDevice) + 16u) + QObject (0x0x7fc1f7d983c0) 0 + primary-for QBluetoothLocalDevice (0x0x7fc1f8031958) + +Class quint128 + size=16 align=1 + base size=16 base align=1 +quint128 (0x0x7fc1f7d987e0) 0 + +Class QBluetoothUuid + size=16 align=4 + base size=16 base align=4 +QBluetoothUuid (0x0x7fc1f80319c0) 0 + QUuid (0x0x7fc1f7d98840) 0 + +Class QBluetoothServiceInfo::Sequence + size=8 align=8 + base size=8 base align=8 +QBluetoothServiceInfo::Sequence (0x0x7fc1f8031a28) 0 + QList (0x0x7fc1f8031a90) 0 + QListSpecialMethods (0x0x7fc1f7d98a80) 0 empty + +Class QBluetoothServiceInfo::Alternative + size=8 align=8 + base size=8 base align=8 +QBluetoothServiceInfo::Alternative (0x0x7fc1f8031af8) 0 + QList (0x0x7fc1f8031b60) 0 + QListSpecialMethods (0x0x7fc1f7d98ae0) 0 empty + +Class QBluetoothServiceInfo + size=16 align=8 + base size=16 base align=8 +QBluetoothServiceInfo (0x0x7fc1f7d98a20) 0 + +Class QAbstractSocket::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractSocket::QPrivateSignal (0x0x7fc1f7d98f60) 0 empty + +Vtable for QAbstractSocket +QAbstractSocket::_ZTV15QAbstractSocket: 41u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QAbstractSocket) +16 (int (*)(...))QAbstractSocket::metaObject +24 (int (*)(...))QAbstractSocket::qt_metacast +32 (int (*)(...))QAbstractSocket::qt_metacall +40 (int (*)(...))QAbstractSocket::~QAbstractSocket +48 (int (*)(...))QAbstractSocket::~QAbstractSocket +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 (*)(...))QAbstractSocket::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QAbstractSocket::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QAbstractSocket::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QAbstractSocket::bytesAvailable +184 (int (*)(...))QAbstractSocket::bytesToWrite +192 (int (*)(...))QAbstractSocket::canReadLine +200 (int (*)(...))QAbstractSocket::waitForReadyRead +208 (int (*)(...))QAbstractSocket::waitForBytesWritten +216 (int (*)(...))QAbstractSocket::readData +224 (int (*)(...))QAbstractSocket::readLineData +232 (int (*)(...))QAbstractSocket::writeData +240 (int (*)(...))QAbstractSocket::resume +248 (int (*)(...))QAbstractSocket::connectToHost +256 (int (*)(...))QAbstractSocket::connectToHost +264 (int (*)(...))QAbstractSocket::disconnectFromHost +272 (int (*)(...))QAbstractSocket::setReadBufferSize +280 (int (*)(...))QAbstractSocket::socketDescriptor +288 (int (*)(...))QAbstractSocket::setSocketDescriptor +296 (int (*)(...))QAbstractSocket::setSocketOption +304 (int (*)(...))QAbstractSocket::socketOption +312 (int (*)(...))QAbstractSocket::waitForConnected +320 (int (*)(...))QAbstractSocket::waitForDisconnected + +Class QAbstractSocket + size=16 align=8 + base size=16 base align=8 +QAbstractSocket (0x0x7fc1f8031dd0) 0 + vptr=((& QAbstractSocket::_ZTV15QAbstractSocket) + 16u) + QIODevice (0x0x7fc1f8031e38) 0 + primary-for QAbstractSocket (0x0x7fc1f8031dd0) + QObject (0x0x7fc1f7d98f00) 0 + primary-for QIODevice (0x0x7fc1f8031e38) + +Class QBluetoothSocket::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothSocket::QPrivateSignal (0x0x7fc1f7efd4e0) 0 empty + +Vtable for QBluetoothSocket +QBluetoothSocket::_ZTV16QBluetoothSocket: 30u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QBluetoothSocket) +16 (int (*)(...))QBluetoothSocket::metaObject +24 (int (*)(...))QBluetoothSocket::qt_metacast +32 (int (*)(...))QBluetoothSocket::qt_metacall +40 (int (*)(...))QBluetoothSocket::~QBluetoothSocket +48 (int (*)(...))QBluetoothSocket::~QBluetoothSocket +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 (*)(...))QBluetoothSocket::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QBluetoothSocket::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QIODevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QBluetoothSocket::bytesAvailable +184 (int (*)(...))QBluetoothSocket::bytesToWrite +192 (int (*)(...))QBluetoothSocket::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QBluetoothSocket::readData +224 (int (*)(...))QIODevice::readLineData +232 (int (*)(...))QBluetoothSocket::writeData + +Class QBluetoothSocket + size=24 align=8 + base size=24 base align=8 +QBluetoothSocket (0x0x7fc1f80311a0) 0 + vptr=((& QBluetoothSocket::_ZTV16QBluetoothSocket) + 16u) + QIODevice (0x0x7fc1f7b70000) 0 + primary-for QBluetoothSocket (0x0x7fc1f80311a0) + QObject (0x0x7fc1f7efd480) 0 + primary-for QIODevice (0x0x7fc1f7b70000) + +Class QBluetoothServer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothServer::QPrivateSignal (0x0x7fc1f7efd5a0) 0 empty + +Vtable for QBluetoothServer +QBluetoothServer::_ZTV16QBluetoothServer: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QBluetoothServer) +16 (int (*)(...))QBluetoothServer::metaObject +24 (int (*)(...))QBluetoothServer::qt_metacast +32 (int (*)(...))QBluetoothServer::qt_metacall +40 (int (*)(...))QBluetoothServer::~QBluetoothServer +48 (int (*)(...))QBluetoothServer::~QBluetoothServer +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 QBluetoothServer + size=24 align=8 + base size=24 base align=8 +QBluetoothServer (0x0x7fc1f7b70068) 0 + vptr=((& QBluetoothServer::_ZTV16QBluetoothServer) + 16u) + QObject (0x0x7fc1f7efd540) 0 + primary-for QBluetoothServer (0x0x7fc1f7b70068) + +Class QBluetoothServiceDiscoveryAgent::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothServiceDiscoveryAgent::QPrivateSignal (0x0x7fc1f7efd660) 0 empty + +Vtable for QBluetoothServiceDiscoveryAgent +QBluetoothServiceDiscoveryAgent::_ZTV31QBluetoothServiceDiscoveryAgent: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI31QBluetoothServiceDiscoveryAgent) +16 (int (*)(...))QBluetoothServiceDiscoveryAgent::metaObject +24 (int (*)(...))QBluetoothServiceDiscoveryAgent::qt_metacast +32 (int (*)(...))QBluetoothServiceDiscoveryAgent::qt_metacall +40 (int (*)(...))QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent +48 (int (*)(...))QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent +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 QBluetoothServiceDiscoveryAgent + size=24 align=8 + base size=24 base align=8 +QBluetoothServiceDiscoveryAgent (0x0x7fc1f7b700d0) 0 + vptr=((& QBluetoothServiceDiscoveryAgent::_ZTV31QBluetoothServiceDiscoveryAgent) + 16u) + QObject (0x0x7fc1f7efd600) 0 + primary-for QBluetoothServiceDiscoveryAgent (0x0x7fc1f7b700d0) + +Class QBluetoothTransferManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothTransferManager::QPrivateSignal (0x0x7fc1f7efd720) 0 empty + +Vtable for QBluetoothTransferManager +QBluetoothTransferManager::_ZTV25QBluetoothTransferManager: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI25QBluetoothTransferManager) +16 (int (*)(...))QBluetoothTransferManager::metaObject +24 (int (*)(...))QBluetoothTransferManager::qt_metacast +32 (int (*)(...))QBluetoothTransferManager::qt_metacall +40 (int (*)(...))QBluetoothTransferManager::~QBluetoothTransferManager +48 (int (*)(...))QBluetoothTransferManager::~QBluetoothTransferManager +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 QBluetoothTransferManager + size=16 align=8 + base size=16 base align=8 +QBluetoothTransferManager (0x0x7fc1f7b70138) 0 + vptr=((& QBluetoothTransferManager::_ZTV25QBluetoothTransferManager) + 16u) + QObject (0x0x7fc1f7efd6c0) 0 + primary-for QBluetoothTransferManager (0x0x7fc1f7b70138) + +Class QBluetoothTransferRequest + size=8 align=8 + base size=8 base align=8 +QBluetoothTransferRequest (0x0x7fc1f7efd780) 0 + +Class QBluetoothTransferReply::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothTransferReply::QPrivateSignal (0x0x7fc1f7efd840) 0 empty + +Vtable for QBluetoothTransferReply +QBluetoothTransferReply::_ZTV23QBluetoothTransferReply: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI23QBluetoothTransferReply) +16 (int (*)(...))QBluetoothTransferReply::metaObject +24 (int (*)(...))QBluetoothTransferReply::qt_metacast +32 (int (*)(...))QBluetoothTransferReply::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 + +Class QBluetoothTransferReply + size=24 align=8 + base size=24 base align=8 +QBluetoothTransferReply (0x0x7fc1f7b701a0) 0 + vptr=((& QBluetoothTransferReply::_ZTV23QBluetoothTransferReply) + 16u) + QObject (0x0x7fc1f7efd7e0) 0 + primary-for QBluetoothTransferReply (0x0x7fc1f7b701a0) + +Class QLowEnergyAdvertisingData + size=8 align=8 + base size=8 base align=8 +QLowEnergyAdvertisingData (0x0x7fc1f7efd9c0) 0 + +Class QLowEnergyDescriptor + size=24 align=8 + base size=24 base align=8 +QLowEnergyDescriptor (0x0x7fc1f7efdd20) 0 + +Class QLowEnergyCharacteristic + size=24 align=8 + base size=24 base align=8 +QLowEnergyCharacteristic (0x0x7fc1f7efdde0) 0 + +Class QLowEnergyService::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLowEnergyService::QPrivateSignal (0x0x7fc1f7c74000) 0 empty + +Vtable for QLowEnergyService +QLowEnergyService::_ZTV17QLowEnergyService: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QLowEnergyService) +16 (int (*)(...))QLowEnergyService::metaObject +24 (int (*)(...))QLowEnergyService::qt_metacast +32 (int (*)(...))QLowEnergyService::qt_metacall +40 (int (*)(...))QLowEnergyService::~QLowEnergyService +48 (int (*)(...))QLowEnergyService::~QLowEnergyService +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 QLowEnergyService + size=32 align=8 + base size=32 base align=8 +QLowEnergyService (0x0x7fc1f7b70410) 0 + vptr=((& QLowEnergyService::_ZTV17QLowEnergyService) + 16u) + QObject (0x0x7fc1f7efdf60) 0 + primary-for QLowEnergyService (0x0x7fc1f7b70410) + +Class QLowEnergyController::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLowEnergyController::QPrivateSignal (0x0x7fc1f7c74660) 0 empty + +Vtable for QLowEnergyController +QLowEnergyController::_ZTV20QLowEnergyController: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI20QLowEnergyController) +16 (int (*)(...))QLowEnergyController::metaObject +24 (int (*)(...))QLowEnergyController::qt_metacast +32 (int (*)(...))QLowEnergyController::qt_metacall +40 (int (*)(...))QLowEnergyController::~QLowEnergyController +48 (int (*)(...))QLowEnergyController::~QLowEnergyController +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 QLowEnergyController + size=24 align=8 + base size=24 base align=8 +QLowEnergyController (0x0x7fc1f7b70548) 0 + vptr=((& QLowEnergyController::_ZTV20QLowEnergyController) + 16u) + QObject (0x0x7fc1f7c74600) 0 + primary-for QLowEnergyController (0x0x7fc1f7b70548) + +Class QLowEnergyAdvertisingParameters::AddressInfo + size=16 align=8 + base size=12 base align=8 +QLowEnergyAdvertisingParameters::AddressInfo (0x0x7fc1f7c74ba0) 0 + +Class QLowEnergyAdvertisingParameters + size=8 align=8 + base size=8 base align=8 +QLowEnergyAdvertisingParameters (0x0x7fc1f7c74b40) 0 + +Class QLowEnergyCharacteristicData + size=8 align=8 + base size=8 base align=8 +QLowEnergyCharacteristicData (0x0x7fc1f79370c0) 0 + +Class QLowEnergyConnectionParameters + size=8 align=8 + base size=8 base align=8 +QLowEnergyConnectionParameters (0x0x7fc1f7937420) 0 + +Class QLowEnergyDescriptorData + size=8 align=8 + base size=8 base align=8 +QLowEnergyDescriptorData (0x0x7fc1f79378a0) 0 + +Class QLowEnergyServiceData + size=8 align=8 + base size=8 base align=8 +QLowEnergyServiceData (0x0x7fc1f7937c00) 0 + diff --git a/tests/auto/bic/data/QtBluetooth.5.9.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtBluetooth.5.9.0.linux-gcc-amd64.txt new file mode 100644 index 0000000..a5d85e0 --- /dev/null +++ b/tests/auto/bic/data/QtBluetooth.5.9.0.linux-gcc-amd64.txt @@ -0,0 +1,4667 @@ +Class std::__failure_type + size=1 align=1 + base size=0 base align=1 +std::__failure_type (0x0x7f663d2f2d20) 0 empty + +Class std::__do_is_destructible_impl + size=1 align=1 + base size=0 base align=1 +std::__do_is_destructible_impl (0x0x7f663d3824e0) 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 (0x0x7f663d382720) 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 (0x0x7f663d382960) 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 (0x0x7f663d382ba0) 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 (0x0x7f663d382d20) 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 (0x0x7f663afb9120) 0 empty + +Class std::__do_common_type_impl + size=1 align=1 + base size=0 base align=1 +std::__do_common_type_impl (0x0x7f663b03b8a0) 0 empty + +Class std::__do_member_type_wrapper + size=1 align=1 + base size=0 base align=1 +std::__do_member_type_wrapper (0x0x7f663b03b960) 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 (0x0x7f663b03bcc0) 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 (0x0x7f663b03bd80) 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 (0x0x7f663b03be40) 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 (0x0x7f663b03bf00) 0 empty + +Class std::__result_of_other_impl + size=1 align=1 + base size=0 base align=1 +std::__result_of_other_impl (0x0x7f663b0721e0) 0 empty + +Class std::piecewise_construct_t + size=1 align=1 + base size=0 base align=1 +std::piecewise_construct_t (0x0x7f663b0723c0) 0 empty + +Class std::__true_type + size=1 align=1 + base size=0 base align=1 +std::__true_type (0x0x7f663b072840) 0 empty + +Class std::__false_type + size=1 align=1 + base size=0 base align=1 +std::__false_type (0x0x7f663b0728a0) 0 empty + +Class std::input_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::input_iterator_tag (0x0x7f663b11e540) 0 empty + +Class std::output_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::output_iterator_tag (0x0x7f663b11e5a0) 0 empty + +Class std::forward_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::forward_iterator_tag (0x0x7f663b065548) 0 empty + std::input_iterator_tag (0x0x7f663b11e600) 0 empty + +Class std::bidirectional_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::bidirectional_iterator_tag (0x0x7f663b0655b0) 0 empty + std::forward_iterator_tag (0x0x7f663b065618) 0 empty + std::input_iterator_tag (0x0x7f663b11e660) 0 empty + +Class std::random_access_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::random_access_iterator_tag (0x0x7f663b065680) 0 empty + std::bidirectional_iterator_tag (0x0x7f663b0656e8) 0 empty + std::forward_iterator_tag (0x0x7f663b065750) 0 empty + std::input_iterator_tag (0x0x7f663b11e6c0) 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 (0x0x7f663b161360) 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 (0x0x7f663b1613c0) 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 (0x0x7f663b161420) 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 (0x0x7f663b161480) 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 (0x0x7f663b1614e0) 0 empty + +Class wait + size=4 align=4 + base size=4 base align=4 +wait (0x0x7f663ae89000) 0 + +Class __locale_struct + size=232 align=8 + base size=232 base align=8 +__locale_struct (0x0x7f663ae89240) 0 + +Class timespec + size=16 align=8 + base size=16 base align=8 +timespec (0x0x7f663ae89300) 0 + +Class timeval + size=16 align=8 + base size=16 base align=8 +timeval (0x0x7f663ae89360) 0 + +Class pthread_attr_t + size=56 align=8 + base size=56 base align=8 +pthread_attr_t (0x0x7f663ae89420) 0 + +Class __pthread_internal_list + size=16 align=8 + base size=16 base align=8 +__pthread_internal_list (0x0x7f663ae89480) 0 + +Class random_data + size=48 align=8 + base size=48 base align=8 +random_data (0x0x7f663ae89900) 0 + +Class drand48_data + size=24 align=8 + base size=24 base align=8 +drand48_data (0x0x7f663ae89960) 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 (0x0x7f663ae899c0) 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 (0x0x7f663b065c98) 0 nearly-empty + vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16u) + std::exception (0x0x7f663ae89a20) 0 nearly-empty + primary-for std::bad_exception (0x0x7f663b065c98) + +Class std::__exception_ptr::exception_ptr + size=8 align=8 + base size=8 base align=8 +std::__exception_ptr::exception_ptr (0x0x7f663ae89a80) 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 (0x0x7f663ae89ae0) 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 (0x0x7f663b065ea0) 0 nearly-empty + vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16u) + std::exception (0x0x7f663ae89f00) 0 nearly-empty + primary-for std::bad_alloc (0x0x7f663b065ea0) + +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 (0x0x7f663b065f08) 0 nearly-empty + vptr=((& std::bad_array_new_length::_ZTVSt20bad_array_new_length) + 16u) + std::bad_alloc (0x0x7f663b065f70) 0 nearly-empty + primary-for std::bad_array_new_length (0x0x7f663b065f08) + std::exception (0x0x7f663ae89f60) 0 nearly-empty + primary-for std::bad_alloc (0x0x7f663b065f70) + +Class std::nothrow_t + size=1 align=1 + base size=0 base align=1 +std::nothrow_t (0x0x7f663afa7000) 0 empty + +Class __exception + size=40 align=8 + base size=40 base align=8 +__exception (0x0x7f663afa7c00) 0 + +Class lconv + size=96 align=8 + base size=96 base align=8 +lconv (0x0x7f663ada4900) 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 (0x0x7f663ada4960) 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 (0x0x7f663aa99840) 0 + +Class __sched_param + size=4 align=4 + base size=4 base align=4 +__sched_param (0x0x7f663aa998a0) 0 + +Class timex + size=208 align=8 + base size=208 base align=8 +timex (0x0x7f663aa99960) 0 + +Class tm + size=56 align=8 + base size=56 base align=8 +tm (0x0x7f663aa999c0) 0 + +Class itimerspec + size=32 align=8 + base size=32 base align=8 +itimerspec (0x0x7f663aa99a20) 0 + +Class _pthread_cleanup_buffer + size=32 align=8 + base size=32 base align=8 +_pthread_cleanup_buffer (0x0x7f663aa99a80) 0 + +Class __pthread_cleanup_frame + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_frame (0x0x7f663aa99ba0) 0 + +Class __pthread_cleanup_class + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_class (0x0x7f663aa99c00) 0 + +Class _IO_marker + size=24 align=8 + base size=24 base align=8 +_IO_marker (0x0x7f663a84d060) 0 + +Class _IO_FILE + size=216 align=8 + base size=216 base align=8 +_IO_FILE (0x0x7f663a84d0c0) 0 + +Class std::_Hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Hash_impl (0x0x7f663a5ed8a0) 0 empty + +Class std::_Fnv_hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Fnv_hash_impl (0x0x7f663a5ed900) 0 empty + +Class std::__numeric_limits_base + size=1 align=1 + base size=0 base align=1 +std::__numeric_limits_base (0x0x7f663a6238a0) 0 empty + +Class std::_Bit_reference + size=16 align=8 + base size=16 base align=8 +std::_Bit_reference (0x0x7f663a41b6c0) 0 + +Class std::_Bit_iterator_base + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator_base (0x0x7f663a609d00) 0 + std::iterator (0x0x7f663a41b780) 0 empty + +Class std::_Bit_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator (0x0x7f663a609d68) 0 + std::_Bit_iterator_base (0x0x7f663a609dd0) 0 + std::iterator (0x0x7f663a41b7e0) 0 empty + +Class std::_Bit_const_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_const_iterator (0x0x7f663a609e38) 0 + std::_Bit_iterator_base (0x0x7f663a609ea0) 0 + std::iterator (0x0x7f663a41b840) 0 empty + +Class std::random_device + size=5000 align=8 + base size=5000 base align=8 +std::random_device (0x0x7f663a249660) 0 + +Class std::bernoulli_distribution::param_type + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution::param_type (0x0x7f663a347420) 0 + +Class std::bernoulli_distribution + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution (0x0x7f663a3473c0) 0 + +Class std::seed_seq + size=24 align=8 + base size=24 base align=8 +std::seed_seq (0x0x7f663a0e33c0) 0 + +Class qIsNull(double)::U + size=8 align=8 + base size=8 base align=8 +qIsNull(double)::U (0x0x7f6638ea9e40) 0 + +Class qIsNull(float)::U + size=4 align=4 + base size=4 base align=4 +qIsNull(float)::U (0x0x7f6638ea9ea0) 0 + +Class QSysInfo + size=1 align=1 + base size=0 base align=1 +QSysInfo (0x0x7f6638cdc9c0) 0 empty + +Class QMessageLogContext + size=32 align=8 + base size=32 base align=8 +QMessageLogContext (0x0x7f6638cdca20) 0 + +Class QMessageLogger + size=32 align=8 + base size=32 base align=8 +QMessageLogger (0x0x7f6638cdca80) 0 + +Class QFlag + size=4 align=4 + base size=4 base align=4 +QFlag (0x0x7f6638cdcae0) 0 + +Class QIncompatibleFlag + size=4 align=4 + base size=4 base align=4 +QIncompatibleFlag (0x0x7f6638cdcd80) 0 + +Class std::__atomic_flag_base + size=1 align=1 + base size=1 base align=1 +std::__atomic_flag_base (0x0x7f6638d48300) 0 + +Class std::atomic_flag + size=1 align=1 + base size=1 base align=1 +std::atomic_flag (0x0x7f6638cdbb60) 0 + std::__atomic_flag_base (0x0x7f6638d48360) 0 + +Class QAtomicInt + size=4 align=4 + base size=4 base align=4 +QAtomicInt (0x0x7f66387e92d8) 0 + QAtomicInteger (0x0x7f66387e9340) 0 + QBasicAtomicInteger (0x0x7f6638b8ea80) 0 + +Class QInternal + size=1 align=1 + base size=0 base align=1 +QInternal (0x0x7f6638705f60) 0 empty + +Class QGenericArgument + size=16 align=8 + base size=16 base align=8 +QGenericArgument (0x0x7f66385a2000) 0 + +Class QGenericReturnArgument + size=16 align=8 + base size=16 base align=8 +QGenericReturnArgument (0x0x7f66386debc8) 0 + QGenericArgument (0x0x7f66385a2060) 0 + +Class QMetaObject + size=48 align=8 + base size=48 base align=8 +QMetaObject (0x0x7f66385a21e0) 0 + +Class QMetaObject::Connection + size=8 align=8 + base size=8 base align=8 +QMetaObject::Connection (0x0x7f66385a22a0) 0 + +Class QLatin1Char + size=1 align=1 + base size=1 base align=1 +QLatin1Char (0x0x7f6638258300) 0 + +Class QChar + size=2 align=2 + base size=2 base align=2 +QChar (0x0x7f6638258360) 0 + +Class QtPrivate::RefCount + size=4 align=4 + base size=4 base align=4 +QtPrivate::RefCount (0x0x7f6638258600) 0 + +Class QArrayData + size=24 align=8 + base size=24 base align=8 +QArrayData (0x0x7f66382586c0) 0 + +Class QtPrivate::QContainerImplHelper + size=1 align=1 + base size=0 base align=1 +QtPrivate::QContainerImplHelper (0x0x7f6638258b40) 0 empty + +Class std::locale + size=8 align=8 + base size=8 base align=8 +std::locale (0x0x7f6638258ba0) 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 (0x0x7f6638258c00) 0 + vptr=((& std::locale::facet::_ZTVNSt6locale5facetE) + 16u) + +Class std::locale::id + size=8 align=8 + base size=8 base align=8 +std::locale::id (0x0x7f6638258c60) 0 + +Class std::locale::_Impl + size=40 align=8 + base size=40 base align=8 +std::locale::_Impl (0x0x7f6638258cc0) 0 + +Class std::__cow_string + size=8 align=8 + base size=8 base align=8 +std::__cow_string (0x0x7f6637fe80c0) 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 (0x0x7f6637fe7138) 0 + vptr=((& std::logic_error::_ZTVSt11logic_error) + 16u) + std::exception (0x0x7f6637fe8180) 0 nearly-empty + primary-for std::logic_error (0x0x7f6637fe7138) + +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 (0x0x7f6637fe71a0) 0 + vptr=((& std::domain_error::_ZTVSt12domain_error) + 16u) + std::logic_error (0x0x7f6637fe7208) 0 + primary-for std::domain_error (0x0x7f6637fe71a0) + std::exception (0x0x7f6637fe81e0) 0 nearly-empty + primary-for std::logic_error (0x0x7f6637fe7208) + +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 (0x0x7f6637fe7270) 0 + vptr=((& std::invalid_argument::_ZTVSt16invalid_argument) + 16u) + std::logic_error (0x0x7f6637fe72d8) 0 + primary-for std::invalid_argument (0x0x7f6637fe7270) + std::exception (0x0x7f6637fe8240) 0 nearly-empty + primary-for std::logic_error (0x0x7f6637fe72d8) + +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 (0x0x7f6637fe7340) 0 + vptr=((& std::length_error::_ZTVSt12length_error) + 16u) + std::logic_error (0x0x7f6637fe73a8) 0 + primary-for std::length_error (0x0x7f6637fe7340) + std::exception (0x0x7f6637fe82a0) 0 nearly-empty + primary-for std::logic_error (0x0x7f6637fe73a8) + +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 (0x0x7f6637fe7410) 0 + vptr=((& std::out_of_range::_ZTVSt12out_of_range) + 16u) + std::logic_error (0x0x7f6637fe7478) 0 + primary-for std::out_of_range (0x0x7f6637fe7410) + std::exception (0x0x7f6637fe8300) 0 nearly-empty + primary-for std::logic_error (0x0x7f6637fe7478) + +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 (0x0x7f6637fe74e0) 0 + vptr=((& std::runtime_error::_ZTVSt13runtime_error) + 16u) + std::exception (0x0x7f6637fe8360) 0 nearly-empty + primary-for std::runtime_error (0x0x7f6637fe74e0) + +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 (0x0x7f6637fe7548) 0 + vptr=((& std::range_error::_ZTVSt11range_error) + 16u) + std::runtime_error (0x0x7f6637fe75b0) 0 + primary-for std::range_error (0x0x7f6637fe7548) + std::exception (0x0x7f6637fe83c0) 0 nearly-empty + primary-for std::runtime_error (0x0x7f6637fe75b0) + +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 (0x0x7f6637fe7618) 0 + vptr=((& std::overflow_error::_ZTVSt14overflow_error) + 16u) + std::runtime_error (0x0x7f6637fe7680) 0 + primary-for std::overflow_error (0x0x7f6637fe7618) + std::exception (0x0x7f6637fe8420) 0 nearly-empty + primary-for std::runtime_error (0x0x7f6637fe7680) + +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 (0x0x7f6637fe76e8) 0 + vptr=((& std::underflow_error::_ZTVSt15underflow_error) + 16u) + std::runtime_error (0x0x7f6637fe7750) 0 + primary-for std::underflow_error (0x0x7f6637fe76e8) + std::exception (0x0x7f6637fe8480) 0 nearly-empty + primary-for std::runtime_error (0x0x7f6637fe7750) + +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 (0x0x7f6637fe8600) 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 (0x0x7f6637fe8840) 0 + +Class std::error_condition + size=16 align=8 + base size=16 base align=8 +std::error_condition (0x0x7f6637fe89c0) 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 (0x0x7f6637fe7c30) 0 + vptr=((& std::system_error::_ZTVSt12system_error) + 16u) + std::runtime_error (0x0x7f6637fe7c98) 0 + primary-for std::system_error (0x0x7f6637fe7c30) + std::exception (0x0x7f6637fe8c00) 0 nearly-empty + primary-for std::runtime_error (0x0x7f6637fe7c98) + +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 (0x0x7f6638082888) 0 + vptr=((& std::ios_base::failure::_ZTVNSt8ios_base7failureB5cxx11E) + 16u) + std::system_error (0x0x7f66380828f0) 0 + primary-for std::ios_base::failure (0x0x7f6638082888) + std::runtime_error (0x0x7f6638082958) 0 + primary-for std::system_error (0x0x7f66380828f0) + std::exception (0x0x7f6637fe8f00) 0 nearly-empty + primary-for std::runtime_error (0x0x7f6638082958) + +Class std::ios_base::_Callback_list + size=24 align=8 + base size=24 base align=8 +std::ios_base::_Callback_list (0x0x7f6637fe8f60) 0 + +Class std::ios_base::_Words + size=16 align=8 + base size=16 base align=8 +std::ios_base::_Words (0x0x7f66380c5000) 0 + +Class std::ios_base::Init + size=1 align=1 + base size=0 base align=1 +std::ios_base::Init (0x0x7f66380c5060) 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 (0x0x7f6637fe8ea0) 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 (0x0x7f66380c57e0) 0 empty + +Class std::__num_base + size=1 align=1 + base size=0 base align=1 +std::__num_base (0x0x7f66380c5ea0) 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 (0x0x7f6637d48208 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 (0x0x7f6637d482d8 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 (0x0x7f6637d48680 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 (0x0x7f6637d48750 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 (0x0x7f6637c76780) 0 + +Class QByteArray + size=8 align=8 + base size=8 base align=8 +QByteArray (0x0x7f6637c767e0) 0 + +Class QByteRef + size=16 align=8 + base size=12 base align=8 +QByteRef (0x0x7f6637a87c60) 0 + +Class QLatin1String + size=16 align=8 + base size=16 base align=8 +QLatin1String (0x0x7f6637a87f60) 0 + +Class QStringDataPtr + size=8 align=8 + base size=8 base align=8 +QStringDataPtr (0x0x7f6637b81300) 0 + +Class QString::Null + size=1 align=1 + base size=0 base align=1 +QString::Null (0x0x7f6637b813c0) 0 empty + +Class QString + size=8 align=8 + base size=8 base align=8 +QString (0x0x7f6637b81360) 0 + +Class QCharRef + size=16 align=8 + base size=12 base align=8 +QCharRef (0x0x7f66379433c0) 0 + +Class QStringRef + size=16 align=8 + base size=16 base align=8 +QStringRef (0x0x7f66376a4180) 0 + +Class QtPrivate::QHashCombine + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombine (0x0x7f66376a46c0) 0 empty + +Class QtPrivate::QHashCombineCommutative + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombineCommutative (0x0x7f66376a4720) 0 empty + +Class std::__detail::_List_node_base + size=16 align=8 + base size=16 base align=8 +std::__detail::_List_node_base (0x0x7f66376a4780) 0 + +Class QListData::NotArrayCompatibleLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotArrayCompatibleLayout (0x0x7f66376a4b40) 0 empty + +Class QListData::NotIndirectLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotIndirectLayout (0x0x7f66376a4ba0) 0 empty + +Class QListData::ArrayCompatibleLayout + size=1 align=1 + base size=1 base align=1 +QListData::ArrayCompatibleLayout (0x0x7f6637670e38) 0 empty + QListData::NotIndirectLayout (0x0x7f66376a4c00) 0 empty + +Class QListData::InlineWithPaddingLayout + size=1 align=1 + base size=1 base align=1 +QListData::InlineWithPaddingLayout (0x0x7f66374d1d90) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7f66376a4c60) 0 empty + QListData::NotIndirectLayout (0x0x7f66376a4cc0) 0 empty + +Class QListData::IndirectLayout + size=1 align=1 + base size=1 base align=1 +QListData::IndirectLayout (0x0x7f6637670ea0) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7f66376a4d20) 0 empty + +Class QListData::Data + size=24 align=8 + base size=24 base align=8 +QListData::Data (0x0x7f66376a4d80) 0 + +Class QListData + size=8 align=8 + base size=8 base align=8 +QListData (0x0x7f66376a4ae0) 0 + +Class QRegExp + size=8 align=8 + base size=8 base align=8 +QRegExp (0x0x7f6637505960) 0 + +Class QStringMatcher::Data + size=272 align=8 + base size=272 base align=8 +QStringMatcher::Data (0x0x7f6637271ba0) 0 + +Class QStringMatcher + size=1048 align=8 + base size=1048 base align=8 +QStringMatcher (0x0x7f6637271b40) 0 + +Class QStringList + size=8 align=8 + base size=8 base align=8 +QStringList (0x0x7f6637278888) 0 + QList (0x0x7f66372788f0) 0 + QListSpecialMethods (0x0x7f6637271d80) 0 empty + +Class QScopedPointerPodDeleter + size=1 align=1 + base size=0 base align=1 +QScopedPointerPodDeleter (0x0x7f66372ec1e0) 0 empty + +Class std::_Rb_tree_node_base + size=32 align=8 + base size=32 base align=8 +std::_Rb_tree_node_base (0x0x7f66372ec600) 0 + +Class std::allocator_arg_t + size=1 align=1 + base size=0 base align=1 +std::allocator_arg_t (0x0x7f66372ecc60) 0 empty + +Class std::__uses_alloc_base + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc_base (0x0x7f66372ecde0) 0 empty + +Class std::__uses_alloc0::_Sink + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc0::_Sink (0x0x7f66372ecea0) 0 empty + +Class std::__uses_alloc0 + size=1 align=1 + base size=1 base align=1 +std::__uses_alloc0 (0x0x7f663735ea28) 0 + std::__uses_alloc_base (0x0x7f66372ece40) 0 empty + +Class std::_Swallow_assign + size=1 align=1 + base size=0 base align=1 +std::_Swallow_assign (0x0x7f6637127f00) 0 empty + +Class QtPrivate::AbstractDebugStreamFunction + size=16 align=8 + base size=16 base align=8 +QtPrivate::AbstractDebugStreamFunction (0x0x7f6636e2c180) 0 + +Class QtPrivate::AbstractComparatorFunction + size=24 align=8 + base size=24 base align=8 +QtPrivate::AbstractComparatorFunction (0x0x7f6636e2c240) 0 + +Class QtPrivate::AbstractConverterFunction + size=8 align=8 + base size=8 base align=8 +QtPrivate::AbstractConverterFunction (0x0x7f6636e2c360) 0 + +Class QMetaType + size=80 align=8 + base size=80 base align=8 +QMetaType (0x0x7f6636e2c4e0) 0 + +Class QtMetaTypePrivate::VariantData + size=24 align=8 + base size=20 base align=8 +QtMetaTypePrivate::VariantData (0x0x7f6636e2c900) 0 + +Class QtMetaTypePrivate::VectorBoolElements + size=1 align=1 + base size=0 base align=1 +QtMetaTypePrivate::VectorBoolElements (0x0x7f6636e2ca20) 0 empty + +Class QtMetaTypePrivate::QSequentialIterableImpl + size=104 align=8 + base size=104 base align=8 +QtMetaTypePrivate::QSequentialIterableImpl (0x0x7f6636bde3c0) 0 + +Class QtMetaTypePrivate::QAssociativeIterableImpl + size=112 align=8 + base size=112 base align=8 +QtMetaTypePrivate::QAssociativeIterableImpl (0x0x7f6636bde8a0) 0 + +Class QtMetaTypePrivate::QPairVariantInterfaceImpl + size=40 align=8 + base size=40 base align=8 +QtMetaTypePrivate::QPairVariantInterfaceImpl (0x0x7f6636bdec00) 0 + +Class QtPrivate::QSlotObjectBase + size=16 align=8 + base size=16 base align=8 +QtPrivate::QSlotObjectBase (0x0x7f66369a6ae0) 0 + +Class std::chrono::_V2::system_clock + size=1 align=1 + base size=0 base align=1 +std::chrono::_V2::system_clock (0x0x7f6636acb000) 0 empty + +Class std::chrono::_V2::steady_clock + size=1 align=1 + base size=0 base align=1 +std::chrono::_V2::steady_clock (0x0x7f6636787e40) 0 empty + +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 (0x0x7f6636787ea0) 0 + vptr=((& QObjectData::_ZTV11QObjectData) + 16u) + +Class QObject::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObject::QPrivateSignal (0x0x7f66367cf0c0) 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 (0x0x7f66367cf060) 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 (0x0x7f66367cf7e0) 0 nearly-empty + vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16u) + +Class QSignalBlocker + size=16 align=8 + base size=10 base align=8 +QSignalBlocker (0x0x7f66367cf840) 0 + +Class QAbstractAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractAnimation::QPrivateSignal (0x0x7f66367cf900) 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 (0x0x7f66368621a0) 0 + vptr=((& QAbstractAnimation::_ZTV18QAbstractAnimation) + 16u) + QObject (0x0x7f66367cf8a0) 0 + primary-for QAbstractAnimation (0x0x7f66368621a0) + +Class QAnimationDriver::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationDriver::QPrivateSignal (0x0x7f66367cf9c0) 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 (0x0x7f6636862208) 0 + vptr=((& QAnimationDriver::_ZTV16QAnimationDriver) + 16u) + QObject (0x0x7f66367cf960) 0 + primary-for QAnimationDriver (0x0x7f6636862208) + +Class QEventLoop::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventLoop::QPrivateSignal (0x0x7f66367cfa80) 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 (0x0x7f6636862270) 0 + vptr=((& QEventLoop::_ZTV10QEventLoop) + 16u) + QObject (0x0x7f66367cfa20) 0 + primary-for QEventLoop (0x0x7f6636862270) + +Class QEventLoopLocker + size=8 align=8 + base size=8 base align=8 +QEventLoopLocker (0x0x7f66367cfc60) 0 + +Class QAbstractEventDispatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractEventDispatcher::QPrivateSignal (0x0x7f66367cfd20) 0 empty + +Class QAbstractEventDispatcher::TimerInfo + size=12 align=4 + base size=12 base align=4 +QAbstractEventDispatcher::TimerInfo (0x0x7f66367cfd80) 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 (0x0x7f66368623a8) 0 + vptr=((& QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher) + 16u) + QObject (0x0x7f66367cfcc0) 0 + primary-for QAbstractEventDispatcher (0x0x7f66368623a8) + +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 (0x0x7f66367cfde0) 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 (0x0x7f6636862410) 0 nearly-empty + vptr=((& std::bad_cast::_ZTVSt8bad_cast) + 16u) + std::exception (0x0x7f66367cfe40) 0 nearly-empty + primary-for std::bad_cast (0x0x7f6636862410) + +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 (0x0x7f6636862478) 0 nearly-empty + vptr=((& std::bad_typeid::_ZTVSt10bad_typeid) + 16u) + std::exception (0x0x7f66367cfea0) 0 nearly-empty + primary-for std::bad_typeid (0x0x7f6636862478) + +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 (0x0x7f663662a6e8) 0 nearly-empty + vptr=((& std::bad_function_call::_ZTVSt17bad_function_call) + 16u) + std::exception (0x0x7f6636605f60) 0 nearly-empty + primary-for std::bad_function_call (0x0x7f663662a6e8) + +Class std::_Nocopy_types + size=16 align=8 + base size=16 base align=8 +std::_Nocopy_types (0x0x7f66366bc060) 0 + +Class std::_Any_data + size=16 align=8 + base size=16 base align=8 +std::_Any_data (0x0x7f66366bc0c0) 0 + +Class std::_Function_base + size=24 align=8 + base size=24 base align=8 +std::_Function_base (0x0x7f66366bc1e0) 0 + +Class QMapNodeBase + size=24 align=8 + base size=24 base align=8 +QMapNodeBase (0x0x7f66366bc6c0) 0 + +Class QMapDataBase + size=40 align=8 + base size=40 base align=8 +QMapDataBase (0x0x7f66366bc780) 0 + +Class QHashData::Node + size=16 align=8 + base size=16 base align=8 +QHashData::Node (0x0x7f66366bcb40) 0 + +Class QHashData + size=48 align=8 + base size=44 base align=8 +QHashData (0x0x7f66366bcae0) 0 + +Class QHashDummyValue + size=1 align=1 + base size=0 base align=1 +QHashDummyValue (0x0x7f66366bcba0) 0 empty + +Class QVariant::PrivateShared + size=16 align=8 + base size=12 base align=8 +QVariant::PrivateShared (0x0x7f663645f720) 0 + +Class QVariant::Private::Data + size=8 align=8 + base size=8 base align=8 +QVariant::Private::Data (0x0x7f663645f7e0) 0 + +Class QVariant::Private + size=16 align=8 + base size=12 base align=8 +QVariant::Private (0x0x7f663645f780) 0 + +Class QVariant::Handler + size=72 align=8 + base size=72 base align=8 +QVariant::Handler (0x0x7f663645f840) 0 + +Class QVariant + size=16 align=8 + base size=16 base align=8 +QVariant (0x0x7f663645f6c0) 0 + +Class QVariantComparisonHelper + size=8 align=8 + base size=8 base align=8 +QVariantComparisonHelper (0x0x7f66361f6b40) 0 + +Class QSequentialIterable::const_iterator + size=112 align=8 + base size=112 base align=8 +QSequentialIterable::const_iterator (0x0x7f66361f6e40) 0 + +Class QSequentialIterable + size=104 align=8 + base size=104 base align=8 +QSequentialIterable (0x0x7f66361f6de0) 0 + +Class QAssociativeIterable::const_iterator + size=120 align=8 + base size=120 base align=8 +QAssociativeIterable::const_iterator (0x0x7f66361f6f00) 0 + +Class QAssociativeIterable + size=112 align=8 + base size=112 base align=8 +QAssociativeIterable (0x0x7f66361f6ea0) 0 + +Class QModelIndex + size=24 align=8 + base size=24 base align=8 +QModelIndex (0x0x7f663601f960) 0 + +Class QPersistentModelIndex + size=8 align=8 + base size=8 base align=8 +QPersistentModelIndex (0x0x7f663601fc00) 0 + +Class QAbstractItemModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractItemModel::QPrivateSignal (0x0x7f6636104c00) 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 (0x0x7f6636117888) 0 + vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16u) + QObject (0x0x7f6636104ba0) 0 + primary-for QAbstractItemModel (0x0x7f6636117888) + +Class QAbstractTableModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTableModel::QPrivateSignal (0x0x7f6636104f60) 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 (0x0x7f6636117a90) 0 + vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16u) + QAbstractItemModel (0x0x7f6636117af8) 0 + primary-for QAbstractTableModel (0x0x7f6636117a90) + QObject (0x0x7f6636104f00) 0 + primary-for QAbstractItemModel (0x0x7f6636117af8) + +Class QAbstractListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractListModel::QPrivateSignal (0x0x7f6635dd6060) 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 (0x0x7f6636117b60) 0 + vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16u) + QAbstractItemModel (0x0x7f6636117bc8) 0 + primary-for QAbstractListModel (0x0x7f6636117b60) + QObject (0x0x7f6635dd6000) 0 + primary-for QAbstractItemModel (0x0x7f6636117bc8) + +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 (0x0x7f6635dd6300) 0 + vptr=((& QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter) + 16u) + +Class QAbstractProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractProxyModel::QPrivateSignal (0x0x7f6635dd63c0) 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 (0x0x7f6636117d00) 0 + vptr=((& QAbstractProxyModel::_ZTV19QAbstractProxyModel) + 16u) + QAbstractItemModel (0x0x7f6636117d68) 0 + primary-for QAbstractProxyModel (0x0x7f6636117d00) + QObject (0x0x7f6635dd6360) 0 + primary-for QAbstractItemModel (0x0x7f6636117d68) + +Class QAbstractState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractState::QPrivateSignal (0x0x7f6635dd6480) 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 (0x0x7f6636117dd0) 0 + vptr=((& QAbstractState::_ZTV14QAbstractState) + 16u) + QObject (0x0x7f6635dd6420) 0 + primary-for QAbstractState (0x0x7f6636117dd0) + +Class QAbstractTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTransition::QPrivateSignal (0x0x7f6635dd6540) 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 (0x0x7f6636117e38) 0 + vptr=((& QAbstractTransition::_ZTV19QAbstractTransition) + 16u) + QObject (0x0x7f6635dd64e0) 0 + primary-for QAbstractTransition (0x0x7f6636117e38) + +Class QAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationGroup::QPrivateSignal (0x0x7f6635dd6600) 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 (0x0x7f6636117ea0) 0 + vptr=((& QAnimationGroup::_ZTV15QAnimationGroup) + 16u) + QAbstractAnimation (0x0x7f6636117f08) 0 + primary-for QAnimationGroup (0x0x7f6636117ea0) + QObject (0x0x7f6635dd65a0) 0 + primary-for QAbstractAnimation (0x0x7f6636117f08) + +Class QBasicTimer + size=4 align=4 + base size=4 base align=4 +QBasicTimer (0x0x7f6635dd6ae0) 0 + +Class QBitArray + size=8 align=8 + base size=8 base align=8 +QBitArray (0x0x7f6635dd6d80) 0 + +Class QBitRef + size=16 align=8 + base size=12 base align=8 +QBitRef (0x0x7f6635f1d000) 0 + +Class QIODevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIODevice::QPrivateSignal (0x0x7f6635f1d360) 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 (0x0x7f6635f33000) 0 + vptr=((& QIODevice::_ZTV9QIODevice) + 16u) + QObject (0x0x7f6635f1d300) 0 + primary-for QIODevice (0x0x7f6635f33000) + +Class QBuffer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBuffer::QPrivateSignal (0x0x7f6635f1d5a0) 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 (0x0x7f6635f33138) 0 + vptr=((& QBuffer::_ZTV7QBuffer) + 16u) + QIODevice (0x0x7f6635f331a0) 0 + primary-for QBuffer (0x0x7f6635f33138) + QObject (0x0x7f6635f1d540) 0 + primary-for QIODevice (0x0x7f6635f331a0) + +Class QByteArrayMatcher::Data + size=272 align=8 + base size=272 base align=8 +QByteArrayMatcher::Data (0x0x7f6635f1d660) 0 + +Class QByteArrayMatcher + size=1040 align=8 + base size=1040 base align=8 +QByteArrayMatcher (0x0x7f6635f1d600) 0 + +Class QStaticByteArrayMatcherBase::Skiptable + size=256 align=1 + base size=256 base align=1 +QStaticByteArrayMatcherBase::Skiptable (0x0x7f6635f1d780) 0 + +Class QStaticByteArrayMatcherBase + size=256 align=16 + base size=256 base align=16 +QStaticByteArrayMatcherBase (0x0x7f6635f1d720) 0 + +Class QSharedData + size=4 align=4 + base size=4 base align=4 +QSharedData (0x0x7f6635f1d960) 0 + +Class QLocale + size=8 align=8 + base size=8 base align=8 +QLocale (0x0x7f6635f1db40) 0 + +Class QCollatorSortKey + size=8 align=8 + base size=8 base align=8 +QCollatorSortKey (0x0x7f6635cd1000) 0 + +Class QCollator + size=8 align=8 + base size=8 base align=8 +QCollator (0x0x7f6635cd10c0) 0 + +Class QCommandLineOption + size=8 align=8 + base size=8 base align=8 +QCommandLineOption (0x0x7f6635d6d0c0) 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 (0x0x7f6635d6d540) 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 (0x0x7f6635d68548) 0 + vptr=((& QTimerEvent::_ZTV11QTimerEvent) + 16u) + QEvent (0x0x7f6635d6d5a0) 0 + primary-for QTimerEvent (0x0x7f6635d68548) + +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 (0x0x7f6635d685b0) 0 + vptr=((& QChildEvent::_ZTV11QChildEvent) + 16u) + QEvent (0x0x7f6635d6d600) 0 + primary-for QChildEvent (0x0x7f6635d685b0) + +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 (0x0x7f6635d68618) 0 + vptr=((& QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent) + 16u) + QEvent (0x0x7f6635d6d660) 0 + primary-for QDynamicPropertyChangeEvent (0x0x7f6635d68618) + +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 (0x0x7f6635d68680) 0 + vptr=((& QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent) + 16u) + QEvent (0x0x7f6635d6d6c0) 0 + primary-for QDeferredDeleteEvent (0x0x7f6635d68680) + +Class QCoreApplication::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QCoreApplication::QPrivateSignal (0x0x7f6635d6d780) 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 (0x0x7f6635d686e8) 0 + vptr=((& QCoreApplication::_ZTV16QCoreApplication) + 16u) + QObject (0x0x7f6635d6d720) 0 + primary-for QCoreApplication (0x0x7f6635d686e8) + +Class QCommandLineParser + size=8 align=8 + base size=8 base align=8 +QCommandLineParser (0x0x7f6635d6d7e0) 0 + +Class QContiguousCacheData + size=24 align=4 + base size=24 base align=4 +QContiguousCacheData (0x0x7f6635d6d840) 0 + +Class QCryptographicHash + size=8 align=8 + base size=8 base align=8 +QCryptographicHash (0x0x7f6635d6dae0) 0 + +Class QDataStream + size=32 align=8 + base size=32 base align=8 +QDataStream (0x0x7f6635d6db40) 0 + +Class QtPrivate::StreamStateSaver + size=16 align=8 + base size=12 base align=8 +QtPrivate::StreamStateSaver (0x0x7f6635d6dc00) 0 + +Class QDate + size=8 align=8 + base size=8 base align=8 +QDate (0x0x7f6635d6dc60) 0 + +Class QTime + size=4 align=4 + base size=4 base align=4 +QTime (0x0x7f6635d6df00) 0 + +Class QDateTime::ShortData + size=8 align=8 + base size=8 base align=8 +QDateTime::ShortData (0x0x7f6635ada240) 0 + +Class QDateTime::Data + size=8 align=8 + base size=8 base align=8 +QDateTime::Data (0x0x7f6635ada2a0) 0 + +Class QDateTime + size=8 align=8 + base size=8 base align=8 +QDateTime (0x0x7f6635ada1e0) 0 + +Class QElapsedTimer + size=16 align=8 + base size=16 base align=8 +QElapsedTimer (0x0x7f663577d060) 0 + +Class QDeadlineTimer + size=16 align=8 + base size=16 base align=8 +QDeadlineTimer (0x0x7f663577d0c0) 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 (0x0x7f6635875cc0) 0 + vptr=((& QTextStream::_ZTV11QTextStream) + 16u) + +Class QTextStreamManipulator + size=40 align=8 + base size=38 base align=8 +QTextStreamManipulator (0x0x7f6635875f60) 0 + +Class QtSharedPointer::NormalDeleter + size=1 align=1 + base size=0 base align=1 +QtSharedPointer::NormalDeleter (0x0x7f66359311e0) 0 empty + +Class QtSharedPointer::ExternalRefCountData + size=16 align=8 + base size=16 base align=8 +QtSharedPointer::ExternalRefCountData (0x0x7f6635931360) 0 + +Class QDebug::Stream + size=80 align=8 + base size=76 base align=8 +QDebug::Stream (0x0x7f66359317e0) 0 + +Class QDebug + size=8 align=8 + base size=8 base align=8 +QDebug (0x0x7f6635931780) 0 + +Class QDebugStateSaver + size=8 align=8 + base size=8 base align=8 +QDebugStateSaver (0x0x7f66357109c0) 0 + +Class QNoDebug + size=1 align=1 + base size=0 base align=1 +QNoDebug (0x0x7f6635710a80) 0 empty + +Class QFileDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileDevice::QPrivateSignal (0x0x7f6635710b40) 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 (0x0x7f663571b680) 0 + vptr=((& QFileDevice::_ZTV11QFileDevice) + 16u) + QIODevice (0x0x7f663571b6e8) 0 + primary-for QFileDevice (0x0x7f663571b680) + QObject (0x0x7f6635710ae0) 0 + primary-for QIODevice (0x0x7f663571b6e8) + +Class QFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFile::QPrivateSignal (0x0x7f6635710d80) 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 (0x0x7f663571b820) 0 + vptr=((& QFile::_ZTV5QFile) + 16u) + QFileDevice (0x0x7f663571b888) 0 + primary-for QFile (0x0x7f663571b820) + QIODevice (0x0x7f663571b8f0) 0 + primary-for QFileDevice (0x0x7f663571b888) + QObject (0x0x7f6635710d20) 0 + primary-for QIODevice (0x0x7f663571b8f0) + +Class QFileInfo + size=8 align=8 + base size=8 base align=8 +QFileInfo (0x0x7f6635710f60) 0 + +Class QDir + size=8 align=8 + base size=8 base align=8 +QDir (0x0x7f66354293c0) 0 + +Class QDirIterator + size=8 align=8 + base size=8 base align=8 +QDirIterator (0x0x7f6635429d80) 0 + +Class QEasingCurve + size=8 align=8 + base size=8 base align=8 +QEasingCurve (0x0x7f663551c000) 0 + +Class QEventTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventTransition::QPrivateSignal (0x0x7f66351ad240) 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 (0x0x7f663519cbc8) 0 + vptr=((& QEventTransition::_ZTV16QEventTransition) + 16u) + QAbstractTransition (0x0x7f663519cc30) 0 + primary-for QEventTransition (0x0x7f663519cbc8) + QObject (0x0x7f66351ad1e0) 0 + primary-for QAbstractTransition (0x0x7f663519cc30) + +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 (0x0x7f663519cc98) 0 nearly-empty + vptr=((& QException::_ZTV10QException) + 16u) + std::exception (0x0x7f66351ad2a0) 0 nearly-empty + primary-for QException (0x0x7f663519cc98) + +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 (0x0x7f663519cd00) 0 nearly-empty + vptr=((& QUnhandledException::_ZTV19QUnhandledException) + 16u) + QException (0x0x7f663519cd68) 0 nearly-empty + primary-for QUnhandledException (0x0x7f663519cd00) + std::exception (0x0x7f66351ad300) 0 nearly-empty + primary-for QException (0x0x7f663519cd68) + +Class QtPrivate::ExceptionHolder + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionHolder (0x0x7f66351ad360) 0 + +Class QtPrivate::ExceptionStore + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionStore (0x0x7f66351ad420) 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 (0x0x7f66351ad480) 0 nearly-empty + vptr=((& QFactoryInterface::_ZTV17QFactoryInterface) + 16u) + +Class QFileSelector::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSelector::QPrivateSignal (0x0x7f66351ad5a0) 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 (0x0x7f663519cdd0) 0 + vptr=((& QFileSelector::_ZTV13QFileSelector) + 16u) + QObject (0x0x7f66351ad540) 0 + primary-for QFileSelector (0x0x7f663519cdd0) + +Class QFileSystemWatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSystemWatcher::QPrivateSignal (0x0x7f66351ad660) 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 (0x0x7f663519ce38) 0 + vptr=((& QFileSystemWatcher::_ZTV18QFileSystemWatcher) + 16u) + QObject (0x0x7f66351ad600) 0 + primary-for QFileSystemWatcher (0x0x7f663519ce38) + +Class QFinalState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFinalState::QPrivateSignal (0x0x7f66351ad720) 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 (0x0x7f663519cea0) 0 + vptr=((& QFinalState::_ZTV11QFinalState) + 16u) + QAbstractState (0x0x7f663519cf08) 0 + primary-for QFinalState (0x0x7f663519cea0) + QObject (0x0x7f66351ad6c0) 0 + primary-for QAbstractState (0x0x7f663519cf08) + +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 (0x0x7f66351ad780) 0 + vptr=((& QRunnable::_ZTV9QRunnable) + 16u) + +Class QBasicMutex + size=8 align=8 + base size=8 base align=8 +QBasicMutex (0x0x7f66351ad7e0) 0 + +Class QMutex + size=8 align=8 + base size=8 base align=8 +QMutex (0x0x7f6635274068) 0 + QBasicMutex (0x0x7f66351ada20) 0 + +Class QMutexLocker + size=8 align=8 + base size=8 base align=8 +QMutexLocker (0x0x7f66351adae0) 0 + +Class QtPrivate::ResultItem + size=16 align=8 + base size=16 base align=8 +QtPrivate::ResultItem (0x0x7f66351adba0) 0 + +Class QtPrivate::ResultIteratorBase + size=16 align=8 + base size=12 base align=8 +QtPrivate::ResultIteratorBase (0x0x7f66351adc00) 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 (0x0x7f66351add20) 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 (0x0x7f66351add80) 0 + vptr=((& QFutureInterfaceBase::_ZTV20QFutureInterfaceBase) + 16u) + +Class QFutureWatcherBase::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFutureWatcherBase::QPrivateSignal (0x0x7f6634f79120) 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 (0x0x7f6635274478) 0 + vptr=((& QFutureWatcherBase::_ZTV18QFutureWatcherBase) + 16u) + QObject (0x0x7f6634f790c0) 0 + primary-for QFutureWatcherBase (0x0x7f6635274478) + +Class QHistoryState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QHistoryState::QPrivateSignal (0x0x7f6634f792a0) 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 (0x0x7f6635274888) 0 + vptr=((& QHistoryState::_ZTV13QHistoryState) + 16u) + QAbstractState (0x0x7f66352748f0) 0 + primary-for QHistoryState (0x0x7f6635274888) + QObject (0x0x7f6634f79240) 0 + primary-for QAbstractState (0x0x7f66352748f0) + +Class QIdentityProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIdentityProxyModel::QPrivateSignal (0x0x7f6634f79360) 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 (0x0x7f6635274958) 0 + vptr=((& QIdentityProxyModel::_ZTV19QIdentityProxyModel) + 16u) + QAbstractProxyModel (0x0x7f66352749c0) 0 + primary-for QIdentityProxyModel (0x0x7f6635274958) + QAbstractItemModel (0x0x7f6635274a28) 0 + primary-for QAbstractProxyModel (0x0x7f66352749c0) + QObject (0x0x7f6634f79300) 0 + primary-for QAbstractItemModel (0x0x7f6635274a28) + +Class QItemSelectionRange + size=16 align=8 + base size=16 base align=8 +QItemSelectionRange (0x0x7f6634f793c0) 0 + +Class QItemSelectionModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QItemSelectionModel::QPrivateSignal (0x0x7f6634f79720) 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 (0x0x7f6635274dd0) 0 + vptr=((& QItemSelectionModel::_ZTV19QItemSelectionModel) + 16u) + QObject (0x0x7f6634f796c0) 0 + primary-for QItemSelectionModel (0x0x7f6635274dd0) + +Class QItemSelection + size=8 align=8 + base size=8 base align=8 +QItemSelection (0x0x7f66352740d0) 0 + QList (0x0x7f66350ae000) 0 + QListSpecialMethods (0x0x7f6634f79a20) 0 empty + +Class QJsonValue + size=24 align=8 + base size=20 base align=8 +QJsonValue (0x0x7f6634f79f00) 0 + +Class QJsonValueRef + size=16 align=8 + base size=12 base align=8 +QJsonValueRef (0x0x7f66350f6000) 0 + +Class QJsonValuePtr + size=24 align=8 + base size=24 base align=8 +QJsonValuePtr (0x0x7f66350f60c0) 0 + +Class QJsonValueRefPtr + size=16 align=8 + base size=16 base align=8 +QJsonValueRefPtr (0x0x7f66350f6120) 0 + +Class QJsonArray::iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::iterator (0x0x7f66350f61e0) 0 + +Class QJsonArray::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::const_iterator (0x0x7f66350f6240) 0 + +Class QJsonArray + size=16 align=8 + base size=16 base align=8 +QJsonArray (0x0x7f66350f6180) 0 + +Class QJsonParseError + size=8 align=4 + base size=8 base align=4 +QJsonParseError (0x0x7f66350f6300) 0 + +Class QJsonDocument + size=8 align=8 + base size=8 base align=8 +QJsonDocument (0x0x7f66350f6360) 0 + +Class QJsonObject::iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::iterator (0x0x7f66350f6420) 0 + +Class QJsonObject::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::const_iterator (0x0x7f66350f6480) 0 + +Class QJsonObject + size=16 align=8 + base size=16 base align=8 +QJsonObject (0x0x7f66350f63c0) 0 + +Class QLibrary::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLibrary::QPrivateSignal (0x0x7f66350f6660) 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 (0x0x7f66350ae3a8) 0 + vptr=((& QLibrary::_ZTV8QLibrary) + 16u) + QObject (0x0x7f66350f6600) 0 + primary-for QLibrary (0x0x7f66350ae3a8) + +Class QVersionNumber::SegmentStorage + size=8 align=8 + base size=8 base align=8 +QVersionNumber::SegmentStorage (0x0x7f66350f68a0) 0 + +Class QVersionNumber + size=8 align=8 + base size=8 base align=8 +QVersionNumber (0x0x7f66350f6840) 0 + +Class QLibraryInfo + size=1 align=1 + base size=0 base align=1 +QLibraryInfo (0x0x7f6634eee600) 0 empty + +Class QPoint + size=8 align=4 + base size=8 base align=4 +QPoint (0x0x7f6634eee660) 0 + +Class QPointF + size=16 align=8 + base size=16 base align=8 +QPointF (0x0x7f6634eee900) 0 + +Class QLine + size=16 align=4 + base size=16 base align=4 +QLine (0x0x7f6634eeeba0) 0 + +Class QLineF + size=32 align=8 + base size=32 base align=8 +QLineF (0x0x7f6634eeee40) 0 + +Class QLinkedListData + size=32 align=8 + base size=25 base align=8 +QLinkedListData (0x0x7f6634bf4120) 0 + +Class QLockFile + size=8 align=8 + base size=8 base align=8 +QLockFile (0x0x7f6634bf48a0) 0 + +Class QLoggingCategory::AtomicBools + size=4 align=1 + base size=4 base align=1 +QLoggingCategory::AtomicBools (0x0x7f6634bf4a20) 0 + +Class QLoggingCategory + size=24 align=8 + base size=24 base align=8 +QLoggingCategory (0x0x7f6634bf49c0) 0 + +Class QMargins + size=16 align=4 + base size=16 base align=4 +QMargins (0x0x7f6634bf4ba0) 0 + +Class QMarginsF + size=32 align=8 + base size=32 base align=8 +QMarginsF (0x0x7f6634bf4e40) 0 + +Class QMessageAuthenticationCode + size=8 align=8 + base size=8 base align=8 +QMessageAuthenticationCode (0x0x7f663496e180) 0 + +Class QMetaMethod + size=16 align=8 + base size=12 base align=8 +QMetaMethod (0x0x7f663496e1e0) 0 + +Class QMetaEnum + size=16 align=8 + base size=12 base align=8 +QMetaEnum (0x0x7f663496e480) 0 + +Class QMetaProperty + size=32 align=8 + base size=32 base align=8 +QMetaProperty (0x0x7f663496e780) 0 + +Class QMetaClassInfo + size=16 align=8 + base size=12 base align=8 +QMetaClassInfo (0x0x7f663496e7e0) 0 + +Class QMimeData::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QMimeData::QPrivateSignal (0x0x7f663496eae0) 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 (0x0x7f66349f04e0) 0 + vptr=((& QMimeData::_ZTV9QMimeData) + 16u) + QObject (0x0x7f663496ea80) 0 + primary-for QMimeData (0x0x7f66349f04e0) + +Class QMimeType + size=8 align=8 + base size=8 base align=8 +QMimeType (0x0x7f663496eb40) 0 + +Class QMimeDatabase + size=8 align=8 + base size=8 base align=8 +QMimeDatabase (0x0x7f663496ee40) 0 + +Class QObjectCleanupHandler::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObjectCleanupHandler::QPrivateSignal (0x0x7f663496ef00) 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 (0x0x7f66349f06e8) 0 + vptr=((& QObjectCleanupHandler::_ZTV21QObjectCleanupHandler) + 16u) + QObject (0x0x7f663496eea0) 0 + primary-for QObjectCleanupHandler (0x0x7f66349f06e8) + +Class QOperatingSystemVersion + size=16 align=4 + base size=16 base align=4 +QOperatingSystemVersion (0x0x7f663496ef60) 0 + +Class QParallelAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QParallelAnimationGroup::QPrivateSignal (0x0x7f6634a7c060) 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 (0x0x7f66349f07b8) 0 + vptr=((& QParallelAnimationGroup::_ZTV23QParallelAnimationGroup) + 16u) + QAnimationGroup (0x0x7f66349f0820) 0 + primary-for QParallelAnimationGroup (0x0x7f66349f07b8) + QAbstractAnimation (0x0x7f66349f0888) 0 + primary-for QAnimationGroup (0x0x7f66349f0820) + QObject (0x0x7f6634a7c000) 0 + primary-for QAbstractAnimation (0x0x7f66349f0888) + +Class QPauseAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPauseAnimation::QPrivateSignal (0x0x7f6634a7c120) 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 (0x0x7f66349f08f0) 0 + vptr=((& QPauseAnimation::_ZTV15QPauseAnimation) + 16u) + QAbstractAnimation (0x0x7f66349f0958) 0 + primary-for QPauseAnimation (0x0x7f66349f08f0) + QObject (0x0x7f6634a7c0c0) 0 + primary-for QAbstractAnimation (0x0x7f66349f0958) + +Class QStaticPlugin + size=16 align=8 + base size=16 base align=8 +QStaticPlugin (0x0x7f6634a7c300) 0 + +Class QPluginLoader::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPluginLoader::QPrivateSignal (0x0x7f6634a7c600) 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 (0x0x7f66349f0b60) 0 + vptr=((& QPluginLoader::_ZTV13QPluginLoader) + 16u) + QObject (0x0x7f6634a7c5a0) 0 + primary-for QPluginLoader (0x0x7f66349f0b60) + +Class QProcessEnvironment + size=8 align=8 + base size=8 base align=8 +QProcessEnvironment (0x0x7f6634a7c660) 0 + +Class QProcess::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QProcess::QPrivateSignal (0x0x7f6634a7c9c0) 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 (0x0x7f66349f0d68) 0 + vptr=((& QProcess::_ZTV8QProcess) + 16u) + QIODevice (0x0x7f66349f0dd0) 0 + primary-for QProcess (0x0x7f66349f0d68) + QObject (0x0x7f6634a7c960) 0 + primary-for QIODevice (0x0x7f66349f0dd0) + +Class QVariantAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QVariantAnimation::QPrivateSignal (0x0x7f6634a7ca80) 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 (0x0x7f66349f0e38) 0 + vptr=((& QVariantAnimation::_ZTV17QVariantAnimation) + 16u) + QAbstractAnimation (0x0x7f66349f0ea0) 0 + primary-for QVariantAnimation (0x0x7f66349f0e38) + QObject (0x0x7f6634a7ca20) 0 + primary-for QAbstractAnimation (0x0x7f66349f0ea0) + +Class QPropertyAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPropertyAnimation::QPrivateSignal (0x0x7f6634a7cb40) 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 (0x0x7f66349f0f70) 0 + vptr=((& QPropertyAnimation::_ZTV18QPropertyAnimation) + 16u) + QVariantAnimation (0x0x7f66349f0750) 0 + primary-for QPropertyAnimation (0x0x7f66349f0f70) + QAbstractAnimation (0x0x7f6634b33000) 0 + primary-for QVariantAnimation (0x0x7f66349f0750) + QObject (0x0x7f6634a7cae0) 0 + primary-for QAbstractAnimation (0x0x7f6634b33000) + +Class QReadWriteLock + size=8 align=8 + base size=8 base align=8 +QReadWriteLock (0x0x7f6634a7cc00) 0 + +Class QReadLocker + size=8 align=8 + base size=8 base align=8 +QReadLocker (0x0x7f6634a7cea0) 0 + +Class QWriteLocker + size=8 align=8 + base size=8 base align=8 +QWriteLocker (0x0x7f6634a7cf00) 0 + +Class QSize + size=8 align=4 + base size=8 base align=4 +QSize (0x0x7f6634a7cf60) 0 + +Class QSizeF + size=16 align=8 + base size=16 base align=8 +QSizeF (0x0x7f66347dd300) 0 + +Class QRect + size=16 align=4 + base size=16 base align=4 +QRect (0x0x7f66347dd660) 0 + +Class QRectF + size=32 align=8 + base size=32 base align=8 +QRectF (0x0x7f66347dd900) 0 + +Class QRegularExpression + size=8 align=8 + base size=8 base align=8 +QRegularExpression (0x0x7f66347ddba0) 0 + +Class QRegularExpressionMatch + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatch (0x0x7f66345b91e0) 0 + +Class QRegularExpressionMatchIterator + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatchIterator (0x0x7f66345b94e0) 0 + +Class QResource + size=8 align=8 + base size=8 base align=8 +QResource (0x0x7f66345b97e0) 0 + +Class QSaveFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSaveFile::QPrivateSignal (0x0x7f66345b9960) 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 (0x0x7f66346022d8) 0 + vptr=((& QSaveFile::_ZTV9QSaveFile) + 16u) + QFileDevice (0x0x7f6634602340) 0 + primary-for QSaveFile (0x0x7f66346022d8) + QIODevice (0x0x7f66346023a8) 0 + primary-for QFileDevice (0x0x7f6634602340) + QObject (0x0x7f66345b9900) 0 + primary-for QIODevice (0x0x7f66346023a8) + +Class QSemaphore + size=8 align=8 + base size=8 base align=8 +QSemaphore (0x0x7f66345b9a20) 0 + +Class QSequentialAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSequentialAnimationGroup::QPrivateSignal (0x0x7f66345b9ae0) 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 (0x0x7f6634602410) 0 + vptr=((& QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup) + 16u) + QAnimationGroup (0x0x7f6634602478) 0 + primary-for QSequentialAnimationGroup (0x0x7f6634602410) + QAbstractAnimation (0x0x7f66346024e0) 0 + primary-for QAnimationGroup (0x0x7f6634602478) + QObject (0x0x7f66345b9a80) 0 + primary-for QAbstractAnimation (0x0x7f66346024e0) + +Class QSettings::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSettings::QPrivateSignal (0x0x7f66345b9ba0) 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 (0x0x7f6634602548) 0 + vptr=((& QSettings::_ZTV9QSettings) + 16u) + QObject (0x0x7f66345b9b40) 0 + primary-for QSettings (0x0x7f6634602548) + +Class QSharedMemory::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSharedMemory::QPrivateSignal (0x0x7f66345b9c60) 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 (0x0x7f66346025b0) 0 + vptr=((& QSharedMemory::_ZTV13QSharedMemory) + 16u) + QObject (0x0x7f66345b9c00) 0 + primary-for QSharedMemory (0x0x7f66346025b0) + +Class QSignalMapper::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalMapper::QPrivateSignal (0x0x7f66345b9d20) 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 (0x0x7f6634602618) 0 + vptr=((& QSignalMapper::_ZTV13QSignalMapper) + 16u) + QObject (0x0x7f66345b9cc0) 0 + primary-for QSignalMapper (0x0x7f6634602618) + +Class QSignalTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalTransition::QPrivateSignal (0x0x7f66345b9de0) 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 (0x0x7f6634602680) 0 + vptr=((& QSignalTransition::_ZTV17QSignalTransition) + 16u) + QAbstractTransition (0x0x7f66346026e8) 0 + primary-for QSignalTransition (0x0x7f6634602680) + QObject (0x0x7f66345b9d80) 0 + primary-for QAbstractTransition (0x0x7f66346026e8) + +Class QSocketNotifier::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSocketNotifier::QPrivateSignal (0x0x7f66345b9ea0) 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 (0x0x7f6634602750) 0 + vptr=((& QSocketNotifier::_ZTV15QSocketNotifier) + 16u) + QObject (0x0x7f66345b9e40) 0 + primary-for QSocketNotifier (0x0x7f6634602750) + +Class QSortFilterProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSortFilterProxyModel::QPrivateSignal (0x0x7f66345b9f60) 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 (0x0x7f66346027b8) 0 + vptr=((& QSortFilterProxyModel::_ZTV21QSortFilterProxyModel) + 16u) + QAbstractProxyModel (0x0x7f6634602820) 0 + primary-for QSortFilterProxyModel (0x0x7f66346027b8) + QAbstractItemModel (0x0x7f6634602888) 0 + primary-for QAbstractProxyModel (0x0x7f6634602820) + QObject (0x0x7f66345b9f00) 0 + primary-for QAbstractItemModel (0x0x7f6634602888) + +Class QStandardPaths + size=1 align=1 + base size=0 base align=1 +QStandardPaths (0x0x7f66346f1180) 0 empty + +Class QState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QState::QPrivateSignal (0x0x7f66346f13c0) 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 (0x0x7f6634602a28) 0 + vptr=((& QState::_ZTV6QState) + 16u) + QAbstractState (0x0x7f6634602a90) 0 + primary-for QState (0x0x7f6634602a28) + QObject (0x0x7f66346f1360) 0 + primary-for QAbstractState (0x0x7f6634602a90) + +Class QStateMachine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStateMachine::QPrivateSignal (0x0x7f66346f14e0) 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 (0x0x7f6634602c30) 0 + vptr=((& QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE) + 16u) + QEvent (0x0x7f66346f1540) 0 + primary-for QStateMachine::SignalEvent (0x0x7f6634602c30) + +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 (0x0x7f6634602c98) 0 + vptr=((& QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE) + 16u) + QEvent (0x0x7f66346f15a0) 0 + primary-for QStateMachine::WrappedEvent (0x0x7f6634602c98) + +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 (0x0x7f6634602af8) 0 + vptr=((& QStateMachine::_ZTV13QStateMachine) + 16u) + QState (0x0x7f6634602b60) 0 + primary-for QStateMachine (0x0x7f6634602af8) + QAbstractState (0x0x7f6634602bc8) 0 + primary-for QState (0x0x7f6634602b60) + QObject (0x0x7f66346f1480) 0 + primary-for QAbstractState (0x0x7f6634602bc8) + +Class QStorageInfo + size=8 align=8 + base size=8 base align=8 +QStorageInfo (0x0x7f66346f1600) 0 + +Class QAbstractConcatenable + size=1 align=1 + base size=0 base align=1 +QAbstractConcatenable (0x0x7f66346f1a20) 0 empty + +Class QStringListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStringListModel::QPrivateSignal (0x0x7f66343f54e0) 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 (0x0x7f66343c4750) 0 + vptr=((& QStringListModel::_ZTV16QStringListModel) + 16u) + QAbstractListModel (0x0x7f66343c47b8) 0 + primary-for QStringListModel (0x0x7f66343c4750) + QAbstractItemModel (0x0x7f66343c4820) 0 + primary-for QAbstractListModel (0x0x7f66343c47b8) + QObject (0x0x7f66343f5480) 0 + primary-for QAbstractItemModel (0x0x7f66343c4820) + +Class QSystemSemaphore + size=8 align=8 + base size=8 base align=8 +QSystemSemaphore (0x0x7f66343f5540) 0 + +Class QTemporaryDir + size=8 align=8 + base size=8 base align=8 +QTemporaryDir (0x0x7f66343f5600) 0 + +Class QTemporaryFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTemporaryFile::QPrivateSignal (0x0x7f66343f5720) 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 (0x0x7f66343c4888) 0 + vptr=((& QTemporaryFile::_ZTV14QTemporaryFile) + 16u) + QFile (0x0x7f66343c48f0) 0 + primary-for QTemporaryFile (0x0x7f66343c4888) + QFileDevice (0x0x7f66343c4958) 0 + primary-for QFile (0x0x7f66343c48f0) + QIODevice (0x0x7f66343c49c0) 0 + primary-for QFileDevice (0x0x7f66343c4958) + QObject (0x0x7f66343f56c0) 0 + primary-for QIODevice (0x0x7f66343c49c0) + +Class QTextBoundaryFinder + size=48 align=8 + base size=48 base align=8 +QTextBoundaryFinder (0x0x7f66343f5780) 0 + +Class QTextCodec::ConverterState + size=32 align=8 + base size=32 base align=8 +QTextCodec::ConverterState (0x0x7f66343f59c0) 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 (0x0x7f66343f5960) 0 nearly-empty + vptr=((& QTextCodec::_ZTV10QTextCodec) + 16u) + +Class QTextEncoder + size=40 align=8 + base size=40 base align=8 +QTextEncoder (0x0x7f66343f5ba0) 0 + +Class QTextDecoder + size=40 align=8 + base size=40 base align=8 +QTextDecoder (0x0x7f66343f5c00) 0 + +Class QThread::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThread::QPrivateSignal (0x0x7f66343f5cc0) 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 (0x0x7f66343c4bc8) 0 + vptr=((& QThread::_ZTV7QThread) + 16u) + QObject (0x0x7f66343f5c60) 0 + primary-for QThread (0x0x7f66343c4bc8) + +Class QThreadPool::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThreadPool::QPrivateSignal (0x0x7f66343f5d80) 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 (0x0x7f66343c4c30) 0 + vptr=((& QThreadPool::_ZTV11QThreadPool) + 16u) + QObject (0x0x7f66343f5d20) 0 + primary-for QThreadPool (0x0x7f66343c4c30) + +Class QThreadStorageData + size=4 align=4 + base size=4 base align=4 +QThreadStorageData (0x0x7f66343f5de0) 0 + +Class QTimeLine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimeLine::QPrivateSignal (0x0x7f66343f5f00) 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 (0x0x7f66343c4c98) 0 + vptr=((& QTimeLine::_ZTV9QTimeLine) + 16u) + QObject (0x0x7f66343f5ea0) 0 + primary-for QTimeLine (0x0x7f66343c4c98) + +Class QTimer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimer::QPrivateSignal (0x0x7f6634144000) 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 (0x0x7f66343c4d00) 0 + vptr=((& QTimer::_ZTV6QTimer) + 16u) + QObject (0x0x7f66343f5f60) 0 + primary-for QTimer (0x0x7f66343c4d00) + +Class QTimeZone::OffsetData + size=32 align=8 + base size=28 base align=8 +QTimeZone::OffsetData (0x0x7f6634144de0) 0 + +Class QTimeZone + size=8 align=8 + base size=8 base align=8 +QTimeZone (0x0x7f6634144d80) 0 + +Class QTranslator::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTranslator::QPrivateSignal (0x0x7f66341b63c0) 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 (0x0x7f6634171f70) 0 + vptr=((& QTranslator::_ZTV11QTranslator) + 16u) + QObject (0x0x7f66341b6360) 0 + primary-for QTranslator (0x0x7f6634171f70) + +Class QUrl + size=8 align=8 + base size=8 base align=8 +QUrl (0x0x7f66341b64e0) 0 + +Class QUrlQuery + size=8 align=8 + base size=8 base align=8 +QUrlQuery (0x0x7f66342ceba0) 0 + +Class QUuid + size=16 align=4 + base size=16 base align=4 +QUuid (0x0x7f66342ceea0) 0 + +Class QWaitCondition + size=8 align=8 + base size=8 base align=8 +QWaitCondition (0x0x7f6633f8b180) 0 + +Class QXmlStreamStringRef + size=16 align=8 + base size=16 base align=8 +QXmlStreamStringRef (0x0x7f6633f8b1e0) 0 + +Class QXmlStreamAttribute + size=80 align=8 + base size=73 base align=8 +QXmlStreamAttribute (0x0x7f663400c600) 0 + +Class QXmlStreamAttributes + size=8 align=8 + base size=8 base align=8 +QXmlStreamAttributes (0x0x7f663400e958) 0 + QVector (0x0x7f663400c9c0) 0 + +Class QXmlStreamNamespaceDeclaration + size=40 align=8 + base size=40 base align=8 +QXmlStreamNamespaceDeclaration (0x0x7f663400ca20) 0 + +Class QXmlStreamNotationDeclaration + size=56 align=8 + base size=56 base align=8 +QXmlStreamNotationDeclaration (0x0x7f663400ccc0) 0 + +Class QXmlStreamEntityDeclaration + size=88 align=8 + base size=88 base align=8 +QXmlStreamEntityDeclaration (0x0x7f663400cf60) 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 (0x0x7f66340cf240) 0 nearly-empty + vptr=((& QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver) + 16u) + +Class QXmlStreamReader + size=8 align=8 + base size=8 base align=8 +QXmlStreamReader (0x0x7f66340cf2a0) 0 + +Class QXmlStreamWriter + size=8 align=8 + base size=8 base align=8 +QXmlStreamWriter (0x0x7f66340cf3c0) 0 + +Class QBluetoothAddress + size=8 align=8 + base size=8 base align=8 +QBluetoothAddress (0x0x7f66340cf7e0) 0 + +Class QBluetoothDeviceInfo + size=8 align=8 + base size=8 base align=8 +QBluetoothDeviceInfo (0x0x7f66340cf960) 0 + +Class QBluetoothDeviceDiscoveryAgent::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothDeviceDiscoveryAgent::QPrivateSignal (0x0x7f66340cfe40) 0 empty + +Vtable for QBluetoothDeviceDiscoveryAgent +QBluetoothDeviceDiscoveryAgent::_ZTV30QBluetoothDeviceDiscoveryAgent: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI30QBluetoothDeviceDiscoveryAgent) +16 (int (*)(...))QBluetoothDeviceDiscoveryAgent::metaObject +24 (int (*)(...))QBluetoothDeviceDiscoveryAgent::qt_metacast +32 (int (*)(...))QBluetoothDeviceDiscoveryAgent::qt_metacall +40 (int (*)(...))QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent +48 (int (*)(...))QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent +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 QBluetoothDeviceDiscoveryAgent + size=24 align=8 + base size=24 base align=8 +QBluetoothDeviceDiscoveryAgent (0x0x7f66340d63a8) 0 + vptr=((& QBluetoothDeviceDiscoveryAgent::_ZTV30QBluetoothDeviceDiscoveryAgent) + 16u) + QObject (0x0x7f66340cfde0) 0 + primary-for QBluetoothDeviceDiscoveryAgent (0x0x7f66340d63a8) + +Class QBluetoothHostInfo + size=8 align=8 + base size=8 base align=8 +QBluetoothHostInfo (0x0x7f6633e3b060) 0 + +Class QBluetoothLocalDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothLocalDevice::QPrivateSignal (0x0x7f6633e3b240) 0 empty + +Vtable for QBluetoothLocalDevice +QBluetoothLocalDevice::_ZTV21QBluetoothLocalDevice: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QBluetoothLocalDevice) +16 (int (*)(...))QBluetoothLocalDevice::metaObject +24 (int (*)(...))QBluetoothLocalDevice::qt_metacast +32 (int (*)(...))QBluetoothLocalDevice::qt_metacall +40 (int (*)(...))QBluetoothLocalDevice::~QBluetoothLocalDevice +48 (int (*)(...))QBluetoothLocalDevice::~QBluetoothLocalDevice +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 QBluetoothLocalDevice + size=24 align=8 + base size=24 base align=8 +QBluetoothLocalDevice (0x0x7f66340d64e0) 0 + vptr=((& QBluetoothLocalDevice::_ZTV21QBluetoothLocalDevice) + 16u) + QObject (0x0x7f6633e3b1e0) 0 + primary-for QBluetoothLocalDevice (0x0x7f66340d64e0) + +Class quint128 + size=16 align=1 + base size=16 base align=1 +quint128 (0x0x7f6633e3b600) 0 + +Class QBluetoothUuid + size=16 align=4 + base size=16 base align=4 +QBluetoothUuid (0x0x7f66340d6548) 0 + QUuid (0x0x7f6633e3b660) 0 + +Class QBluetoothServiceInfo::Sequence + size=8 align=8 + base size=8 base align=8 +QBluetoothServiceInfo::Sequence (0x0x7f66340d65b0) 0 + QList (0x0x7f66340d6618) 0 + QListSpecialMethods (0x0x7f6633e3b900) 0 empty + +Class QBluetoothServiceInfo::Alternative + size=8 align=8 + base size=8 base align=8 +QBluetoothServiceInfo::Alternative (0x0x7f66340d6680) 0 + QList (0x0x7f66340d66e8) 0 + QListSpecialMethods (0x0x7f6633e3b960) 0 empty + +Class QBluetoothServiceInfo + size=16 align=8 + base size=16 base align=8 +QBluetoothServiceInfo (0x0x7f6633e3b8a0) 0 + +Class QAbstractSocket::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractSocket::QPrivateSignal (0x0x7f6633e3bde0) 0 empty + +Vtable for QAbstractSocket +QAbstractSocket::_ZTV15QAbstractSocket: 41u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QAbstractSocket) +16 (int (*)(...))QAbstractSocket::metaObject +24 (int (*)(...))QAbstractSocket::qt_metacast +32 (int (*)(...))QAbstractSocket::qt_metacall +40 (int (*)(...))QAbstractSocket::~QAbstractSocket +48 (int (*)(...))QAbstractSocket::~QAbstractSocket +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 (*)(...))QAbstractSocket::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QAbstractSocket::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QAbstractSocket::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QAbstractSocket::bytesAvailable +184 (int (*)(...))QAbstractSocket::bytesToWrite +192 (int (*)(...))QAbstractSocket::canReadLine +200 (int (*)(...))QAbstractSocket::waitForReadyRead +208 (int (*)(...))QAbstractSocket::waitForBytesWritten +216 (int (*)(...))QAbstractSocket::readData +224 (int (*)(...))QAbstractSocket::readLineData +232 (int (*)(...))QAbstractSocket::writeData +240 (int (*)(...))QAbstractSocket::resume +248 (int (*)(...))QAbstractSocket::connectToHost +256 (int (*)(...))QAbstractSocket::connectToHost +264 (int (*)(...))QAbstractSocket::disconnectFromHost +272 (int (*)(...))QAbstractSocket::setReadBufferSize +280 (int (*)(...))QAbstractSocket::socketDescriptor +288 (int (*)(...))QAbstractSocket::setSocketDescriptor +296 (int (*)(...))QAbstractSocket::setSocketOption +304 (int (*)(...))QAbstractSocket::socketOption +312 (int (*)(...))QAbstractSocket::waitForConnected +320 (int (*)(...))QAbstractSocket::waitForDisconnected + +Class QAbstractSocket + size=16 align=8 + base size=16 base align=8 +QAbstractSocket (0x0x7f66340d6958) 0 + vptr=((& QAbstractSocket::_ZTV15QAbstractSocket) + 16u) + QIODevice (0x0x7f66340d69c0) 0 + primary-for QAbstractSocket (0x0x7f66340d6958) + QObject (0x0x7f6633e3bd80) 0 + primary-for QIODevice (0x0x7f66340d69c0) + +Class QBluetoothSocket::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothSocket::QPrivateSignal (0x0x7f6633baa420) 0 empty + +Vtable for QBluetoothSocket +QBluetoothSocket::_ZTV16QBluetoothSocket: 30u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QBluetoothSocket) +16 (int (*)(...))QBluetoothSocket::metaObject +24 (int (*)(...))QBluetoothSocket::qt_metacast +32 (int (*)(...))QBluetoothSocket::qt_metacall +40 (int (*)(...))QBluetoothSocket::~QBluetoothSocket +48 (int (*)(...))QBluetoothSocket::~QBluetoothSocket +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 (*)(...))QBluetoothSocket::isSequential +120 (int (*)(...))QIODevice::open +128 (int (*)(...))QBluetoothSocket::close +136 (int (*)(...))QIODevice::pos +144 (int (*)(...))QIODevice::size +152 (int (*)(...))QIODevice::seek +160 (int (*)(...))QIODevice::atEnd +168 (int (*)(...))QIODevice::reset +176 (int (*)(...))QBluetoothSocket::bytesAvailable +184 (int (*)(...))QBluetoothSocket::bytesToWrite +192 (int (*)(...))QBluetoothSocket::canReadLine +200 (int (*)(...))QIODevice::waitForReadyRead +208 (int (*)(...))QIODevice::waitForBytesWritten +216 (int (*)(...))QBluetoothSocket::readData +224 (int (*)(...))QIODevice::readLineData +232 (int (*)(...))QBluetoothSocket::writeData + +Class QBluetoothSocket + size=24 align=8 + base size=24 base align=8 +QBluetoothSocket (0x0x7f66340d6bc8) 0 + vptr=((& QBluetoothSocket::_ZTV16QBluetoothSocket) + 16u) + QIODevice (0x0x7f66340d6c30) 0 + primary-for QBluetoothSocket (0x0x7f66340d6bc8) + QObject (0x0x7f6633baa3c0) 0 + primary-for QIODevice (0x0x7f66340d6c30) + +Class QBluetoothServer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothServer::QPrivateSignal (0x0x7f6633baa4e0) 0 empty + +Vtable for QBluetoothServer +QBluetoothServer::_ZTV16QBluetoothServer: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QBluetoothServer) +16 (int (*)(...))QBluetoothServer::metaObject +24 (int (*)(...))QBluetoothServer::qt_metacast +32 (int (*)(...))QBluetoothServer::qt_metacall +40 (int (*)(...))QBluetoothServer::~QBluetoothServer +48 (int (*)(...))QBluetoothServer::~QBluetoothServer +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 QBluetoothServer + size=24 align=8 + base size=24 base align=8 +QBluetoothServer (0x0x7f66340d6c98) 0 + vptr=((& QBluetoothServer::_ZTV16QBluetoothServer) + 16u) + QObject (0x0x7f6633baa480) 0 + primary-for QBluetoothServer (0x0x7f66340d6c98) + +Class QBluetoothServiceDiscoveryAgent::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothServiceDiscoveryAgent::QPrivateSignal (0x0x7f6633baa5a0) 0 empty + +Vtable for QBluetoothServiceDiscoveryAgent +QBluetoothServiceDiscoveryAgent::_ZTV31QBluetoothServiceDiscoveryAgent: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI31QBluetoothServiceDiscoveryAgent) +16 (int (*)(...))QBluetoothServiceDiscoveryAgent::metaObject +24 (int (*)(...))QBluetoothServiceDiscoveryAgent::qt_metacast +32 (int (*)(...))QBluetoothServiceDiscoveryAgent::qt_metacall +40 (int (*)(...))QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent +48 (int (*)(...))QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent +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 QBluetoothServiceDiscoveryAgent + size=24 align=8 + base size=24 base align=8 +QBluetoothServiceDiscoveryAgent (0x0x7f66340d6d00) 0 + vptr=((& QBluetoothServiceDiscoveryAgent::_ZTV31QBluetoothServiceDiscoveryAgent) + 16u) + QObject (0x0x7f6633baa540) 0 + primary-for QBluetoothServiceDiscoveryAgent (0x0x7f66340d6d00) + +Class QBluetoothTransferManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothTransferManager::QPrivateSignal (0x0x7f6633baa660) 0 empty + +Vtable for QBluetoothTransferManager +QBluetoothTransferManager::_ZTV25QBluetoothTransferManager: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI25QBluetoothTransferManager) +16 (int (*)(...))QBluetoothTransferManager::metaObject +24 (int (*)(...))QBluetoothTransferManager::qt_metacast +32 (int (*)(...))QBluetoothTransferManager::qt_metacall +40 (int (*)(...))QBluetoothTransferManager::~QBluetoothTransferManager +48 (int (*)(...))QBluetoothTransferManager::~QBluetoothTransferManager +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 QBluetoothTransferManager + size=16 align=8 + base size=16 base align=8 +QBluetoothTransferManager (0x0x7f66340d6d68) 0 + vptr=((& QBluetoothTransferManager::_ZTV25QBluetoothTransferManager) + 16u) + QObject (0x0x7f6633baa600) 0 + primary-for QBluetoothTransferManager (0x0x7f66340d6d68) + +Class QBluetoothTransferRequest + size=8 align=8 + base size=8 base align=8 +QBluetoothTransferRequest (0x0x7f6633baa6c0) 0 + +Class QBluetoothTransferReply::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBluetoothTransferReply::QPrivateSignal (0x0x7f6633baa780) 0 empty + +Vtable for QBluetoothTransferReply +QBluetoothTransferReply::_ZTV23QBluetoothTransferReply: 18u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI23QBluetoothTransferReply) +16 (int (*)(...))QBluetoothTransferReply::metaObject +24 (int (*)(...))QBluetoothTransferReply::qt_metacast +32 (int (*)(...))QBluetoothTransferReply::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 + +Class QBluetoothTransferReply + size=24 align=8 + base size=24 base align=8 +QBluetoothTransferReply (0x0x7f66340d6dd0) 0 + vptr=((& QBluetoothTransferReply::_ZTV23QBluetoothTransferReply) + 16u) + QObject (0x0x7f6633baa720) 0 + primary-for QBluetoothTransferReply (0x0x7f66340d6dd0) + +Class QLowEnergyAdvertisingData + size=8 align=8 + base size=8 base align=8 +QLowEnergyAdvertisingData (0x0x7f6633baa900) 0 + +Class QLowEnergyDescriptor + size=24 align=8 + base size=24 base align=8 +QLowEnergyDescriptor (0x0x7f6633baac00) 0 + +Class QLowEnergyCharacteristic + size=24 align=8 + base size=24 base align=8 +QLowEnergyCharacteristic (0x0x7f6633baacc0) 0 + +Class QLowEnergyService::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLowEnergyService::QPrivateSignal (0x0x7f6633baaf00) 0 empty + +Vtable for QLowEnergyService +QLowEnergyService::_ZTV17QLowEnergyService: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QLowEnergyService) +16 (int (*)(...))QLowEnergyService::metaObject +24 (int (*)(...))QLowEnergyService::qt_metacast +32 (int (*)(...))QLowEnergyService::qt_metacall +40 (int (*)(...))QLowEnergyService::~QLowEnergyService +48 (int (*)(...))QLowEnergyService::~QLowEnergyService +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 QLowEnergyService + size=32 align=8 + base size=32 base align=8 +QLowEnergyService (0x0x7f6633cba0d0) 0 + vptr=((& QLowEnergyService::_ZTV17QLowEnergyService) + 16u) + QObject (0x0x7f6633baaea0) 0 + primary-for QLowEnergyService (0x0x7f6633cba0d0) + +Class QLowEnergyController::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLowEnergyController::QPrivateSignal (0x0x7f6633d08600) 0 empty + +Vtable for QLowEnergyController +QLowEnergyController::_ZTV20QLowEnergyController: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI20QLowEnergyController) +16 (int (*)(...))QLowEnergyController::metaObject +24 (int (*)(...))QLowEnergyController::qt_metacast +32 (int (*)(...))QLowEnergyController::qt_metacall +40 (int (*)(...))QLowEnergyController::~QLowEnergyController +48 (int (*)(...))QLowEnergyController::~QLowEnergyController +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 QLowEnergyController + size=24 align=8 + base size=24 base align=8 +QLowEnergyController (0x0x7f6633cba208) 0 + vptr=((& QLowEnergyController::_ZTV20QLowEnergyController) + 16u) + QObject (0x0x7f6633d085a0) 0 + primary-for QLowEnergyController (0x0x7f6633cba208) + +Class QLowEnergyAdvertisingParameters::AddressInfo + size=16 align=8 + base size=12 base align=8 +QLowEnergyAdvertisingParameters::AddressInfo (0x0x7f6633d08b40) 0 + +Class QLowEnergyAdvertisingParameters + size=8 align=8 + base size=8 base align=8 +QLowEnergyAdvertisingParameters (0x0x7f6633d08ae0) 0 + +Class QLowEnergyCharacteristicData + size=8 align=8 + base size=8 base align=8 +QLowEnergyCharacteristicData (0x0x7f6633d08e40) 0 + +Class QLowEnergyConnectionParameters + size=8 align=8 + base size=8 base align=8 +QLowEnergyConnectionParameters (0x0x7f66339c8180) 0 + +Class QLowEnergyDescriptorData + size=8 align=8 + base size=8 base align=8 +QLowEnergyDescriptorData (0x0x7f66339c85a0) 0 + +Class QLowEnergyServiceData + size=8 align=8 + base size=8 base align=8 +QLowEnergyServiceData (0x0x7f66339c88a0) 0 + diff --git a/tests/auto/bic/data/QtNfc.5.10.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtNfc.5.10.0.linux-gcc-amd64.txt new file mode 100644 index 0000000..c9a39b6 --- /dev/null +++ b/tests/auto/bic/data/QtNfc.5.10.0.linux-gcc-amd64.txt @@ -0,0 +1,4754 @@ +Class std::__failure_type + size=1 align=1 + base size=0 base align=1 +std::__failure_type (0x0x7ffb4a1ffb40) 0 empty + +Class std::__do_is_destructible_impl + size=1 align=1 + base size=0 base align=1 +std::__do_is_destructible_impl (0x0x7ffb4a2ca300) 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 (0x0x7ffb4a2ca540) 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 (0x0x7ffb4a2ca780) 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 (0x0x7ffb4a2ca9c0) 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 (0x0x7ffb4a2cab40) 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 (0x0x7ffb4a2caf00) 0 empty + +Class std::__do_common_type_impl + size=1 align=1 + base size=0 base align=1 +std::__do_common_type_impl (0x0x7ffb47f866c0) 0 empty + +Class std::__do_member_type_wrapper + size=1 align=1 + base size=0 base align=1 +std::__do_member_type_wrapper (0x0x7ffb47f86780) 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 (0x0x7ffb47f86ae0) 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 (0x0x7ffb47f86ba0) 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 (0x0x7ffb47f86c60) 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 (0x0x7ffb47f86d20) 0 empty + +Class std::__result_of_other_impl + size=1 align=1 + base size=0 base align=1 +std::__result_of_other_impl (0x0x7ffb47fc2000) 0 empty + +Class std::piecewise_construct_t + size=1 align=1 + base size=0 base align=1 +std::piecewise_construct_t (0x0x7ffb47fc21e0) 0 empty + +Class std::__true_type + size=1 align=1 + base size=0 base align=1 +std::__true_type (0x0x7ffb47fc2660) 0 empty + +Class std::__false_type + size=1 align=1 + base size=0 base align=1 +std::__false_type (0x0x7ffb47fc26c0) 0 empty + +Class std::input_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::input_iterator_tag (0x0x7ffb48066360) 0 empty + +Class std::output_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::output_iterator_tag (0x0x7ffb480663c0) 0 empty + +Class std::forward_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::forward_iterator_tag (0x0x7ffb47f72888) 0 empty + std::input_iterator_tag (0x0x7ffb48066420) 0 empty + +Class std::bidirectional_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::bidirectional_iterator_tag (0x0x7ffb47f728f0) 0 empty + std::forward_iterator_tag (0x0x7ffb47f72958) 0 empty + std::input_iterator_tag (0x0x7ffb48066480) 0 empty + +Class std::random_access_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::random_access_iterator_tag (0x0x7ffb47f729c0) 0 empty + std::bidirectional_iterator_tag (0x0x7ffb47f72a28) 0 empty + std::forward_iterator_tag (0x0x7ffb47f72a90) 0 empty + std::input_iterator_tag (0x0x7ffb480664e0) 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 (0x0x7ffb480d0180) 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 (0x0x7ffb480d01e0) 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 (0x0x7ffb480d0240) 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 (0x0x7ffb480d02a0) 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 (0x0x7ffb480d0300) 0 empty + +Class wait + size=4 align=4 + base size=4 base align=4 +wait (0x0x7ffb480d0de0) 0 + +Class __locale_struct + size=232 align=8 + base size=232 base align=8 +__locale_struct (0x0x7ffb47dd0060) 0 + +Class timespec + size=16 align=8 + base size=16 base align=8 +timespec (0x0x7ffb47dd0120) 0 + +Class timeval + size=16 align=8 + base size=16 base align=8 +timeval (0x0x7ffb47dd0180) 0 + +Class pthread_attr_t + size=56 align=8 + base size=56 base align=8 +pthread_attr_t (0x0x7ffb47dd0240) 0 + +Class __pthread_internal_list + size=16 align=8 + base size=16 base align=8 +__pthread_internal_list (0x0x7ffb47dd02a0) 0 + +Class random_data + size=48 align=8 + base size=48 base align=8 +random_data (0x0x7ffb47dd0720) 0 + +Class drand48_data + size=24 align=8 + base size=24 base align=8 +drand48_data (0x0x7ffb47dd0780) 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 (0x0x7ffb47dd07e0) 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 (0x0x7ffb47ead000) 0 nearly-empty + vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16u) + std::exception (0x0x7ffb47dd0840) 0 nearly-empty + primary-for std::bad_exception (0x0x7ffb47ead000) + +Class std::__exception_ptr::exception_ptr + size=8 align=8 + base size=8 base align=8 +std::__exception_ptr::exception_ptr (0x0x7ffb47dd08a0) 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 (0x0x7ffb47dd0900) 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 (0x0x7ffb47ead208) 0 nearly-empty + vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16u) + std::exception (0x0x7ffb47dd0d20) 0 nearly-empty + primary-for std::bad_alloc (0x0x7ffb47ead208) + +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 (0x0x7ffb47ead270) 0 nearly-empty + vptr=((& std::bad_array_new_length::_ZTVSt20bad_array_new_length) + 16u) + std::bad_alloc (0x0x7ffb47ead2d8) 0 nearly-empty + primary-for std::bad_array_new_length (0x0x7ffb47ead270) + std::exception (0x0x7ffb47dd0d80) 0 nearly-empty + primary-for std::bad_alloc (0x0x7ffb47ead2d8) + +Class std::nothrow_t + size=1 align=1 + base size=0 base align=1 +std::nothrow_t (0x0x7ffb47dd0de0) 0 empty + +Class __exception + size=40 align=8 + base size=40 base align=8 +__exception (0x0x7ffb47b09a20) 0 + +Class lconv + size=96 align=8 + base size=96 base align=8 +lconv (0x0x7ffb47938720) 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 (0x0x7ffb47938780) 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 (0x0x7ffb479e6660) 0 + +Class __sched_param + size=4 align=4 + base size=4 base align=4 +__sched_param (0x0x7ffb479e66c0) 0 + +Class timex + size=208 align=8 + base size=208 base align=8 +timex (0x0x7ffb479e6780) 0 + +Class tm + size=56 align=8 + base size=56 base align=8 +tm (0x0x7ffb479e67e0) 0 + +Class itimerspec + size=32 align=8 + base size=32 base align=8 +itimerspec (0x0x7ffb479e6840) 0 + +Class _pthread_cleanup_buffer + size=32 align=8 + base size=32 base align=8 +_pthread_cleanup_buffer (0x0x7ffb479e68a0) 0 + +Class __pthread_cleanup_frame + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_frame (0x0x7ffb479e69c0) 0 + +Class __pthread_cleanup_class + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_class (0x0x7ffb479e6a20) 0 + +Class _IO_marker + size=24 align=8 + base size=24 base align=8 +_IO_marker (0x0x7ffb479e6e40) 0 + +Class _IO_FILE + size=216 align=8 + base size=216 base align=8 +_IO_FILE (0x0x7ffb479e6ea0) 0 + +Class std::_Hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Hash_impl (0x0x7ffb475376c0) 0 empty + +Class std::_Fnv_hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Fnv_hash_impl (0x0x7ffb47537720) 0 empty + +Class std::__numeric_limits_base + size=1 align=1 + base size=0 base align=1 +std::__numeric_limits_base (0x0x7ffb4758e6c0) 0 empty + +Class std::_Bit_reference + size=16 align=8 + base size=16 base align=8 +std::_Bit_reference (0x0x7ffb473834e0) 0 + +Class std::_Bit_iterator_base + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator_base (0x0x7ffb47538888) 0 + std::iterator (0x0x7ffb473835a0) 0 empty + +Class std::_Bit_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator (0x0x7ffb47538b60) 0 + std::_Bit_iterator_base (0x0x7ffb47538bc8) 0 + std::iterator (0x0x7ffb47383600) 0 empty + +Class std::_Bit_const_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_const_iterator (0x0x7ffb47472000) 0 + std::_Bit_iterator_base (0x0x7ffb47472068) 0 + std::iterator (0x0x7ffb47383660) 0 empty + +Class std::random_device + size=5000 align=8 + base size=5000 base align=8 +std::random_device (0x0x7ffb47193480) 0 + +Class std::bernoulli_distribution::param_type + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution::param_type (0x0x7ffb472bc240) 0 + +Class std::bernoulli_distribution + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution (0x0x7ffb472bc1e0) 0 + +Class std::seed_seq + size=24 align=8 + base size=24 base align=8 +std::seed_seq (0x0x7ffb470881e0) 0 + +Class qIsNull(double)::U + size=8 align=8 + base size=8 base align=8 +qIsNull(double)::U (0x0x7ffb45eddcc0) 0 + +Class qIsNull(float)::U + size=4 align=4 + base size=4 base align=4 +qIsNull(float)::U (0x0x7ffb45eddd20) 0 + +Class QSysInfo + size=1 align=1 + base size=0 base align=1 +QSysInfo (0x0x7ffb45c287e0) 0 empty + +Class QMessageLogContext + size=32 align=8 + base size=32 base align=8 +QMessageLogContext (0x0x7ffb45c28840) 0 + +Class QMessageLogger + size=32 align=8 + base size=32 base align=8 +QMessageLogger (0x0x7ffb45c288a0) 0 + +Class QFlag + size=4 align=4 + base size=4 base align=4 +QFlag (0x0x7ffb45c28900) 0 + +Class QIncompatibleFlag + size=4 align=4 + base size=4 base align=4 +QIncompatibleFlag (0x0x7ffb45c28ba0) 0 + +Class std::__atomic_flag_base + size=1 align=1 + base size=1 base align=1 +std::__atomic_flag_base (0x0x7ffb45caa120) 0 + +Class std::atomic_flag + size=1 align=1 + base size=1 base align=1 +std::atomic_flag (0x0x7ffb45c10f08) 0 + std::__atomic_flag_base (0x0x7ffb45caa180) 0 + +Class QAtomicInt + size=4 align=4 + base size=4 base align=4 +QAtomicInt (0x0x7ffb459fc680) 0 + QAtomicInteger (0x0x7ffb459fc6e8) 0 + QBasicAtomicInteger (0x0x7ffb4572d8a0) 0 + +Class QInternal + size=1 align=1 + base size=0 base align=1 +QInternal (0x0x7ffb45653e40) 0 empty + +Class QtPrivate::QSlotObjectBase + size=16 align=8 + base size=16 base align=8 +QtPrivate::QSlotObjectBase (0x0x7ffb45498ea0) 0 + +Class QGenericArgument + size=16 align=8 + base size=16 base align=8 +QGenericArgument (0x0x7ffb45104000) 0 + +Class QGenericReturnArgument + size=16 align=8 + base size=16 base align=8 +QGenericReturnArgument (0x0x7ffb450fc138) 0 + QGenericArgument (0x0x7ffb45104060) 0 + +Class QMetaObject + size=48 align=8 + base size=48 base align=8 +QMetaObject (0x0x7ffb451041e0) 0 + +Class QMetaObject::Connection + size=8 align=8 + base size=8 base align=8 +QMetaObject::Connection (0x0x7ffb451042a0) 0 + +Class QLatin1Char + size=1 align=1 + base size=1 base align=1 +QLatin1Char (0x0x7ffb451c2300) 0 + +Class QChar + size=2 align=2 + base size=2 base align=2 +QChar (0x0x7ffb451c2360) 0 + +Class QtPrivate::RefCount + size=4 align=4 + base size=4 base align=4 +QtPrivate::RefCount (0x0x7ffb451c2600) 0 + +Class QArrayData + size=24 align=8 + base size=24 base align=8 +QArrayData (0x0x7ffb451c2660) 0 + +Class QtPrivate::QContainerImplHelper + size=1 align=1 + base size=0 base align=1 +QtPrivate::QContainerImplHelper (0x0x7ffb451c29c0) 0 empty + +Class std::locale + size=8 align=8 + base size=8 base align=8 +std::locale (0x0x7ffb451c2a20) 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 (0x0x7ffb451c2a80) 0 + vptr=((& std::locale::facet::_ZTVNSt6locale5facetE) + 16u) + +Class std::locale::id + size=8 align=8 + base size=8 base align=8 +std::locale::id (0x0x7ffb451c2ae0) 0 + +Class std::locale::_Impl + size=40 align=8 + base size=40 base align=8 +std::locale::_Impl (0x0x7ffb451c2b40) 0 + +Class std::__cow_string + size=8 align=8 + base size=8 base align=8 +std::__cow_string (0x0x7ffb451c2f00) 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 (0x0x7ffb452d5750) 0 + vptr=((& std::logic_error::_ZTVSt11logic_error) + 16u) + std::exception (0x0x7ffb44f6c000) 0 nearly-empty + primary-for std::logic_error (0x0x7ffb452d5750) + +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 (0x0x7ffb452d57b8) 0 + vptr=((& std::domain_error::_ZTVSt12domain_error) + 16u) + std::logic_error (0x0x7ffb452d5820) 0 + primary-for std::domain_error (0x0x7ffb452d57b8) + std::exception (0x0x7ffb44f6c060) 0 nearly-empty + primary-for std::logic_error (0x0x7ffb452d5820) + +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 (0x0x7ffb452d5888) 0 + vptr=((& std::invalid_argument::_ZTVSt16invalid_argument) + 16u) + std::logic_error (0x0x7ffb452d58f0) 0 + primary-for std::invalid_argument (0x0x7ffb452d5888) + std::exception (0x0x7ffb44f6c0c0) 0 nearly-empty + primary-for std::logic_error (0x0x7ffb452d58f0) + +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 (0x0x7ffb452d5958) 0 + vptr=((& std::length_error::_ZTVSt12length_error) + 16u) + std::logic_error (0x0x7ffb452d59c0) 0 + primary-for std::length_error (0x0x7ffb452d5958) + std::exception (0x0x7ffb44f6c120) 0 nearly-empty + primary-for std::logic_error (0x0x7ffb452d59c0) + +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 (0x0x7ffb452d5a28) 0 + vptr=((& std::out_of_range::_ZTVSt12out_of_range) + 16u) + std::logic_error (0x0x7ffb452d5a90) 0 + primary-for std::out_of_range (0x0x7ffb452d5a28) + std::exception (0x0x7ffb44f6c180) 0 nearly-empty + primary-for std::logic_error (0x0x7ffb452d5a90) + +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 (0x0x7ffb452d5af8) 0 + vptr=((& std::runtime_error::_ZTVSt13runtime_error) + 16u) + std::exception (0x0x7ffb44f6c1e0) 0 nearly-empty + primary-for std::runtime_error (0x0x7ffb452d5af8) + +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 (0x0x7ffb452d5b60) 0 + vptr=((& std::range_error::_ZTVSt11range_error) + 16u) + std::runtime_error (0x0x7ffb452d5bc8) 0 + primary-for std::range_error (0x0x7ffb452d5b60) + std::exception (0x0x7ffb44f6c240) 0 nearly-empty + primary-for std::runtime_error (0x0x7ffb452d5bc8) + +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 (0x0x7ffb452d5c30) 0 + vptr=((& std::overflow_error::_ZTVSt14overflow_error) + 16u) + std::runtime_error (0x0x7ffb452d5c98) 0 + primary-for std::overflow_error (0x0x7ffb452d5c30) + std::exception (0x0x7ffb44f6c2a0) 0 nearly-empty + primary-for std::runtime_error (0x0x7ffb452d5c98) + +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 (0x0x7ffb452d5d00) 0 + vptr=((& std::underflow_error::_ZTVSt15underflow_error) + 16u) + std::runtime_error (0x0x7ffb452d5d68) 0 + primary-for std::underflow_error (0x0x7ffb452d5d00) + std::exception (0x0x7ffb44f6c300) 0 nearly-empty + primary-for std::runtime_error (0x0x7ffb452d5d68) + +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 (0x0x7ffb44f6c480) 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 (0x0x7ffb44f6c6c0) 0 + +Class std::error_condition + size=16 align=8 + base size=16 base align=8 +std::error_condition (0x0x7ffb44f6c840) 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 (0x0x7ffb44fcf1a0) 0 + vptr=((& std::system_error::_ZTVSt12system_error) + 16u) + std::runtime_error (0x0x7ffb44fcf208) 0 + primary-for std::system_error (0x0x7ffb44fcf1a0) + std::exception (0x0x7ffb44f6ca80) 0 nearly-empty + primary-for std::runtime_error (0x0x7ffb44fcf208) + +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 (0x0x7ffb44fcfdd0) 0 + vptr=((& std::ios_base::failure::_ZTVNSt8ios_base7failureB5cxx11E) + 16u) + std::system_error (0x0x7ffb44fcfe38) 0 + primary-for std::ios_base::failure (0x0x7ffb44fcfdd0) + std::runtime_error (0x0x7ffb44fcfea0) 0 + primary-for std::system_error (0x0x7ffb44fcfe38) + std::exception (0x0x7ffb44f6cd80) 0 nearly-empty + primary-for std::runtime_error (0x0x7ffb44fcfea0) + +Class std::ios_base::_Callback_list + size=24 align=8 + base size=24 base align=8 +std::ios_base::_Callback_list (0x0x7ffb44f6cde0) 0 + +Class std::ios_base::_Words + size=16 align=8 + base size=16 base align=8 +std::ios_base::_Words (0x0x7ffb44f6ce40) 0 + +Class std::ios_base::Init + size=1 align=1 + base size=0 base align=1 +std::ios_base::Init (0x0x7ffb44f6cea0) 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 (0x0x7ffb44f6cd20) 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 (0x0x7ffb450a3660) 0 empty + +Class std::__num_base + size=1 align=1 + base size=0 base align=1 +std::__num_base (0x0x7ffb450a3d20) 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 (0x0x7ffb44c857b8 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 (0x0x7ffb44c85888 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 (0x0x7ffb44c85c30 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 (0x0x7ffb44c85d00 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 (0x0x7ffb44c555a0) 0 + +Class QByteArray + size=8 align=8 + base size=8 base align=8 +QByteArray (0x0x7ffb44c55600) 0 + +Class QByteRef + size=16 align=8 + base size=12 base align=8 +QByteRef (0x0x7ffb449f6960) 0 + +Class QStringDataPtr + size=8 align=8 + base size=8 base align=8 +QStringDataPtr (0x0x7ffb449f6cc0) 0 + +Class QStringView + size=16 align=8 + base size=16 base align=8 +QStringView (0x0x7ffb44aec180) 0 + +Class QLatin1String + size=16 align=8 + base size=16 base align=8 +QLatin1String (0x0x7ffb44788000) 0 + +Class QString::Null + size=1 align=1 + base size=0 base align=1 +QString::Null (0x0x7ffb44788660) 0 empty + +Class QString + size=8 align=8 + base size=8 base align=8 +QString (0x0x7ffb44788600) 0 + +Class QCharRef + size=16 align=8 + base size=12 base align=8 +QCharRef (0x0x7ffb44550720) 0 + +Class QStringRef + size=16 align=8 + base size=16 base align=8 +QStringRef (0x0x7ffb446e6360) 0 + +Class QtPrivate::QHashCombine + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombine (0x0x7ffb446e6f60) 0 empty + +Class QtPrivate::QHashCombineCommutative + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombineCommutative (0x0x7ffb444e9000) 0 empty + +Class std::__detail::_List_node_base + size=16 align=8 + base size=16 base align=8 +std::__detail::_List_node_base (0x0x7ffb444e9060) 0 + +Class QListData::NotArrayCompatibleLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotArrayCompatibleLayout (0x0x7ffb444e9420) 0 empty + +Class QListData::NotIndirectLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotIndirectLayout (0x0x7ffb444e9480) 0 empty + +Class QListData::ArrayCompatibleLayout + size=1 align=1 + base size=1 base align=1 +QListData::ArrayCompatibleLayout (0x0x7ffb444a86e8) 0 empty + QListData::NotIndirectLayout (0x0x7ffb444e94e0) 0 empty + +Class QListData::InlineWithPaddingLayout + size=1 align=1 + base size=1 base align=1 +QListData::InlineWithPaddingLayout (0x0x7ffb44199620) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7ffb444e9540) 0 empty + QListData::NotIndirectLayout (0x0x7ffb444e95a0) 0 empty + +Class QListData::IndirectLayout + size=1 align=1 + base size=1 base align=1 +QListData::IndirectLayout (0x0x7ffb444a8750) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7ffb444e9600) 0 empty + +Class QListData::Data + size=24 align=8 + base size=24 base align=8 +QListData::Data (0x0x7ffb444e9660) 0 + +Class QListData + size=8 align=8 + base size=8 base align=8 +QListData (0x0x7ffb444e93c0) 0 + +Class QRegExp + size=8 align=8 + base size=8 base align=8 +QRegExp (0x0x7ffb444e9ae0) 0 + +Class QStringMatcher::Data + size=272 align=8 + base size=272 base align=8 +QStringMatcher::Data (0x0x7ffb43f3fd20) 0 + +Class QStringMatcher + size=1048 align=8 + base size=1048 base align=8 +QStringMatcher (0x0x7ffb43f3fcc0) 0 + +Class QStringList + size=8 align=8 + base size=8 base align=8 +QStringList (0x0x7ffb43f561a0) 0 + QList (0x0x7ffb43f56208) 0 + QListSpecialMethods (0x0x7ffb43f3ff00) 0 empty + +Class QScopedPointerPodDeleter + size=1 align=1 + base size=0 base align=1 +QScopedPointerPodDeleter (0x0x7ffb43fa9360) 0 empty + +Class std::_Rb_tree_node_base + size=32 align=8 + base size=32 base align=8 +std::_Rb_tree_node_base (0x0x7ffb43fa9e40) 0 + +Class std::allocator_arg_t + size=1 align=1 + base size=0 base align=1 +std::allocator_arg_t (0x0x7ffb440a44e0) 0 empty + +Class std::__uses_alloc_base + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc_base (0x0x7ffb440a4660) 0 empty + +Class std::__uses_alloc0::_Sink + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc0::_Sink (0x0x7ffb440a4720) 0 empty + +Class std::__uses_alloc0 + size=1 align=1 + base size=1 base align=1 +std::__uses_alloc0 (0x0x7ffb43f56af8) 0 + std::__uses_alloc_base (0x0x7ffb440a46c0) 0 empty + +Class std::_Swallow_assign + size=1 align=1 + base size=0 base align=1 +std::_Swallow_assign (0x0x7ffb43eb7780) 0 empty + +Class QtPrivate::AbstractDebugStreamFunction + size=16 align=8 + base size=16 base align=8 +QtPrivate::AbstractDebugStreamFunction (0x0x7ffb43eb79c0) 0 + +Class QtPrivate::AbstractComparatorFunction + size=24 align=8 + base size=24 base align=8 +QtPrivate::AbstractComparatorFunction (0x0x7ffb43eb7a80) 0 + +Class QtPrivate::AbstractConverterFunction + size=8 align=8 + base size=8 base align=8 +QtPrivate::AbstractConverterFunction (0x0x7ffb43eb7ba0) 0 + +Class QMetaType + size=80 align=8 + base size=80 base align=8 +QMetaType (0x0x7ffb43eb7d20) 0 + +Class QtMetaTypePrivate::VariantData + size=24 align=8 + base size=20 base align=8 +QtMetaTypePrivate::VariantData (0x0x7ffb43c16180) 0 + +Class QtMetaTypePrivate::VectorBoolElements + size=1 align=1 + base size=0 base align=1 +QtMetaTypePrivate::VectorBoolElements (0x0x7ffb43c162a0) 0 empty + +Class QtMetaTypePrivate::QSequentialIterableImpl + size=104 align=8 + base size=104 base align=8 +QtMetaTypePrivate::QSequentialIterableImpl (0x0x7ffb43c16c00) 0 + +Class QtMetaTypePrivate::QAssociativeIterableImpl + size=112 align=8 + base size=112 base align=8 +QtMetaTypePrivate::QAssociativeIterableImpl (0x0x7ffb438e4060) 0 + +Class QtMetaTypePrivate::QPairVariantInterfaceImpl + size=40 align=8 + base size=40 base align=8 +QtMetaTypePrivate::QPairVariantInterfaceImpl (0x0x7ffb438e4360) 0 + +Class std::chrono::_V2::system_clock + size=1 align=1 + base size=0 base align=1 +std::chrono::_V2::system_clock (0x0x7ffb43707ba0) 0 empty + +Class std::chrono::_V2::steady_clock + size=1 align=1 + base size=0 base align=1 +std::chrono::_V2::steady_clock (0x0x7ffb43879a20) 0 empty + +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 (0x0x7ffb43879a80) 0 + vptr=((& QObjectData::_ZTV11QObjectData) + 16u) + +Class QObject::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObject::QPrivateSignal (0x0x7ffb43879c60) 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 (0x0x7ffb43879c00) 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 (0x0x7ffb43513f00) 0 nearly-empty + vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16u) + +Class QSignalBlocker + size=16 align=8 + base size=10 base align=8 +QSignalBlocker (0x0x7ffb43513f60) 0 + +Class QAbstractAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractAnimation::QPrivateSignal (0x0x7ffb43596060) 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 (0x0x7ffb43546ea0) 0 + vptr=((& QAbstractAnimation::_ZTV18QAbstractAnimation) + 16u) + QObject (0x0x7ffb43596000) 0 + primary-for QAbstractAnimation (0x0x7ffb43546ea0) + +Class QAnimationDriver::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationDriver::QPrivateSignal (0x0x7ffb43596120) 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 (0x0x7ffb43546f08) 0 + vptr=((& QAnimationDriver::_ZTV16QAnimationDriver) + 16u) + QObject (0x0x7ffb435960c0) 0 + primary-for QAnimationDriver (0x0x7ffb43546f08) + +Class QEventLoop::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventLoop::QPrivateSignal (0x0x7ffb435961e0) 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 (0x0x7ffb43546f70) 0 + vptr=((& QEventLoop::_ZTV10QEventLoop) + 16u) + QObject (0x0x7ffb43596180) 0 + primary-for QEventLoop (0x0x7ffb43546f70) + +Class QEventLoopLocker + size=8 align=8 + base size=8 base align=8 +QEventLoopLocker (0x0x7ffb435963c0) 0 + +Class QAbstractEventDispatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractEventDispatcher::QPrivateSignal (0x0x7ffb43596480) 0 empty + +Class QAbstractEventDispatcher::TimerInfo + size=12 align=4 + base size=12 base align=4 +QAbstractEventDispatcher::TimerInfo (0x0x7ffb435964e0) 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 (0x0x7ffb435462d8) 0 + vptr=((& QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher) + 16u) + QObject (0x0x7ffb43596420) 0 + primary-for QAbstractEventDispatcher (0x0x7ffb435462d8) + +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 (0x0x7ffb43596780) 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 (0x0x7ffb43616138) 0 nearly-empty + vptr=((& std::bad_cast::_ZTVSt8bad_cast) + 16u) + std::exception (0x0x7ffb435967e0) 0 nearly-empty + primary-for std::bad_cast (0x0x7ffb43616138) + +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 (0x0x7ffb436161a0) 0 nearly-empty + vptr=((& std::bad_typeid::_ZTVSt10bad_typeid) + 16u) + std::exception (0x0x7ffb43596840) 0 nearly-empty + primary-for std::bad_typeid (0x0x7ffb436161a0) + +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 (0x0x7ffb43392410) 0 nearly-empty + vptr=((& std::bad_function_call::_ZTVSt17bad_function_call) + 16u) + std::exception (0x0x7ffb43344900) 0 nearly-empty + primary-for std::bad_function_call (0x0x7ffb43392410) + +Class std::_Nocopy_types + size=16 align=8 + base size=16 base align=8 +std::_Nocopy_types (0x0x7ffb433449c0) 0 + +Class std::_Any_data + size=16 align=8 + base size=16 base align=8 +std::_Any_data (0x0x7ffb43344a20) 0 + +Class std::_Function_base + size=24 align=8 + base size=24 base align=8 +std::_Function_base (0x0x7ffb43344b40) 0 + +Class QMapNodeBase + size=24 align=8 + base size=24 base align=8 +QMapNodeBase (0x0x7ffb4340c060) 0 + +Class QMapDataBase + size=40 align=8 + base size=40 base align=8 +QMapDataBase (0x0x7ffb4340c5a0) 0 + +Class QHashData::Node + size=16 align=8 + base size=16 base align=8 +QHashData::Node (0x0x7ffb4340c960) 0 + +Class QHashData + size=48 align=8 + base size=44 base align=8 +QHashData (0x0x7ffb4340c900) 0 + +Class QHashDummyValue + size=1 align=1 + base size=0 base align=1 +QHashDummyValue (0x0x7ffb4340c9c0) 0 empty + +Class QVariant::PrivateShared + size=16 align=8 + base size=12 base align=8 +QVariant::PrivateShared (0x0x7ffb432242a0) 0 + +Class QVariant::Private::Data + size=8 align=8 + base size=8 base align=8 +QVariant::Private::Data (0x0x7ffb43224360) 0 + +Class QVariant::Private + size=16 align=8 + base size=12 base align=8 +QVariant::Private (0x0x7ffb43224300) 0 + +Class QVariant::Handler + size=72 align=8 + base size=72 base align=8 +QVariant::Handler (0x0x7ffb432243c0) 0 + +Class QVariant + size=16 align=8 + base size=16 base align=8 +QVariant (0x0x7ffb43224240) 0 + +Class QVariantComparisonHelper + size=8 align=8 + base size=8 base align=8 +QVariantComparisonHelper (0x0x7ffb42f17ea0) 0 + +Class QSequentialIterable::const_iterator + size=112 align=8 + base size=112 base align=8 +QSequentialIterable::const_iterator (0x0x7ffb42fc3540) 0 + +Class QSequentialIterable + size=104 align=8 + base size=104 base align=8 +QSequentialIterable (0x0x7ffb42fc34e0) 0 + +Class QAssociativeIterable::const_iterator + size=120 align=8 + base size=120 base align=8 +QAssociativeIterable::const_iterator (0x0x7ffb42fc3600) 0 + +Class QAssociativeIterable + size=112 align=8 + base size=112 base align=8 +QAssociativeIterable (0x0x7ffb42fc35a0) 0 + +Class QModelIndex + size=24 align=8 + base size=24 base align=8 +QModelIndex (0x0x7ffb42cdf900) 0 + +Class QPersistentModelIndex + size=8 align=8 + base size=8 base align=8 +QPersistentModelIndex (0x0x7ffb42e25000) 0 + +Class QAbstractItemModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractItemModel::QPrivateSignal (0x0x7ffb42eb4720) 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 (0x0x7ffb42ebe1a0) 0 + vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16u) + QObject (0x0x7ffb42eb46c0) 0 + primary-for QAbstractItemModel (0x0x7ffb42ebe1a0) + +Class QAbstractTableModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTableModel::QPrivateSignal (0x0x7ffb42eb4a80) 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 (0x0x7ffb42ebe3a8) 0 + vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16u) + QAbstractItemModel (0x0x7ffb42ebe410) 0 + primary-for QAbstractTableModel (0x0x7ffb42ebe3a8) + QObject (0x0x7ffb42eb4a20) 0 + primary-for QAbstractItemModel (0x0x7ffb42ebe410) + +Class QAbstractListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractListModel::QPrivateSignal (0x0x7ffb42eb4b40) 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 (0x0x7ffb42ebe478) 0 + vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16u) + QAbstractItemModel (0x0x7ffb42ebe4e0) 0 + primary-for QAbstractListModel (0x0x7ffb42ebe478) + QObject (0x0x7ffb42eb4ae0) 0 + primary-for QAbstractItemModel (0x0x7ffb42ebe4e0) + +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 (0x0x7ffb42eb4de0) 0 + vptr=((& QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter) + 16u) + +Class QAbstractProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractProxyModel::QPrivateSignal (0x0x7ffb42eb4ea0) 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 (0x0x7ffb42ebe618) 0 + vptr=((& QAbstractProxyModel::_ZTV19QAbstractProxyModel) + 16u) + QAbstractItemModel (0x0x7ffb42ebe680) 0 + primary-for QAbstractProxyModel (0x0x7ffb42ebe618) + QObject (0x0x7ffb42eb4e40) 0 + primary-for QAbstractItemModel (0x0x7ffb42ebe680) + +Class QAbstractState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractState::QPrivateSignal (0x0x7ffb42eb4f60) 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 (0x0x7ffb42ebe6e8) 0 + vptr=((& QAbstractState::_ZTV14QAbstractState) + 16u) + QObject (0x0x7ffb42eb4f00) 0 + primary-for QAbstractState (0x0x7ffb42ebe6e8) + +Class QAbstractTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTransition::QPrivateSignal (0x0x7ffb42bee060) 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 (0x0x7ffb42ebe750) 0 + vptr=((& QAbstractTransition::_ZTV19QAbstractTransition) + 16u) + QObject (0x0x7ffb42bee000) 0 + primary-for QAbstractTransition (0x0x7ffb42ebe750) + +Class QAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationGroup::QPrivateSignal (0x0x7ffb42bee120) 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 (0x0x7ffb42ebe7b8) 0 + vptr=((& QAnimationGroup::_ZTV15QAnimationGroup) + 16u) + QAbstractAnimation (0x0x7ffb42ebe820) 0 + primary-for QAnimationGroup (0x0x7ffb42ebe7b8) + QObject (0x0x7ffb42bee0c0) 0 + primary-for QAbstractAnimation (0x0x7ffb42ebe820) + +Class QBasicTimer + size=4 align=4 + base size=4 base align=4 +QBasicTimer (0x0x7ffb42c2ce40) 0 + +Class QBitArray + size=8 align=8 + base size=8 base align=8 +QBitArray (0x0x7ffb42c73120) 0 + +Class QBitRef + size=16 align=8 + base size=12 base align=8 +QBitRef (0x0x7ffb42c731e0) 0 + +Class QIODevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIODevice::QPrivateSignal (0x0x7ffb42c734e0) 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 (0x0x7ffb42ebeea0) 0 + vptr=((& QIODevice::_ZTV9QIODevice) + 16u) + QObject (0x0x7ffb42c73480) 0 + primary-for QIODevice (0x0x7ffb42ebeea0) + +Class QBuffer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBuffer::QPrivateSignal (0x0x7ffb42c73720) 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 (0x0x7ffb42914000) 0 + vptr=((& QBuffer::_ZTV7QBuffer) + 16u) + QIODevice (0x0x7ffb42914068) 0 + primary-for QBuffer (0x0x7ffb42914000) + QObject (0x0x7ffb42c736c0) 0 + primary-for QIODevice (0x0x7ffb42914068) + +Class QByteArrayMatcher::Data + size=272 align=8 + base size=272 base align=8 +QByteArrayMatcher::Data (0x0x7ffb42c737e0) 0 + +Class QByteArrayMatcher + size=1040 align=8 + base size=1040 base align=8 +QByteArrayMatcher (0x0x7ffb42c73780) 0 + +Class QStaticByteArrayMatcherBase::Skiptable + size=256 align=1 + base size=256 base align=1 +QStaticByteArrayMatcherBase::Skiptable (0x0x7ffb42c73900) 0 + +Class QStaticByteArrayMatcherBase + size=256 align=16 + base size=256 base align=16 +QStaticByteArrayMatcherBase (0x0x7ffb42c738a0) 0 + +Class QSharedData + size=4 align=4 + base size=4 base align=4 +QSharedData (0x0x7ffb42c73ae0) 0 + +Class QLocale + size=8 align=8 + base size=8 base align=8 +QLocale (0x0x7ffb42c73cc0) 0 + +Class QCollatorSortKey + size=8 align=8 + base size=8 base align=8 +QCollatorSortKey (0x0x7ffb42a51300) 0 + +Class QCollator + size=8 align=8 + base size=8 base align=8 +QCollator (0x0x7ffb42a513c0) 0 + +Class QCommandLineOption + size=8 align=8 + base size=8 base align=8 +QCommandLineOption (0x0x7ffb426d63c0) 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 (0x0x7ffb426d6840) 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 (0x0x7ffb426db548) 0 + vptr=((& QTimerEvent::_ZTV11QTimerEvent) + 16u) + QEvent (0x0x7ffb426d68a0) 0 + primary-for QTimerEvent (0x0x7ffb426db548) + +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 (0x0x7ffb426db5b0) 0 + vptr=((& QChildEvent::_ZTV11QChildEvent) + 16u) + QEvent (0x0x7ffb426d6900) 0 + primary-for QChildEvent (0x0x7ffb426db5b0) + +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 (0x0x7ffb426dbaf8) 0 + vptr=((& QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent) + 16u) + QEvent (0x0x7ffb426d6de0) 0 + primary-for QDynamicPropertyChangeEvent (0x0x7ffb426dbaf8) + +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 (0x0x7ffb426dbb60) 0 + vptr=((& QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent) + 16u) + QEvent (0x0x7ffb426d6e40) 0 + primary-for QDeferredDeleteEvent (0x0x7ffb426dbb60) + +Class QCoreApplication::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QCoreApplication::QPrivateSignal (0x0x7ffb426d6f00) 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 (0x0x7ffb426dbbc8) 0 + vptr=((& QCoreApplication::_ZTV16QCoreApplication) + 16u) + QObject (0x0x7ffb426d6ea0) 0 + primary-for QCoreApplication (0x0x7ffb426dbbc8) + +Class QCommandLineParser + size=8 align=8 + base size=8 base align=8 +QCommandLineParser (0x0x7ffb426d6f60) 0 + +Class QContiguousCacheData + size=24 align=4 + base size=24 base align=4 +QContiguousCacheData (0x0x7ffb42797000) 0 + +Class QCryptographicHash + size=8 align=8 + base size=8 base align=8 +QCryptographicHash (0x0x7ffb42797600) 0 + +Class QDataStream + size=32 align=8 + base size=32 base align=8 +QDataStream (0x0x7ffb42797660) 0 + +Class QtPrivate::StreamStateSaver + size=16 align=8 + base size=12 base align=8 +QtPrivate::StreamStateSaver (0x0x7ffb42797720) 0 + +Class QDate + size=8 align=8 + base size=8 base align=8 +QDate (0x0x7ffb42797c00) 0 + +Class QTime + size=4 align=4 + base size=4 base align=4 +QTime (0x0x7ffb42797ea0) 0 + +Class QDateTime::ShortData + size=8 align=8 + base size=8 base align=8 +QDateTime::ShortData (0x0x7ffb42494660) 0 + +Class QDateTime::Data + size=8 align=8 + base size=8 base align=8 +QDateTime::Data (0x0x7ffb424946c0) 0 + +Class QDateTime + size=8 align=8 + base size=8 base align=8 +QDateTime (0x0x7ffb42494600) 0 + +Class QElapsedTimer + size=16 align=8 + base size=16 base align=8 +QElapsedTimer (0x0x7ffb425467e0) 0 + +Class QDeadlineTimer + size=16 align=8 + base size=16 base align=8 +QDeadlineTimer (0x0x7ffb42546cc0) 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 (0x0x7ffb42667c60) 0 + vptr=((& QTextStream::_ZTV11QTextStream) + 16u) + +Class QTextStreamManipulator + size=40 align=8 + base size=38 base align=8 +QTextStreamManipulator (0x0x7ffb42667f00) 0 + +Class QtSharedPointer::NormalDeleter + size=1 align=1 + base size=0 base align=1 +QtSharedPointer::NormalDeleter (0x0x7ffb42330180) 0 empty + +Class QtSharedPointer::ExternalRefCountData + size=16 align=8 + base size=16 base align=8 +QtSharedPointer::ExternalRefCountData (0x0x7ffb42330300) 0 + +Class QDebug::Stream + size=80 align=8 + base size=76 base align=8 +QDebug::Stream (0x0x7ffb42330840) 0 + +Class QDebug + size=8 align=8 + base size=8 base align=8 +QDebug (0x0x7ffb423307e0) 0 + +Class QDebugStateSaver + size=8 align=8 + base size=8 base align=8 +QDebugStateSaver (0x0x7ffb42109d20) 0 + +Class QNoDebug + size=1 align=1 + base size=0 base align=1 +QNoDebug (0x0x7ffb42109de0) 0 empty + +Class QFileDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileDevice::QPrivateSignal (0x0x7ffb421d1f60) 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 (0x0x7ffb421ead00) 0 + vptr=((& QFileDevice::_ZTV11QFileDevice) + 16u) + QIODevice (0x0x7ffb421ead68) 0 + primary-for QFileDevice (0x0x7ffb421ead00) + QObject (0x0x7ffb421d1f00) 0 + primary-for QIODevice (0x0x7ffb421ead68) + +Class QFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFile::QPrivateSignal (0x0x7ffb422251e0) 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 (0x0x7ffb421eaea0) 0 + vptr=((& QFile::_ZTV5QFile) + 16u) + QFileDevice (0x0x7ffb421eaf08) 0 + primary-for QFile (0x0x7ffb421eaea0) + QIODevice (0x0x7ffb421eaf70) 0 + primary-for QFileDevice (0x0x7ffb421eaf08) + QObject (0x0x7ffb42225180) 0 + primary-for QIODevice (0x0x7ffb421eaf70) + +Class QFileInfo + size=8 align=8 + base size=8 base align=8 +QFileInfo (0x0x7ffb422253c0) 0 + +Class QDir + size=8 align=8 + base size=8 base align=8 +QDir (0x0x7ffb422257e0) 0 + +Class QDirIterator + size=8 align=8 + base size=8 base align=8 +QDirIterator (0x0x7ffb41f201e0) 0 + +Class QEasingCurve + size=8 align=8 + base size=8 base align=8 +QEasingCurve (0x0x7ffb41f20420) 0 + +Class QEventTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventTransition::QPrivateSignal (0x0x7ffb42005840) 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 (0x0x7ffb41ffef70) 0 + vptr=((& QEventTransition::_ZTV16QEventTransition) + 16u) + QAbstractTransition (0x0x7ffb42050000) 0 + primary-for QEventTransition (0x0x7ffb41ffef70) + QObject (0x0x7ffb420057e0) 0 + primary-for QAbstractTransition (0x0x7ffb42050000) + +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 (0x0x7ffb42050068) 0 nearly-empty + vptr=((& QException::_ZTV10QException) + 16u) + std::exception (0x0x7ffb420058a0) 0 nearly-empty + primary-for QException (0x0x7ffb42050068) + +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 (0x0x7ffb420500d0) 0 nearly-empty + vptr=((& QUnhandledException::_ZTV19QUnhandledException) + 16u) + QException (0x0x7ffb42050138) 0 nearly-empty + primary-for QUnhandledException (0x0x7ffb420500d0) + std::exception (0x0x7ffb42005900) 0 nearly-empty + primary-for QException (0x0x7ffb42050138) + +Class QtPrivate::ExceptionHolder + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionHolder (0x0x7ffb42005960) 0 + +Class QtPrivate::ExceptionStore + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionStore (0x0x7ffb42005a20) 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 (0x0x7ffb42005a80) 0 nearly-empty + vptr=((& QFactoryInterface::_ZTV17QFactoryInterface) + 16u) + +Class QFileSelector::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSelector::QPrivateSignal (0x0x7ffb42005ba0) 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 (0x0x7ffb420501a0) 0 + vptr=((& QFileSelector::_ZTV13QFileSelector) + 16u) + QObject (0x0x7ffb42005b40) 0 + primary-for QFileSelector (0x0x7ffb420501a0) + +Class QFileSystemWatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSystemWatcher::QPrivateSignal (0x0x7ffb42005c60) 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 (0x0x7ffb42050208) 0 + vptr=((& QFileSystemWatcher::_ZTV18QFileSystemWatcher) + 16u) + QObject (0x0x7ffb42005c00) 0 + primary-for QFileSystemWatcher (0x0x7ffb42050208) + +Class QFinalState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFinalState::QPrivateSignal (0x0x7ffb42005d20) 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 (0x0x7ffb42050270) 0 + vptr=((& QFinalState::_ZTV11QFinalState) + 16u) + QAbstractState (0x0x7ffb420502d8) 0 + primary-for QFinalState (0x0x7ffb42050270) + QObject (0x0x7ffb42005cc0) 0 + primary-for QAbstractState (0x0x7ffb420502d8) + +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 (0x0x7ffb42005d80) 0 + vptr=((& QRunnable::_ZTV9QRunnable) + 16u) + +Class QBasicMutex + size=8 align=8 + base size=8 base align=8 +QBasicMutex (0x0x7ffb42005de0) 0 + +Class QMutex + size=8 align=8 + base size=8 base align=8 +QMutex (0x0x7ffb42050410) 0 + QBasicMutex (0x0x7ffb41d2b000) 0 + +Class QMutexLocker + size=8 align=8 + base size=8 base align=8 +QMutexLocker (0x0x7ffb41d2b060) 0 + +Class QtPrivate::ResultItem + size=16 align=8 + base size=16 base align=8 +QtPrivate::ResultItem (0x0x7ffb41d2b0c0) 0 + +Class QtPrivate::ResultIteratorBase + size=16 align=8 + base size=12 base align=8 +QtPrivate::ResultIteratorBase (0x0x7ffb41d2b120) 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 (0x0x7ffb41d2b240) 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 (0x0x7ffb41d2ba80) 0 + vptr=((& QFutureInterfaceBase::_ZTV20QFutureInterfaceBase) + 16u) + +Class QFutureWatcherBase::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFutureWatcherBase::QPrivateSignal (0x0x7ffb41e1c2a0) 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 (0x0x7ffb41dc9548) 0 + vptr=((& QFutureWatcherBase::_ZTV18QFutureWatcherBase) + 16u) + QObject (0x0x7ffb41e1c240) 0 + primary-for QFutureWatcherBase (0x0x7ffb41dc9548) + +Class QHistoryState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QHistoryState::QPrivateSignal (0x0x7ffb41e1c8a0) 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 (0x0x7ffb41dc9e38) 0 + vptr=((& QHistoryState::_ZTV13QHistoryState) + 16u) + QAbstractState (0x0x7ffb41dc9ea0) 0 + primary-for QHistoryState (0x0x7ffb41dc9e38) + QObject (0x0x7ffb41e1c840) 0 + primary-for QAbstractState (0x0x7ffb41dc9ea0) + +Class QIdentityProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIdentityProxyModel::QPrivateSignal (0x0x7ffb41e1c960) 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 (0x0x7ffb41dc9f08) 0 + vptr=((& QIdentityProxyModel::_ZTV19QIdentityProxyModel) + 16u) + QAbstractProxyModel (0x0x7ffb41dc9f70) 0 + primary-for QIdentityProxyModel (0x0x7ffb41dc9f08) + QAbstractItemModel (0x0x7ffb41a91000) 0 + primary-for QAbstractProxyModel (0x0x7ffb41dc9f70) + QObject (0x0x7ffb41e1c900) 0 + primary-for QAbstractItemModel (0x0x7ffb41a91000) + +Class QItemSelectionRange + size=16 align=8 + base size=16 base align=8 +QItemSelectionRange (0x0x7ffb41e1c9c0) 0 + +Class QItemSelectionModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QItemSelectionModel::QPrivateSignal (0x0x7ffb41af30c0) 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 (0x0x7ffb41a91820) 0 + vptr=((& QItemSelectionModel::_ZTV19QItemSelectionModel) + 16u) + QObject (0x0x7ffb41af3060) 0 + primary-for QItemSelectionModel (0x0x7ffb41a91820) + +Class QItemSelection + size=8 align=8 + base size=8 base align=8 +QItemSelection (0x0x7ffb41a91a28) 0 + QList (0x0x7ffb41a91a90) 0 + QListSpecialMethods (0x0x7ffb41af33c0) 0 empty + +Class QJsonValue + size=24 align=8 + base size=20 base align=8 +QJsonValue (0x0x7ffb41af38a0) 0 + +Class QJsonValueRef + size=16 align=8 + base size=12 base align=8 +QJsonValueRef (0x0x7ffb4190d000) 0 + +Class QJsonValuePtr + size=24 align=8 + base size=24 base align=8 +QJsonValuePtr (0x0x7ffb4190d540) 0 + +Class QJsonValueRefPtr + size=16 align=8 + base size=16 base align=8 +QJsonValueRefPtr (0x0x7ffb4190d5a0) 0 + +Class QJsonArray::iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::iterator (0x0x7ffb4190d780) 0 + +Class QJsonArray::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::const_iterator (0x0x7ffb4190d7e0) 0 + +Class QJsonArray + size=16 align=8 + base size=16 base align=8 +QJsonArray (0x0x7ffb4190d720) 0 + +Class QJsonParseError + size=8 align=4 + base size=8 base align=4 +QJsonParseError (0x0x7ffb419ffa20) 0 + +Class QJsonDocument + size=8 align=8 + base size=8 base align=8 +QJsonDocument (0x0x7ffb419ffa80) 0 + +Class QJsonObject::iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::iterator (0x0x7ffb41a77120) 0 + +Class QJsonObject::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::const_iterator (0x0x7ffb41a77180) 0 + +Class QJsonObject + size=16 align=8 + base size=16 base align=8 +QJsonObject (0x0x7ffb41a770c0) 0 + +Class QLibrary::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLibrary::QPrivateSignal (0x0x7ffb4170f420) 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 (0x0x7ffb41700dd0) 0 + vptr=((& QLibrary::_ZTV8QLibrary) + 16u) + QObject (0x0x7ffb4170f3c0) 0 + primary-for QLibrary (0x0x7ffb41700dd0) + +Class QVersionNumber::SegmentStorage + size=8 align=8 + base size=8 base align=8 +QVersionNumber::SegmentStorage (0x0x7ffb4170fae0) 0 + +Class QVersionNumber + size=8 align=8 + base size=8 base align=8 +QVersionNumber (0x0x7ffb4170f600) 0 + +Class QLibraryInfo + size=1 align=1 + base size=0 base align=1 +QLibraryInfo (0x0x7ffb41805000) 0 empty + +Class QPoint + size=8 align=4 + base size=8 base align=4 +QPoint (0x0x7ffb41805060) 0 + +Class QPointF + size=16 align=8 + base size=16 base align=8 +QPointF (0x0x7ffb41805300) 0 + +Class QLine + size=16 align=4 + base size=16 base align=4 +QLine (0x0x7ffb418055a0) 0 + +Class QLineF + size=32 align=8 + base size=32 base align=8 +QLineF (0x0x7ffb41805f00) 0 + +Class QLinkedListData + size=32 align=8 + base size=25 base align=8 +QLinkedListData (0x0x7ffb414d48a0) 0 + +Class QLockFile + size=8 align=8 + base size=8 base align=8 +QLockFile (0x0x7ffb414d4c00) 0 + +Class QLoggingCategory::AtomicBools + size=4 align=1 + base size=4 base align=1 +QLoggingCategory::AtomicBools (0x0x7ffb414d4d80) 0 + +Class QLoggingCategory + size=24 align=8 + base size=24 base align=8 +QLoggingCategory (0x0x7ffb414d4d20) 0 + +Class QMargins + size=16 align=4 + base size=16 base align=4 +QMargins (0x0x7ffb414d4f00) 0 + +Class QMarginsF + size=32 align=8 + base size=32 base align=8 +QMarginsF (0x0x7ffb4161f1e0) 0 + +Class QMessageAuthenticationCode + size=8 align=8 + base size=8 base align=8 +QMessageAuthenticationCode (0x0x7ffb4161f840) 0 + +Class QMetaMethod + size=16 align=8 + base size=12 base align=8 +QMetaMethod (0x0x7ffb4161f8a0) 0 + +Class QMetaEnum + size=16 align=8 + base size=12 base align=8 +QMetaEnum (0x0x7ffb4161fea0) 0 + +Class QMetaProperty + size=32 align=8 + base size=32 base align=8 +QMetaProperty (0x0x7ffb413031e0) 0 + +Class QMetaClassInfo + size=16 align=8 + base size=12 base align=8 +QMetaClassInfo (0x0x7ffb41303240) 0 + +Class QMimeData::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QMimeData::QPrivateSignal (0x0x7ffb41303540) 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 (0x0x7ffb4131c068) 0 + vptr=((& QMimeData::_ZTV9QMimeData) + 16u) + QObject (0x0x7ffb413034e0) 0 + primary-for QMimeData (0x0x7ffb4131c068) + +Class QMimeType + size=8 align=8 + base size=8 base align=8 +QMimeType (0x0x7ffb413035a0) 0 + +Class QMimeDatabase + size=8 align=8 + base size=8 base align=8 +QMimeDatabase (0x0x7ffb413038a0) 0 + +Class QObjectCleanupHandler::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObjectCleanupHandler::QPrivateSignal (0x0x7ffb41303960) 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 (0x0x7ffb4131c270) 0 + vptr=((& QObjectCleanupHandler::_ZTV21QObjectCleanupHandler) + 16u) + QObject (0x0x7ffb41303900) 0 + primary-for QObjectCleanupHandler (0x0x7ffb4131c270) + +Class QOperatingSystemVersion + size=16 align=4 + base size=16 base align=4 +QOperatingSystemVersion (0x0x7ffb413039c0) 0 + +Class QParallelAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QParallelAnimationGroup::QPrivateSignal (0x0x7ffb41390180) 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 (0x0x7ffb4131c9c0) 0 + vptr=((& QParallelAnimationGroup::_ZTV23QParallelAnimationGroup) + 16u) + QAnimationGroup (0x0x7ffb4131ca28) 0 + primary-for QParallelAnimationGroup (0x0x7ffb4131c9c0) + QAbstractAnimation (0x0x7ffb4131ca90) 0 + primary-for QAnimationGroup (0x0x7ffb4131ca28) + QObject (0x0x7ffb41390120) 0 + primary-for QAbstractAnimation (0x0x7ffb4131ca90) + +Class QPauseAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPauseAnimation::QPrivateSignal (0x0x7ffb41390240) 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 (0x0x7ffb4131caf8) 0 + vptr=((& QPauseAnimation::_ZTV15QPauseAnimation) + 16u) + QAbstractAnimation (0x0x7ffb4131cb60) 0 + primary-for QPauseAnimation (0x0x7ffb4131caf8) + QObject (0x0x7ffb413901e0) 0 + primary-for QAbstractAnimation (0x0x7ffb4131cb60) + +Class QStaticPlugin + size=16 align=8 + base size=16 base align=8 +QStaticPlugin (0x0x7ffb41390420) 0 + +Class QPluginLoader::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPluginLoader::QPrivateSignal (0x0x7ffb41390720) 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 (0x0x7ffb4131cd68) 0 + vptr=((& QPluginLoader::_ZTV13QPluginLoader) + 16u) + QObject (0x0x7ffb413906c0) 0 + primary-for QPluginLoader (0x0x7ffb4131cd68) + +Class QProcessEnvironment + size=8 align=8 + base size=8 base align=8 +QProcessEnvironment (0x0x7ffb41390780) 0 + +Class QProcess::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QProcess::QPrivateSignal (0x0x7ffb41390e40) 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 (0x0x7ffb413f93a8) 0 + vptr=((& QProcess::_ZTV8QProcess) + 16u) + QIODevice (0x0x7ffb413f9410) 0 + primary-for QProcess (0x0x7ffb413f93a8) + QObject (0x0x7ffb41390de0) 0 + primary-for QIODevice (0x0x7ffb413f9410) + +Class QVariantAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QVariantAnimation::QPrivateSignal (0x0x7ffb41390f00) 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 (0x0x7ffb413f9478) 0 + vptr=((& QVariantAnimation::_ZTV17QVariantAnimation) + 16u) + QAbstractAnimation (0x0x7ffb413f94e0) 0 + primary-for QVariantAnimation (0x0x7ffb413f9478) + QObject (0x0x7ffb41390ea0) 0 + primary-for QAbstractAnimation (0x0x7ffb413f94e0) + +Class QPropertyAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPropertyAnimation::QPrivateSignal (0x0x7ffb4105a000) 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 (0x0x7ffb413f95b0) 0 + vptr=((& QPropertyAnimation::_ZTV18QPropertyAnimation) + 16u) + QVariantAnimation (0x0x7ffb413f9618) 0 + primary-for QPropertyAnimation (0x0x7ffb413f95b0) + QAbstractAnimation (0x0x7ffb413f9680) 0 + primary-for QVariantAnimation (0x0x7ffb413f9618) + QObject (0x0x7ffb41390f60) 0 + primary-for QAbstractAnimation (0x0x7ffb413f9680) + +Class QRandomGenerator::Storage + size=2504 align=8 + base size=2504 base align=8 +QRandomGenerator::Storage (0x0x7ffb4105a120) 0 + +Class QRandomGenerator + size=2512 align=8 + base size=2512 base align=8 +QRandomGenerator (0x0x7ffb4105a0c0) 0 + +Class QRandomGenerator64 + size=2512 align=8 + base size=2512 base align=8 +QRandomGenerator64 (0x0x7ffb410db958) 0 + QRandomGenerator (0x0x7ffb410f90c0) 0 + +Class QReadWriteLock + size=8 align=8 + base size=8 base align=8 +QReadWriteLock (0x0x7ffb410f9180) 0 + +Class QReadLocker + size=8 align=8 + base size=8 base align=8 +QReadLocker (0x0x7ffb410f9420) 0 + +Class QWriteLocker + size=8 align=8 + base size=8 base align=8 +QWriteLocker (0x0x7ffb410f94e0) 0 + +Class QSize + size=8 align=4 + base size=8 base align=4 +QSize (0x0x7ffb410f95a0) 0 + +Class QSizeF + size=16 align=8 + base size=16 base align=8 +QSizeF (0x0x7ffb410f9840) 0 + +Class QRect + size=16 align=4 + base size=16 base align=4 +QRect (0x0x7ffb410f9ae0) 0 + +Class QRectF + size=32 align=8 + base size=32 base align=8 +QRectF (0x0x7ffb410f9d80) 0 + +Class QRegularExpression + size=8 align=8 + base size=8 base align=8 +QRegularExpression (0x0x7ffb40ee7060) 0 + +Class QRegularExpressionMatch + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatch (0x0x7ffb40ee7660) 0 + +Class QRegularExpressionMatchIterator + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatchIterator (0x0x7ffb40ee7960) 0 + +Class QResource + size=8 align=8 + base size=8 base align=8 +QResource (0x0x7ffb40ee7c60) 0 + +Class QSaveFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSaveFile::QPrivateSignal (0x0x7ffb40ee7de0) 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 (0x0x7ffb41226b60) 0 + vptr=((& QSaveFile::_ZTV9QSaveFile) + 16u) + QFileDevice (0x0x7ffb41226bc8) 0 + primary-for QSaveFile (0x0x7ffb41226b60) + QIODevice (0x0x7ffb41226c30) 0 + primary-for QFileDevice (0x0x7ffb41226bc8) + QObject (0x0x7ffb40ee7d80) 0 + primary-for QIODevice (0x0x7ffb41226c30) + +Class QSemaphore + size=8 align=8 + base size=8 base align=8 +QSemaphore (0x0x7ffb40ee7ea0) 0 + +Class QSemaphoreReleaser + size=16 align=8 + base size=12 base align=8 +QSemaphoreReleaser (0x0x7ffb40ee7f00) 0 + +Class QSequentialAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSequentialAnimationGroup::QPrivateSignal (0x0x7ffb40d14540) 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 (0x0x7ffb40d18478) 0 + vptr=((& QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup) + 16u) + QAnimationGroup (0x0x7ffb40d184e0) 0 + primary-for QSequentialAnimationGroup (0x0x7ffb40d18478) + QAbstractAnimation (0x0x7ffb40d18548) 0 + primary-for QAnimationGroup (0x0x7ffb40d184e0) + QObject (0x0x7ffb40d144e0) 0 + primary-for QAbstractAnimation (0x0x7ffb40d18548) + +Class QSettings::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSettings::QPrivateSignal (0x0x7ffb40d14600) 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 (0x0x7ffb40d185b0) 0 + vptr=((& QSettings::_ZTV9QSettings) + 16u) + QObject (0x0x7ffb40d145a0) 0 + primary-for QSettings (0x0x7ffb40d185b0) + +Class QSharedMemory::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSharedMemory::QPrivateSignal (0x0x7ffb40d146c0) 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 (0x0x7ffb40d18618) 0 + vptr=((& QSharedMemory::_ZTV13QSharedMemory) + 16u) + QObject (0x0x7ffb40d14660) 0 + primary-for QSharedMemory (0x0x7ffb40d18618) + +Class QSignalMapper::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalMapper::QPrivateSignal (0x0x7ffb40d14780) 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 (0x0x7ffb40d18680) 0 + vptr=((& QSignalMapper::_ZTV13QSignalMapper) + 16u) + QObject (0x0x7ffb40d14720) 0 + primary-for QSignalMapper (0x0x7ffb40d18680) + +Class QSignalTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalTransition::QPrivateSignal (0x0x7ffb40d14840) 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 (0x0x7ffb40d186e8) 0 + vptr=((& QSignalTransition::_ZTV17QSignalTransition) + 16u) + QAbstractTransition (0x0x7ffb40d18750) 0 + primary-for QSignalTransition (0x0x7ffb40d186e8) + QObject (0x0x7ffb40d147e0) 0 + primary-for QAbstractTransition (0x0x7ffb40d18750) + +Class QSocketNotifier::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSocketNotifier::QPrivateSignal (0x0x7ffb40d14900) 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 (0x0x7ffb40d187b8) 0 + vptr=((& QSocketNotifier::_ZTV15QSocketNotifier) + 16u) + QObject (0x0x7ffb40d148a0) 0 + primary-for QSocketNotifier (0x0x7ffb40d187b8) + +Class QSortFilterProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSortFilterProxyModel::QPrivateSignal (0x0x7ffb40d149c0) 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 (0x0x7ffb40d18820) 0 + vptr=((& QSortFilterProxyModel::_ZTV21QSortFilterProxyModel) + 16u) + QAbstractProxyModel (0x0x7ffb40d18888) 0 + primary-for QSortFilterProxyModel (0x0x7ffb40d18820) + QAbstractItemModel (0x0x7ffb40d188f0) 0 + primary-for QAbstractProxyModel (0x0x7ffb40d18888) + QObject (0x0x7ffb40d14960) 0 + primary-for QAbstractItemModel (0x0x7ffb40d188f0) + +Class QStandardPaths + size=1 align=1 + base size=0 base align=1 +QStandardPaths (0x0x7ffb40d14a80) 0 empty + +Class QState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QState::QPrivateSignal (0x0x7ffb40d14cc0) 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 (0x0x7ffb40d18a90) 0 + vptr=((& QState::_ZTV6QState) + 16u) + QAbstractState (0x0x7ffb40d18af8) 0 + primary-for QState (0x0x7ffb40d18a90) + QObject (0x0x7ffb40d14c60) 0 + primary-for QAbstractState (0x0x7ffb40d18af8) + +Class QStateMachine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStateMachine::QPrivateSignal (0x0x7ffb40d14de0) 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 (0x0x7ffb40d18c98) 0 + vptr=((& QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE) + 16u) + QEvent (0x0x7ffb40d14e40) 0 + primary-for QStateMachine::SignalEvent (0x0x7ffb40d18c98) + +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 (0x0x7ffb40d18d00) 0 + vptr=((& QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE) + 16u) + QEvent (0x0x7ffb40d14ea0) 0 + primary-for QStateMachine::WrappedEvent (0x0x7ffb40d18d00) + +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 (0x0x7ffb40d18b60) 0 + vptr=((& QStateMachine::_ZTV13QStateMachine) + 16u) + QState (0x0x7ffb40d18bc8) 0 + primary-for QStateMachine (0x0x7ffb40d18b60) + QAbstractState (0x0x7ffb40d18c30) 0 + primary-for QState (0x0x7ffb40d18bc8) + QObject (0x0x7ffb40d14d80) 0 + primary-for QAbstractState (0x0x7ffb40d18c30) + +Class QStorageInfo + size=8 align=8 + base size=8 base align=8 +QStorageInfo (0x0x7ffb40d14f00) 0 + +Class QAbstractConcatenable + size=1 align=1 + base size=0 base align=1 +QAbstractConcatenable (0x0x7ffb40a5ee40) 0 empty + +Class QStringListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStringListModel::QPrivateSignal (0x0x7ffb40a9c960) 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 (0x0x7ffb40af5208) 0 + vptr=((& QStringListModel::_ZTV16QStringListModel) + 16u) + QAbstractListModel (0x0x7ffb40af5270) 0 + primary-for QStringListModel (0x0x7ffb40af5208) + QAbstractItemModel (0x0x7ffb40af52d8) 0 + primary-for QAbstractListModel (0x0x7ffb40af5270) + QObject (0x0x7ffb40a9c900) 0 + primary-for QAbstractItemModel (0x0x7ffb40af52d8) + +Class QSystemSemaphore + size=8 align=8 + base size=8 base align=8 +QSystemSemaphore (0x0x7ffb40a9c9c0) 0 + +Class QTemporaryDir + size=8 align=8 + base size=8 base align=8 +QTemporaryDir (0x0x7ffb40a9ca80) 0 + +Class QTemporaryFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTemporaryFile::QPrivateSignal (0x0x7ffb40a9cba0) 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 (0x0x7ffb40af5340) 0 + vptr=((& QTemporaryFile::_ZTV14QTemporaryFile) + 16u) + QFile (0x0x7ffb40af53a8) 0 + primary-for QTemporaryFile (0x0x7ffb40af5340) + QFileDevice (0x0x7ffb40af5410) 0 + primary-for QFile (0x0x7ffb40af53a8) + QIODevice (0x0x7ffb40af5478) 0 + primary-for QFileDevice (0x0x7ffb40af5410) + QObject (0x0x7ffb40a9cb40) 0 + primary-for QIODevice (0x0x7ffb40af5478) + +Class QTextBoundaryFinder + size=48 align=8 + base size=48 base align=8 +QTextBoundaryFinder (0x0x7ffb40a9cc00) 0 + +Class QTextCodec::ConverterState + size=32 align=8 + base size=32 base align=8 +QTextCodec::ConverterState (0x0x7ffb40a9ce40) 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 (0x0x7ffb40a9cde0) 0 nearly-empty + vptr=((& QTextCodec::_ZTV10QTextCodec) + 16u) + +Class QTextEncoder + size=40 align=8 + base size=40 base align=8 +QTextEncoder (0x0x7ffb40b9a060) 0 + +Class QTextDecoder + size=40 align=8 + base size=40 base align=8 +QTextDecoder (0x0x7ffb40b9a0c0) 0 + +Class std::__mutex_base + size=40 align=8 + base size=40 base align=8 +std::__mutex_base (0x0x7ffb40b9a120) 0 + +Class std::__recursive_mutex_base + size=40 align=8 + base size=40 base align=8 +std::__recursive_mutex_base (0x0x7ffb40b9a180) 0 + +Class std::mutex + size=40 align=8 + base size=40 base align=8 +std::mutex (0x0x7ffb40af5680) 0 + std::__mutex_base (0x0x7ffb40b9a1e0) 0 + +Class std::recursive_mutex + size=40 align=8 + base size=40 base align=8 +std::recursive_mutex (0x0x7ffb40af56e8) 0 + std::__recursive_mutex_base (0x0x7ffb40b9a240) 0 + +Class std::timed_mutex + size=40 align=8 + base size=40 base align=8 +std::timed_mutex (0x0x7ffb40bf6460) 0 + std::__mutex_base (0x0x7ffb40b9a360) 0 + std::__timed_mutex_impl (0x0x7ffb40b9a3c0) 0 empty + +Class std::recursive_timed_mutex + size=40 align=8 + base size=40 base align=8 +std::recursive_timed_mutex (0x0x7ffb40c0e0e0) 0 + std::__recursive_mutex_base (0x0x7ffb40b9a480) 0 + std::__timed_mutex_impl (0x0x7ffb40b9a4e0) 0 empty + +Class std::defer_lock_t + size=1 align=1 + base size=0 base align=1 +std::defer_lock_t (0x0x7ffb40b9a540) 0 empty + +Class std::try_to_lock_t + size=1 align=1 + base size=0 base align=1 +std::try_to_lock_t (0x0x7ffb40b9a5a0) 0 empty + +Class std::adopt_lock_t + size=1 align=1 + base size=0 base align=1 +std::adopt_lock_t (0x0x7ffb40b9a600) 0 empty + +Class std::once_flag + size=4 align=4 + base size=4 base align=4 +std::once_flag (0x0x7ffb40b9a840) 0 + +Vtable for __gnu_cxx::__concurrence_lock_error +__gnu_cxx::__concurrence_lock_error::_ZTVN9__gnu_cxx24__concurrence_lock_errorE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx24__concurrence_lock_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_lock_error::~__concurrence_lock_error +24 (int (*)(...))__gnu_cxx::__concurrence_lock_error::~__concurrence_lock_error +32 (int (*)(...))__gnu_cxx::__concurrence_lock_error::what + +Class __gnu_cxx::__concurrence_lock_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_lock_error (0x0x7ffb40af5820) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_lock_error::_ZTVN9__gnu_cxx24__concurrence_lock_errorE) + 16u) + std::exception (0x0x7ffb40b9a900) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_lock_error (0x0x7ffb40af5820) + +Vtable for __gnu_cxx::__concurrence_unlock_error +__gnu_cxx::__concurrence_unlock_error::_ZTVN9__gnu_cxx26__concurrence_unlock_errorE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx26__concurrence_unlock_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::~__concurrence_unlock_error +24 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::~__concurrence_unlock_error +32 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::what + +Class __gnu_cxx::__concurrence_unlock_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_unlock_error (0x0x7ffb40af5888) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_unlock_error::_ZTVN9__gnu_cxx26__concurrence_unlock_errorE) + 16u) + std::exception (0x0x7ffb40b9a9c0) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_unlock_error (0x0x7ffb40af5888) + +Vtable for __gnu_cxx::__concurrence_broadcast_error +__gnu_cxx::__concurrence_broadcast_error::_ZTVN9__gnu_cxx29__concurrence_broadcast_errorE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx29__concurrence_broadcast_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::~__concurrence_broadcast_error +24 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::~__concurrence_broadcast_error +32 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::what + +Class __gnu_cxx::__concurrence_broadcast_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_broadcast_error (0x0x7ffb40af58f0) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_broadcast_error::_ZTVN9__gnu_cxx29__concurrence_broadcast_errorE) + 16u) + std::exception (0x0x7ffb40b9aa80) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_broadcast_error (0x0x7ffb40af58f0) + +Vtable for __gnu_cxx::__concurrence_wait_error +__gnu_cxx::__concurrence_wait_error::_ZTVN9__gnu_cxx24__concurrence_wait_errorE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx24__concurrence_wait_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_wait_error::~__concurrence_wait_error +24 (int (*)(...))__gnu_cxx::__concurrence_wait_error::~__concurrence_wait_error +32 (int (*)(...))__gnu_cxx::__concurrence_wait_error::what + +Class __gnu_cxx::__concurrence_wait_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_wait_error (0x0x7ffb40af59c0) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_wait_error::_ZTVN9__gnu_cxx24__concurrence_wait_errorE) + 16u) + std::exception (0x0x7ffb40b9ab40) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_wait_error (0x0x7ffb40af59c0) + +Class __gnu_cxx::__mutex + size=40 align=8 + base size=40 base align=8 +__gnu_cxx::__mutex (0x0x7ffb40b9ac00) 0 + +Class __gnu_cxx::__recursive_mutex + size=40 align=8 + base size=40 base align=8 +__gnu_cxx::__recursive_mutex (0x0x7ffb40b9ac60) 0 + +Class __gnu_cxx::__scoped_lock + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__scoped_lock (0x0x7ffb40b9acc0) 0 + +Class __gnu_cxx::__cond + size=48 align=8 + base size=48 base align=8 +__gnu_cxx::__cond (0x0x7ffb40b9ad20) 0 + +Vtable for std::bad_weak_ptr +std::bad_weak_ptr::_ZTVSt12bad_weak_ptr: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt12bad_weak_ptr) +16 (int (*)(...))std::bad_weak_ptr::~bad_weak_ptr +24 (int (*)(...))std::bad_weak_ptr::~bad_weak_ptr +32 (int (*)(...))std::bad_weak_ptr::what + +Class std::bad_weak_ptr + size=8 align=8 + base size=8 base align=8 +std::bad_weak_ptr (0x0x7ffb40af5c98) 0 nearly-empty + vptr=((& std::bad_weak_ptr::_ZTVSt12bad_weak_ptr) + 16u) + std::exception (0x0x7ffb409190c0) 0 nearly-empty + primary-for std::bad_weak_ptr (0x0x7ffb40af5c98) + +Class std::_Sp_make_shared_tag + size=1 align=1 + base size=0 base align=1 +std::_Sp_make_shared_tag (0x0x7ffb40919900) 0 empty + +Class std::_Sp_locker + size=2 align=1 + base size=2 base align=1 +std::_Sp_locker (0x0x7ffb40589120) 0 + +Class std::thread::id + size=8 align=8 + base size=8 base align=8 +std::thread::id (0x0x7ffb40589300) 0 + +Vtable for std::thread::_Impl_base +std::thread::_Impl_base::_ZTVNSt6thread10_Impl_baseE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt6thread10_Impl_baseE) +16 0u +24 0u +32 (int (*)(...))__cxa_pure_virtual + +Class std::thread::_Impl_base + size=24 align=8 + base size=24 base align=8 +std::thread::_Impl_base (0x0x7ffb40589360) 0 + vptr=((& std::thread::_Impl_base::_ZTVNSt6thread10_Impl_baseE) + 16u) + +Class std::thread + size=8 align=8 + base size=8 base align=8 +std::thread (0x0x7ffb405892a0) 0 + +Class std::condition_variable + size=48 align=8 + base size=48 base align=8 +std::condition_variable (0x0x7ffb40702f60) 0 + +Class std::__at_thread_exit_elt + size=16 align=8 + base size=16 base align=8 +std::__at_thread_exit_elt (0x0x7ffb40356060) 0 + +Class std::_V2::condition_variable_any + size=64 align=8 + base size=64 base align=8 +std::_V2::condition_variable_any (0x0x7ffb403560c0) 0 + +Class std::__atomic_futex_unsigned_base + size=1 align=1 + base size=0 base align=1 +std::__atomic_futex_unsigned_base (0x0x7ffb403f0720) 0 empty + +Vtable for std::future_error +std::future_error::_ZTVSt12future_error: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt12future_error) +16 (int (*)(...))std::future_error::~future_error +24 (int (*)(...))std::future_error::~future_error +32 (int (*)(...))std::future_error::what + +Class std::future_error + size=32 align=8 + base size=32 base align=8 +std::future_error (0x0x7ffb40441000) 0 + vptr=((& std::future_error::_ZTVSt12future_error) + 16u) + std::logic_error (0x0x7ffb40441068) 0 + primary-for std::future_error (0x0x7ffb40441000) + std::exception (0x0x7ffb403f0840) 0 nearly-empty + primary-for std::logic_error (0x0x7ffb40441068) + +Class std::__future_base::_Result_base::_Deleter + size=1 align=1 + base size=0 base align=1 +std::__future_base::_Result_base::_Deleter (0x0x7ffb403f0960) 0 empty + +Vtable for std::__future_base::_Result_base +std::__future_base::_Result_base::_ZTVNSt13__future_base12_Result_baseE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt13__future_base12_Result_baseE) +16 (int (*)(...))__cxa_pure_virtual +24 0u +32 0u + +Class std::__future_base::_Result_base + size=16 align=8 + base size=16 base align=8 +std::__future_base::_Result_base (0x0x7ffb403f0900) 0 + vptr=((& std::__future_base::_Result_base::_ZTVNSt13__future_base12_Result_baseE) + 16u) + +Class std::__future_base::_State_baseV2::__exception_ptr_tag + size=1 align=1 + base size=0 base align=1 +std::__future_base::_State_baseV2::__exception_ptr_tag (0x0x7ffb404c8ea0) 0 empty + +Class std::__future_base::_State_baseV2::_Make_ready + size=32 align=8 + base size=32 base align=8 +std::__future_base::_State_baseV2::_Make_ready (0x0x7ffb4014d618) 0 + std::__at_thread_exit_elt (0x0x7ffb404c8f60) 0 + +Vtable for std::__future_base::_State_baseV2 +std::__future_base::_State_baseV2::_ZTVNSt13__future_base13_State_baseV2E: 6u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt13__future_base13_State_baseV2E) +16 (int (*)(...))std::__future_base::_State_baseV2::~_State_baseV2 +24 (int (*)(...))std::__future_base::_State_baseV2::~_State_baseV2 +32 (int (*)(...))std::__future_base::_State_baseV2::_M_complete_async +40 (int (*)(...))std::__future_base::_State_baseV2::_M_is_deferred_future + +Class std::__future_base::_State_baseV2 + size=32 align=8 + base size=28 base align=8 +std::__future_base::_State_baseV2 (0x0x7ffb403f0ae0) 0 + vptr=((& std::__future_base::_State_baseV2::_ZTVNSt13__future_base13_State_baseV2E) + 16u) + +Class std::__future_base + size=1 align=1 + base size=0 base align=1 +std::__future_base (0x0x7ffb403f08a0) 0 empty + +Vtable for std::__future_base::_Async_state_commonV2 +std::__future_base::_Async_state_commonV2::_ZTVNSt13__future_base21_Async_state_commonV2E: 6u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt13__future_base21_Async_state_commonV2E) +16 (int (*)(...))std::__future_base::_Async_state_commonV2::~_Async_state_commonV2 +24 (int (*)(...))std::__future_base::_Async_state_commonV2::~_Async_state_commonV2 +32 (int (*)(...))std::__future_base::_Async_state_commonV2::_M_complete_async +40 (int (*)(...))std::__future_base::_State_baseV2::_M_is_deferred_future + +Class std::__future_base::_Async_state_commonV2 + size=48 align=8 + base size=44 base align=8 +std::__future_base::_Async_state_commonV2 (0x0x7ffb3fee4208) 0 + vptr=((& std::__future_base::_Async_state_commonV2::_ZTVNSt13__future_base21_Async_state_commonV2E) + 16u) + std::__future_base::_State_baseV2 (0x0x7ffb3fe8fe40) 0 + primary-for std::__future_base::_Async_state_commonV2 (0x0x7ffb3fee4208) + +Class QThread::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThread::QPrivateSignal (0x0x7ffb3fef65a0) 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 (0x0x7ffb3fee4c98) 0 + vptr=((& QThread::_ZTV7QThread) + 16u) + QObject (0x0x7ffb3fef6540) 0 + primary-for QThread (0x0x7ffb3fee4c98) + +Class QThreadPool::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThreadPool::QPrivateSignal (0x0x7ffb3fef66c0) 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 (0x0x7ffb3fee4d00) 0 + vptr=((& QThreadPool::_ZTV11QThreadPool) + 16u) + QObject (0x0x7ffb3fef6660) 0 + primary-for QThreadPool (0x0x7ffb3fee4d00) + +Class QThreadStorageData + size=4 align=4 + base size=4 base align=4 +QThreadStorageData (0x0x7ffb3fef6720) 0 + +Class QTimeLine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimeLine::QPrivateSignal (0x0x7ffb3fef6840) 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 (0x0x7ffb3fee4d68) 0 + vptr=((& QTimeLine::_ZTV9QTimeLine) + 16u) + QObject (0x0x7ffb3fef67e0) 0 + primary-for QTimeLine (0x0x7ffb3fee4d68) + +Class QTimer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimer::QPrivateSignal (0x0x7ffb3fef6900) 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 (0x0x7ffb3fee4dd0) 0 + vptr=((& QTimer::_ZTV6QTimer) + 16u) + QObject (0x0x7ffb3fef68a0) 0 + primary-for QTimer (0x0x7ffb3fee4dd0) + +Class QTimeZone::OffsetData + size=32 align=8 + base size=28 base align=8 +QTimeZone::OffsetData (0x0x7ffb3fbc3000) 0 + +Class QTimeZone + size=8 align=8 + base size=8 base align=8 +QTimeZone (0x0x7ffb3fef6f60) 0 + +Class QTranslator::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTranslator::QPrivateSignal (0x0x7ffb3fbc35a0) 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 (0x0x7ffb3fba9820) 0 + vptr=((& QTranslator::_ZTV11QTranslator) + 16u) + QObject (0x0x7ffb3fbc3540) 0 + primary-for QTranslator (0x0x7ffb3fba9820) + +Class QUrl + size=8 align=8 + base size=8 base align=8 +QUrl (0x0x7ffb3fbc36c0) 0 + +Class QUrlQuery + size=8 align=8 + base size=8 base align=8 +QUrlQuery (0x0x7ffb3fcf0d80) 0 + +Class QUuid + size=16 align=4 + base size=16 base align=4 +QUuid (0x0x7ffb3f993420) 0 + +Class QWaitCondition + size=8 align=8 + base size=8 base align=8 +QWaitCondition (0x0x7ffb3f993a20) 0 + +Class QXmlStreamStringRef + size=16 align=8 + base size=16 base align=8 +QXmlStreamStringRef (0x0x7ffb3f993a80) 0 + +Class QXmlStreamAttribute + size=80 align=8 + base size=73 base align=8 +QXmlStreamAttribute (0x0x7ffb3f993d80) 0 + +Class QXmlStreamAttributes + size=8 align=8 + base size=8 base align=8 +QXmlStreamAttributes (0x0x7ffb3fa1c2d8) 0 + QVector (0x0x7ffb3fa39180) 0 + +Class QXmlStreamNamespaceDeclaration + size=40 align=8 + base size=40 base align=8 +QXmlStreamNamespaceDeclaration (0x0x7ffb3fa391e0) 0 + +Class QXmlStreamNotationDeclaration + size=56 align=8 + base size=56 base align=8 +QXmlStreamNotationDeclaration (0x0x7ffb3fa39480) 0 + +Class QXmlStreamEntityDeclaration + size=88 align=8 + base size=88 base align=8 +QXmlStreamEntityDeclaration (0x0x7ffb3fa39720) 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 (0x0x7ffb3fa399c0) 0 nearly-empty + vptr=((& QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver) + 16u) + +Class QXmlStreamReader + size=8 align=8 + base size=8 base align=8 +QXmlStreamReader (0x0x7ffb3fa39a20) 0 + +Class QXmlStreamWriter + size=8 align=8 + base size=8 base align=8 +QXmlStreamWriter (0x0x7ffb3fb31480) 0 + +Class QNdefRecord + size=8 align=8 + base size=8 base align=8 +QNdefRecord (0x0x7ffb3fb315a0) 0 + +Class QNdefFilter::Record + size=24 align=8 + base size=24 base align=8 +QNdefFilter::Record (0x0x7ffb3fb316c0) 0 + +Class QNdefFilter + size=8 align=8 + base size=8 base align=8 +QNdefFilter (0x0x7ffb3fb31660) 0 + +Class QNdefMessage + size=8 align=8 + base size=8 base align=8 +QNdefMessage (0x0x7ffb3fb344e0) 0 + QList (0x0x7ffb3fb34548) 0 + QListSpecialMethods (0x0x7ffb3fb318a0) 0 empty + +Class QNdefNfcTextRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcTextRecord (0x0x7ffb3fb345b0) 0 + QNdefRecord (0x0x7ffb3fb31a80) 0 + +Class QNdefNfcUriRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcUriRecord (0x0x7ffb3fb34af8) 0 + QNdefRecord (0x0x7ffb3fb31f60) 0 + +Class QNdefNfcIconRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcIconRecord (0x0x7ffb3fb34b60) 0 + QNdefRecord (0x0x7ffb3f7f7000) 0 + +Class QNdefNfcSmartPosterRecord + size=16 align=8 + base size=16 base align=8 +QNdefNfcSmartPosterRecord (0x0x7ffb3fb34bc8) 0 + QNdefRecord (0x0x7ffb3f7f7060) 0 + +Class QNearFieldTarget::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldTarget::QPrivateSignal (0x0x7ffb3f7f7180) 0 empty + +Class QNearFieldTarget::RequestId + size=8 align=8 + base size=8 base align=8 +QNearFieldTarget::RequestId (0x0x7ffb3f7f71e0) 0 + +Vtable for QNearFieldTarget +QNearFieldTarget::_ZTV16QNearFieldTarget: 25u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QNearFieldTarget) +16 (int (*)(...))QNearFieldTarget::metaObject +24 (int (*)(...))QNearFieldTarget::qt_metacast +32 (int (*)(...))QNearFieldTarget::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 (*)(...))QNearFieldTarget::url +128 (int (*)(...))__cxa_pure_virtual +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))QNearFieldTarget::hasNdefMessage +152 (int (*)(...))QNearFieldTarget::readNdefMessages +160 (int (*)(...))QNearFieldTarget::writeNdefMessages +168 (int (*)(...))QNearFieldTarget::sendCommand +176 (int (*)(...))QNearFieldTarget::sendCommands +184 (int (*)(...))QNearFieldTarget::waitForRequestCompleted +192 (int (*)(...))QNearFieldTarget::handleResponse + +Class QNearFieldTarget + size=24 align=8 + base size=24 base align=8 +QNearFieldTarget (0x0x7ffb3fb34c30) 0 + vptr=((& QNearFieldTarget::_ZTV16QNearFieldTarget) + 16u) + QObject (0x0x7ffb3f7f7120) 0 + primary-for QNearFieldTarget (0x0x7ffb3fb34c30) + +Class QNearFieldManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldManager::QPrivateSignal (0x0x7ffb3f7f75a0) 0 empty + +Vtable for QNearFieldManager +QNearFieldManager::_ZTV17QNearFieldManager: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QNearFieldManager) +16 (int (*)(...))QNearFieldManager::metaObject +24 (int (*)(...))QNearFieldManager::qt_metacast +32 (int (*)(...))QNearFieldManager::qt_metacall +40 (int (*)(...))QNearFieldManager::~QNearFieldManager +48 (int (*)(...))QNearFieldManager::~QNearFieldManager +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 QNearFieldManager + size=24 align=8 + base size=24 base align=8 +QNearFieldManager (0x0x7ffb3fb34d68) 0 + vptr=((& QNearFieldManager::_ZTV17QNearFieldManager) + 16u) + QObject (0x0x7ffb3f7f7540) 0 + primary-for QNearFieldManager (0x0x7ffb3fb34d68) + +Class QNearFieldShareManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldShareManager::QPrivateSignal (0x0x7ffb3f7f77e0) 0 empty + +Vtable for QNearFieldShareManager +QNearFieldShareManager::_ZTV22QNearFieldShareManager: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI22QNearFieldShareManager) +16 (int (*)(...))QNearFieldShareManager::metaObject +24 (int (*)(...))QNearFieldShareManager::qt_metacast +32 (int (*)(...))QNearFieldShareManager::qt_metacall +40 (int (*)(...))QNearFieldShareManager::~QNearFieldShareManager +48 (int (*)(...))QNearFieldShareManager::~QNearFieldShareManager +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 QNearFieldShareManager + size=24 align=8 + base size=24 base align=8 +QNearFieldShareManager (0x0x7ffb3fb34f08) 0 + vptr=((& QNearFieldShareManager::_ZTV22QNearFieldShareManager) + 16u) + QObject (0x0x7ffb3f7f7780) 0 + primary-for QNearFieldShareManager (0x0x7ffb3fb34f08) + +Class QNearFieldShareTarget::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldShareTarget::QPrivateSignal (0x0x7ffb3f7f7ae0) 0 empty + +Vtable for QNearFieldShareTarget +QNearFieldShareTarget::_ZTV21QNearFieldShareTarget: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QNearFieldShareTarget) +16 (int (*)(...))QNearFieldShareTarget::metaObject +24 (int (*)(...))QNearFieldShareTarget::qt_metacast +32 (int (*)(...))QNearFieldShareTarget::qt_metacall +40 (int (*)(...))QNearFieldShareTarget::~QNearFieldShareTarget +48 (int (*)(...))QNearFieldShareTarget::~QNearFieldShareTarget +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 QNearFieldShareTarget + size=24 align=8 + base size=24 base align=8 +QNearFieldShareTarget (0x0x7ffb3f8f5068) 0 + vptr=((& QNearFieldShareTarget::_ZTV21QNearFieldShareTarget) + 16u) + QObject (0x0x7ffb3f7f7a80) 0 + primary-for QNearFieldShareTarget (0x0x7ffb3f8f5068) + +Class QQmlNdefRecord::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QQmlNdefRecord::QPrivateSignal (0x0x7ffb3f7f7ba0) 0 empty + +Vtable for QQmlNdefRecord +QQmlNdefRecord::_ZTV14QQmlNdefRecord: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI14QQmlNdefRecord) +16 (int (*)(...))QQmlNdefRecord::metaObject +24 (int (*)(...))QQmlNdefRecord::qt_metacast +32 (int (*)(...))QQmlNdefRecord::qt_metacall +40 (int (*)(...))QQmlNdefRecord::~QQmlNdefRecord +48 (int (*)(...))QQmlNdefRecord::~QQmlNdefRecord +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 QQmlNdefRecord + size=24 align=8 + base size=24 base align=8 +QQmlNdefRecord (0x0x7ffb3f8f50d0) 0 + vptr=((& QQmlNdefRecord::_ZTV14QQmlNdefRecord) + 16u) + QObject (0x0x7ffb3f7f7b40) 0 + primary-for QQmlNdefRecord (0x0x7ffb3f8f50d0) + diff --git a/tests/auto/bic/data/QtNfc.5.11.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtNfc.5.11.0.linux-gcc-amd64.txt new file mode 100644 index 0000000..da6230b --- /dev/null +++ b/tests/auto/bic/data/QtNfc.5.11.0.linux-gcc-amd64.txt @@ -0,0 +1,4754 @@ +Class std::__failure_type + size=1 align=1 + base size=0 base align=1 +std::__failure_type (0x0x7f4a13c830c0) 0 empty + +Class std::__do_is_destructible_impl + size=1 align=1 + base size=0 base align=1 +std::__do_is_destructible_impl (0x0x7f4a13cc9840) 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 (0x0x7f4a13cc9a80) 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 (0x0x7f4a13cc9cc0) 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 (0x0x7f4a13cc9f00) 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 (0x0x7f4a13cf70c0) 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 (0x0x7f4a13cf7480) 0 empty + +Class std::__do_common_type_impl + size=1 align=1 + base size=0 base align=1 +std::__do_common_type_impl (0x0x7f4a11902c00) 0 empty + +Class std::__do_member_type_wrapper + size=1 align=1 + base size=0 base align=1 +std::__do_member_type_wrapper (0x0x7f4a11902cc0) 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 (0x0x7f4a11931060) 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 (0x0x7f4a11931120) 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 (0x0x7f4a119311e0) 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 (0x0x7f4a119312a0) 0 empty + +Class std::__result_of_other_impl + size=1 align=1 + base size=0 base align=1 +std::__result_of_other_impl (0x0x7f4a11931540) 0 empty + +Class std::piecewise_construct_t + size=1 align=1 + base size=0 base align=1 +std::piecewise_construct_t (0x0x7f4a11931720) 0 empty + +Class std::__true_type + size=1 align=1 + base size=0 base align=1 +std::__true_type (0x0x7f4a11931ba0) 0 empty + +Class std::__false_type + size=1 align=1 + base size=0 base align=1 +std::__false_type (0x0x7f4a11931c00) 0 empty + +Class std::input_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::input_iterator_tag (0x0x7f4a119e48a0) 0 empty + +Class std::output_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::output_iterator_tag (0x0x7f4a119e4900) 0 empty + +Class std::forward_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::forward_iterator_tag (0x0x7f4a118f08f0) 0 empty + std::input_iterator_tag (0x0x7f4a119e4960) 0 empty + +Class std::bidirectional_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::bidirectional_iterator_tag (0x0x7f4a118f0958) 0 empty + std::forward_iterator_tag (0x0x7f4a118f09c0) 0 empty + std::input_iterator_tag (0x0x7f4a119e49c0) 0 empty + +Class std::random_access_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::random_access_iterator_tag (0x0x7f4a118f0a28) 0 empty + std::bidirectional_iterator_tag (0x0x7f4a118f0a90) 0 empty + std::forward_iterator_tag (0x0x7f4a118f0af8) 0 empty + std::input_iterator_tag (0x0x7f4a119e4a20) 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 (0x0x7f4a11a256c0) 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 (0x0x7f4a11a25720) 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 (0x0x7f4a11a25780) 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 (0x0x7f4a11a257e0) 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 (0x0x7f4a11a25840) 0 empty + +Class wait + size=4 align=4 + base size=4 base align=4 +wait (0x0x7f4a11718360) 0 + +Class __locale_struct + size=232 align=8 + base size=232 base align=8 +__locale_struct (0x0x7f4a117185a0) 0 + +Class timespec + size=16 align=8 + base size=16 base align=8 +timespec (0x0x7f4a11718660) 0 + +Class timeval + size=16 align=8 + base size=16 base align=8 +timeval (0x0x7f4a117186c0) 0 + +Class pthread_attr_t + size=56 align=8 + base size=56 base align=8 +pthread_attr_t (0x0x7f4a11718780) 0 + +Class __pthread_internal_list + size=16 align=8 + base size=16 base align=8 +__pthread_internal_list (0x0x7f4a117187e0) 0 + +Class random_data + size=48 align=8 + base size=48 base align=8 +random_data (0x0x7f4a11718c60) 0 + +Class drand48_data + size=24 align=8 + base size=24 base align=8 +drand48_data (0x0x7f4a11718cc0) 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 (0x0x7f4a11718d20) 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 (0x0x7f4a116f7068) 0 nearly-empty + vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16u) + std::exception (0x0x7f4a11718d80) 0 nearly-empty + primary-for std::bad_exception (0x0x7f4a116f7068) + +Class std::__exception_ptr::exception_ptr + size=8 align=8 + base size=8 base align=8 +std::__exception_ptr::exception_ptr (0x0x7f4a11718de0) 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 (0x0x7f4a11718e40) 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 (0x0x7f4a116f7270) 0 nearly-empty + vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16u) + std::exception (0x0x7f4a118692a0) 0 nearly-empty + primary-for std::bad_alloc (0x0x7f4a116f7270) + +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 (0x0x7f4a116f72d8) 0 nearly-empty + vptr=((& std::bad_array_new_length::_ZTVSt20bad_array_new_length) + 16u) + std::bad_alloc (0x0x7f4a116f7340) 0 nearly-empty + primary-for std::bad_array_new_length (0x0x7f4a116f72d8) + std::exception (0x0x7f4a11869300) 0 nearly-empty + primary-for std::bad_alloc (0x0x7f4a116f7340) + +Class std::nothrow_t + size=1 align=1 + base size=0 base align=1 +std::nothrow_t (0x0x7f4a11869360) 0 empty + +Class __exception + size=40 align=8 + base size=40 base align=8 +__exception (0x0x7f4a11869f60) 0 + +Class lconv + size=96 align=8 + base size=96 base align=8 +lconv (0x0x7f4a115b1c60) 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 (0x0x7f4a115b1cc0) 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 (0x0x7f4a1136eba0) 0 + +Class __sched_param + size=4 align=4 + base size=4 base align=4 +__sched_param (0x0x7f4a1136ec00) 0 + +Class timex + size=208 align=8 + base size=208 base align=8 +timex (0x0x7f4a1136ecc0) 0 + +Class tm + size=56 align=8 + base size=56 base align=8 +tm (0x0x7f4a1136ed20) 0 + +Class itimerspec + size=32 align=8 + base size=32 base align=8 +itimerspec (0x0x7f4a1136ed80) 0 + +Class _pthread_cleanup_buffer + size=32 align=8 + base size=32 base align=8 +_pthread_cleanup_buffer (0x0x7f4a1136ede0) 0 + +Class __pthread_cleanup_frame + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_frame (0x0x7f4a1136ef00) 0 + +Class __pthread_cleanup_class + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_class (0x0x7f4a1136ef60) 0 + +Class _IO_marker + size=24 align=8 + base size=24 base align=8 +_IO_marker (0x0x7f4a114633c0) 0 + +Class _IO_FILE + size=216 align=8 + base size=216 base align=8 +_IO_FILE (0x0x7f4a11463420) 0 + +Class std::_Hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Hash_impl (0x0x7f4a10ed0c00) 0 empty + +Class std::_Fnv_hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Fnv_hash_impl (0x0x7f4a10ed0c60) 0 empty + +Class std::__numeric_limits_base + size=1 align=1 + base size=0 base align=1 +std::__numeric_limits_base (0x0x7f4a10f08c00) 0 empty + +Class std::_Bit_reference + size=16 align=8 + base size=16 base align=8 +std::_Bit_reference (0x0x7f4a10ccca20) 0 + +Class std::_Bit_iterator_base + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator_base (0x0x7f4a10ee1bc8) 0 + std::iterator (0x0x7f4a10cccae0) 0 empty + +Class std::_Bit_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator (0x0x7f4a10ee1c30) 0 + std::_Bit_iterator_base (0x0x7f4a10e0b000) 0 + std::iterator (0x0x7f4a10cccb40) 0 empty + +Class std::_Bit_const_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_const_iterator (0x0x7f4a10e0b068) 0 + std::_Bit_iterator_base (0x0x7f4a10e0b0d0) 0 + std::iterator (0x0x7f4a10cccba0) 0 empty + +Class std::random_device + size=5000 align=8 + base size=5000 base align=8 +std::random_device (0x0x7f4a10aac9c0) 0 + +Class std::bernoulli_distribution::param_type + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution::param_type (0x0x7f4a10bd1780) 0 + +Class std::bernoulli_distribution + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution (0x0x7f4a10bd1720) 0 + +Class std::seed_seq + size=24 align=8 + base size=24 base align=8 +std::seed_seq (0x0x7f4a109a7720) 0 + +Class qIsNull(double)::U + size=8 align=8 + base size=8 base align=8 +qIsNull(double)::U (0x0x7f4a0f5a9240) 0 + +Class qIsNull(float)::U + size=4 align=4 + base size=4 base align=4 +qIsNull(float)::U (0x0x7f4a0f5a92a0) 0 + +Class QSysInfo + size=1 align=1 + base size=0 base align=1 +QSysInfo (0x0x7f4a0f650d20) 0 empty + +Class QMessageLogContext + size=32 align=8 + base size=32 base align=8 +QMessageLogContext (0x0x7f4a0f650d80) 0 + +Class QMessageLogger + size=32 align=8 + base size=32 base align=8 +QMessageLogger (0x0x7f4a0f650de0) 0 + +Class QFlag + size=4 align=4 + base size=4 base align=4 +QFlag (0x0x7f4a0f650e40) 0 + +Class QIncompatibleFlag + size=4 align=4 + base size=4 base align=4 +QIncompatibleFlag (0x0x7f4a0f2bc120) 0 + +Class std::__atomic_flag_base + size=1 align=1 + base size=1 base align=1 +std::__atomic_flag_base (0x0x7f4a0f2bc660) 0 + +Class std::atomic_flag + size=1 align=1 + base size=1 base align=1 +std::atomic_flag (0x0x7f4a0f647f70) 0 + std::__atomic_flag_base (0x0x7f4a0f2bc6c0) 0 + +Class QAtomicInt + size=4 align=4 + base size=4 base align=4 +QAtomicInt (0x0x7f4a0f4186e8) 0 + QAtomicInteger (0x0x7f4a0f418750) 0 + QBasicAtomicInteger (0x0x7f4a0f082de0) 0 + +Class QInternal + size=1 align=1 + base size=0 base align=1 +QInternal (0x0x7f4a0ed3f3c0) 0 empty + +Class QtPrivate::QSlotObjectBase + size=16 align=8 + base size=16 base align=8 +QtPrivate::QSlotObjectBase (0x0x7f4a0eb29420) 0 + +Class QGenericArgument + size=16 align=8 + base size=16 base align=8 +QGenericArgument (0x0x7f4a0eb29540) 0 + +Class QGenericReturnArgument + size=16 align=8 + base size=16 base align=8 +QGenericReturnArgument (0x0x7f4a0eb521a0) 0 + QGenericArgument (0x0x7f4a0eb295a0) 0 + +Class QMetaObject + size=48 align=8 + base size=48 base align=8 +QMetaObject (0x0x7f4a0eb29720) 0 + +Class QMetaObject::Connection + size=8 align=8 + base size=8 base align=8 +QMetaObject::Connection (0x0x7f4a0eb297e0) 0 + +Class QLatin1Char + size=1 align=1 + base size=1 base align=1 +QLatin1Char (0x0x7f4a0ec10840) 0 + +Class QChar + size=2 align=2 + base size=2 base align=2 +QChar (0x0x7f4a0ec108a0) 0 + +Class QtPrivate::RefCount + size=4 align=4 + base size=4 base align=4 +QtPrivate::RefCount (0x0x7f4a0ec10b40) 0 + +Class QArrayData + size=24 align=8 + base size=24 base align=8 +QArrayData (0x0x7f4a0ec10ba0) 0 + +Class QtPrivate::QContainerImplHelper + size=1 align=1 + base size=0 base align=1 +QtPrivate::QContainerImplHelper (0x0x7f4a0ec10f00) 0 empty + +Class std::locale + size=8 align=8 + base size=8 base align=8 +std::locale (0x0x7f4a0ec10f60) 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 (0x0x7f4a0e954000) 0 + vptr=((& std::locale::facet::_ZTVNSt6locale5facetE) + 16u) + +Class std::locale::id + size=8 align=8 + base size=8 base align=8 +std::locale::id (0x0x7f4a0e954060) 0 + +Class std::locale::_Impl + size=40 align=8 + base size=40 base align=8 +std::locale::_Impl (0x0x7f4a0e9540c0) 0 + +Class std::__cow_string + size=8 align=8 + base size=8 base align=8 +std::__cow_string (0x0x7f4a0e954480) 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 (0x0x7f4a0e9307b8) 0 + vptr=((& std::logic_error::_ZTVSt11logic_error) + 16u) + std::exception (0x0x7f4a0e954540) 0 nearly-empty + primary-for std::logic_error (0x0x7f4a0e9307b8) + +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 (0x0x7f4a0e930820) 0 + vptr=((& std::domain_error::_ZTVSt12domain_error) + 16u) + std::logic_error (0x0x7f4a0e930888) 0 + primary-for std::domain_error (0x0x7f4a0e930820) + std::exception (0x0x7f4a0e9545a0) 0 nearly-empty + primary-for std::logic_error (0x0x7f4a0e930888) + +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 (0x0x7f4a0e9308f0) 0 + vptr=((& std::invalid_argument::_ZTVSt16invalid_argument) + 16u) + std::logic_error (0x0x7f4a0e930958) 0 + primary-for std::invalid_argument (0x0x7f4a0e9308f0) + std::exception (0x0x7f4a0e954600) 0 nearly-empty + primary-for std::logic_error (0x0x7f4a0e930958) + +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 (0x0x7f4a0e9309c0) 0 + vptr=((& std::length_error::_ZTVSt12length_error) + 16u) + std::logic_error (0x0x7f4a0e930a28) 0 + primary-for std::length_error (0x0x7f4a0e9309c0) + std::exception (0x0x7f4a0e954660) 0 nearly-empty + primary-for std::logic_error (0x0x7f4a0e930a28) + +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 (0x0x7f4a0e930a90) 0 + vptr=((& std::out_of_range::_ZTVSt12out_of_range) + 16u) + std::logic_error (0x0x7f4a0e930af8) 0 + primary-for std::out_of_range (0x0x7f4a0e930a90) + std::exception (0x0x7f4a0e9546c0) 0 nearly-empty + primary-for std::logic_error (0x0x7f4a0e930af8) + +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 (0x0x7f4a0e930b60) 0 + vptr=((& std::runtime_error::_ZTVSt13runtime_error) + 16u) + std::exception (0x0x7f4a0e954720) 0 nearly-empty + primary-for std::runtime_error (0x0x7f4a0e930b60) + +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 (0x0x7f4a0e930bc8) 0 + vptr=((& std::range_error::_ZTVSt11range_error) + 16u) + std::runtime_error (0x0x7f4a0e930c30) 0 + primary-for std::range_error (0x0x7f4a0e930bc8) + std::exception (0x0x7f4a0e954780) 0 nearly-empty + primary-for std::runtime_error (0x0x7f4a0e930c30) + +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 (0x0x7f4a0e930c98) 0 + vptr=((& std::overflow_error::_ZTVSt14overflow_error) + 16u) + std::runtime_error (0x0x7f4a0e930d00) 0 + primary-for std::overflow_error (0x0x7f4a0e930c98) + std::exception (0x0x7f4a0e9547e0) 0 nearly-empty + primary-for std::runtime_error (0x0x7f4a0e930d00) + +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 (0x0x7f4a0e930d68) 0 + vptr=((& std::underflow_error::_ZTVSt15underflow_error) + 16u) + std::runtime_error (0x0x7f4a0e930dd0) 0 + primary-for std::underflow_error (0x0x7f4a0e930d68) + std::exception (0x0x7f4a0e954840) 0 nearly-empty + primary-for std::runtime_error (0x0x7f4a0e930dd0) + +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 (0x0x7f4a0e9549c0) 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 (0x0x7f4a0e954c00) 0 + +Class std::error_condition + size=16 align=8 + base size=16 base align=8 +std::error_condition (0x0x7f4a0e954d80) 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 (0x0x7f4a0ea2c208) 0 + vptr=((& std::system_error::_ZTVSt12system_error) + 16u) + std::runtime_error (0x0x7f4a0ea2c270) 0 + primary-for std::system_error (0x0x7f4a0ea2c208) + std::exception (0x0x7f4a0ea41000) 0 nearly-empty + primary-for std::runtime_error (0x0x7f4a0ea2c270) + +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 (0x0x7f4a0ea2ce38) 0 + vptr=((& std::ios_base::failure::_ZTVNSt8ios_base7failureB5cxx11E) + 16u) + std::system_error (0x0x7f4a0ea2cea0) 0 + primary-for std::ios_base::failure (0x0x7f4a0ea2ce38) + std::runtime_error (0x0x7f4a0ea2cf08) 0 + primary-for std::system_error (0x0x7f4a0ea2cea0) + std::exception (0x0x7f4a0ea41300) 0 nearly-empty + primary-for std::runtime_error (0x0x7f4a0ea2cf08) + +Class std::ios_base::_Callback_list + size=24 align=8 + base size=24 base align=8 +std::ios_base::_Callback_list (0x0x7f4a0ea41360) 0 + +Class std::ios_base::_Words + size=16 align=8 + base size=16 base align=8 +std::ios_base::_Words (0x0x7f4a0ea413c0) 0 + +Class std::ios_base::Init + size=1 align=1 + base size=0 base align=1 +std::ios_base::Init (0x0x7f4a0ea41420) 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 (0x0x7f4a0ea412a0) 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 (0x0x7f4a0ea41ba0) 0 empty + +Class std::__num_base + size=1 align=1 + base size=0 base align=1 +std::__num_base (0x0x7f4a0e7e02a0) 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 (0x0x7f4a0e2e8820 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 (0x0x7f4a0e2e88f0 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 (0x0x7f4a0e2e8c98 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 (0x0x7f4a0e2e8d68 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 (0x0x7f4a0e59dae0) 0 + +Class QByteArray + size=8 align=8 + base size=8 base align=8 +QByteArray (0x0x7f4a0e59db40) 0 + +Class QByteRef + size=16 align=8 + base size=12 base align=8 +QByteRef (0x0x7f4a0e459ea0) 0 + +Class QStringDataPtr + size=8 align=8 + base size=8 base align=8 +QStringDataPtr (0x0x7f4a0e141240) 0 + +Class QStringView + size=16 align=8 + base size=16 base align=8 +QStringView (0x0x7f4a0e1416c0) 0 + +Class QLatin1String + size=16 align=8 + base size=16 base align=8 +QLatin1String (0x0x7f4a0e1cc540) 0 + +Class QString::Null + size=1 align=1 + base size=0 base align=1 +QString::Null (0x0x7f4a0e1ccba0) 0 empty + +Class QString + size=8 align=8 + base size=8 base align=8 +QString (0x0x7f4a0e1ccb40) 0 + +Class QCharRef + size=16 align=8 + base size=12 base align=8 +QCharRef (0x0x7f4a0dfbec60) 0 + +Class QStringRef + size=16 align=8 + base size=16 base align=8 +QStringRef (0x0x7f4a0dd5b8a0) 0 + +Class QtPrivate::QHashCombine + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombine (0x0x7f4a0dafa540) 0 empty + +Class QtPrivate::QHashCombineCommutative + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombineCommutative (0x0x7f4a0dafa5a0) 0 empty + +Class std::__detail::_List_node_base + size=16 align=8 + base size=16 base align=8 +std::__detail::_List_node_base (0x0x7f4a0dafa600) 0 + +Class QListData::NotArrayCompatibleLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotArrayCompatibleLayout (0x0x7f4a0dafa9c0) 0 empty + +Class QListData::NotIndirectLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotIndirectLayout (0x0x7f4a0dafaa20) 0 empty + +Class QListData::ArrayCompatibleLayout + size=1 align=1 + base size=1 base align=1 +QListData::ArrayCompatibleLayout (0x0x7f4a0dae57b8) 0 empty + QListData::NotIndirectLayout (0x0x7f4a0dafaa80) 0 empty + +Class QListData::InlineWithPaddingLayout + size=1 align=1 + base size=1 base align=1 +QListData::InlineWithPaddingLayout (0x0x7f4a0dc34a10) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7f4a0dafaae0) 0 empty + QListData::NotIndirectLayout (0x0x7f4a0dafab40) 0 empty + +Class QListData::IndirectLayout + size=1 align=1 + base size=1 base align=1 +QListData::IndirectLayout (0x0x7f4a0dae5820) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7f4a0dafaba0) 0 empty + +Class QListData::Data + size=24 align=8 + base size=24 base align=8 +QListData::Data (0x0x7f4a0dafac00) 0 + +Class QListData + size=8 align=8 + base size=8 base align=8 +QListData (0x0x7f4a0dafa960) 0 + +Class QRegExp + size=8 align=8 + base size=8 base align=8 +QRegExp (0x0x7f4a0d9490c0) 0 + +Class QStringMatcher::Data + size=272 align=8 + base size=272 base align=8 +QStringMatcher::Data (0x0x7f4a0d9f3300) 0 + +Class QStringMatcher + size=1048 align=8 + base size=1048 base align=8 +QStringMatcher (0x0x7f4a0d9f32a0) 0 + +Class QStringList + size=8 align=8 + base size=8 base align=8 +QStringList (0x0x7f4a0d9f7270) 0 + QList (0x0x7f4a0d9f72d8) 0 + QListSpecialMethods (0x0x7f4a0d9f34e0) 0 empty + +Class QScopedPointerPodDeleter + size=1 align=1 + base size=0 base align=1 +QScopedPointerPodDeleter (0x0x7f4a0d9f3900) 0 empty + +Class std::_Rb_tree_node_base + size=32 align=8 + base size=32 base align=8 +std::_Rb_tree_node_base (0x0x7f4a0d7094e0) 0 + +Class std::allocator_arg_t + size=1 align=1 + base size=0 base align=1 +std::allocator_arg_t (0x0x7f4a0d709b40) 0 empty + +Class std::__uses_alloc_base + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc_base (0x0x7f4a0d709cc0) 0 empty + +Class std::__uses_alloc0::_Sink + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc0::_Sink (0x0x7f4a0d709d80) 0 empty + +Class std::__uses_alloc0 + size=1 align=1 + base size=1 base align=1 +std::__uses_alloc0 (0x0x7f4a0d9f7bc8) 0 + std::__uses_alloc_base (0x0x7f4a0d709d20) 0 empty + +Class std::_Swallow_assign + size=1 align=1 + base size=0 base align=1 +std::_Swallow_assign (0x0x7f4a0d4c8de0) 0 empty + +Class QtPrivate::AbstractDebugStreamFunction + size=16 align=8 + base size=16 base align=8 +QtPrivate::AbstractDebugStreamFunction (0x0x7f4a0d60a060) 0 + +Class QtPrivate::AbstractComparatorFunction + size=24 align=8 + base size=24 base align=8 +QtPrivate::AbstractComparatorFunction (0x0x7f4a0d60a120) 0 + +Class QtPrivate::AbstractConverterFunction + size=8 align=8 + base size=8 base align=8 +QtPrivate::AbstractConverterFunction (0x0x7f4a0d60a240) 0 + +Class QMetaType + size=80 align=8 + base size=80 base align=8 +QMetaType (0x0x7f4a0d60a3c0) 0 + +Class QtMetaTypePrivate::VariantData + size=24 align=8 + base size=20 base align=8 +QtMetaTypePrivate::VariantData (0x0x7f4a0d60a7e0) 0 + +Class QtMetaTypePrivate::VectorBoolElements + size=1 align=1 + base size=0 base align=1 +QtMetaTypePrivate::VectorBoolElements (0x0x7f4a0d60a900) 0 empty + +Class QtMetaTypePrivate::QSequentialIterableImpl + size=104 align=8 + base size=104 base align=8 +QtMetaTypePrivate::QSequentialIterableImpl (0x0x7f4a0d37d2a0) 0 + +Class QtMetaTypePrivate::QAssociativeIterableImpl + size=112 align=8 + base size=112 base align=8 +QtMetaTypePrivate::QAssociativeIterableImpl (0x0x7f4a0d37d6c0) 0 + +Class QtMetaTypePrivate::QPairVariantInterfaceImpl + size=40 align=8 + base size=40 base align=8 +QtMetaTypePrivate::QPairVariantInterfaceImpl (0x0x7f4a0d37d9c0) 0 + +Class std::chrono::_V2::system_clock + size=1 align=1 + base size=0 base align=1 +std::chrono::_V2::system_clock (0x0x7f4a0d235240) 0 empty + +Class std::chrono::_V2::steady_clock + size=1 align=1 + base size=0 base align=1 +std::chrono::_V2::steady_clock (0x0x7f4a0cf7e0c0) 0 empty + +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 (0x0x7f4a0cf7e120) 0 + vptr=((& QObjectData::_ZTV11QObjectData) + 16u) + +Class QObject::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObject::QPrivateSignal (0x0x7f4a0cf7e300) 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 (0x0x7f4a0cf7e2a0) 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 (0x0x7f4a0d05c5a0) 0 nearly-empty + vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16u) + +Class QSignalBlocker + size=16 align=8 + base size=10 base align=8 +QSignalBlocker (0x0x7f4a0d05c600) 0 + +Class QAbstractAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractAnimation::QPrivateSignal (0x0x7f4a0d05c6c0) 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 (0x0x7f4a0d035f70) 0 + vptr=((& QAbstractAnimation::_ZTV18QAbstractAnimation) + 16u) + QObject (0x0x7f4a0d05c660) 0 + primary-for QAbstractAnimation (0x0x7f4a0d035f70) + +Class QAnimationDriver::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationDriver::QPrivateSignal (0x0x7f4a0d05c780) 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 (0x0x7f4a0d035138) 0 + vptr=((& QAnimationDriver::_ZTV16QAnimationDriver) + 16u) + QObject (0x0x7f4a0d05c720) 0 + primary-for QAnimationDriver (0x0x7f4a0d035138) + +Class QEventLoop::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventLoop::QPrivateSignal (0x0x7f4a0d05c840) 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 (0x0x7f4a0d0352d8) 0 + vptr=((& QEventLoop::_ZTV10QEventLoop) + 16u) + QObject (0x0x7f4a0d05c7e0) 0 + primary-for QEventLoop (0x0x7f4a0d0352d8) + +Class QEventLoopLocker + size=8 align=8 + base size=8 base align=8 +QEventLoopLocker (0x0x7f4a0d05ca20) 0 + +Class QAbstractEventDispatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractEventDispatcher::QPrivateSignal (0x0x7f4a0d05cae0) 0 empty + +Class QAbstractEventDispatcher::TimerInfo + size=12 align=4 + base size=12 base align=4 +QAbstractEventDispatcher::TimerInfo (0x0x7f4a0d05cb40) 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 (0x0x7f4a0cce9000) 0 + vptr=((& QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher) + 16u) + QObject (0x0x7f4a0d05ca80) 0 + primary-for QAbstractEventDispatcher (0x0x7f4a0cce9000) + +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 (0x0x7f4a0d05cde0) 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 (0x0x7f4a0cce9208) 0 nearly-empty + vptr=((& std::bad_cast::_ZTVSt8bad_cast) + 16u) + std::exception (0x0x7f4a0d05ce40) 0 nearly-empty + primary-for std::bad_cast (0x0x7f4a0cce9208) + +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 (0x0x7f4a0cce9270) 0 nearly-empty + vptr=((& std::bad_typeid::_ZTVSt10bad_typeid) + 16u) + std::exception (0x0x7f4a0d05cea0) 0 nearly-empty + primary-for std::bad_typeid (0x0x7f4a0cce9270) + +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 (0x0x7f4a0ce5e4e0) 0 nearly-empty + vptr=((& std::bad_function_call::_ZTVSt17bad_function_call) + 16u) + std::exception (0x0x7f4a0cdf9f60) 0 nearly-empty + primary-for std::bad_function_call (0x0x7f4a0ce5e4e0) + +Class std::_Nocopy_types + size=16 align=8 + base size=16 base align=8 +std::_Nocopy_types (0x0x7f4a0caaf060) 0 + +Class std::_Any_data + size=16 align=8 + base size=16 base align=8 +std::_Any_data (0x0x7f4a0caaf0c0) 0 + +Class std::_Function_base + size=24 align=8 + base size=24 base align=8 +std::_Function_base (0x0x7f4a0caaf1e0) 0 + +Class QMapNodeBase + size=24 align=8 + base size=24 base align=8 +QMapNodeBase (0x0x7f4a0caaf6c0) 0 + +Class QMapDataBase + size=40 align=8 + base size=40 base align=8 +QMapDataBase (0x0x7f4a0caafc00) 0 + +Class QHashData::Node + size=16 align=8 + base size=16 base align=8 +QHashData::Node (0x0x7f4a0cc4d000) 0 + +Class QHashData + size=48 align=8 + base size=44 base align=8 +QHashData (0x0x7f4a0caaff60) 0 + +Class QHashDummyValue + size=1 align=1 + base size=0 base align=1 +QHashDummyValue (0x0x7f4a0cc4d060) 0 empty + +Class QVariant::PrivateShared + size=16 align=8 + base size=12 base align=8 +QVariant::PrivateShared (0x0x7f4a0cc4d900) 0 + +Class QVariant::Private::Data + size=8 align=8 + base size=8 base align=8 +QVariant::Private::Data (0x0x7f4a0cc4d9c0) 0 + +Class QVariant::Private + size=16 align=8 + base size=12 base align=8 +QVariant::Private (0x0x7f4a0cc4d960) 0 + +Class QVariant::Handler + size=72 align=8 + base size=72 base align=8 +QVariant::Handler (0x0x7f4a0cc4da20) 0 + +Class QVariant + size=16 align=8 + base size=16 base align=8 +QVariant (0x0x7f4a0cc4d8a0) 0 + +Class QVariantComparisonHelper + size=8 align=8 + base size=8 base align=8 +QVariantComparisonHelper (0x0x7f4a0c6a9540) 0 + +Class QSequentialIterable::const_iterator + size=112 align=8 + base size=112 base align=8 +QSequentialIterable::const_iterator (0x0x7f4a0c6a9ba0) 0 + +Class QSequentialIterable + size=104 align=8 + base size=104 base align=8 +QSequentialIterable (0x0x7f4a0c6a9b40) 0 + +Class QAssociativeIterable::const_iterator + size=120 align=8 + base size=120 base align=8 +QAssociativeIterable::const_iterator (0x0x7f4a0c6a9c60) 0 + +Class QAssociativeIterable + size=112 align=8 + base size=112 base align=8 +QAssociativeIterable (0x0x7f4a0c6a9c00) 0 + +Class QModelIndex + size=24 align=8 + base size=24 base align=8 +QModelIndex (0x0x7f4a0c7cff60) 0 + +Class QPersistentModelIndex + size=8 align=8 + base size=8 base align=8 +QPersistentModelIndex (0x0x7f4a0c51b660) 0 + +Class QAbstractItemModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractItemModel::QPrivateSignal (0x0x7f4a0c5b7d80) 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 (0x0x7f4a0c5d0270) 0 + vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16u) + QObject (0x0x7f4a0c5b7d20) 0 + primary-for QAbstractItemModel (0x0x7f4a0c5d0270) + +Class QAbstractTableModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTableModel::QPrivateSignal (0x0x7f4a0c61a660) 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 (0x0x7f4a0c5d0958) 0 + vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16u) + QAbstractItemModel (0x0x7f4a0c5d09c0) 0 + primary-for QAbstractTableModel (0x0x7f4a0c5d0958) + QObject (0x0x7f4a0c61a600) 0 + primary-for QAbstractItemModel (0x0x7f4a0c5d09c0) + +Class QAbstractListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractListModel::QPrivateSignal (0x0x7f4a0c61a720) 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 (0x0x7f4a0c5d0a28) 0 + vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16u) + QAbstractItemModel (0x0x7f4a0c5d0a90) 0 + primary-for QAbstractListModel (0x0x7f4a0c5d0a28) + QObject (0x0x7f4a0c61a6c0) 0 + primary-for QAbstractItemModel (0x0x7f4a0c5d0a90) + +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 (0x0x7f4a0c61a9c0) 0 + vptr=((& QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter) + 16u) + +Class QAbstractProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractProxyModel::QPrivateSignal (0x0x7f4a0c61aa80) 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 (0x0x7f4a0c5d0bc8) 0 + vptr=((& QAbstractProxyModel::_ZTV19QAbstractProxyModel) + 16u) + QAbstractItemModel (0x0x7f4a0c5d0c30) 0 + primary-for QAbstractProxyModel (0x0x7f4a0c5d0bc8) + QObject (0x0x7f4a0c61aa20) 0 + primary-for QAbstractItemModel (0x0x7f4a0c5d0c30) + +Class QAbstractState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractState::QPrivateSignal (0x0x7f4a0c61ab40) 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 (0x0x7f4a0c5d0c98) 0 + vptr=((& QAbstractState::_ZTV14QAbstractState) + 16u) + QObject (0x0x7f4a0c61aae0) 0 + primary-for QAbstractState (0x0x7f4a0c5d0c98) + +Class QAbstractTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTransition::QPrivateSignal (0x0x7f4a0c61ac00) 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 (0x0x7f4a0c5d0d00) 0 + vptr=((& QAbstractTransition::_ZTV19QAbstractTransition) + 16u) + QObject (0x0x7f4a0c61aba0) 0 + primary-for QAbstractTransition (0x0x7f4a0c5d0d00) + +Class QAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationGroup::QPrivateSignal (0x0x7f4a0c61acc0) 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 (0x0x7f4a0c5d0d68) 0 + vptr=((& QAnimationGroup::_ZTV15QAnimationGroup) + 16u) + QAbstractAnimation (0x0x7f4a0c5d0dd0) 0 + primary-for QAnimationGroup (0x0x7f4a0c5d0d68) + QObject (0x0x7f4a0c61ac60) 0 + primary-for QAbstractAnimation (0x0x7f4a0c5d0dd0) + +Class QBasicTimer + size=4 align=4 + base size=4 base align=4 +QBasicTimer (0x0x7f4a0c380a20) 0 + +Class QBitArray + size=8 align=8 + base size=8 base align=8 +QBitArray (0x0x7f4a0c380cc0) 0 + +Class QBitRef + size=16 align=8 + base size=12 base align=8 +QBitRef (0x0x7f4a0c380d80) 0 + +Class QIODevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIODevice::QPrivateSignal (0x0x7f4a0c41c0c0) 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 (0x0x7f4a0c3a8478) 0 + vptr=((& QIODevice::_ZTV9QIODevice) + 16u) + QObject (0x0x7f4a0c41c060) 0 + primary-for QIODevice (0x0x7f4a0c3a8478) + +Class QBuffer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBuffer::QPrivateSignal (0x0x7f4a0c41c300) 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 (0x0x7f4a0c3a85b0) 0 + vptr=((& QBuffer::_ZTV7QBuffer) + 16u) + QIODevice (0x0x7f4a0c3a8618) 0 + primary-for QBuffer (0x0x7f4a0c3a85b0) + QObject (0x0x7f4a0c41c2a0) 0 + primary-for QIODevice (0x0x7f4a0c3a8618) + +Class QByteArrayMatcher::Data + size=272 align=8 + base size=272 base align=8 +QByteArrayMatcher::Data (0x0x7f4a0c41c3c0) 0 + +Class QByteArrayMatcher + size=1040 align=8 + base size=1040 base align=8 +QByteArrayMatcher (0x0x7f4a0c41c360) 0 + +Class QStaticByteArrayMatcherBase::Skiptable + size=256 align=1 + base size=256 base align=1 +QStaticByteArrayMatcherBase::Skiptable (0x0x7f4a0c41c4e0) 0 + +Class QStaticByteArrayMatcherBase + size=256 align=16 + base size=256 base align=16 +QStaticByteArrayMatcherBase (0x0x7f4a0c41c480) 0 + +Class QSharedData + size=4 align=4 + base size=4 base align=4 +QSharedData (0x0x7f4a0c41c6c0) 0 + +Class QLocale + size=8 align=8 + base size=8 base align=8 +QLocale (0x0x7f4a0c41c8a0) 0 + +Class QCollatorSortKey + size=8 align=8 + base size=8 base align=8 +QCollatorSortKey (0x0x7f4a0c41cea0) 0 + +Class QCollator + size=8 align=8 + base size=8 base align=8 +QCollator (0x0x7f4a0c41cf60) 0 + +Class QCommandLineOption + size=8 align=8 + base size=8 base align=8 +QCommandLineOption (0x0x7f4a0c256f60) 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 (0x0x7f4a0be8d420) 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 (0x0x7f4a0c270af8) 0 + vptr=((& QTimerEvent::_ZTV11QTimerEvent) + 16u) + QEvent (0x0x7f4a0be8d480) 0 + primary-for QTimerEvent (0x0x7f4a0c270af8) + +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 (0x0x7f4a0c270b60) 0 + vptr=((& QChildEvent::_ZTV11QChildEvent) + 16u) + QEvent (0x0x7f4a0be8d4e0) 0 + primary-for QChildEvent (0x0x7f4a0c270b60) + +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 (0x0x7f4a0bef90d0) 0 + vptr=((& QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent) + 16u) + QEvent (0x0x7f4a0be8d9c0) 0 + primary-for QDynamicPropertyChangeEvent (0x0x7f4a0bef90d0) + +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 (0x0x7f4a0bef9138) 0 + vptr=((& QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent) + 16u) + QEvent (0x0x7f4a0be8da20) 0 + primary-for QDeferredDeleteEvent (0x0x7f4a0bef9138) + +Class QCoreApplication::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QCoreApplication::QPrivateSignal (0x0x7f4a0be8dae0) 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 (0x0x7f4a0bef91a0) 0 + vptr=((& QCoreApplication::_ZTV16QCoreApplication) + 16u) + QObject (0x0x7f4a0be8da80) 0 + primary-for QCoreApplication (0x0x7f4a0bef91a0) + +Class QCommandLineParser + size=8 align=8 + base size=8 base align=8 +QCommandLineParser (0x0x7f4a0be8db40) 0 + +Class QContiguousCacheData + size=24 align=4 + base size=24 base align=4 +QContiguousCacheData (0x0x7f4a0be8dba0) 0 + +Class QCryptographicHash + size=8 align=8 + base size=8 base align=8 +QCryptographicHash (0x0x7f4a0bf7d1e0) 0 + +Class QDataStream + size=32 align=8 + base size=32 base align=8 +QDataStream (0x0x7f4a0bf7d240) 0 + +Class QtPrivate::StreamStateSaver + size=16 align=8 + base size=12 base align=8 +QtPrivate::StreamStateSaver (0x0x7f4a0bf7d300) 0 + +Class QDate + size=8 align=8 + base size=8 base align=8 +QDate (0x0x7f4a0bf7d7e0) 0 + +Class QTime + size=4 align=4 + base size=4 base align=4 +QTime (0x0x7f4a0bf7da80) 0 + +Class QDateTime::ShortData + size=8 align=8 + base size=8 base align=8 +QDateTime::ShortData (0x0x7f4a0c054240) 0 + +Class QDateTime::Data + size=8 align=8 + base size=8 base align=8 +QDateTime::Data (0x0x7f4a0c0542a0) 0 + +Class QDateTime + size=8 align=8 + base size=8 base align=8 +QDateTime (0x0x7f4a0c0541e0) 0 + +Class QElapsedTimer + size=16 align=8 + base size=16 base align=8 +QElapsedTimer (0x0x7f4a0bcfb3c0) 0 + +Class QDeadlineTimer + size=16 align=8 + base size=16 base align=8 +QDeadlineTimer (0x0x7f4a0bcfb8a0) 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 (0x0x7f4a0be1d840) 0 + vptr=((& QTextStream::_ZTV11QTextStream) + 16u) + +Class QTextStreamManipulator + size=40 align=8 + base size=38 base align=8 +QTextStreamManipulator (0x0x7f4a0be1dae0) 0 + +Class QtSharedPointer::NormalDeleter + size=1 align=1 + base size=0 base align=1 +QtSharedPointer::NormalDeleter (0x0x7f4a0be1dd20) 0 empty + +Class QtSharedPointer::ExternalRefCountData + size=16 align=8 + base size=16 base align=8 +QtSharedPointer::ExternalRefCountData (0x0x7f4a0be1dea0) 0 + +Class QDebug::Stream + size=80 align=8 + base size=76 base align=8 +QDebug::Stream (0x0x7f4a0bb6f420) 0 + +Class QDebug + size=8 align=8 + base size=8 base align=8 +QDebug (0x0x7f4a0bb6f3c0) 0 + +Class QDebugStateSaver + size=8 align=8 + base size=8 base align=8 +QDebugStateSaver (0x0x7f4a0b8c2900) 0 + +Class QNoDebug + size=1 align=1 + base size=0 base align=1 +QNoDebug (0x0x7f4a0b8c29c0) 0 empty + +Class QFileDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileDevice::QPrivateSignal (0x0x7f4a0b999b40) 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 (0x0x7f4a0b998c30) 0 + vptr=((& QFileDevice::_ZTV11QFileDevice) + 16u) + QIODevice (0x0x7f4a0b998e38) 0 + primary-for QFileDevice (0x0x7f4a0b998c30) + QObject (0x0x7f4a0b999ae0) 0 + primary-for QIODevice (0x0x7f4a0b998e38) + +Class QFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFile::QPrivateSignal (0x0x7f4a0b999d80) 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 (0x0x7f4a0b9de0d0) 0 + vptr=((& QFile::_ZTV5QFile) + 16u) + QFileDevice (0x0x7f4a0b9de138) 0 + primary-for QFile (0x0x7f4a0b9de0d0) + QIODevice (0x0x7f4a0b9de1a0) 0 + primary-for QFileDevice (0x0x7f4a0b9de138) + QObject (0x0x7f4a0b999d20) 0 + primary-for QIODevice (0x0x7f4a0b9de1a0) + +Class QFileInfo + size=8 align=8 + base size=8 base align=8 +QFileInfo (0x0x7f4a0b999f60) 0 + +Class QDir + size=8 align=8 + base size=8 base align=8 +QDir (0x0x7f4a0ba4b3c0) 0 + +Class QDirIterator + size=8 align=8 + base size=8 base align=8 +QDirIterator (0x0x7f4a0ba4b9c0) 0 + +Class QEasingCurve + size=8 align=8 + base size=8 base align=8 +QEasingCurve (0x0x7f4a0ba4bc00) 0 + +Class QEventTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventTransition::QPrivateSignal (0x0x7f4a0b80b060) 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 (0x0x7f4a0b7ca1a0) 0 + vptr=((& QEventTransition::_ZTV16QEventTransition) + 16u) + QAbstractTransition (0x0x7f4a0b7ca208) 0 + primary-for QEventTransition (0x0x7f4a0b7ca1a0) + QObject (0x0x7f4a0b80b000) 0 + primary-for QAbstractTransition (0x0x7f4a0b7ca208) + +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 (0x0x7f4a0b7ca270) 0 nearly-empty + vptr=((& QException::_ZTV10QException) + 16u) + std::exception (0x0x7f4a0b80b0c0) 0 nearly-empty + primary-for QException (0x0x7f4a0b7ca270) + +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 (0x0x7f4a0b7ca2d8) 0 nearly-empty + vptr=((& QUnhandledException::_ZTV19QUnhandledException) + 16u) + QException (0x0x7f4a0b7ca340) 0 nearly-empty + primary-for QUnhandledException (0x0x7f4a0b7ca2d8) + std::exception (0x0x7f4a0b80b120) 0 nearly-empty + primary-for QException (0x0x7f4a0b7ca340) + +Class QtPrivate::ExceptionHolder + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionHolder (0x0x7f4a0b80b180) 0 + +Class QtPrivate::ExceptionStore + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionStore (0x0x7f4a0b80b240) 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 (0x0x7f4a0b80b2a0) 0 nearly-empty + vptr=((& QFactoryInterface::_ZTV17QFactoryInterface) + 16u) + +Class QFileSelector::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSelector::QPrivateSignal (0x0x7f4a0b80b3c0) 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 (0x0x7f4a0b7ca3a8) 0 + vptr=((& QFileSelector::_ZTV13QFileSelector) + 16u) + QObject (0x0x7f4a0b80b360) 0 + primary-for QFileSelector (0x0x7f4a0b7ca3a8) + +Class QFileSystemWatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSystemWatcher::QPrivateSignal (0x0x7f4a0b80b480) 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 (0x0x7f4a0b7ca410) 0 + vptr=((& QFileSystemWatcher::_ZTV18QFileSystemWatcher) + 16u) + QObject (0x0x7f4a0b80b420) 0 + primary-for QFileSystemWatcher (0x0x7f4a0b7ca410) + +Class QFinalState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFinalState::QPrivateSignal (0x0x7f4a0b80b540) 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 (0x0x7f4a0b7ca478) 0 + vptr=((& QFinalState::_ZTV11QFinalState) + 16u) + QAbstractState (0x0x7f4a0b7ca4e0) 0 + primary-for QFinalState (0x0x7f4a0b7ca478) + QObject (0x0x7f4a0b80b4e0) 0 + primary-for QAbstractState (0x0x7f4a0b7ca4e0) + +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 (0x0x7f4a0b80b5a0) 0 + vptr=((& QRunnable::_ZTV9QRunnable) + 16u) + +Class QBasicMutex + size=8 align=8 + base size=8 base align=8 +QBasicMutex (0x0x7f4a0b80b600) 0 + +Class QMutex + size=8 align=8 + base size=8 base align=8 +QMutex (0x0x7f4a0b7ca618) 0 + QBasicMutex (0x0x7f4a0b80b7e0) 0 + +Class QMutexLocker + size=8 align=8 + base size=8 base align=8 +QMutexLocker (0x0x7f4a0b80b840) 0 + +Class QtPrivate::ResultItem + size=16 align=8 + base size=16 base align=8 +QtPrivate::ResultItem (0x0x7f4a0b80b8a0) 0 + +Class QtPrivate::ResultIteratorBase + size=16 align=8 + base size=12 base align=8 +QtPrivate::ResultIteratorBase (0x0x7f4a0b80b900) 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 (0x0x7f4a0b80ba20) 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 (0x0x7f4a0b5542a0) 0 + vptr=((& QFutureInterfaceBase::_ZTV20QFutureInterfaceBase) + 16u) + +Class QFutureWatcherBase::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFutureWatcherBase::QPrivateSignal (0x0x7f4a0b554a80) 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 (0x0x7f4a0b575750) 0 + vptr=((& QFutureWatcherBase::_ZTV18QFutureWatcherBase) + 16u) + QObject (0x0x7f4a0b554a20) 0 + primary-for QFutureWatcherBase (0x0x7f4a0b575750) + +Class QHistoryState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QHistoryState::QPrivateSignal (0x0x7f4a0b6350c0) 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 (0x0x7f4a0b639068) 0 + vptr=((& QHistoryState::_ZTV13QHistoryState) + 16u) + QAbstractState (0x0x7f4a0b6390d0) 0 + primary-for QHistoryState (0x0x7f4a0b639068) + QObject (0x0x7f4a0b635060) 0 + primary-for QAbstractState (0x0x7f4a0b6390d0) + +Class QIdentityProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIdentityProxyModel::QPrivateSignal (0x0x7f4a0b635180) 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 (0x0x7f4a0b639138) 0 + vptr=((& QIdentityProxyModel::_ZTV19QIdentityProxyModel) + 16u) + QAbstractProxyModel (0x0x7f4a0b6391a0) 0 + primary-for QIdentityProxyModel (0x0x7f4a0b639138) + QAbstractItemModel (0x0x7f4a0b639208) 0 + primary-for QAbstractProxyModel (0x0x7f4a0b6391a0) + QObject (0x0x7f4a0b635120) 0 + primary-for QAbstractItemModel (0x0x7f4a0b639208) + +Class QItemSelectionRange + size=16 align=8 + base size=16 base align=8 +QItemSelectionRange (0x0x7f4a0b6351e0) 0 + +Class QItemSelectionModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QItemSelectionModel::QPrivateSignal (0x0x7f4a0b6358a0) 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 (0x0x7f4a0b639a28) 0 + vptr=((& QItemSelectionModel::_ZTV19QItemSelectionModel) + 16u) + QObject (0x0x7f4a0b635840) 0 + primary-for QItemSelectionModel (0x0x7f4a0b639a28) + +Class QItemSelection + size=8 align=8 + base size=8 base align=8 +QItemSelection (0x0x7f4a0b639c30) 0 + QList (0x0x7f4a0b639c98) 0 + QListSpecialMethods (0x0x7f4a0b635ba0) 0 empty + +Class QJsonValue + size=24 align=8 + base size=20 base align=8 +QJsonValue (0x0x7f4a0b33f0c0) 0 + +Class QJsonValueRef + size=16 align=8 + base size=12 base align=8 +QJsonValueRef (0x0x7f4a0b0a87e0) 0 + +Class QJsonValuePtr + size=24 align=8 + base size=24 base align=8 +QJsonValuePtr (0x0x7f4a0b0a8d20) 0 + +Class QJsonValueRefPtr + size=16 align=8 + base size=16 base align=8 +QJsonValueRefPtr (0x0x7f4a0b0a8d80) 0 + +Class QJsonArray::iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::iterator (0x0x7f4a0b0a8f60) 0 + +Class QJsonArray::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::const_iterator (0x0x7f4a0b135000) 0 + +Class QJsonArray + size=16 align=8 + base size=16 base align=8 +QJsonArray (0x0x7f4a0b0a8f00) 0 + +Class QJsonParseError + size=8 align=4 + base size=8 base align=4 +QJsonParseError (0x0x7f4a0b216240) 0 + +Class QJsonDocument + size=8 align=8 + base size=8 base align=8 +QJsonDocument (0x0x7f4a0b2162a0) 0 + +Class QJsonObject::iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::iterator (0x0x7f4a0b216900) 0 + +Class QJsonObject::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::const_iterator (0x0x7f4a0b216960) 0 + +Class QJsonObject + size=16 align=8 + base size=16 base align=8 +QJsonObject (0x0x7f4a0b2168a0) 0 + +Class QLibrary::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLibrary::QPrivateSignal (0x0x7f4a0aec9c00) 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 (0x0x7f4a0af0f000) 0 + vptr=((& QLibrary::_ZTV8QLibrary) + 16u) + QObject (0x0x7f4a0aec9ba0) 0 + primary-for QLibrary (0x0x7f4a0af0f000) + +Class QVersionNumber::SegmentStorage + size=8 align=8 + base size=8 base align=8 +QVersionNumber::SegmentStorage (0x0x7f4a0af5b300) 0 + +Class QVersionNumber + size=8 align=8 + base size=8 base align=8 +QVersionNumber (0x0x7f4a0aec9de0) 0 + +Class QLibraryInfo + size=1 align=1 + base size=0 base align=1 +QLibraryInfo (0x0x7f4a0af5b7e0) 0 empty + +Class QPoint + size=8 align=4 + base size=8 base align=4 +QPoint (0x0x7f4a0af5b840) 0 + +Class QPointF + size=16 align=8 + base size=16 base align=8 +QPointF (0x0x7f4a0af5bae0) 0 + +Class QLine + size=16 align=4 + base size=16 base align=4 +QLine (0x0x7f4a0af5bd80) 0 + +Class QLineF + size=32 align=8 + base size=32 base align=8 +QLineF (0x0x7f4a0b051720) 0 + +Class QLinkedListData + size=32 align=8 + base size=25 base align=8 +QLinkedListData (0x0x7f4a0ace40c0) 0 + +Class QLockFile + size=8 align=8 + base size=8 base align=8 +QLockFile (0x0x7f4a0ace4420) 0 + +Class QLoggingCategory::AtomicBools + size=4 align=1 + base size=4 base align=1 +QLoggingCategory::AtomicBools (0x0x7f4a0ace45a0) 0 + +Class QLoggingCategory + size=24 align=8 + base size=24 base align=8 +QLoggingCategory (0x0x7f4a0ace4540) 0 + +Class QMargins + size=16 align=4 + base size=16 base align=4 +QMargins (0x0x7f4a0ace4720) 0 + +Class QMarginsF + size=32 align=8 + base size=32 base align=8 +QMarginsF (0x0x7f4a0ace49c0) 0 + +Class QMessageAuthenticationCode + size=8 align=8 + base size=8 base align=8 +QMessageAuthenticationCode (0x0x7f4a0aa84060) 0 + +Class QMetaMethod + size=16 align=8 + base size=12 base align=8 +QMetaMethod (0x0x7f4a0aa840c0) 0 + +Class QMetaEnum + size=16 align=8 + base size=12 base align=8 +QMetaEnum (0x0x7f4a0aa846c0) 0 + +Class QMetaProperty + size=32 align=8 + base size=32 base align=8 +QMetaProperty (0x0x7f4a0aa849c0) 0 + +Class QMetaClassInfo + size=16 align=8 + base size=12 base align=8 +QMetaClassInfo (0x0x7f4a0aa84a20) 0 + +Class QMimeData::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QMimeData::QPrivateSignal (0x0x7f4a0aa84d20) 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 (0x0x7f4a0aade270) 0 + vptr=((& QMimeData::_ZTV9QMimeData) + 16u) + QObject (0x0x7f4a0aa84cc0) 0 + primary-for QMimeData (0x0x7f4a0aade270) + +Class QMimeType + size=8 align=8 + base size=8 base align=8 +QMimeType (0x0x7f4a0aa84d80) 0 + +Class QMimeDatabase + size=8 align=8 + base size=8 base align=8 +QMimeDatabase (0x0x7f4a0ab230c0) 0 + +Class QObjectCleanupHandler::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObjectCleanupHandler::QPrivateSignal (0x0x7f4a0ab23180) 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 (0x0x7f4a0aade478) 0 + vptr=((& QObjectCleanupHandler::_ZTV21QObjectCleanupHandler) + 16u) + QObject (0x0x7f4a0ab23120) 0 + primary-for QObjectCleanupHandler (0x0x7f4a0aade478) + +Class QOperatingSystemVersion + size=16 align=4 + base size=16 base align=4 +QOperatingSystemVersion (0x0x7f4a0ab231e0) 0 + +Class QParallelAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QParallelAnimationGroup::QPrivateSignal (0x0x7f4a0ab23960) 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 (0x0x7f4a0aadebc8) 0 + vptr=((& QParallelAnimationGroup::_ZTV23QParallelAnimationGroup) + 16u) + QAnimationGroup (0x0x7f4a0aadec30) 0 + primary-for QParallelAnimationGroup (0x0x7f4a0aadebc8) + QAbstractAnimation (0x0x7f4a0aadec98) 0 + primary-for QAnimationGroup (0x0x7f4a0aadec30) + QObject (0x0x7f4a0ab23900) 0 + primary-for QAbstractAnimation (0x0x7f4a0aadec98) + +Class QPauseAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPauseAnimation::QPrivateSignal (0x0x7f4a0ab23a20) 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 (0x0x7f4a0aaded00) 0 + vptr=((& QPauseAnimation::_ZTV15QPauseAnimation) + 16u) + QAbstractAnimation (0x0x7f4a0aaded68) 0 + primary-for QPauseAnimation (0x0x7f4a0aaded00) + QObject (0x0x7f4a0ab239c0) 0 + primary-for QAbstractAnimation (0x0x7f4a0aaded68) + +Class QStaticPlugin + size=16 align=8 + base size=16 base align=8 +QStaticPlugin (0x0x7f4a0ab23c00) 0 + +Class QPluginLoader::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPluginLoader::QPrivateSignal (0x0x7f4a0ab23f00) 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 (0x0x7f4a0aadef70) 0 + vptr=((& QPluginLoader::_ZTV13QPluginLoader) + 16u) + QObject (0x0x7f4a0ab23ea0) 0 + primary-for QPluginLoader (0x0x7f4a0aadef70) + +Class QProcessEnvironment + size=8 align=8 + base size=8 base align=8 +QProcessEnvironment (0x0x7f4a0ab23f60) 0 + +Class QProcess::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QProcess::QPrivateSignal (0x0x7f4a0abbf660) 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 (0x0x7f4a0abd25b0) 0 + vptr=((& QProcess::_ZTV8QProcess) + 16u) + QIODevice (0x0x7f4a0abd2618) 0 + primary-for QProcess (0x0x7f4a0abd25b0) + QObject (0x0x7f4a0abbf600) 0 + primary-for QIODevice (0x0x7f4a0abd2618) + +Class QVariantAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QVariantAnimation::QPrivateSignal (0x0x7f4a0abbf720) 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 (0x0x7f4a0abd2680) 0 + vptr=((& QVariantAnimation::_ZTV17QVariantAnimation) + 16u) + QAbstractAnimation (0x0x7f4a0abd26e8) 0 + primary-for QVariantAnimation (0x0x7f4a0abd2680) + QObject (0x0x7f4a0abbf6c0) 0 + primary-for QAbstractAnimation (0x0x7f4a0abd26e8) + +Class QPropertyAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPropertyAnimation::QPrivateSignal (0x0x7f4a0abbf7e0) 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 (0x0x7f4a0abd27b8) 0 + vptr=((& QPropertyAnimation::_ZTV18QPropertyAnimation) + 16u) + QVariantAnimation (0x0x7f4a0abd2820) 0 + primary-for QPropertyAnimation (0x0x7f4a0abd27b8) + QAbstractAnimation (0x0x7f4a0abd2888) 0 + primary-for QVariantAnimation (0x0x7f4a0abd2820) + QObject (0x0x7f4a0abbf780) 0 + primary-for QAbstractAnimation (0x0x7f4a0abd2888) + +Class QRandomGenerator::Storage + size=2504 align=8 + base size=2504 base align=8 +QRandomGenerator::Storage (0x0x7f4a0abbf900) 0 + +Class QRandomGenerator + size=2512 align=8 + base size=2512 base align=8 +QRandomGenerator (0x0x7f4a0abbf8a0) 0 + +Class QRandomGenerator64 + size=2512 align=8 + base size=2512 base align=8 +QRandomGenerator64 (0x0x7f4a0a8b5b60) 0 + QRandomGenerator (0x0x7f4a0a8bb8a0) 0 + +Class QReadWriteLock + size=8 align=8 + base size=8 base align=8 +QReadWriteLock (0x0x7f4a0a8bb960) 0 + +Class QReadLocker + size=8 align=8 + base size=8 base align=8 +QReadLocker (0x0x7f4a0a8bbc00) 0 + +Class QWriteLocker + size=8 align=8 + base size=8 base align=8 +QWriteLocker (0x0x7f4a0a8bbcc0) 0 + +Class QSize + size=8 align=4 + base size=8 base align=4 +QSize (0x0x7f4a0a8bbd80) 0 + +Class QSizeF + size=16 align=8 + base size=16 base align=8 +QSizeF (0x0x7f4a0a99c060) 0 + +Class QRect + size=16 align=4 + base size=16 base align=4 +QRect (0x0x7f4a0a99c300) 0 + +Class QRectF + size=32 align=8 + base size=32 base align=8 +QRectF (0x0x7f4a0a99c5a0) 0 + +Class QRegularExpression + size=8 align=8 + base size=8 base align=8 +QRegularExpression (0x0x7f4a0a99c840) 0 + +Class QRegularExpressionMatch + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatch (0x0x7f4a0a99ce40) 0 + +Class QRegularExpressionMatchIterator + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatchIterator (0x0x7f4a0a7c6180) 0 + +Class QResource + size=8 align=8 + base size=8 base align=8 +QResource (0x0x7f4a0a7c6480) 0 + +Class QSaveFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSaveFile::QPrivateSignal (0x0x7f4a0a7c6600) 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 (0x0x7f4a0a9dcd68) 0 + vptr=((& QSaveFile::_ZTV9QSaveFile) + 16u) + QFileDevice (0x0x7f4a0a9dcdd0) 0 + primary-for QSaveFile (0x0x7f4a0a9dcd68) + QIODevice (0x0x7f4a0a9dce38) 0 + primary-for QFileDevice (0x0x7f4a0a9dcdd0) + QObject (0x0x7f4a0a7c65a0) 0 + primary-for QIODevice (0x0x7f4a0a9dce38) + +Class QSemaphore + size=8 align=8 + base size=8 base align=8 +QSemaphore (0x0x7f4a0a7c66c0) 0 + +Class QSemaphoreReleaser + size=16 align=8 + base size=12 base align=8 +QSemaphoreReleaser (0x0x7f4a0a7c6840) 0 + +Class QSequentialAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSequentialAnimationGroup::QPrivateSignal (0x0x7f4a0a521e40) 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 (0x0x7f4a0a53a6e8) 0 + vptr=((& QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup) + 16u) + QAnimationGroup (0x0x7f4a0a53a750) 0 + primary-for QSequentialAnimationGroup (0x0x7f4a0a53a6e8) + QAbstractAnimation (0x0x7f4a0a53a7b8) 0 + primary-for QAnimationGroup (0x0x7f4a0a53a750) + QObject (0x0x7f4a0a521de0) 0 + primary-for QAbstractAnimation (0x0x7f4a0a53a7b8) + +Class QSettings::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSettings::QPrivateSignal (0x0x7f4a0a521f00) 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 (0x0x7f4a0a53a820) 0 + vptr=((& QSettings::_ZTV9QSettings) + 16u) + QObject (0x0x7f4a0a521ea0) 0 + primary-for QSettings (0x0x7f4a0a53a820) + +Class QSharedMemory::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSharedMemory::QPrivateSignal (0x0x7f4a0a57f000) 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 (0x0x7f4a0a53a888) 0 + vptr=((& QSharedMemory::_ZTV13QSharedMemory) + 16u) + QObject (0x0x7f4a0a521f60) 0 + primary-for QSharedMemory (0x0x7f4a0a53a888) + +Class QSignalMapper::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalMapper::QPrivateSignal (0x0x7f4a0a57f0c0) 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 (0x0x7f4a0a53a8f0) 0 + vptr=((& QSignalMapper::_ZTV13QSignalMapper) + 16u) + QObject (0x0x7f4a0a57f060) 0 + primary-for QSignalMapper (0x0x7f4a0a53a8f0) + +Class QSignalTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalTransition::QPrivateSignal (0x0x7f4a0a57f180) 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 (0x0x7f4a0a53a958) 0 + vptr=((& QSignalTransition::_ZTV17QSignalTransition) + 16u) + QAbstractTransition (0x0x7f4a0a53a9c0) 0 + primary-for QSignalTransition (0x0x7f4a0a53a958) + QObject (0x0x7f4a0a57f120) 0 + primary-for QAbstractTransition (0x0x7f4a0a53a9c0) + +Class QSocketNotifier::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSocketNotifier::QPrivateSignal (0x0x7f4a0a57f240) 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 (0x0x7f4a0a53aa28) 0 + vptr=((& QSocketNotifier::_ZTV15QSocketNotifier) + 16u) + QObject (0x0x7f4a0a57f1e0) 0 + primary-for QSocketNotifier (0x0x7f4a0a53aa28) + +Class QSortFilterProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSortFilterProxyModel::QPrivateSignal (0x0x7f4a0a57f300) 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 (0x0x7f4a0a53aa90) 0 + vptr=((& QSortFilterProxyModel::_ZTV21QSortFilterProxyModel) + 16u) + QAbstractProxyModel (0x0x7f4a0a53aaf8) 0 + primary-for QSortFilterProxyModel (0x0x7f4a0a53aa90) + QAbstractItemModel (0x0x7f4a0a53ab60) 0 + primary-for QAbstractProxyModel (0x0x7f4a0a53aaf8) + QObject (0x0x7f4a0a57f2a0) 0 + primary-for QAbstractItemModel (0x0x7f4a0a53ab60) + +Class QStandardPaths + size=1 align=1 + base size=0 base align=1 +QStandardPaths (0x0x7f4a0a57f3c0) 0 empty + +Class QState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QState::QPrivateSignal (0x0x7f4a0a57f600) 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 (0x0x7f4a0a53ad00) 0 + vptr=((& QState::_ZTV6QState) + 16u) + QAbstractState (0x0x7f4a0a53ad68) 0 + primary-for QState (0x0x7f4a0a53ad00) + QObject (0x0x7f4a0a57f5a0) 0 + primary-for QAbstractState (0x0x7f4a0a53ad68) + +Class QStateMachine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStateMachine::QPrivateSignal (0x0x7f4a0a57f720) 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 (0x0x7f4a0a53af08) 0 + vptr=((& QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE) + 16u) + QEvent (0x0x7f4a0a57f780) 0 + primary-for QStateMachine::SignalEvent (0x0x7f4a0a53af08) + +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 (0x0x7f4a0a53af70) 0 + vptr=((& QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE) + 16u) + QEvent (0x0x7f4a0a57f7e0) 0 + primary-for QStateMachine::WrappedEvent (0x0x7f4a0a53af70) + +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 (0x0x7f4a0a53add0) 0 + vptr=((& QStateMachine::_ZTV13QStateMachine) + 16u) + QState (0x0x7f4a0a53ae38) 0 + primary-for QStateMachine (0x0x7f4a0a53add0) + QAbstractState (0x0x7f4a0a53aea0) 0 + primary-for QState (0x0x7f4a0a53ae38) + QObject (0x0x7f4a0a57f6c0) 0 + primary-for QAbstractState (0x0x7f4a0a53aea0) + +Class QStorageInfo + size=8 align=8 + base size=8 base align=8 +QStorageInfo (0x0x7f4a0a57f840) 0 + +Class QAbstractConcatenable + size=1 align=1 + base size=0 base align=1 +QAbstractConcatenable (0x0x7f4a0a291780) 0 empty + +Class QStringListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStringListModel::QPrivateSignal (0x0x7f4a0a31db40) 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 (0x0x7f4a0a30cf70) 0 + vptr=((& QStringListModel::_ZTV16QStringListModel) + 16u) + QAbstractListModel (0x0x7f4a0a356000) 0 + primary-for QStringListModel (0x0x7f4a0a30cf70) + QAbstractItemModel (0x0x7f4a0a356068) 0 + primary-for QAbstractListModel (0x0x7f4a0a356000) + QObject (0x0x7f4a0a31dae0) 0 + primary-for QAbstractItemModel (0x0x7f4a0a356068) + +Class QSystemSemaphore + size=8 align=8 + base size=8 base align=8 +QSystemSemaphore (0x0x7f4a0a31dba0) 0 + +Class QTemporaryDir + size=8 align=8 + base size=8 base align=8 +QTemporaryDir (0x0x7f4a0a31dc60) 0 + +Class QTemporaryFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTemporaryFile::QPrivateSignal (0x0x7f4a0a31dd80) 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 (0x0x7f4a0a3560d0) 0 + vptr=((& QTemporaryFile::_ZTV14QTemporaryFile) + 16u) + QFile (0x0x7f4a0a356138) 0 + primary-for QTemporaryFile (0x0x7f4a0a3560d0) + QFileDevice (0x0x7f4a0a3561a0) 0 + primary-for QFile (0x0x7f4a0a356138) + QIODevice (0x0x7f4a0a356208) 0 + primary-for QFileDevice (0x0x7f4a0a3561a0) + QObject (0x0x7f4a0a31dd20) 0 + primary-for QIODevice (0x0x7f4a0a356208) + +Class QTextBoundaryFinder + size=48 align=8 + base size=48 base align=8 +QTextBoundaryFinder (0x0x7f4a0a31dde0) 0 + +Class QTextCodec::ConverterState + size=32 align=8 + base size=32 base align=8 +QTextCodec::ConverterState (0x0x7f4a0a3d5060) 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 (0x0x7f4a0a3d5000) 0 nearly-empty + vptr=((& QTextCodec::_ZTV10QTextCodec) + 16u) + +Class QTextEncoder + size=40 align=8 + base size=40 base align=8 +QTextEncoder (0x0x7f4a0a3d5240) 0 + +Class QTextDecoder + size=40 align=8 + base size=40 base align=8 +QTextDecoder (0x0x7f4a0a3d52a0) 0 + +Class std::__mutex_base + size=40 align=8 + base size=40 base align=8 +std::__mutex_base (0x0x7f4a0a3d5300) 0 + +Class std::__recursive_mutex_base + size=40 align=8 + base size=40 base align=8 +std::__recursive_mutex_base (0x0x7f4a0a3d5360) 0 + +Class std::mutex + size=40 align=8 + base size=40 base align=8 +std::mutex (0x0x7f4a0a356410) 0 + std::__mutex_base (0x0x7f4a0a3d53c0) 0 + +Class std::recursive_mutex + size=40 align=8 + base size=40 base align=8 +std::recursive_mutex (0x0x7f4a0a356478) 0 + std::__recursive_mutex_base (0x0x7f4a0a3d5420) 0 + +Class std::timed_mutex + size=40 align=8 + base size=40 base align=8 +std::timed_mutex (0x0x7f4a0a43ab60) 0 + std::__mutex_base (0x0x7f4a0a3d5540) 0 + std::__timed_mutex_impl (0x0x7f4a0a3d55a0) 0 empty + +Class std::recursive_timed_mutex + size=40 align=8 + base size=40 base align=8 +std::recursive_timed_mutex (0x0x7f4a0a45a540) 0 + std::__recursive_mutex_base (0x0x7f4a0a3d5660) 0 + std::__timed_mutex_impl (0x0x7f4a0a3d56c0) 0 empty + +Class std::defer_lock_t + size=1 align=1 + base size=0 base align=1 +std::defer_lock_t (0x0x7f4a0a3d5720) 0 empty + +Class std::try_to_lock_t + size=1 align=1 + base size=0 base align=1 +std::try_to_lock_t (0x0x7f4a0a3d5780) 0 empty + +Class std::adopt_lock_t + size=1 align=1 + base size=0 base align=1 +std::adopt_lock_t (0x0x7f4a0a3d57e0) 0 empty + +Class std::once_flag + size=4 align=4 + base size=4 base align=4 +std::once_flag (0x0x7f4a0a3d5a20) 0 + +Vtable for __gnu_cxx::__concurrence_lock_error +__gnu_cxx::__concurrence_lock_error::_ZTVN9__gnu_cxx24__concurrence_lock_errorE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx24__concurrence_lock_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_lock_error::~__concurrence_lock_error +24 (int (*)(...))__gnu_cxx::__concurrence_lock_error::~__concurrence_lock_error +32 (int (*)(...))__gnu_cxx::__concurrence_lock_error::what + +Class __gnu_cxx::__concurrence_lock_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_lock_error (0x0x7f4a0a3565b0) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_lock_error::_ZTVN9__gnu_cxx24__concurrence_lock_errorE) + 16u) + std::exception (0x0x7f4a0a3d5ae0) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_lock_error (0x0x7f4a0a3565b0) + +Vtable for __gnu_cxx::__concurrence_unlock_error +__gnu_cxx::__concurrence_unlock_error::_ZTVN9__gnu_cxx26__concurrence_unlock_errorE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx26__concurrence_unlock_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::~__concurrence_unlock_error +24 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::~__concurrence_unlock_error +32 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::what + +Class __gnu_cxx::__concurrence_unlock_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_unlock_error (0x0x7f4a0a356618) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_unlock_error::_ZTVN9__gnu_cxx26__concurrence_unlock_errorE) + 16u) + std::exception (0x0x7f4a0a3d5ba0) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_unlock_error (0x0x7f4a0a356618) + +Vtable for __gnu_cxx::__concurrence_broadcast_error +__gnu_cxx::__concurrence_broadcast_error::_ZTVN9__gnu_cxx29__concurrence_broadcast_errorE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx29__concurrence_broadcast_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::~__concurrence_broadcast_error +24 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::~__concurrence_broadcast_error +32 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::what + +Class __gnu_cxx::__concurrence_broadcast_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_broadcast_error (0x0x7f4a0a356680) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_broadcast_error::_ZTVN9__gnu_cxx29__concurrence_broadcast_errorE) + 16u) + std::exception (0x0x7f4a0a3d5c60) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_broadcast_error (0x0x7f4a0a356680) + +Vtable for __gnu_cxx::__concurrence_wait_error +__gnu_cxx::__concurrence_wait_error::_ZTVN9__gnu_cxx24__concurrence_wait_errorE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx24__concurrence_wait_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_wait_error::~__concurrence_wait_error +24 (int (*)(...))__gnu_cxx::__concurrence_wait_error::~__concurrence_wait_error +32 (int (*)(...))__gnu_cxx::__concurrence_wait_error::what + +Class __gnu_cxx::__concurrence_wait_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_wait_error (0x0x7f4a0a356750) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_wait_error::_ZTVN9__gnu_cxx24__concurrence_wait_errorE) + 16u) + std::exception (0x0x7f4a0a3d5d20) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_wait_error (0x0x7f4a0a356750) + +Class __gnu_cxx::__mutex + size=40 align=8 + base size=40 base align=8 +__gnu_cxx::__mutex (0x0x7f4a0a3d5de0) 0 + +Class __gnu_cxx::__recursive_mutex + size=40 align=8 + base size=40 base align=8 +__gnu_cxx::__recursive_mutex (0x0x7f4a0a3d5e40) 0 + +Class __gnu_cxx::__scoped_lock + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__scoped_lock (0x0x7f4a0a3d5ea0) 0 + +Class __gnu_cxx::__cond + size=48 align=8 + base size=48 base align=8 +__gnu_cxx::__cond (0x0x7f4a0a3d5f00) 0 + +Vtable for std::bad_weak_ptr +std::bad_weak_ptr::_ZTVSt12bad_weak_ptr: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt12bad_weak_ptr) +16 (int (*)(...))std::bad_weak_ptr::~bad_weak_ptr +24 (int (*)(...))std::bad_weak_ptr::~bad_weak_ptr +32 (int (*)(...))std::bad_weak_ptr::what + +Class std::bad_weak_ptr + size=8 align=8 + base size=8 base align=8 +std::bad_weak_ptr (0x0x7f4a0a356a28) 0 nearly-empty + vptr=((& std::bad_weak_ptr::_ZTVSt12bad_weak_ptr) + 16u) + std::exception (0x0x7f4a0a0042a0) 0 nearly-empty + primary-for std::bad_weak_ptr (0x0x7f4a0a356a28) + +Class std::_Sp_make_shared_tag + size=1 align=1 + base size=0 base align=1 +std::_Sp_make_shared_tag (0x0x7f4a0a004ae0) 0 empty + +Class std::_Sp_locker + size=2 align=1 + base size=2 base align=1 +std::_Sp_locker (0x0x7f4a09d9c300) 0 + +Class std::thread::id + size=8 align=8 + base size=8 base align=8 +std::thread::id (0x0x7f4a09d9c4e0) 0 + +Vtable for std::thread::_Impl_base +std::thread::_Impl_base::_ZTVNSt6thread10_Impl_baseE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt6thread10_Impl_baseE) +16 0u +24 0u +32 (int (*)(...))__cxa_pure_virtual + +Class std::thread::_Impl_base + size=24 align=8 + base size=24 base align=8 +std::thread::_Impl_base (0x0x7f4a09d9c540) 0 + vptr=((& std::thread::_Impl_base::_ZTVNSt6thread10_Impl_baseE) + 16u) + +Class std::thread + size=8 align=8 + base size=8 base align=8 +std::thread (0x0x7f4a09d9c480) 0 + +Class std::condition_variable + size=48 align=8 + base size=48 base align=8 +std::condition_variable (0x0x7f4a09b81180) 0 + +Class std::__at_thread_exit_elt + size=16 align=8 + base size=16 base align=8 +std::__at_thread_exit_elt (0x0x7f4a09b81240) 0 + +Class std::_V2::condition_variable_any + size=64 align=8 + base size=64 base align=8 +std::_V2::condition_variable_any (0x0x7f4a09b812a0) 0 + +Class std::__atomic_futex_unsigned_base + size=1 align=1 + base size=0 base align=1 +std::__atomic_futex_unsigned_base (0x0x7f4a09c3e900) 0 empty + +Vtable for std::future_error +std::future_error::_ZTVSt12future_error: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt12future_error) +16 (int (*)(...))std::future_error::~future_error +24 (int (*)(...))std::future_error::~future_error +32 (int (*)(...))std::future_error::what + +Class std::future_error + size=32 align=8 + base size=32 base align=8 +std::future_error (0x0x7f4a09c3dd68) 0 + vptr=((& std::future_error::_ZTVSt12future_error) + 16u) + std::logic_error (0x0x7f4a09c3ddd0) 0 + primary-for std::future_error (0x0x7f4a09c3dd68) + std::exception (0x0x7f4a09c3ea20) 0 nearly-empty + primary-for std::logic_error (0x0x7f4a09c3ddd0) + +Class std::__future_base::_Result_base::_Deleter + size=1 align=1 + base size=0 base align=1 +std::__future_base::_Result_base::_Deleter (0x0x7f4a09c3eb40) 0 empty + +Vtable for std::__future_base::_Result_base +std::__future_base::_Result_base::_ZTVNSt13__future_base12_Result_baseE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt13__future_base12_Result_baseE) +16 (int (*)(...))__cxa_pure_virtual +24 0u +32 0u + +Class std::__future_base::_Result_base + size=16 align=8 + base size=16 base align=8 +std::__future_base::_Result_base (0x0x7f4a09c3eae0) 0 + vptr=((& std::__future_base::_Result_base::_ZTVNSt13__future_base12_Result_baseE) + 16u) + +Class std::__future_base::_State_baseV2::__exception_ptr_tag + size=1 align=1 + base size=0 base align=1 +std::__future_base::_State_baseV2::__exception_ptr_tag (0x0x7f4a099c80c0) 0 empty + +Class std::__future_base::_State_baseV2::_Make_ready + size=32 align=8 + base size=32 base align=8 +std::__future_base::_State_baseV2::_Make_ready (0x0x7f4a099ab3a8) 0 + std::__at_thread_exit_elt (0x0x7f4a099c8180) 0 + +Vtable for std::__future_base::_State_baseV2 +std::__future_base::_State_baseV2::_ZTVNSt13__future_base13_State_baseV2E: 6u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt13__future_base13_State_baseV2E) +16 (int (*)(...))std::__future_base::_State_baseV2::~_State_baseV2 +24 (int (*)(...))std::__future_base::_State_baseV2::~_State_baseV2 +32 (int (*)(...))std::__future_base::_State_baseV2::_M_complete_async +40 (int (*)(...))std::__future_base::_State_baseV2::_M_is_deferred_future + +Class std::__future_base::_State_baseV2 + size=32 align=8 + base size=28 base align=8 +std::__future_base::_State_baseV2 (0x0x7f4a09c3ecc0) 0 + vptr=((& std::__future_base::_State_baseV2::_ZTVNSt13__future_base13_State_baseV2E) + 16u) + +Class std::__future_base + size=1 align=1 + base size=0 base align=1 +std::__future_base (0x0x7f4a09c3ea80) 0 empty + +Vtable for std::__future_base::_Async_state_commonV2 +std::__future_base::_Async_state_commonV2::_ZTVNSt13__future_base21_Async_state_commonV2E: 6u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt13__future_base21_Async_state_commonV2E) +16 (int (*)(...))std::__future_base::_Async_state_commonV2::~_Async_state_commonV2 +24 (int (*)(...))std::__future_base::_Async_state_commonV2::~_Async_state_commonV2 +32 (int (*)(...))std::__future_base::_Async_state_commonV2::_M_complete_async +40 (int (*)(...))std::__future_base::_State_baseV2::_M_is_deferred_future + +Class std::__future_base::_Async_state_commonV2 + size=48 align=8 + base size=44 base align=8 +std::__future_base::_Async_state_commonV2 (0x0x7f4a096f2f70) 0 + vptr=((& std::__future_base::_Async_state_commonV2::_ZTVNSt13__future_base21_Async_state_commonV2E) + 16u) + std::__future_base::_State_baseV2 (0x0x7f4a0934c060) 0 + primary-for std::__future_base::_Async_state_commonV2 (0x0x7f4a096f2f70) + +Class QThread::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThread::QPrivateSignal (0x0x7f4a0934c780) 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 (0x0x7f4a09356a28) 0 + vptr=((& QThread::_ZTV7QThread) + 16u) + QObject (0x0x7f4a0934c720) 0 + primary-for QThread (0x0x7f4a09356a28) + +Class QThreadPool::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThreadPool::QPrivateSignal (0x0x7f4a0934c8a0) 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 (0x0x7f4a09356a90) 0 + vptr=((& QThreadPool::_ZTV11QThreadPool) + 16u) + QObject (0x0x7f4a0934c840) 0 + primary-for QThreadPool (0x0x7f4a09356a90) + +Class QThreadStorageData + size=4 align=4 + base size=4 base align=4 +QThreadStorageData (0x0x7f4a0934c900) 0 + +Class QTimeLine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimeLine::QPrivateSignal (0x0x7f4a0934ca20) 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 (0x0x7f4a09356af8) 0 + vptr=((& QTimeLine::_ZTV9QTimeLine) + 16u) + QObject (0x0x7f4a0934c9c0) 0 + primary-for QTimeLine (0x0x7f4a09356af8) + +Class QTimer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimer::QPrivateSignal (0x0x7f4a0934cae0) 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 (0x0x7f4a09356b60) 0 + vptr=((& QTimer::_ZTV6QTimer) + 16u) + QObject (0x0x7f4a0934ca80) 0 + primary-for QTimer (0x0x7f4a09356b60) + +Class QTimeZone::OffsetData + size=32 align=8 + base size=28 base align=8 +QTimeZone::OffsetData (0x0x7f4a0941a1e0) 0 + +Class QTimeZone + size=8 align=8 + base size=8 base align=8 +QTimeZone (0x0x7f4a0941a180) 0 + +Class QTranslator::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTranslator::QPrivateSignal (0x0x7f4a0941a780) 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 (0x0x7f4a094155b0) 0 + vptr=((& QTranslator::_ZTV11QTranslator) + 16u) + QObject (0x0x7f4a0941a720) 0 + primary-for QTranslator (0x0x7f4a094155b0) + +Class QUrl + size=8 align=8 + base size=8 base align=8 +QUrl (0x0x7f4a0941a8a0) 0 + +Class QUrlQuery + size=8 align=8 + base size=8 base align=8 +QUrlQuery (0x0x7f4a09156f60) 0 + +Class QUuid + size=16 align=4 + base size=16 base align=4 +QUuid (0x0x7f4a091ec600) 0 + +Class QWaitCondition + size=8 align=8 + base size=8 base align=8 +QWaitCondition (0x0x7f4a091ecc00) 0 + +Class QXmlStreamStringRef + size=16 align=8 + base size=16 base align=8 +QXmlStreamStringRef (0x0x7f4a091ecc60) 0 + +Class QXmlStreamAttribute + size=80 align=8 + base size=73 base align=8 +QXmlStreamAttribute (0x0x7f4a091ecf00) 0 + +Class QXmlStreamAttributes + size=8 align=8 + base size=8 base align=8 +QXmlStreamAttributes (0x0x7f4a09200d68) 0 + QVector (0x0x7f4a092a1300) 0 + +Class QXmlStreamNamespaceDeclaration + size=40 align=8 + base size=40 base align=8 +QXmlStreamNamespaceDeclaration (0x0x7f4a092a1360) 0 + +Class QXmlStreamNotationDeclaration + size=56 align=8 + base size=56 base align=8 +QXmlStreamNotationDeclaration (0x0x7f4a092a1600) 0 + +Class QXmlStreamEntityDeclaration + size=88 align=8 + base size=88 base align=8 +QXmlStreamEntityDeclaration (0x0x7f4a092a18a0) 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 (0x0x7f4a092a1b40) 0 nearly-empty + vptr=((& QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver) + 16u) + +Class QXmlStreamReader + size=8 align=8 + base size=8 base align=8 +QXmlStreamReader (0x0x7f4a092a1ba0) 0 + +Class QXmlStreamWriter + size=8 align=8 + base size=8 base align=8 +QXmlStreamWriter (0x0x7f4a08f7a600) 0 + +Class QNdefRecord + size=8 align=8 + base size=8 base align=8 +QNdefRecord (0x0x7f4a08f7a720) 0 + +Class QNdefFilter::Record + size=24 align=8 + base size=24 base align=8 +QNdefFilter::Record (0x0x7f4a08f7a840) 0 + +Class QNdefFilter + size=8 align=8 + base size=8 base align=8 +QNdefFilter (0x0x7f4a08f7a7e0) 0 + +Class QNdefMessage + size=8 align=8 + base size=8 base align=8 +QNdefMessage (0x0x7f4a08fa9208) 0 + QList (0x0x7f4a08fa9270) 0 + QListSpecialMethods (0x0x7f4a08f7aa20) 0 empty + +Class QNdefNfcTextRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcTextRecord (0x0x7f4a08fa92d8) 0 + QNdefRecord (0x0x7f4a08f7ac00) 0 + +Class QNdefNfcUriRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcUriRecord (0x0x7f4a08fa9820) 0 + QNdefRecord (0x0x7f4a09045120) 0 + +Class QNdefNfcIconRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcIconRecord (0x0x7f4a08fa9888) 0 + QNdefRecord (0x0x7f4a09045180) 0 + +Class QNdefNfcSmartPosterRecord + size=16 align=8 + base size=16 base align=8 +QNdefNfcSmartPosterRecord (0x0x7f4a08fa98f0) 0 + QNdefRecord (0x0x7f4a090451e0) 0 + +Class QNearFieldTarget::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldTarget::QPrivateSignal (0x0x7f4a09045300) 0 empty + +Class QNearFieldTarget::RequestId + size=8 align=8 + base size=8 base align=8 +QNearFieldTarget::RequestId (0x0x7f4a09045360) 0 + +Vtable for QNearFieldTarget +QNearFieldTarget::_ZTV16QNearFieldTarget: 25u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QNearFieldTarget) +16 (int (*)(...))QNearFieldTarget::metaObject +24 (int (*)(...))QNearFieldTarget::qt_metacast +32 (int (*)(...))QNearFieldTarget::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 (*)(...))QNearFieldTarget::url +128 (int (*)(...))__cxa_pure_virtual +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))QNearFieldTarget::hasNdefMessage +152 (int (*)(...))QNearFieldTarget::readNdefMessages +160 (int (*)(...))QNearFieldTarget::writeNdefMessages +168 (int (*)(...))QNearFieldTarget::sendCommand +176 (int (*)(...))QNearFieldTarget::sendCommands +184 (int (*)(...))QNearFieldTarget::waitForRequestCompleted +192 (int (*)(...))QNearFieldTarget::handleResponse + +Class QNearFieldTarget + size=24 align=8 + base size=24 base align=8 +QNearFieldTarget (0x0x7f4a08fa9958) 0 + vptr=((& QNearFieldTarget::_ZTV16QNearFieldTarget) + 16u) + QObject (0x0x7f4a090452a0) 0 + primary-for QNearFieldTarget (0x0x7f4a08fa9958) + +Class QNearFieldManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldManager::QPrivateSignal (0x0x7f4a09045720) 0 empty + +Vtable for QNearFieldManager +QNearFieldManager::_ZTV17QNearFieldManager: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QNearFieldManager) +16 (int (*)(...))QNearFieldManager::metaObject +24 (int (*)(...))QNearFieldManager::qt_metacast +32 (int (*)(...))QNearFieldManager::qt_metacall +40 (int (*)(...))QNearFieldManager::~QNearFieldManager +48 (int (*)(...))QNearFieldManager::~QNearFieldManager +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 QNearFieldManager + size=24 align=8 + base size=24 base align=8 +QNearFieldManager (0x0x7f4a08fa9a90) 0 + vptr=((& QNearFieldManager::_ZTV17QNearFieldManager) + 16u) + QObject (0x0x7f4a090456c0) 0 + primary-for QNearFieldManager (0x0x7f4a08fa9a90) + +Class QNearFieldShareManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldShareManager::QPrivateSignal (0x0x7f4a09045960) 0 empty + +Vtable for QNearFieldShareManager +QNearFieldShareManager::_ZTV22QNearFieldShareManager: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI22QNearFieldShareManager) +16 (int (*)(...))QNearFieldShareManager::metaObject +24 (int (*)(...))QNearFieldShareManager::qt_metacast +32 (int (*)(...))QNearFieldShareManager::qt_metacall +40 (int (*)(...))QNearFieldShareManager::~QNearFieldShareManager +48 (int (*)(...))QNearFieldShareManager::~QNearFieldShareManager +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 QNearFieldShareManager + size=24 align=8 + base size=24 base align=8 +QNearFieldShareManager (0x0x7f4a08fa9c30) 0 + vptr=((& QNearFieldShareManager::_ZTV22QNearFieldShareManager) + 16u) + QObject (0x0x7f4a09045900) 0 + primary-for QNearFieldShareManager (0x0x7f4a08fa9c30) + +Class QNearFieldShareTarget::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldShareTarget::QPrivateSignal (0x0x7f4a09045c60) 0 empty + +Vtable for QNearFieldShareTarget +QNearFieldShareTarget::_ZTV21QNearFieldShareTarget: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QNearFieldShareTarget) +16 (int (*)(...))QNearFieldShareTarget::metaObject +24 (int (*)(...))QNearFieldShareTarget::qt_metacast +32 (int (*)(...))QNearFieldShareTarget::qt_metacall +40 (int (*)(...))QNearFieldShareTarget::~QNearFieldShareTarget +48 (int (*)(...))QNearFieldShareTarget::~QNearFieldShareTarget +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 QNearFieldShareTarget + size=24 align=8 + base size=24 base align=8 +QNearFieldShareTarget (0x0x7f4a08fa9d68) 0 + vptr=((& QNearFieldShareTarget::_ZTV21QNearFieldShareTarget) + 16u) + QObject (0x0x7f4a09045c00) 0 + primary-for QNearFieldShareTarget (0x0x7f4a08fa9d68) + +Class QQmlNdefRecord::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QQmlNdefRecord::QPrivateSignal (0x0x7f4a09045d20) 0 empty + +Vtable for QQmlNdefRecord +QQmlNdefRecord::_ZTV14QQmlNdefRecord: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI14QQmlNdefRecord) +16 (int (*)(...))QQmlNdefRecord::metaObject +24 (int (*)(...))QQmlNdefRecord::qt_metacast +32 (int (*)(...))QQmlNdefRecord::qt_metacall +40 (int (*)(...))QQmlNdefRecord::~QQmlNdefRecord +48 (int (*)(...))QQmlNdefRecord::~QQmlNdefRecord +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 QQmlNdefRecord + size=24 align=8 + base size=24 base align=8 +QQmlNdefRecord (0x0x7f4a08fa9dd0) 0 + vptr=((& QQmlNdefRecord::_ZTV14QQmlNdefRecord) + 16u) + QObject (0x0x7f4a09045cc0) 0 + primary-for QQmlNdefRecord (0x0x7f4a08fa9dd0) + diff --git a/tests/auto/bic/data/QtNfc.5.12.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtNfc.5.12.0.linux-gcc-amd64.txt new file mode 100644 index 0000000..05dc407 --- /dev/null +++ b/tests/auto/bic/data/QtNfc.5.12.0.linux-gcc-amd64.txt @@ -0,0 +1,4819 @@ +Class std::__failure_type + size=1 align=1 + base size=0 base align=1 +std::__failure_type (0x0x7f0532c1a5a0) 0 empty + +Class std::__do_is_destructible_impl + size=1 align=1 + base size=0 base align=1 +std::__do_is_destructible_impl (0x0x7f0532c70d20) 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 (0x0x7f0532c70f60) 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 (0x0x7f05308181e0) 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 (0x0x7f0530818420) 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 (0x0x7f05308185a0) 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 (0x0x7f0530818960) 0 empty + +Class std::__do_common_type_impl + size=1 align=1 + base size=0 base align=1 +std::__do_common_type_impl (0x0x7f05308d4120) 0 empty + +Class std::__do_member_type_wrapper + size=1 align=1 + base size=0 base align=1 +std::__do_member_type_wrapper (0x0x7f05308d41e0) 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 (0x0x7f05308d4540) 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 (0x0x7f05308d4600) 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 (0x0x7f05308d46c0) 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 (0x0x7f05308d4780) 0 empty + +Class std::__result_of_other_impl + size=1 align=1 + base size=0 base align=1 +std::__result_of_other_impl (0x0x7f05308d4a20) 0 empty + +Class std::piecewise_construct_t + size=1 align=1 + base size=0 base align=1 +std::piecewise_construct_t (0x0x7f05308d4c00) 0 empty + +Class std::__true_type + size=1 align=1 + base size=0 base align=1 +std::__true_type (0x0x7f053095b0c0) 0 empty + +Class std::__false_type + size=1 align=1 + base size=0 base align=1 +std::__false_type (0x0x7f053095b120) 0 empty + +Class std::input_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::input_iterator_tag (0x0x7f053098fd80) 0 empty + +Class std::output_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::output_iterator_tag (0x0x7f053098fde0) 0 empty + +Class std::forward_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::forward_iterator_tag (0x0x7f0530885bc8) 0 empty + std::input_iterator_tag (0x0x7f053098fe40) 0 empty + +Class std::bidirectional_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::bidirectional_iterator_tag (0x0x7f0530885c30) 0 empty + std::forward_iterator_tag (0x0x7f0530885c98) 0 empty + std::input_iterator_tag (0x0x7f053098fea0) 0 empty + +Class std::random_access_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::random_access_iterator_tag (0x0x7f0530885d00) 0 empty + std::bidirectional_iterator_tag (0x0x7f0530885d68) 0 empty + std::forward_iterator_tag (0x0x7f0530885dd0) 0 empty + std::input_iterator_tag (0x0x7f053098ff00) 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 (0x0x7f05309bcba0) 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 (0x0x7f05309bcc00) 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 (0x0x7f05309bcc60) 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 (0x0x7f05309bccc0) 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 (0x0x7f05309bcd20) 0 empty + +Class wait + size=4 align=4 + base size=4 base align=4 +wait (0x0x7f0530695840) 0 + +Class __locale_struct + size=232 align=8 + base size=232 base align=8 +__locale_struct (0x0x7f0530695a80) 0 + +Class timespec + size=16 align=8 + base size=16 base align=8 +timespec (0x0x7f0530695b40) 0 + +Class timeval + size=16 align=8 + base size=16 base align=8 +timeval (0x0x7f0530695ba0) 0 + +Class pthread_attr_t + size=56 align=8 + base size=56 base align=8 +pthread_attr_t (0x0x7f0530695c60) 0 + +Class __pthread_internal_list + size=16 align=8 + base size=16 base align=8 +__pthread_internal_list (0x0x7f0530695cc0) 0 + +Class random_data + size=48 align=8 + base size=48 base align=8 +random_data (0x0x7f0530734180) 0 + +Class drand48_data + size=24 align=8 + base size=24 base align=8 +drand48_data (0x0x7f05307341e0) 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 (0x0x7f0530734240) 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 (0x0x7f05309d5340) 0 nearly-empty + vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16u) + std::exception (0x0x7f05307342a0) 0 nearly-empty + primary-for std::bad_exception (0x0x7f05309d5340) + +Class std::__exception_ptr::exception_ptr + size=8 align=8 + base size=8 base align=8 +std::__exception_ptr::exception_ptr (0x0x7f0530734300) 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 (0x0x7f0530734360) 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 (0x0x7f05309d5548) 0 nearly-empty + vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16u) + std::exception (0x0x7f0530734780) 0 nearly-empty + primary-for std::bad_alloc (0x0x7f05309d5548) + +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 (0x0x7f05309d55b0) 0 nearly-empty + vptr=((& std::bad_array_new_length::_ZTVSt20bad_array_new_length) + 16u) + std::bad_alloc (0x0x7f05309d5618) 0 nearly-empty + primary-for std::bad_array_new_length (0x0x7f05309d55b0) + std::exception (0x0x7f05307347e0) 0 nearly-empty + primary-for std::bad_alloc (0x0x7f05309d5618) + +Class std::nothrow_t + size=1 align=1 + base size=0 base align=1 +std::nothrow_t (0x0x7f0530734840) 0 empty + +Class __exception + size=40 align=8 + base size=40 base align=8 +__exception (0x0x7f05304b0480) 0 + +Class lconv + size=96 align=8 + base size=96 base align=8 +lconv (0x0x7f05302d0180) 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 (0x0x7f05302d01e0) 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 (0x0x7f05303890c0) 0 + +Class __sched_param + size=4 align=4 + base size=4 base align=4 +__sched_param (0x0x7f0530389120) 0 + +Class timex + size=208 align=8 + base size=208 base align=8 +timex (0x0x7f05303891e0) 0 + +Class tm + size=56 align=8 + base size=56 base align=8 +tm (0x0x7f0530389240) 0 + +Class itimerspec + size=32 align=8 + base size=32 base align=8 +itimerspec (0x0x7f05303892a0) 0 + +Class _pthread_cleanup_buffer + size=32 align=8 + base size=32 base align=8 +_pthread_cleanup_buffer (0x0x7f0530389300) 0 + +Class __pthread_cleanup_frame + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_frame (0x0x7f0530389420) 0 + +Class __pthread_cleanup_class + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_class (0x0x7f0530389480) 0 + +Class _IO_marker + size=24 align=8 + base size=24 base align=8 +_IO_marker (0x0x7f05303898a0) 0 + +Class _IO_FILE + size=216 align=8 + base size=216 base align=8 +_IO_FILE (0x0x7f0530389900) 0 + +Class std::_Hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Hash_impl (0x0x7f052fea9120) 0 empty + +Class std::_Fnv_hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Fnv_hash_impl (0x0x7f052fea9180) 0 empty + +Class std::__numeric_limits_base + size=1 align=1 + base size=0 base align=1 +std::__numeric_limits_base (0x0x7f052ff85120) 0 empty + +Class std::_Bit_reference + size=16 align=8 + base size=16 base align=8 +std::_Bit_reference (0x0x7f052ff85f00) 0 + +Class std::_Bit_iterator_base + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator_base (0x0x7f052fc58208) 0 + std::iterator (0x0x7f052fdab000) 0 empty + +Class std::_Bit_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator (0x0x7f052fc58270) 0 + std::_Bit_iterator_base (0x0x7f052fc582d8) 0 + std::iterator (0x0x7f052fdab060) 0 empty + +Class std::_Bit_const_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_const_iterator (0x0x7f052fc58340) 0 + std::_Bit_iterator_base (0x0x7f052fc583a8) 0 + std::iterator (0x0x7f052fdab0c0) 0 empty + +Class std::random_device + size=5000 align=8 + base size=5000 base align=8 +std::random_device (0x0x7f052fdabea0) 0 + +Class std::bernoulli_distribution::param_type + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution::param_type (0x0x7f052fb80c60) 0 + +Class std::bernoulli_distribution + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution (0x0x7f052fb80c00) 0 + +Class std::seed_seq + size=24 align=8 + base size=24 base align=8 +std::seed_seq (0x0x7f052f8cfc00) 0 + +Class qIsNull(double)::U + size=8 align=8 + base size=8 base align=8 +qIsNull(double)::U (0x0x7f052e544720) 0 + +Class qIsNull(float)::U + size=4 align=4 + base size=4 base align=4 +qIsNull(float)::U (0x0x7f052e544780) 0 + +Class QSysInfo + size=1 align=1 + base size=0 base align=1 +QSysInfo (0x0x7f052e226240) 0 empty + +Class QMessageLogContext + size=32 align=8 + base size=32 base align=8 +QMessageLogContext (0x0x7f052e2262a0) 0 + +Class QMessageLogger + size=32 align=8 + base size=32 base align=8 +QMessageLogger (0x0x7f052e226300) 0 + +Class QFlag + size=4 align=4 + base size=4 base align=4 +QFlag (0x0x7f052e226360) 0 + +Class QIncompatibleFlag + size=4 align=4 + base size=4 base align=4 +QIncompatibleFlag (0x0x7f052e226600) 0 + +Class std::__atomic_flag_base + size=1 align=1 + base size=1 base align=1 +std::__atomic_flag_base (0x0x7f052e226b40) 0 + +Class std::atomic_flag + size=1 align=1 + base size=1 base align=1 +std::atomic_flag (0x0x7f052e273270) 0 + std::__atomic_flag_base (0x0x7f052e226ba0) 0 + +Class QAtomicInt + size=4 align=4 + base size=4 base align=4 +QAtomicInt (0x0x7f052e2739c0) 0 + QAtomicInteger (0x0x7f052e273a28) 0 + QBasicAtomicInteger (0x0x7f052e1de300) 0 + +Class QInternal + size=1 align=1 + base size=0 base align=1 +QInternal (0x0x7f052dd288a0) 0 empty + +Class QtPrivate::QSlotObjectBase + size=16 align=8 + base size=16 base align=8 +QtPrivate::QSlotObjectBase (0x0x7f052dabba80) 0 + +Class QGenericArgument + size=16 align=8 + base size=16 base align=8 +QGenericArgument (0x0x7f052dabbba0) 0 + +Class QGenericReturnArgument + size=16 align=8 + base size=16 base align=8 +QGenericReturnArgument (0x0x7f052dab2618) 0 + QGenericArgument (0x0x7f052dabbc00) 0 + +Class QMetaObject + size=48 align=8 + base size=48 base align=8 +QMetaObject (0x0x7f052dabbd80) 0 + +Class QMetaObject::Connection + size=8 align=8 + base size=8 base align=8 +QMetaObject::Connection (0x0x7f052dabbe40) 0 + +Class QLatin1Char + size=1 align=1 + base size=1 base align=1 +QLatin1Char (0x0x7f052dbb3ea0) 0 + +Class QChar + size=2 align=2 + base size=2 base align=2 +QChar (0x0x7f052dbb3f00) 0 + +Class QtPrivate::RefCount + size=4 align=4 + base size=4 base align=4 +QtPrivate::RefCount (0x0x7f052d8631e0) 0 + +Class QArrayData + size=24 align=8 + base size=24 base align=8 +QArrayData (0x0x7f052d863240) 0 + +Class QtPrivate::QContainerImplHelper + size=1 align=1 + base size=0 base align=1 +QtPrivate::QContainerImplHelper (0x0x7f052d8635a0) 0 empty + +Class std::locale + size=8 align=8 + base size=8 base align=8 +std::locale (0x0x7f052d863600) 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 (0x0x7f052d863660) 0 + vptr=((& std::locale::facet::_ZTVNSt6locale5facetE) + 16u) + +Class std::locale::id + size=8 align=8 + base size=8 base align=8 +std::locale::id (0x0x7f052d8636c0) 0 + +Class std::locale::_Impl + size=40 align=8 + base size=40 base align=8 +std::locale::_Impl (0x0x7f052d863720) 0 + +Class std::__cow_string + size=8 align=8 + base size=8 base align=8 +std::__cow_string (0x0x7f052d863ae0) 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 (0x0x7f052d866c30) 0 + vptr=((& std::logic_error::_ZTVSt11logic_error) + 16u) + std::exception (0x0x7f052d863ba0) 0 nearly-empty + primary-for std::logic_error (0x0x7f052d866c30) + +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 (0x0x7f052d866c98) 0 + vptr=((& std::domain_error::_ZTVSt12domain_error) + 16u) + std::logic_error (0x0x7f052d866d00) 0 + primary-for std::domain_error (0x0x7f052d866c98) + std::exception (0x0x7f052d863c00) 0 nearly-empty + primary-for std::logic_error (0x0x7f052d866d00) + +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 (0x0x7f052d866d68) 0 + vptr=((& std::invalid_argument::_ZTVSt16invalid_argument) + 16u) + std::logic_error (0x0x7f052d866dd0) 0 + primary-for std::invalid_argument (0x0x7f052d866d68) + std::exception (0x0x7f052d863c60) 0 nearly-empty + primary-for std::logic_error (0x0x7f052d866dd0) + +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 (0x0x7f052d866e38) 0 + vptr=((& std::length_error::_ZTVSt12length_error) + 16u) + std::logic_error (0x0x7f052d866ea0) 0 + primary-for std::length_error (0x0x7f052d866e38) + std::exception (0x0x7f052d863cc0) 0 nearly-empty + primary-for std::logic_error (0x0x7f052d866ea0) + +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 (0x0x7f052d866f08) 0 + vptr=((& std::out_of_range::_ZTVSt12out_of_range) + 16u) + std::logic_error (0x0x7f052d866f70) 0 + primary-for std::out_of_range (0x0x7f052d866f08) + std::exception (0x0x7f052d863d20) 0 nearly-empty + primary-for std::logic_error (0x0x7f052d866f70) + +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 (0x0x7f052d866958) 0 + vptr=((& std::runtime_error::_ZTVSt13runtime_error) + 16u) + std::exception (0x0x7f052d863d80) 0 nearly-empty + primary-for std::runtime_error (0x0x7f052d866958) + +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 (0x0x7f052d866a28) 0 + vptr=((& std::range_error::_ZTVSt11range_error) + 16u) + std::runtime_error (0x0x7f052d99c000) 0 + primary-for std::range_error (0x0x7f052d866a28) + std::exception (0x0x7f052d863de0) 0 nearly-empty + primary-for std::runtime_error (0x0x7f052d99c000) + +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 (0x0x7f052d99c068) 0 + vptr=((& std::overflow_error::_ZTVSt14overflow_error) + 16u) + std::runtime_error (0x0x7f052d99c0d0) 0 + primary-for std::overflow_error (0x0x7f052d99c068) + std::exception (0x0x7f052d863e40) 0 nearly-empty + primary-for std::runtime_error (0x0x7f052d99c0d0) + +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 (0x0x7f052d99c138) 0 + vptr=((& std::underflow_error::_ZTVSt15underflow_error) + 16u) + std::runtime_error (0x0x7f052d99c1a0) 0 + primary-for std::underflow_error (0x0x7f052d99c138) + std::exception (0x0x7f052d863ea0) 0 nearly-empty + primary-for std::runtime_error (0x0x7f052d99c1a0) + +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 (0x0x7f052d9aa060) 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 (0x0x7f052d9aa2a0) 0 + +Class std::error_condition + size=16 align=8 + base size=16 base align=8 +std::error_condition (0x0x7f052d9aa420) 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 (0x0x7f052d99c680) 0 + vptr=((& std::system_error::_ZTVSt12system_error) + 16u) + std::runtime_error (0x0x7f052d99c6e8) 0 + primary-for std::system_error (0x0x7f052d99c680) + std::exception (0x0x7f052d9aa660) 0 nearly-empty + primary-for std::runtime_error (0x0x7f052d99c6e8) + +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 (0x0x7f052d60d2d8) 0 + vptr=((& std::ios_base::failure::_ZTVNSt8ios_base7failureB5cxx11E) + 16u) + std::system_error (0x0x7f052d60d340) 0 + primary-for std::ios_base::failure (0x0x7f052d60d2d8) + std::runtime_error (0x0x7f052d60d3a8) 0 + primary-for std::system_error (0x0x7f052d60d340) + std::exception (0x0x7f052d9aa960) 0 nearly-empty + primary-for std::runtime_error (0x0x7f052d60d3a8) + +Class std::ios_base::_Callback_list + size=24 align=8 + base size=24 base align=8 +std::ios_base::_Callback_list (0x0x7f052d9aa9c0) 0 + +Class std::ios_base::_Words + size=16 align=8 + base size=16 base align=8 +std::ios_base::_Words (0x0x7f052d9aaa20) 0 + +Class std::ios_base::Init + size=1 align=1 + base size=0 base align=1 +std::ios_base::Init (0x0x7f052d9aaa80) 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 (0x0x7f052d9aa900) 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 (0x0x7f052d6e1240) 0 empty + +Class std::__num_base + size=1 align=1 + base size=0 base align=1 +std::__num_base (0x0x7f052d6e1900) 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 (0x0x7f052d270ea0 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 (0x0x7f052d270f70 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 (0x0x7f052d270af8 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 (0x0x7f052d31f068 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 (0x0x7f052d320180) 0 + +Class QByteArray + size=8 align=8 + base size=8 base align=8 +QByteArray (0x0x7f052d3201e0) 0 + +Class QByteRef + size=16 align=8 + base size=12 base align=8 +QByteRef (0x0x7f052d022540) 0 + +Class QStringDataPtr + size=8 align=8 + base size=8 base align=8 +QStringDataPtr (0x0x7f052d0228a0) 0 + +Class QStringView + size=16 align=8 + base size=16 base align=8 +QStringView (0x0x7f052d022d20) 0 + +Class QLatin1String + size=16 align=8 + base size=16 base align=8 +QLatin1String (0x0x7f052d158ba0) 0 + +Class QString::Null + size=1 align=1 + base size=0 base align=1 +QString::Null (0x0x7f052d1ea240) 0 empty + +Class QString + size=8 align=8 + base size=8 base align=8 +QString (0x0x7f052d1ea1e0) 0 + +Class QCharRef + size=16 align=8 + base size=12 base align=8 +QCharRef (0x0x7f052cf94300) 0 + +Class QStringRef + size=16 align=8 + base size=16 base align=8 +QStringRef (0x0x7f052cf94f00) 0 + +Class QtPrivate::QHashCombine + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombine (0x0x7f052cd9aba0) 0 empty + +Class QtPrivate::QHashCombineCommutative + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombineCommutative (0x0x7f052cd9ac00) 0 empty + +Class std::__detail::_List_node_base + size=16 align=8 + base size=16 base align=8 +std::__detail::_List_node_base (0x0x7f052cd9ac60) 0 + +Class QListData::NotArrayCompatibleLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotArrayCompatibleLayout (0x0x7f052cbf7060) 0 empty + +Class QListData::NotIndirectLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotIndirectLayout (0x0x7f052cbf70c0) 0 empty + +Class QListData::ArrayCompatibleLayout + size=1 align=1 + base size=1 base align=1 +QListData::ArrayCompatibleLayout (0x0x7f052cd9fc30) 0 empty + QListData::NotIndirectLayout (0x0x7f052cbf7120) 0 empty + +Class QListData::InlineWithPaddingLayout + size=1 align=1 + base size=1 base align=1 +QListData::InlineWithPaddingLayout (0x0x7f052cbf53f0) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7f052cbf7180) 0 empty + QListData::NotIndirectLayout (0x0x7f052cbf71e0) 0 empty + +Class QListData::IndirectLayout + size=1 align=1 + base size=1 base align=1 +QListData::IndirectLayout (0x0x7f052cd9fc98) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7f052cbf7240) 0 empty + +Class QListData::Data + size=24 align=8 + base size=24 base align=8 +QListData::Data (0x0x7f052cbf72a0) 0 + +Class QListData + size=8 align=8 + base size=8 base align=8 +QListData (0x0x7f052cbf7000) 0 + +Class QRegExp + size=8 align=8 + base size=8 base align=8 +QRegExp (0x0x7f052cbf7720) 0 + +Class QStringMatcher::Data + size=272 align=8 + base size=272 base align=8 +QStringMatcher::Data (0x0x7f052c9a7960) 0 + +Class QStringMatcher + size=1048 align=8 + base size=1048 base align=8 +QStringMatcher (0x0x7f052c9a7900) 0 + +Class QStringList + size=8 align=8 + base size=8 base align=8 +QStringList (0x0x7f052c9b16e8) 0 + QList (0x0x7f052c9b1750) 0 + QListSpecialMethods (0x0x7f052c9a7b40) 0 empty + +Class QScopedPointerPodDeleter + size=1 align=1 + base size=0 base align=1 +QScopedPointerPodDeleter (0x0x7f052c9a7f60) 0 empty + +Class std::_Rb_tree_node_base + size=32 align=8 + base size=32 base align=8 +std::_Rb_tree_node_base (0x0x7f052c64fb40) 0 + +Class std::allocator_arg_t + size=1 align=1 + base size=0 base align=1 +std::allocator_arg_t (0x0x7f052c43d1e0) 0 empty + +Class std::__uses_alloc_base + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc_base (0x0x7f052c43d360) 0 empty + +Class std::__uses_alloc0::_Sink + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc0::_Sink (0x0x7f052c43d420) 0 empty + +Class std::__uses_alloc0 + size=1 align=1 + base size=1 base align=1 +std::__uses_alloc0 (0x0x7f052c9b1bc8) 0 + std::__uses_alloc_base (0x0x7f052c43d3c0) 0 empty + +Class std::_Swallow_assign + size=1 align=1 + base size=0 base align=1 +std::_Swallow_assign (0x0x7f052c557480) 0 empty + +Class QtPrivate::AbstractDebugStreamFunction + size=16 align=8 + base size=16 base align=8 +QtPrivate::AbstractDebugStreamFunction (0x0x7f052c5576c0) 0 + +Class QtPrivate::AbstractComparatorFunction + size=24 align=8 + base size=24 base align=8 +QtPrivate::AbstractComparatorFunction (0x0x7f052c557780) 0 + +Class QtPrivate::AbstractConverterFunction + size=8 align=8 + base size=8 base align=8 +QtPrivate::AbstractConverterFunction (0x0x7f052c5578a0) 0 + +Class QMetaType + size=80 align=8 + base size=80 base align=8 +QMetaType (0x0x7f052c557a20) 0 + +Class QtMetaTypePrivate::VariantData + size=24 align=8 + base size=20 base align=8 +QtMetaTypePrivate::VariantData (0x0x7f052c557e40) 0 + +Class QtMetaTypePrivate::VectorBoolElements + size=1 align=1 + base size=0 base align=1 +QtMetaTypePrivate::VectorBoolElements (0x0x7f052c557f60) 0 empty + +Class QtMetaTypePrivate::QSequentialIterableImpl + size=104 align=8 + base size=104 base align=8 +QtMetaTypePrivate::QSequentialIterableImpl (0x0x7f052c2b1900) 0 + +Class QtMetaTypePrivate::QAssociativeIterableImpl + size=112 align=8 + base size=112 base align=8 +QtMetaTypePrivate::QAssociativeIterableImpl (0x0x7f052c2b1d20) 0 + +Class QtMetaTypePrivate::QPairVariantInterfaceImpl + size=40 align=8 + base size=40 base align=8 +QtMetaTypePrivate::QPairVariantInterfaceImpl (0x0x7f052c3a2060) 0 + +Class std::chrono::_V2::system_clock + size=1 align=1 + base size=0 base align=1 +std::chrono::_V2::system_clock (0x0x7f052c1c3a20) 0 empty + +Class std::chrono::_V2::steady_clock + size=1 align=1 + base size=0 base align=1 +std::chrono::_V2::steady_clock (0x0x7f052bf318a0) 0 empty + +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 (0x0x7f052bf31900) 0 + vptr=((& QObjectData::_ZTV11QObjectData) + 16u) + +Class QObject::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObject::QPrivateSignal (0x0x7f052bf31ae0) 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 (0x0x7f052bf31a80) 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 (0x0x7f052bfe2d80) 0 nearly-empty + vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16u) + +Class QSignalBlocker + size=16 align=8 + base size=10 base align=8 +QSignalBlocker (0x0x7f052bfe2de0) 0 + +Class QAbstractAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractAnimation::QPrivateSignal (0x0x7f052bfe2ea0) 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 (0x0x7f052bc28270) 0 + vptr=((& QAbstractAnimation::_ZTV18QAbstractAnimation) + 16u) + QObject (0x0x7f052bfe2e40) 0 + primary-for QAbstractAnimation (0x0x7f052bc28270) + +Class QAnimationDriver::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationDriver::QPrivateSignal (0x0x7f052bfe2f60) 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 (0x0x7f052bc282d8) 0 + vptr=((& QAnimationDriver::_ZTV16QAnimationDriver) + 16u) + QObject (0x0x7f052bfe2f00) 0 + primary-for QAnimationDriver (0x0x7f052bc282d8) + +Class QEventLoop::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventLoop::QPrivateSignal (0x0x7f052bc79060) 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 (0x0x7f052bc28340) 0 + vptr=((& QEventLoop::_ZTV10QEventLoop) + 16u) + QObject (0x0x7f052bc79000) 0 + primary-for QEventLoop (0x0x7f052bc28340) + +Class QEventLoopLocker + size=8 align=8 + base size=8 base align=8 +QEventLoopLocker (0x0x7f052bc79240) 0 + +Class QAbstractEventDispatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractEventDispatcher::QPrivateSignal (0x0x7f052bc79300) 0 empty + +Class QAbstractEventDispatcher::TimerInfo + size=12 align=4 + base size=12 base align=4 +QAbstractEventDispatcher::TimerInfo (0x0x7f052bc79360) 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 (0x0x7f052bc28478) 0 + vptr=((& QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher) + 16u) + QObject (0x0x7f052bc792a0) 0 + primary-for QAbstractEventDispatcher (0x0x7f052bc28478) + +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 (0x0x7f052bc79600) 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 (0x0x7f052bc28680) 0 nearly-empty + vptr=((& std::bad_cast::_ZTVSt8bad_cast) + 16u) + std::exception (0x0x7f052bc79660) 0 nearly-empty + primary-for std::bad_cast (0x0x7f052bc28680) + +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 (0x0x7f052bc286e8) 0 nearly-empty + vptr=((& std::bad_typeid::_ZTVSt10bad_typeid) + 16u) + std::exception (0x0x7f052bc796c0) 0 nearly-empty + primary-for std::bad_typeid (0x0x7f052bc286e8) + +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 (0x0x7f052bd9e958) 0 nearly-empty + vptr=((& std::bad_function_call::_ZTVSt17bad_function_call) + 16u) + std::exception (0x0x7f052ba21780) 0 nearly-empty + primary-for std::bad_function_call (0x0x7f052bd9e958) + +Class std::_Nocopy_types + size=16 align=8 + base size=16 base align=8 +std::_Nocopy_types (0x0x7f052ba21840) 0 + +Class std::_Any_data + size=16 align=8 + base size=16 base align=8 +std::_Any_data (0x0x7f052ba218a0) 0 + +Class std::_Function_base + size=24 align=8 + base size=24 base align=8 +std::_Function_base (0x0x7f052ba219c0) 0 + +Class QMapNodeBase + size=24 align=8 + base size=24 base align=8 +QMapNodeBase (0x0x7f052ba21ea0) 0 + +Class QMapDataBase + size=40 align=8 + base size=40 base align=8 +QMapDataBase (0x0x7f052baff420) 0 + +Class QHashData::Node + size=16 align=8 + base size=16 base align=8 +QHashData::Node (0x0x7f052baff7e0) 0 + +Class QHashData + size=48 align=8 + base size=44 base align=8 +QHashData (0x0x7f052baff780) 0 + +Class QHashDummyValue + size=1 align=1 + base size=0 base align=1 +QHashDummyValue (0x0x7f052baff840) 0 empty + +Class QVariant::PrivateShared + size=16 align=8 + base size=12 base align=8 +QVariant::PrivateShared (0x0x7f052b913120) 0 + +Class QVariant::Private::Data + size=8 align=8 + base size=8 base align=8 +QVariant::Private::Data (0x0x7f052b9131e0) 0 + +Class QVariant::Private + size=16 align=8 + base size=12 base align=8 +QVariant::Private (0x0x7f052b913180) 0 + +Class QVariant::Handler + size=72 align=8 + base size=72 base align=8 +QVariant::Handler (0x0x7f052b913240) 0 + +Class QVariant + size=16 align=8 + base size=16 base align=8 +QVariant (0x0x7f052b9130c0) 0 + +Class QVariantComparisonHelper + size=8 align=8 + base size=8 base align=8 +QVariantComparisonHelper (0x0x7f052b9e4d20) 0 + +Class QSequentialIterable::const_iterator + size=112 align=8 + base size=112 base align=8 +QSequentialIterable::const_iterator (0x0x7f052b68b3c0) 0 + +Class QSequentialIterable + size=104 align=8 + base size=104 base align=8 +QSequentialIterable (0x0x7f052b68b360) 0 + +Class QAssociativeIterable::const_iterator + size=120 align=8 + base size=120 base align=8 +QAssociativeIterable::const_iterator (0x0x7f052b68b480) 0 + +Class QAssociativeIterable + size=112 align=8 + base size=112 base align=8 +QAssociativeIterable (0x0x7f052b68b420) 0 + +Class QModelIndex + size=24 align=8 + base size=24 base align=8 +QModelIndex (0x0x7f052b7ae780) 0 + +Class QPersistentModelIndex + size=8 align=8 + base size=8 base align=8 +QPersistentModelIndex (0x0x7f052b7aee40) 0 + +Class QAbstractItemModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractItemModel::QPrivateSignal (0x0x7f052b5985a0) 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 (0x0x7f052b59d6e8) 0 + vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16u) + QObject (0x0x7f052b598540) 0 + primary-for QAbstractItemModel (0x0x7f052b59d6e8) + +Class QAbstractTableModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTableModel::QPrivateSignal (0x0x7f052b598e40) 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 (0x0x7f052b59ddd0) 0 + vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16u) + QAbstractItemModel (0x0x7f052b59de38) 0 + primary-for QAbstractTableModel (0x0x7f052b59ddd0) + QObject (0x0x7f052b598de0) 0 + primary-for QAbstractItemModel (0x0x7f052b59de38) + +Class QAbstractListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractListModel::QPrivateSignal (0x0x7f052b598f00) 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 (0x0x7f052b59dea0) 0 + vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16u) + QAbstractItemModel (0x0x7f052b59df08) 0 + primary-for QAbstractListModel (0x0x7f052b59dea0) + QObject (0x0x7f052b598ea0) 0 + primary-for QAbstractItemModel (0x0x7f052b59df08) + +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 (0x0x7f052b2aa1e0) 0 + vptr=((& QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter) + 16u) + +Class QAbstractProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractProxyModel::QPrivateSignal (0x0x7f052b2aa2a0) 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 (0x0x7f052b2ae068) 0 + vptr=((& QAbstractProxyModel::_ZTV19QAbstractProxyModel) + 16u) + QAbstractItemModel (0x0x7f052b2ae0d0) 0 + primary-for QAbstractProxyModel (0x0x7f052b2ae068) + QObject (0x0x7f052b2aa240) 0 + primary-for QAbstractItemModel (0x0x7f052b2ae0d0) + +Class QAbstractState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractState::QPrivateSignal (0x0x7f052b2aa360) 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 (0x0x7f052b2ae138) 0 + vptr=((& QAbstractState::_ZTV14QAbstractState) + 16u) + QObject (0x0x7f052b2aa300) 0 + primary-for QAbstractState (0x0x7f052b2ae138) + +Class QAbstractTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTransition::QPrivateSignal (0x0x7f052b2aa420) 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 (0x0x7f052b2ae1a0) 0 + vptr=((& QAbstractTransition::_ZTV19QAbstractTransition) + 16u) + QObject (0x0x7f052b2aa3c0) 0 + primary-for QAbstractTransition (0x0x7f052b2ae1a0) + +Class QAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationGroup::QPrivateSignal (0x0x7f052b2aa4e0) 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 (0x0x7f052b2ae208) 0 + vptr=((& QAnimationGroup::_ZTV15QAnimationGroup) + 16u) + QAbstractAnimation (0x0x7f052b2ae270) 0 + primary-for QAnimationGroup (0x0x7f052b2ae208) + QObject (0x0x7f052b2aa480) 0 + primary-for QAbstractAnimation (0x0x7f052b2ae270) + +Class QBasicTimer + size=4 align=4 + base size=4 base align=4 +QBasicTimer (0x0x7f052b368240) 0 + +Class QBitArray + size=8 align=8 + base size=8 base align=8 +QBitArray (0x0x7f052b3684e0) 0 + +Class QBitRef + size=16 align=8 + base size=12 base align=8 +QBitRef (0x0x7f052b3685a0) 0 + +Class QIODevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIODevice::QPrivateSignal (0x0x7f052b3688a0) 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 (0x0x7f052b2ae8f0) 0 + vptr=((& QIODevice::_ZTV9QIODevice) + 16u) + QObject (0x0x7f052b368840) 0 + primary-for QIODevice (0x0x7f052b2ae8f0) + +Class QBuffer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBuffer::QPrivateSignal (0x0x7f052b368ae0) 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 (0x0x7f052b2aea28) 0 + vptr=((& QBuffer::_ZTV7QBuffer) + 16u) + QIODevice (0x0x7f052b2aea90) 0 + primary-for QBuffer (0x0x7f052b2aea28) + QObject (0x0x7f052b368a80) 0 + primary-for QIODevice (0x0x7f052b2aea90) + +Class QByteArrayMatcher::Data + size=272 align=8 + base size=272 base align=8 +QByteArrayMatcher::Data (0x0x7f052b368ba0) 0 + +Class QByteArrayMatcher + size=1040 align=8 + base size=1040 base align=8 +QByteArrayMatcher (0x0x7f052b368b40) 0 + +Class QStaticByteArrayMatcherBase::Skiptable + size=256 align=1 + base size=256 base align=1 +QStaticByteArrayMatcherBase::Skiptable (0x0x7f052b368cc0) 0 + +Class QStaticByteArrayMatcherBase + size=256 align=16 + base size=256 base align=16 +QStaticByteArrayMatcherBase (0x0x7f052b368c60) 0 + +Class QSharedData + size=4 align=4 + base size=4 base align=4 +QSharedData (0x0x7f052b368ea0) 0 + +Class QDate + size=8 align=8 + base size=8 base align=8 +QDate (0x0x7f052b0cf0c0) 0 + +Class QTime + size=4 align=4 + base size=4 base align=4 +QTime (0x0x7f052b0cf360) 0 + +Class QDateTime::ShortData + size=8 align=8 + base size=8 base align=8 +QDateTime::ShortData (0x0x7f052b0cfae0) 0 + +Class QDateTime::Data + size=8 align=8 + base size=8 base align=8 +QDateTime::Data (0x0x7f052b0cfb40) 0 + +Class QDateTime + size=8 align=8 + base size=8 base align=8 +QDateTime (0x0x7f052b0cfa80) 0 + +Class QLocale + size=8 align=8 + base size=8 base align=8 +QLocale (0x0x7f052b1bcc60) 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 (0x0x7f052ae852a0) 0 + vptr=((& QTextStream::_ZTV11QTextStream) + 16u) + +Class QTextStreamManipulator + size=40 align=8 + base size=38 base align=8 +QTextStreamManipulator (0x0x7f052ae85540) 0 + +Class QContiguousCacheData + size=24 align=4 + base size=24 base align=4 +QContiguousCacheData (0x0x7f052ae85780) 0 + +Class QtSharedPointer::NormalDeleter + size=1 align=1 + base size=0 base align=1 +QtSharedPointer::NormalDeleter (0x0x7f052ae85e40) 0 empty + +Class QtSharedPointer::ExternalRefCountData + size=16 align=8 + base size=16 base align=8 +QtSharedPointer::ExternalRefCountData (0x0x7f052b002000) 0 + +Class QDebug::Stream + size=80 align=8 + base size=76 base align=8 +QDebug::Stream (0x0x7f052b002540) 0 + +Class QDebug + size=8 align=8 + base size=8 base align=8 +QDebug (0x0x7f052b0024e0) 0 + +Class QDebugStateSaver + size=8 align=8 + base size=8 base align=8 +QDebugStateSaver (0x0x7f052aa14840) 0 + +Class QNoDebug + size=1 align=1 + base size=0 base align=1 +QNoDebug (0x0x7f052aa14900) 0 empty + +Class QCborError + size=4 align=4 + base size=4 base align=4 +QCborError (0x0x7f052aa8ec60) 0 + +Class QRegularExpression + size=8 align=8 + base size=8 base align=8 +QRegularExpression (0x0x7f052aa8ede0) 0 + +Class QRegularExpressionMatch + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatch (0x0x7f052ab01420) 0 + +Class QRegularExpressionMatchIterator + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatchIterator (0x0x7f052ab01720) 0 + +Class QUrl + size=8 align=8 + base size=8 base align=8 +QUrl (0x0x7f052ab01ae0) 0 + +Class QUuid + size=16 align=4 + base size=16 base align=4 +QUuid (0x0x7f052a8941e0) 0 + +Class QCborParserError + size=16 align=8 + base size=12 base align=8 +QCborParserError (0x0x7f052a8947e0) 0 + +Class QCborValue + size=24 align=8 + base size=20 base align=8 +QCborValue (0x0x7f052a894840) 0 + +Class QCborValueRef + size=16 align=8 + base size=16 base align=8 +QCborValueRef (0x0x7f052a74b840) 0 + +Class QCborArray::Iterator + size=16 align=8 + base size=16 base align=8 +QCborArray::Iterator (0x0x7f052a74bde0) 0 + +Class QCborArray::ConstIterator + size=16 align=8 + base size=16 base align=8 +QCborArray::ConstIterator (0x0x7f052a74be40) 0 + +Class QCborArray + size=8 align=8 + base size=8 base align=8 +QCborArray (0x0x7f052a74bd80) 0 + +Class QCborMap::Iterator + size=16 align=8 + base size=16 base align=8 +QCborMap::Iterator (0x0x7f052a47dea0) 0 + +Class QCborMap::ConstIterator + size=16 align=8 + base size=16 base align=8 +QCborMap::ConstIterator (0x0x7f052a47df00) 0 + +Class QCborMap + size=8 align=8 + base size=8 base align=8 +QCborMap (0x0x7f052a47de40) 0 + +Class qfloat16 + size=2 align=2 + base size=2 base align=2 +qfloat16 (0x0x7f052a242a80) 0 + +Class QCborStreamWriter + size=8 align=8 + base size=8 base align=8 +QCborStreamWriter (0x0x7f052a242e40) 0 + +Class QCborStreamReader + size=24 align=8 + base size=20 base align=8 +QCborStreamReader (0x0x7f052a399840) 0 + +Class QCollatorSortKey + size=8 align=8 + base size=8 base align=8 +QCollatorSortKey (0x0x7f052a399ea0) 0 + +Class QCollator + size=8 align=8 + base size=8 base align=8 +QCollator (0x0x7f052a399f60) 0 + +Class QCommandLineOption + size=8 align=8 + base size=8 base align=8 +QCommandLineOption (0x0x7f052a08df60) 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 (0x0x7f052a0c7420) 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 (0x0x7f052a0e2068) 0 + vptr=((& QTimerEvent::_ZTV11QTimerEvent) + 16u) + QEvent (0x0x7f052a0c7480) 0 + primary-for QTimerEvent (0x0x7f052a0e2068) + +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 (0x0x7f052a0e20d0) 0 + vptr=((& QChildEvent::_ZTV11QChildEvent) + 16u) + QEvent (0x0x7f052a0c74e0) 0 + primary-for QChildEvent (0x0x7f052a0e20d0) + +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 (0x0x7f052a0e2618) 0 + vptr=((& QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent) + 16u) + QEvent (0x0x7f052a0c79c0) 0 + primary-for QDynamicPropertyChangeEvent (0x0x7f052a0e2618) + +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 (0x0x7f052a0e2680) 0 + vptr=((& QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent) + 16u) + QEvent (0x0x7f052a0c7a20) 0 + primary-for QDeferredDeleteEvent (0x0x7f052a0e2680) + +Class QCoreApplication::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QCoreApplication::QPrivateSignal (0x0x7f052a0c7ae0) 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 (0x0x7f052a0e26e8) 0 + vptr=((& QCoreApplication::_ZTV16QCoreApplication) + 16u) + QObject (0x0x7f052a0c7a80) 0 + primary-for QCoreApplication (0x0x7f052a0e26e8) + +Class QCommandLineParser + size=8 align=8 + base size=8 base align=8 +QCommandLineParser (0x0x7f052a0c7b40) 0 + +Class QCryptographicHash + size=8 align=8 + base size=8 base align=8 +QCryptographicHash (0x0x7f052a0c7ba0) 0 + +Class QDataStream + size=32 align=8 + base size=32 base align=8 +QDataStream (0x0x7f052a0c7c00) 0 + +Class QtPrivate::StreamStateSaver + size=16 align=8 + base size=12 base align=8 +QtPrivate::StreamStateSaver (0x0x7f052a0c7cc0) 0 + +Class QElapsedTimer + size=16 align=8 + base size=16 base align=8 +QElapsedTimer (0x0x7f052a1b01e0) 0 + +Class QDeadlineTimer + size=16 align=8 + base size=16 base align=8 +QDeadlineTimer (0x0x7f052a1b06c0) 0 + +Class QFileDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileDevice::QPrivateSignal (0x0x7f0529f1c540) 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 (0x0x7f0529f15b60) 0 + vptr=((& QFileDevice::_ZTV11QFileDevice) + 16u) + QIODevice (0x0x7f0529f15bc8) 0 + primary-for QFileDevice (0x0x7f0529f15b60) + QObject (0x0x7f0529f1c4e0) 0 + primary-for QIODevice (0x0x7f0529f15bc8) + +Class QFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFile::QPrivateSignal (0x0x7f0529f1c780) 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 (0x0x7f0529f15d00) 0 + vptr=((& QFile::_ZTV5QFile) + 16u) + QFileDevice (0x0x7f0529f15d68) 0 + primary-for QFile (0x0x7f0529f15d00) + QIODevice (0x0x7f0529f15dd0) 0 + primary-for QFileDevice (0x0x7f0529f15d68) + QObject (0x0x7f0529f1c720) 0 + primary-for QIODevice (0x0x7f0529f15dd0) + +Class QFileInfo + size=8 align=8 + base size=8 base align=8 +QFileInfo (0x0x7f0529f1c960) 0 + +Class QDir + size=8 align=8 + base size=8 base align=8 +QDir (0x0x7f0529f1cd80) 0 + +Class QDirIterator + size=8 align=8 + base size=8 base align=8 +QDirIterator (0x0x7f0529c1e3c0) 0 + +Class QEasingCurve + size=8 align=8 + base size=8 base align=8 +QEasingCurve (0x0x7f0529c1e600) 0 + +Class QEventTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventTransition::QPrivateSignal (0x0x7f0529d26a20) 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 (0x0x7f0529d24dd0) 0 + vptr=((& QEventTransition::_ZTV16QEventTransition) + 16u) + QAbstractTransition (0x0x7f0529d24e38) 0 + primary-for QEventTransition (0x0x7f0529d24dd0) + QObject (0x0x7f0529d269c0) 0 + primary-for QAbstractTransition (0x0x7f0529d24e38) + +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 (0x0x7f0529d24ea0) 0 nearly-empty + vptr=((& QException::_ZTV10QException) + 16u) + std::exception (0x0x7f0529d26a80) 0 nearly-empty + primary-for QException (0x0x7f0529d24ea0) + +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 (0x0x7f0529d24f08) 0 nearly-empty + vptr=((& QUnhandledException::_ZTV19QUnhandledException) + 16u) + QException (0x0x7f0529d24f70) 0 nearly-empty + primary-for QUnhandledException (0x0x7f0529d24f08) + std::exception (0x0x7f0529d26ae0) 0 nearly-empty + primary-for QException (0x0x7f0529d24f70) + +Class QtPrivate::ExceptionHolder + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionHolder (0x0x7f0529d26b40) 0 + +Class QtPrivate::ExceptionStore + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionStore (0x0x7f0529d26c00) 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 (0x0x7f0529d26c60) 0 nearly-empty + vptr=((& QFactoryInterface::_ZTV17QFactoryInterface) + 16u) + +Class QFileSelector::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSelector::QPrivateSignal (0x0x7f0529d26d80) 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 (0x0x7f0529dbc000) 0 + vptr=((& QFileSelector::_ZTV13QFileSelector) + 16u) + QObject (0x0x7f0529d26d20) 0 + primary-for QFileSelector (0x0x7f0529dbc000) + +Class QFileSystemWatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSystemWatcher::QPrivateSignal (0x0x7f0529d26e40) 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 (0x0x7f0529dbc068) 0 + vptr=((& QFileSystemWatcher::_ZTV18QFileSystemWatcher) + 16u) + QObject (0x0x7f0529d26de0) 0 + primary-for QFileSystemWatcher (0x0x7f0529dbc068) + +Class QFinalState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFinalState::QPrivateSignal (0x0x7f0529d26f00) 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 (0x0x7f0529dbc0d0) 0 + vptr=((& QFinalState::_ZTV11QFinalState) + 16u) + QAbstractState (0x0x7f0529dbc138) 0 + primary-for QFinalState (0x0x7f0529dbc0d0) + QObject (0x0x7f0529d26ea0) 0 + primary-for QAbstractState (0x0x7f0529dbc138) + +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 (0x0x7f0529d26f60) 0 + vptr=((& QRunnable::_ZTV9QRunnable) + 16u) + +Class QBasicMutex + size=8 align=8 + base size=8 base align=8 +QBasicMutex (0x0x7f05299ef000) 0 + +Class QMutex + size=8 align=8 + base size=8 base align=8 +QMutex (0x0x7f0529dbc270) 0 + QBasicMutex (0x0x7f05299ef1e0) 0 + +Class QMutexLocker + size=8 align=8 + base size=8 base align=8 +QMutexLocker (0x0x7f05299ef240) 0 + +Class QtPrivate::ResultItem + size=16 align=8 + base size=16 base align=8 +QtPrivate::ResultItem (0x0x7f05299ef2a0) 0 + +Class QtPrivate::ResultIteratorBase + size=16 align=8 + base size=12 base align=8 +QtPrivate::ResultIteratorBase (0x0x7f05299ef300) 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 (0x0x7f05299ef420) 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 (0x0x7f05299efc60) 0 + vptr=((& QFutureInterfaceBase::_ZTV20QFutureInterfaceBase) + 16u) + +Class QFutureWatcherBase::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFutureWatcherBase::QPrivateSignal (0x0x7f0529b58480) 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 (0x0x7f0529b5a3a8) 0 + vptr=((& QFutureWatcherBase::_ZTV18QFutureWatcherBase) + 16u) + QObject (0x0x7f0529b58420) 0 + primary-for QFutureWatcherBase (0x0x7f0529b5a3a8) + +Class QHistoryState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QHistoryState::QPrivateSignal (0x0x7f0529b58a80) 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 (0x0x7f0529b5ac98) 0 + vptr=((& QHistoryState::_ZTV13QHistoryState) + 16u) + QAbstractState (0x0x7f0529b5ad00) 0 + primary-for QHistoryState (0x0x7f0529b5ac98) + QObject (0x0x7f0529b58a20) 0 + primary-for QAbstractState (0x0x7f0529b5ad00) + +Class QIdentityProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIdentityProxyModel::QPrivateSignal (0x0x7f0529b58b40) 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 (0x0x7f0529b5ad68) 0 + vptr=((& QIdentityProxyModel::_ZTV19QIdentityProxyModel) + 16u) + QAbstractProxyModel (0x0x7f0529b5add0) 0 + primary-for QIdentityProxyModel (0x0x7f0529b5ad68) + QAbstractItemModel (0x0x7f0529b5ae38) 0 + primary-for QAbstractProxyModel (0x0x7f0529b5add0) + QObject (0x0x7f0529b58ae0) 0 + primary-for QAbstractItemModel (0x0x7f0529b5ae38) + +Class QItemSelectionRange + size=16 align=8 + base size=16 base align=8 +QItemSelectionRange (0x0x7f0529b58ba0) 0 + +Class QItemSelectionModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QItemSelectionModel::QPrivateSignal (0x0x7f05298372a0) 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 (0x0x7f0529811680) 0 + vptr=((& QItemSelectionModel::_ZTV19QItemSelectionModel) + 16u) + QObject (0x0x7f0529837240) 0 + primary-for QItemSelectionModel (0x0x7f0529811680) + +Class QItemSelection + size=8 align=8 + base size=8 base align=8 +QItemSelection (0x0x7f0529811888) 0 + QList (0x0x7f05298118f0) 0 + QListSpecialMethods (0x0x7f05298375a0) 0 empty + +Class QJsonValue + size=24 align=8 + base size=20 base align=8 +QJsonValue (0x0x7f0529837a80) 0 + +Class QJsonValueRef + size=16 align=8 + base size=12 base align=8 +QJsonValueRef (0x0x7f05296391e0) 0 + +Class QJsonValuePtr + size=24 align=8 + base size=24 base align=8 +QJsonValuePtr (0x0x7f0529639720) 0 + +Class QJsonValueRefPtr + size=16 align=8 + base size=16 base align=8 +QJsonValueRefPtr (0x0x7f0529639780) 0 + +Class QJsonArray::iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::iterator (0x0x7f0529639960) 0 + +Class QJsonArray::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::const_iterator (0x0x7f05296399c0) 0 + +Class QJsonArray + size=16 align=8 + base size=16 base align=8 +QJsonArray (0x0x7f0529639900) 0 + +Class QJsonParseError + size=8 align=4 + base size=8 base align=4 +QJsonParseError (0x0x7f052974dc00) 0 + +Class QJsonDocument + size=8 align=8 + base size=8 base align=8 +QJsonDocument (0x0x7f052974dc60) 0 + +Class QJsonObject::iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::iterator (0x0x7f05297c8300) 0 + +Class QJsonObject::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::const_iterator (0x0x7f05297c8360) 0 + +Class QJsonObject + size=16 align=8 + base size=16 base align=8 +QJsonObject (0x0x7f05297c82a0) 0 + +Class QLibrary::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLibrary::QPrivateSignal (0x0x7f052947e600) 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 (0x0x7f0529478c30) 0 + vptr=((& QLibrary::_ZTV8QLibrary) + 16u) + QObject (0x0x7f052947e5a0) 0 + primary-for QLibrary (0x0x7f0529478c30) + +Class QVersionNumber::SegmentStorage + size=8 align=8 + base size=8 base align=8 +QVersionNumber::SegmentStorage (0x0x7f052947ecc0) 0 + +Class QVersionNumber + size=8 align=8 + base size=8 base align=8 +QVersionNumber (0x0x7f052947e7e0) 0 + +Class QLibraryInfo + size=1 align=1 + base size=0 base align=1 +QLibraryInfo (0x0x7f052956e1e0) 0 empty + +Class QPoint + size=8 align=4 + base size=8 base align=4 +QPoint (0x0x7f052956e240) 0 + +Class QPointF + size=16 align=8 + base size=16 base align=8 +QPointF (0x0x7f052956e4e0) 0 + +Class QLine + size=16 align=4 + base size=16 base align=4 +QLine (0x0x7f052956eae0) 0 + +Class QLineF + size=32 align=8 + base size=32 base align=8 +QLineF (0x0x7f0529212480) 0 + +Class QLinkedListData + size=32 align=8 + base size=25 base align=8 +QLinkedListData (0x0x7f0529212a80) 0 + +Class QLockFile + size=8 align=8 + base size=8 base align=8 +QLockFile (0x0x7f0529212de0) 0 + +Class QLoggingCategory::AtomicBools + size=4 align=1 + base size=4 base align=1 +QLoggingCategory::AtomicBools (0x0x7f0529212f60) 0 + +Class QLoggingCategory + size=24 align=8 + base size=24 base align=8 +QLoggingCategory (0x0x7f0529212f00) 0 + +Class QMargins + size=16 align=4 + base size=16 base align=4 +QMargins (0x0x7f0529355120) 0 + +Class QMarginsF + size=32 align=8 + base size=32 base align=8 +QMarginsF (0x0x7f05293553c0) 0 + +Class QMessageAuthenticationCode + size=8 align=8 + base size=8 base align=8 +QMessageAuthenticationCode (0x0x7f0529355a20) 0 + +Class QMetaMethod + size=16 align=8 + base size=12 base align=8 +QMetaMethod (0x0x7f0529355a80) 0 + +Class QMetaEnum + size=16 align=8 + base size=12 base align=8 +QMetaEnum (0x0x7f0528f830c0) 0 + +Class QMetaProperty + size=32 align=8 + base size=32 base align=8 +QMetaProperty (0x0x7f0528f833c0) 0 + +Class QMetaClassInfo + size=16 align=8 + base size=12 base align=8 +QMetaClassInfo (0x0x7f0528f83420) 0 + +Class QMimeData::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QMimeData::QPrivateSignal (0x0x7f0528f83720) 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 (0x0x7f0528eefea0) 0 + vptr=((& QMimeData::_ZTV9QMimeData) + 16u) + QObject (0x0x7f0528f836c0) 0 + primary-for QMimeData (0x0x7f0528eefea0) + +Class QMimeType + size=8 align=8 + base size=8 base align=8 +QMimeType (0x0x7f0528f83780) 0 + +Class QMimeDatabase + size=8 align=8 + base size=8 base align=8 +QMimeDatabase (0x0x7f0528f83a80) 0 + +Class QObjectCleanupHandler::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObjectCleanupHandler::QPrivateSignal (0x0x7f0528f83b40) 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 (0x0x7f0528fd90d0) 0 + vptr=((& QObjectCleanupHandler::_ZTV21QObjectCleanupHandler) + 16u) + QObject (0x0x7f0528f83ae0) 0 + primary-for QObjectCleanupHandler (0x0x7f0528fd90d0) + +Class QOperatingSystemVersion + size=16 align=4 + base size=16 base align=4 +QOperatingSystemVersion (0x0x7f0528f83ba0) 0 + +Class QParallelAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QParallelAnimationGroup::QPrivateSignal (0x0x7f052900d360) 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 (0x0x7f0528fd9820) 0 + vptr=((& QParallelAnimationGroup::_ZTV23QParallelAnimationGroup) + 16u) + QAnimationGroup (0x0x7f0528fd9888) 0 + primary-for QParallelAnimationGroup (0x0x7f0528fd9820) + QAbstractAnimation (0x0x7f0528fd98f0) 0 + primary-for QAnimationGroup (0x0x7f0528fd9888) + QObject (0x0x7f052900d300) 0 + primary-for QAbstractAnimation (0x0x7f0528fd98f0) + +Class QPauseAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPauseAnimation::QPrivateSignal (0x0x7f052900d420) 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 (0x0x7f0528fd9958) 0 + vptr=((& QPauseAnimation::_ZTV15QPauseAnimation) + 16u) + QAbstractAnimation (0x0x7f0528fd99c0) 0 + primary-for QPauseAnimation (0x0x7f0528fd9958) + QObject (0x0x7f052900d3c0) 0 + primary-for QAbstractAnimation (0x0x7f0528fd99c0) + +Class QStaticPlugin + size=16 align=8 + base size=16 base align=8 +QStaticPlugin (0x0x7f052900d600) 0 + +Class QPluginLoader::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPluginLoader::QPrivateSignal (0x0x7f052900d900) 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 (0x0x7f0528fd9bc8) 0 + vptr=((& QPluginLoader::_ZTV13QPluginLoader) + 16u) + QObject (0x0x7f052900d8a0) 0 + primary-for QPluginLoader (0x0x7f0528fd9bc8) + +Class QProcessEnvironment + size=8 align=8 + base size=8 base align=8 +QProcessEnvironment (0x0x7f052900d960) 0 + +Class QProcess::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QProcess::QPrivateSignal (0x0x7f0529098060) 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 (0x0x7f052908f208) 0 + vptr=((& QProcess::_ZTV8QProcess) + 16u) + QIODevice (0x0x7f052908f270) 0 + primary-for QProcess (0x0x7f052908f208) + QObject (0x0x7f0529098000) 0 + primary-for QIODevice (0x0x7f052908f270) + +Class QVariantAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QVariantAnimation::QPrivateSignal (0x0x7f0529098120) 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 (0x0x7f052908f2d8) 0 + vptr=((& QVariantAnimation::_ZTV17QVariantAnimation) + 16u) + QAbstractAnimation (0x0x7f052908f340) 0 + primary-for QVariantAnimation (0x0x7f052908f2d8) + QObject (0x0x7f05290980c0) 0 + primary-for QAbstractAnimation (0x0x7f052908f340) + +Class QPropertyAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPropertyAnimation::QPrivateSignal (0x0x7f05290981e0) 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 (0x0x7f052908f410) 0 + vptr=((& QPropertyAnimation::_ZTV18QPropertyAnimation) + 16u) + QVariantAnimation (0x0x7f052908f478) 0 + primary-for QPropertyAnimation (0x0x7f052908f410) + QAbstractAnimation (0x0x7f052908f4e0) 0 + primary-for QVariantAnimation (0x0x7f052908f478) + QObject (0x0x7f0529098180) 0 + primary-for QAbstractAnimation (0x0x7f052908f4e0) + +Class QRandomGenerator::Storage + size=2504 align=8 + base size=2504 base align=8 +QRandomGenerator::Storage (0x0x7f0529098300) 0 + +Class QRandomGenerator + size=2512 align=8 + base size=2512 base align=8 +QRandomGenerator (0x0x7f05290982a0) 0 + +Class QRandomGenerator64 + size=2512 align=8 + base size=2512 base align=8 +QRandomGenerator64 (0x0x7f0528d737b8) 0 + QRandomGenerator (0x0x7f0528d8b2a0) 0 + +Class QReadWriteLock + size=8 align=8 + base size=8 base align=8 +QReadWriteLock (0x0x7f0528d8b360) 0 + +Class QReadLocker + size=8 align=8 + base size=8 base align=8 +QReadLocker (0x0x7f0528d8b600) 0 + +Class QWriteLocker + size=8 align=8 + base size=8 base align=8 +QWriteLocker (0x0x7f0528d8b6c0) 0 + +Class QSize + size=8 align=4 + base size=8 base align=4 +QSize (0x0x7f0528d8b780) 0 + +Class QSizeF + size=16 align=8 + base size=16 base align=8 +QSizeF (0x0x7f0528d8ba20) 0 + +Class QRect + size=16 align=4 + base size=16 base align=4 +QRect (0x0x7f0528d8bcc0) 0 + +Class QRectF + size=32 align=8 + base size=32 base align=8 +QRectF (0x0x7f0528d8bf60) 0 + +Class QResource + size=8 align=8 + base size=8 base align=8 +QResource (0x0x7f0528b7f240) 0 + +Class QSaveFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSaveFile::QPrivateSignal (0x0x7f0528b7f3c0) 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 (0x0x7f0528ee6340) 0 + vptr=((& QSaveFile::_ZTV9QSaveFile) + 16u) + QFileDevice (0x0x7f0528ee63a8) 0 + primary-for QSaveFile (0x0x7f0528ee6340) + QIODevice (0x0x7f0528ee6410) 0 + primary-for QFileDevice (0x0x7f0528ee63a8) + QObject (0x0x7f0528b7f360) 0 + primary-for QIODevice (0x0x7f0528ee6410) + +Class QSemaphore + size=8 align=8 + base size=8 base align=8 +QSemaphore (0x0x7f0528b7f4e0) 0 + +Class QSemaphoreReleaser + size=16 align=8 + base size=12 base align=8 +QSemaphoreReleaser (0x0x7f0528b7f660) 0 + +Class QSequentialAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSequentialAnimationGroup::QPrivateSignal (0x0x7f0528930c60) 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 (0x0x7f052893fc98) 0 + vptr=((& QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup) + 16u) + QAnimationGroup (0x0x7f052893fd00) 0 + primary-for QSequentialAnimationGroup (0x0x7f052893fc98) + QAbstractAnimation (0x0x7f052893fd68) 0 + primary-for QAnimationGroup (0x0x7f052893fd00) + QObject (0x0x7f0528930c00) 0 + primary-for QAbstractAnimation (0x0x7f052893fd68) + +Class QSettings::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSettings::QPrivateSignal (0x0x7f0528930d20) 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 (0x0x7f052893fdd0) 0 + vptr=((& QSettings::_ZTV9QSettings) + 16u) + QObject (0x0x7f0528930cc0) 0 + primary-for QSettings (0x0x7f052893fdd0) + +Class QSharedMemory::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSharedMemory::QPrivateSignal (0x0x7f0528930de0) 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 (0x0x7f052893fe38) 0 + vptr=((& QSharedMemory::_ZTV13QSharedMemory) + 16u) + QObject (0x0x7f0528930d80) 0 + primary-for QSharedMemory (0x0x7f052893fe38) + +Class QSignalMapper::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalMapper::QPrivateSignal (0x0x7f0528930ea0) 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 (0x0x7f052893fea0) 0 + vptr=((& QSignalMapper::_ZTV13QSignalMapper) + 16u) + QObject (0x0x7f0528930e40) 0 + primary-for QSignalMapper (0x0x7f052893fea0) + +Class QSignalTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalTransition::QPrivateSignal (0x0x7f0528930f60) 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 (0x0x7f052893ff08) 0 + vptr=((& QSignalTransition::_ZTV17QSignalTransition) + 16u) + QAbstractTransition (0x0x7f052893ff70) 0 + primary-for QSignalTransition (0x0x7f052893ff08) + QObject (0x0x7f0528930f00) 0 + primary-for QAbstractTransition (0x0x7f052893ff70) + +Class QSocketNotifier::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSocketNotifier::QPrivateSignal (0x0x7f05289be060) 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 (0x0x7f05289bd000) 0 + vptr=((& QSocketNotifier::_ZTV15QSocketNotifier) + 16u) + QObject (0x0x7f05289be000) 0 + primary-for QSocketNotifier (0x0x7f05289bd000) + +Class QSortFilterProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSortFilterProxyModel::QPrivateSignal (0x0x7f05289be120) 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 (0x0x7f05289bd068) 0 + vptr=((& QSortFilterProxyModel::_ZTV21QSortFilterProxyModel) + 16u) + QAbstractProxyModel (0x0x7f05289bd0d0) 0 + primary-for QSortFilterProxyModel (0x0x7f05289bd068) + QAbstractItemModel (0x0x7f05289bd138) 0 + primary-for QAbstractProxyModel (0x0x7f05289bd0d0) + QObject (0x0x7f05289be0c0) 0 + primary-for QAbstractItemModel (0x0x7f05289bd138) + +Class QStandardPaths + size=1 align=1 + base size=0 base align=1 +QStandardPaths (0x0x7f05289be1e0) 0 empty + +Class QState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QState::QPrivateSignal (0x0x7f05289be420) 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 (0x0x7f05289bd2d8) 0 + vptr=((& QState::_ZTV6QState) + 16u) + QAbstractState (0x0x7f05289bd340) 0 + primary-for QState (0x0x7f05289bd2d8) + QObject (0x0x7f05289be3c0) 0 + primary-for QAbstractState (0x0x7f05289bd340) + +Class QStateMachine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStateMachine::QPrivateSignal (0x0x7f05289be540) 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 (0x0x7f05289bd4e0) 0 + vptr=((& QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE) + 16u) + QEvent (0x0x7f05289be5a0) 0 + primary-for QStateMachine::SignalEvent (0x0x7f05289bd4e0) + +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 (0x0x7f05289bd548) 0 + vptr=((& QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE) + 16u) + QEvent (0x0x7f05289be600) 0 + primary-for QStateMachine::WrappedEvent (0x0x7f05289bd548) + +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 (0x0x7f05289bd3a8) 0 + vptr=((& QStateMachine::_ZTV13QStateMachine) + 16u) + QState (0x0x7f05289bd410) 0 + primary-for QStateMachine (0x0x7f05289bd3a8) + QAbstractState (0x0x7f05289bd478) 0 + primary-for QState (0x0x7f05289bd410) + QObject (0x0x7f05289be4e0) 0 + primary-for QAbstractState (0x0x7f05289bd478) + +Class QStorageInfo + size=8 align=8 + base size=8 base align=8 +QStorageInfo (0x0x7f05289be660) 0 + +Class QAbstractConcatenable + size=1 align=1 + base size=0 base align=1 +QAbstractConcatenable (0x0x7f0528ab25a0) 0 empty + +Class QStringListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStringListModel::QPrivateSignal (0x0x7f0528737960) 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 (0x0x7f052874a548) 0 + vptr=((& QStringListModel::_ZTV16QStringListModel) + 16u) + QAbstractListModel (0x0x7f052874a5b0) 0 + primary-for QStringListModel (0x0x7f052874a548) + QAbstractItemModel (0x0x7f052874a618) 0 + primary-for QAbstractListModel (0x0x7f052874a5b0) + QObject (0x0x7f0528737900) 0 + primary-for QAbstractItemModel (0x0x7f052874a618) + +Class QSystemSemaphore + size=8 align=8 + base size=8 base align=8 +QSystemSemaphore (0x0x7f05287379c0) 0 + +Class QTemporaryDir + size=8 align=8 + base size=8 base align=8 +QTemporaryDir (0x0x7f0528737a80) 0 + +Class QTemporaryFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTemporaryFile::QPrivateSignal (0x0x7f0528737ba0) 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 (0x0x7f052874a680) 0 + vptr=((& QTemporaryFile::_ZTV14QTemporaryFile) + 16u) + QFile (0x0x7f052874a6e8) 0 + primary-for QTemporaryFile (0x0x7f052874a680) + QFileDevice (0x0x7f052874a750) 0 + primary-for QFile (0x0x7f052874a6e8) + QIODevice (0x0x7f052874a7b8) 0 + primary-for QFileDevice (0x0x7f052874a750) + QObject (0x0x7f0528737b40) 0 + primary-for QIODevice (0x0x7f052874a7b8) + +Class QTextBoundaryFinder + size=48 align=8 + base size=48 base align=8 +QTextBoundaryFinder (0x0x7f0528737c00) 0 + +Class QTextCodec::ConverterState + size=32 align=8 + base size=32 base align=8 +QTextCodec::ConverterState (0x0x7f0528737e40) 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 (0x0x7f0528737de0) 0 nearly-empty + vptr=((& QTextCodec::_ZTV10QTextCodec) + 16u) + +Class QTextEncoder + size=40 align=8 + base size=40 base align=8 +QTextEncoder (0x0x7f05287f4060) 0 + +Class QTextDecoder + size=40 align=8 + base size=40 base align=8 +QTextDecoder (0x0x7f05287f40c0) 0 + +Class std::__mutex_base + size=40 align=8 + base size=40 base align=8 +std::__mutex_base (0x0x7f05287f4120) 0 + +Class std::__recursive_mutex_base + size=40 align=8 + base size=40 base align=8 +std::__recursive_mutex_base (0x0x7f05287f4180) 0 + +Class std::mutex + size=40 align=8 + base size=40 base align=8 +std::mutex (0x0x7f052874a9c0) 0 + std::__mutex_base (0x0x7f05287f41e0) 0 + +Class std::recursive_mutex + size=40 align=8 + base size=40 base align=8 +std::recursive_mutex (0x0x7f052874aa28) 0 + std::__recursive_mutex_base (0x0x7f05287f4240) 0 + +Class std::timed_mutex + size=40 align=8 + base size=40 base align=8 +std::timed_mutex (0x0x7f052884f4d0) 0 + std::__mutex_base (0x0x7f05287f4360) 0 + std::__timed_mutex_impl (0x0x7f05287f43c0) 0 empty + +Class std::recursive_timed_mutex + size=40 align=8 + base size=40 base align=8 +std::recursive_timed_mutex (0x0x7f052884fe70) 0 + std::__recursive_mutex_base (0x0x7f05287f4480) 0 + std::__timed_mutex_impl (0x0x7f05287f44e0) 0 empty + +Class std::defer_lock_t + size=1 align=1 + base size=0 base align=1 +std::defer_lock_t (0x0x7f05287f4540) 0 empty + +Class std::try_to_lock_t + size=1 align=1 + base size=0 base align=1 +std::try_to_lock_t (0x0x7f05287f45a0) 0 empty + +Class std::adopt_lock_t + size=1 align=1 + base size=0 base align=1 +std::adopt_lock_t (0x0x7f05287f4600) 0 empty + +Class std::once_flag + size=4 align=4 + base size=4 base align=4 +std::once_flag (0x0x7f05287f4840) 0 + +Vtable for __gnu_cxx::__concurrence_lock_error +__gnu_cxx::__concurrence_lock_error::_ZTVN9__gnu_cxx24__concurrence_lock_errorE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx24__concurrence_lock_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_lock_error::~__concurrence_lock_error +24 (int (*)(...))__gnu_cxx::__concurrence_lock_error::~__concurrence_lock_error +32 (int (*)(...))__gnu_cxx::__concurrence_lock_error::what + +Class __gnu_cxx::__concurrence_lock_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_lock_error (0x0x7f052874ab60) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_lock_error::_ZTVN9__gnu_cxx24__concurrence_lock_errorE) + 16u) + std::exception (0x0x7f05287f4900) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_lock_error (0x0x7f052874ab60) + +Vtable for __gnu_cxx::__concurrence_unlock_error +__gnu_cxx::__concurrence_unlock_error::_ZTVN9__gnu_cxx26__concurrence_unlock_errorE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx26__concurrence_unlock_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::~__concurrence_unlock_error +24 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::~__concurrence_unlock_error +32 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::what + +Class __gnu_cxx::__concurrence_unlock_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_unlock_error (0x0x7f052874abc8) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_unlock_error::_ZTVN9__gnu_cxx26__concurrence_unlock_errorE) + 16u) + std::exception (0x0x7f05287f49c0) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_unlock_error (0x0x7f052874abc8) + +Vtable for __gnu_cxx::__concurrence_broadcast_error +__gnu_cxx::__concurrence_broadcast_error::_ZTVN9__gnu_cxx29__concurrence_broadcast_errorE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx29__concurrence_broadcast_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::~__concurrence_broadcast_error +24 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::~__concurrence_broadcast_error +32 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::what + +Class __gnu_cxx::__concurrence_broadcast_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_broadcast_error (0x0x7f052874ac30) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_broadcast_error::_ZTVN9__gnu_cxx29__concurrence_broadcast_errorE) + 16u) + std::exception (0x0x7f05287f4a80) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_broadcast_error (0x0x7f052874ac30) + +Vtable for __gnu_cxx::__concurrence_wait_error +__gnu_cxx::__concurrence_wait_error::_ZTVN9__gnu_cxx24__concurrence_wait_errorE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx24__concurrence_wait_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_wait_error::~__concurrence_wait_error +24 (int (*)(...))__gnu_cxx::__concurrence_wait_error::~__concurrence_wait_error +32 (int (*)(...))__gnu_cxx::__concurrence_wait_error::what + +Class __gnu_cxx::__concurrence_wait_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_wait_error (0x0x7f052874ad00) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_wait_error::_ZTVN9__gnu_cxx24__concurrence_wait_errorE) + 16u) + std::exception (0x0x7f05287f4b40) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_wait_error (0x0x7f052874ad00) + +Class __gnu_cxx::__mutex + size=40 align=8 + base size=40 base align=8 +__gnu_cxx::__mutex (0x0x7f05287f4c00) 0 + +Class __gnu_cxx::__recursive_mutex + size=40 align=8 + base size=40 base align=8 +__gnu_cxx::__recursive_mutex (0x0x7f05287f4c60) 0 + +Class __gnu_cxx::__scoped_lock + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__scoped_lock (0x0x7f05287f4cc0) 0 + +Class __gnu_cxx::__cond + size=48 align=8 + base size=48 base align=8 +__gnu_cxx::__cond (0x0x7f05287f4d20) 0 + +Vtable for std::bad_weak_ptr +std::bad_weak_ptr::_ZTVSt12bad_weak_ptr: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt12bad_weak_ptr) +16 (int (*)(...))std::bad_weak_ptr::~bad_weak_ptr +24 (int (*)(...))std::bad_weak_ptr::~bad_weak_ptr +32 (int (*)(...))std::bad_weak_ptr::what + +Class std::bad_weak_ptr + size=8 align=8 + base size=8 base align=8 +std::bad_weak_ptr (0x0x7f052874ae38) 0 nearly-empty + vptr=((& std::bad_weak_ptr::_ZTVSt12bad_weak_ptr) + 16u) + std::exception (0x0x7f05285750c0) 0 nearly-empty + primary-for std::bad_weak_ptr (0x0x7f052874ae38) + +Class std::_Sp_make_shared_tag + size=1 align=1 + base size=0 base align=1 +std::_Sp_make_shared_tag (0x0x7f0528575900) 0 empty + +Class std::_Sp_locker + size=2 align=1 + base size=2 base align=1 +std::_Sp_locker (0x0x7f05282f1120) 0 + +Class std::thread::id + size=8 align=8 + base size=8 base align=8 +std::thread::id (0x0x7f05282f1300) 0 + +Vtable for std::thread::_Impl_base +std::thread::_Impl_base::_ZTVNSt6thread10_Impl_baseE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt6thread10_Impl_baseE) +16 0u +24 0u +32 (int (*)(...))__cxa_pure_virtual + +Class std::thread::_Impl_base + size=24 align=8 + base size=24 base align=8 +std::thread::_Impl_base (0x0x7f05282f1360) 0 + vptr=((& std::thread::_Impl_base::_ZTVNSt6thread10_Impl_baseE) + 16u) + +Class std::thread + size=8 align=8 + base size=8 base align=8 +std::thread (0x0x7f05282f12a0) 0 + +Class std::condition_variable + size=48 align=8 + base size=48 base align=8 +std::condition_variable (0x0x7f0528468f60) 0 + +Class std::__at_thread_exit_elt + size=16 align=8 + base size=16 base align=8 +std::__at_thread_exit_elt (0x0x7f05284be060) 0 + +Class std::_V2::condition_variable_any + size=64 align=8 + base size=64 base align=8 +std::_V2::condition_variable_any (0x0x7f05284be0c0) 0 + +Class std::__atomic_futex_unsigned_base + size=1 align=1 + base size=0 base align=1 +std::__atomic_futex_unsigned_base (0x0x7f0528136720) 0 empty + +Vtable for std::future_error +std::future_error::_ZTVSt12future_error: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt12future_error) +16 (int (*)(...))std::future_error::~future_error +24 (int (*)(...))std::future_error::~future_error +32 (int (*)(...))std::future_error::what + +Class std::future_error + size=32 align=8 + base size=32 base align=8 +std::future_error (0x0x7f052813e340) 0 + vptr=((& std::future_error::_ZTVSt12future_error) + 16u) + std::logic_error (0x0x7f052813e3a8) 0 + primary-for std::future_error (0x0x7f052813e340) + std::exception (0x0x7f0528136840) 0 nearly-empty + primary-for std::logic_error (0x0x7f052813e3a8) + +Class std::__future_base::_Result_base::_Deleter + size=1 align=1 + base size=0 base align=1 +std::__future_base::_Result_base::_Deleter (0x0x7f0528136960) 0 empty + +Vtable for std::__future_base::_Result_base +std::__future_base::_Result_base::_ZTVNSt13__future_base12_Result_baseE: 5u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt13__future_base12_Result_baseE) +16 (int (*)(...))__cxa_pure_virtual +24 0u +32 0u + +Class std::__future_base::_Result_base + size=16 align=8 + base size=16 base align=8 +std::__future_base::_Result_base (0x0x7f0528136900) 0 + vptr=((& std::__future_base::_Result_base::_ZTVNSt13__future_base12_Result_baseE) + 16u) + +Class std::__future_base::_State_baseV2::__exception_ptr_tag + size=1 align=1 + base size=0 base align=1 +std::__future_base::_State_baseV2::__exception_ptr_tag (0x0x7f0528213ea0) 0 empty + +Class std::__future_base::_State_baseV2::_Make_ready + size=32 align=8 + base size=32 base align=8 +std::__future_base::_State_baseV2::_Make_ready (0x0x7f0528296958) 0 + std::__at_thread_exit_elt (0x0x7f0528213f60) 0 + +Vtable for std::__future_base::_State_baseV2 +std::__future_base::_State_baseV2::_ZTVNSt13__future_base13_State_baseV2E: 6u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt13__future_base13_State_baseV2E) +16 (int (*)(...))std::__future_base::_State_baseV2::~_State_baseV2 +24 (int (*)(...))std::__future_base::_State_baseV2::~_State_baseV2 +32 (int (*)(...))std::__future_base::_State_baseV2::_M_complete_async +40 (int (*)(...))std::__future_base::_State_baseV2::_M_is_deferred_future + +Class std::__future_base::_State_baseV2 + size=32 align=8 + base size=28 base align=8 +std::__future_base::_State_baseV2 (0x0x7f0528136ae0) 0 + vptr=((& std::__future_base::_State_baseV2::_ZTVNSt13__future_base13_State_baseV2E) + 16u) + +Class std::__future_base + size=1 align=1 + base size=0 base align=1 +std::__future_base (0x0x7f05281368a0) 0 empty + +Vtable for std::__future_base::_Async_state_commonV2 +std::__future_base::_Async_state_commonV2::_ZTVNSt13__future_base21_Async_state_commonV2E: 6u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt13__future_base21_Async_state_commonV2E) +16 (int (*)(...))std::__future_base::_Async_state_commonV2::~_Async_state_commonV2 +24 (int (*)(...))std::__future_base::_Async_state_commonV2::~_Async_state_commonV2 +32 (int (*)(...))std::__future_base::_Async_state_commonV2::_M_complete_async +40 (int (*)(...))std::__future_base::_State_baseV2::_M_is_deferred_future + +Class std::__future_base::_Async_state_commonV2 + size=48 align=8 + base size=44 base align=8 +std::__future_base::_Async_state_commonV2 (0x0x7f0527c15548) 0 + vptr=((& std::__future_base::_Async_state_commonV2::_ZTVNSt13__future_base21_Async_state_commonV2E) + 16u) + std::__future_base::_State_baseV2 (0x0x7f0527c01e40) 0 + primary-for std::__future_base::_Async_state_commonV2 (0x0x7f0527c15548) + +Class QThread::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThread::QPrivateSignal (0x0x7f0527c685a0) 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 (0x0x7f0527c9b000) 0 + vptr=((& QThread::_ZTV7QThread) + 16u) + QObject (0x0x7f0527c68540) 0 + primary-for QThread (0x0x7f0527c9b000) + +Class QThreadPool::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThreadPool::QPrivateSignal (0x0x7f0527c686c0) 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 (0x0x7f0527c9b068) 0 + vptr=((& QThreadPool::_ZTV11QThreadPool) + 16u) + QObject (0x0x7f0527c68660) 0 + primary-for QThreadPool (0x0x7f0527c9b068) + +Class QThreadStorageData + size=4 align=4 + base size=4 base align=4 +QThreadStorageData (0x0x7f0527c68720) 0 + +Class QTimeLine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimeLine::QPrivateSignal (0x0x7f0527c68840) 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 (0x0x7f0527c9b0d0) 0 + vptr=((& QTimeLine::_ZTV9QTimeLine) + 16u) + QObject (0x0x7f0527c687e0) 0 + primary-for QTimeLine (0x0x7f0527c9b0d0) + +Class QTimer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimer::QPrivateSignal (0x0x7f0527c68900) 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 (0x0x7f0527c9b138) 0 + vptr=((& QTimer::_ZTV6QTimer) + 16u) + QObject (0x0x7f0527c688a0) 0 + primary-for QTimer (0x0x7f0527c9b138) + +Class QTimeZone::OffsetData + size=32 align=8 + base size=28 base align=8 +QTimeZone::OffsetData (0x0x7f0527938060) 0 + +Class QTimeZone + size=8 align=8 + base size=8 base align=8 +QTimeZone (0x0x7f0527938000) 0 + +Class QTranslator::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTranslator::QPrivateSignal (0x0x7f0527938600) 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 (0x0x7f0527c9bd00) 0 + vptr=((& QTranslator::_ZTV11QTranslator) + 16u) + QObject (0x0x7f05279385a0) 0 + primary-for QTranslator (0x0x7f0527c9bd00) + +Class QUrlQuery + size=8 align=8 + base size=8 base align=8 +QUrlQuery (0x0x7f0527938660) 0 + +Class QWaitCondition + size=8 align=8 + base size=8 base align=8 +QWaitCondition (0x0x7f0527938cc0) 0 + +Class QXmlStreamStringRef + size=16 align=8 + base size=16 base align=8 +QXmlStreamStringRef (0x0x7f0527938d20) 0 + +Class QXmlStreamAttribute + size=80 align=8 + base size=73 base align=8 +QXmlStreamAttribute (0x0x7f05279db000) 0 + +Class QXmlStreamAttributes + size=8 align=8 + base size=8 base align=8 +QXmlStreamAttributes (0x0x7f052799a9c0) 0 + QVector (0x0x7f05279db3c0) 0 + +Class QXmlStreamNamespaceDeclaration + size=40 align=8 + base size=40 base align=8 +QXmlStreamNamespaceDeclaration (0x0x7f05279db420) 0 + +Class QXmlStreamNotationDeclaration + size=56 align=8 + base size=56 base align=8 +QXmlStreamNotationDeclaration (0x0x7f05279db6c0) 0 + +Class QXmlStreamEntityDeclaration + size=88 align=8 + base size=88 base align=8 +QXmlStreamEntityDeclaration (0x0x7f05279db960) 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 (0x0x7f05279dbc00) 0 nearly-empty + vptr=((& QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver) + 16u) + +Class QXmlStreamReader + size=8 align=8 + base size=8 base align=8 +QXmlStreamReader (0x0x7f05279dbc60) 0 + +Class QXmlStreamWriter + size=8 align=8 + base size=8 base align=8 +QXmlStreamWriter (0x0x7f05276e36c0) 0 + +Class QNdefRecord + size=8 align=8 + base size=8 base align=8 +QNdefRecord (0x0x7f05276e37e0) 0 + +Class QNdefFilter::Record + size=24 align=8 + base size=24 base align=8 +QNdefFilter::Record (0x0x7f05276e3900) 0 + +Class QNdefFilter + size=8 align=8 + base size=8 base align=8 +QNdefFilter (0x0x7f05276e38a0) 0 + +Class QNdefMessage + size=8 align=8 + base size=8 base align=8 +QNdefMessage (0x0x7f0527ab8b60) 0 + QList (0x0x7f0527ab8bc8) 0 + QListSpecialMethods (0x0x7f05276e3ae0) 0 empty + +Class QNdefNfcTextRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcTextRecord (0x0x7f0527ab8c30) 0 + QNdefRecord (0x0x7f05276e3cc0) 0 + +Class QNdefNfcUriRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcUriRecord (0x0x7f05277b61a0) 0 + QNdefRecord (0x0x7f05277b41e0) 0 + +Class QNdefNfcIconRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcIconRecord (0x0x7f05277b6208) 0 + QNdefRecord (0x0x7f05277b4240) 0 + +Class QNdefNfcSmartPosterRecord + size=16 align=8 + base size=16 base align=8 +QNdefNfcSmartPosterRecord (0x0x7f05277b6270) 0 + QNdefRecord (0x0x7f05277b42a0) 0 + +Class QNearFieldTarget::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldTarget::QPrivateSignal (0x0x7f05277b43c0) 0 empty + +Class QNearFieldTarget::RequestId + size=8 align=8 + base size=8 base align=8 +QNearFieldTarget::RequestId (0x0x7f05277b4420) 0 + +Vtable for QNearFieldTarget +QNearFieldTarget::_ZTV16QNearFieldTarget: 25u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QNearFieldTarget) +16 (int (*)(...))QNearFieldTarget::metaObject +24 (int (*)(...))QNearFieldTarget::qt_metacast +32 (int (*)(...))QNearFieldTarget::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 (*)(...))QNearFieldTarget::url +128 (int (*)(...))__cxa_pure_virtual +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))QNearFieldTarget::hasNdefMessage +152 (int (*)(...))QNearFieldTarget::readNdefMessages +160 (int (*)(...))QNearFieldTarget::writeNdefMessages +168 (int (*)(...))QNearFieldTarget::sendCommand +176 (int (*)(...))QNearFieldTarget::sendCommands +184 (int (*)(...))QNearFieldTarget::waitForRequestCompleted +192 (int (*)(...))QNearFieldTarget::handleResponse + +Class QNearFieldTarget + size=24 align=8 + base size=24 base align=8 +QNearFieldTarget (0x0x7f05277b62d8) 0 + vptr=((& QNearFieldTarget::_ZTV16QNearFieldTarget) + 16u) + QObject (0x0x7f05277b4360) 0 + primary-for QNearFieldTarget (0x0x7f05277b62d8) + +Class QNearFieldManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldManager::QPrivateSignal (0x0x7f05277b47e0) 0 empty + +Vtable for QNearFieldManager +QNearFieldManager::_ZTV17QNearFieldManager: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QNearFieldManager) +16 (int (*)(...))QNearFieldManager::metaObject +24 (int (*)(...))QNearFieldManager::qt_metacast +32 (int (*)(...))QNearFieldManager::qt_metacall +40 (int (*)(...))QNearFieldManager::~QNearFieldManager +48 (int (*)(...))QNearFieldManager::~QNearFieldManager +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 QNearFieldManager + size=24 align=8 + base size=24 base align=8 +QNearFieldManager (0x0x7f05277b6410) 0 + vptr=((& QNearFieldManager::_ZTV17QNearFieldManager) + 16u) + QObject (0x0x7f05277b4780) 0 + primary-for QNearFieldManager (0x0x7f05277b6410) + +Class QNearFieldShareManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldShareManager::QPrivateSignal (0x0x7f05277b4a20) 0 empty + +Vtable for QNearFieldShareManager +QNearFieldShareManager::_ZTV22QNearFieldShareManager: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI22QNearFieldShareManager) +16 (int (*)(...))QNearFieldShareManager::metaObject +24 (int (*)(...))QNearFieldShareManager::qt_metacast +32 (int (*)(...))QNearFieldShareManager::qt_metacall +40 (int (*)(...))QNearFieldShareManager::~QNearFieldShareManager +48 (int (*)(...))QNearFieldShareManager::~QNearFieldShareManager +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 QNearFieldShareManager + size=24 align=8 + base size=24 base align=8 +QNearFieldShareManager (0x0x7f05277b6548) 0 + vptr=((& QNearFieldShareManager::_ZTV22QNearFieldShareManager) + 16u) + QObject (0x0x7f05277b49c0) 0 + primary-for QNearFieldShareManager (0x0x7f05277b6548) + +Class QNearFieldShareTarget::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldShareTarget::QPrivateSignal (0x0x7f05277b4d20) 0 empty + +Vtable for QNearFieldShareTarget +QNearFieldShareTarget::_ZTV21QNearFieldShareTarget: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QNearFieldShareTarget) +16 (int (*)(...))QNearFieldShareTarget::metaObject +24 (int (*)(...))QNearFieldShareTarget::qt_metacast +32 (int (*)(...))QNearFieldShareTarget::qt_metacall +40 (int (*)(...))QNearFieldShareTarget::~QNearFieldShareTarget +48 (int (*)(...))QNearFieldShareTarget::~QNearFieldShareTarget +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 QNearFieldShareTarget + size=24 align=8 + base size=24 base align=8 +QNearFieldShareTarget (0x0x7f05277b6680) 0 + vptr=((& QNearFieldShareTarget::_ZTV21QNearFieldShareTarget) + 16u) + QObject (0x0x7f05277b4cc0) 0 + primary-for QNearFieldShareTarget (0x0x7f05277b6680) + +Class QQmlNdefRecord::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QQmlNdefRecord::QPrivateSignal (0x0x7f05277b4de0) 0 empty + +Vtable for QQmlNdefRecord +QQmlNdefRecord::_ZTV14QQmlNdefRecord: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI14QQmlNdefRecord) +16 (int (*)(...))QQmlNdefRecord::metaObject +24 (int (*)(...))QQmlNdefRecord::qt_metacast +32 (int (*)(...))QQmlNdefRecord::qt_metacall +40 (int (*)(...))QQmlNdefRecord::~QQmlNdefRecord +48 (int (*)(...))QQmlNdefRecord::~QQmlNdefRecord +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 QQmlNdefRecord + size=24 align=8 + base size=24 base align=8 +QQmlNdefRecord (0x0x7f05277b66e8) 0 + vptr=((& QQmlNdefRecord::_ZTV14QQmlNdefRecord) + 16u) + QObject (0x0x7f05277b4d80) 0 + primary-for QQmlNdefRecord (0x0x7f05277b66e8) + diff --git a/tests/auto/bic/data/QtNfc.5.13.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtNfc.5.13.0.linux-gcc-amd64.txt new file mode 100644 index 0000000..e35780a --- /dev/null +++ b/tests/auto/bic/data/QtNfc.5.13.0.linux-gcc-amd64.txt @@ -0,0 +1,5189 @@ +Class std::__failure_type + size=1 align=1 + base size=0 base align=1 +std::__failure_type (0x0x7ff78ae54f60) 0 empty + +Class std::__do_is_destructible_impl + size=1 align=1 + base size=0 base align=1 +std::__do_is_destructible_impl (0x0x7ff789b2c720) 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 (0x0x7ff789b2c960) 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 (0x0x7ff789b2cba0) 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 (0x0x7ff789b2cde0) 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 (0x0x7ff789b2cf60) 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 (0x0x7ff789b5b360) 0 empty + +Class std::__do_is_implicitly_default_constructible_impl + size=1 align=1 + base size=0 base align=1 +std::__do_is_implicitly_default_constructible_impl (0x0x7ff789b98480) 0 empty + +Class std::__do_common_type_impl + size=1 align=1 + base size=0 base align=1 +std::__do_common_type_impl (0x0x7ff789befb40) 0 empty + +Class std::__do_member_type_wrapper + size=1 align=1 + base size=0 base align=1 +std::__do_member_type_wrapper (0x0x7ff789befc00) 0 empty + +Class std::__invoke_memfun_ref + size=1 align=1 + base size=0 base align=1 +std::__invoke_memfun_ref (0x0x7ff789c1e000) 0 empty + +Class std::__invoke_memfun_deref + size=1 align=1 + base size=0 base align=1 +std::__invoke_memfun_deref (0x0x7ff789c1e060) 0 empty + +Class std::__invoke_memobj_ref + size=1 align=1 + base size=0 base align=1 +std::__invoke_memobj_ref (0x0x7ff789c1e0c0) 0 empty + +Class std::__invoke_memobj_deref + size=1 align=1 + base size=0 base align=1 +std::__invoke_memobj_deref (0x0x7ff789c1e120) 0 empty + +Class std::__invoke_other + size=1 align=1 + base size=0 base align=1 +std::__invoke_other (0x0x7ff789c1e180) 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 (0x0x7ff789c1e240) 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 (0x0x7ff789c1e300) 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 (0x0x7ff789c1e3c0) 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 (0x0x7ff789c1e480) 0 empty + +Class std::__result_of_other_impl + size=1 align=1 + base size=0 base align=1 +std::__result_of_other_impl (0x0x7ff789c1e7e0) 0 empty + +Class std::__swappable_details::__do_is_swappable_impl + size=1 align=1 + base size=0 base align=1 +std::__swappable_details::__do_is_swappable_impl (0x0x7ff789c1eb40) 0 empty + +Class std::__swappable_details::__do_is_nothrow_swappable_impl + size=1 align=1 + base size=0 base align=1 +std::__swappable_details::__do_is_nothrow_swappable_impl (0x0x7ff789c1eba0) 0 empty + +Class std::__nonesuch + size=1 align=1 + base size=0 base align=1 +std::__nonesuch (0x0x7ff789868180) 0 empty + +Class std::piecewise_construct_t + size=1 align=1 + base size=0 base align=1 +std::piecewise_construct_t (0x0x7ff7898687e0) 0 empty + +Class std::__nonesuch_no_braces + size=1 align=1 + base size=1 base align=1 +std::__nonesuch_no_braces (0x0x7ff789c58410) 0 empty + std::__nonesuch (0x0x7ff789868cc0) 0 empty + +Class std::__true_type + size=1 align=1 + base size=0 base align=1 +std::__true_type (0x0x7ff7898e9660) 0 empty + +Class std::__false_type + size=1 align=1 + base size=0 base align=1 +std::__false_type (0x0x7ff7898e96c0) 0 empty + +Class std::input_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::input_iterator_tag (0x0x7ff78993f3c0) 0 empty + +Class std::output_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::output_iterator_tag (0x0x7ff78993f420) 0 empty + +Class std::forward_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::forward_iterator_tag (0x0x7ff789c588f0) 0 empty + std::input_iterator_tag (0x0x7ff78993f480) 0 empty + +Class std::bidirectional_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::bidirectional_iterator_tag (0x0x7ff789c58958) 0 empty + std::forward_iterator_tag (0x0x7ff789c589c0) 0 empty + std::input_iterator_tag (0x0x7ff78993f4e0) 0 empty + +Class std::random_access_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::random_access_iterator_tag (0x0x7ff789c58a28) 0 empty + std::bidirectional_iterator_tag (0x0x7ff789c58a90) 0 empty + std::forward_iterator_tag (0x0x7ff789c58af8) 0 empty + std::input_iterator_tag (0x0x7ff78993f540) 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 (0x0x7ff7899f8060) 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 (0x0x7ff7899f8180) 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 (0x0x7ff7899f8480) 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 (0x0x7ff7899f8780) 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 (0x0x7ff7899f88a0) 0 empty + +Class __locale_struct + size=232 align=8 + base size=232 base align=8 +__locale_struct (0x0x7ff789683ba0) 0 + +Class timeval + size=16 align=8 + base size=16 base align=8 +timeval (0x0x7ff789683ea0) 0 + +Class timespec + size=16 align=8 + base size=16 base align=8 +timespec (0x0x7ff789683f00) 0 + +Class __pthread_rwlock_arch_t + size=56 align=8 + base size=56 base align=8 +__pthread_rwlock_arch_t (0x0x7ff7896ce000) 0 + +Class __pthread_internal_list + size=16 align=8 + base size=16 base align=8 +__pthread_internal_list (0x0x7ff7896ce060) 0 + +Class __pthread_mutex_s + size=40 align=8 + base size=40 base align=8 +__pthread_mutex_s (0x0x7ff7896ce0c0) 0 + +Class __pthread_cond_s + size=48 align=8 + base size=48 base align=8 +__pthread_cond_s (0x0x7ff7896ce120) 0 + +Class pthread_attr_t + size=56 align=8 + base size=56 base align=8 +pthread_attr_t (0x0x7ff7896ce3c0) 0 + +Class random_data + size=48 align=8 + base size=48 base align=8 +random_data (0x0x7ff7896ce660) 0 + +Class drand48_data + size=24 align=8 + base size=24 base align=8 +drand48_data (0x0x7ff7896ce6c0) 0 + +Vtable for std::exception +std::exception::_ZTVSt9exception: 5 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 (0x0x7ff789782480) 0 nearly-empty + vptr=((& std::exception::_ZTVSt9exception) + 16) + +Vtable for std::bad_exception +std::bad_exception::_ZTVSt13bad_exception: 5 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 (0x0x7ff789c58e38) 0 nearly-empty + vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16) + std::exception (0x0x7ff789782660) 0 nearly-empty + primary-for std::bad_exception (0x0x7ff789c58e38) + +Vtable for std::type_info +std::type_info::_ZTVSt9type_info: 8 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 (0x0x7ff789782840) 0 + vptr=((& std::type_info::_ZTVSt9type_info) + 16) + +Vtable for std::bad_cast +std::bad_cast::_ZTVSt8bad_cast: 5 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 (0x0x7ff789c58ea0) 0 nearly-empty + vptr=((& std::bad_cast::_ZTVSt8bad_cast) + 16) + std::exception (0x0x7ff789782c00) 0 nearly-empty + primary-for std::bad_cast (0x0x7ff789c58ea0) + +Vtable for std::bad_typeid +std::bad_typeid::_ZTVSt10bad_typeid: 5 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 (0x0x7ff789c58f08) 0 nearly-empty + vptr=((& std::bad_typeid::_ZTVSt10bad_typeid) + 16) + std::exception (0x0x7ff789782de0) 0 nearly-empty + primary-for std::bad_typeid (0x0x7ff789c58f08) + +Class std::__exception_ptr::exception_ptr + size=8 align=8 + base size=8 base align=8 +std::__exception_ptr::exception_ptr (0x0x7ff7897b4000) 0 + +Vtable for std::nested_exception +std::nested_exception::_ZTVSt16nested_exception: 4 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 (0x0x7ff7897b45a0) 0 + vptr=((& std::nested_exception::_ZTVSt16nested_exception) + 16) + +Vtable for std::bad_alloc +std::bad_alloc::_ZTVSt9bad_alloc: 5 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 (0x0x7ff789c58f70) 0 nearly-empty + vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16) + std::exception (0x0x7ff7897b4c60) 0 nearly-empty + primary-for std::bad_alloc (0x0x7ff789c58f70) + +Vtable for std::bad_array_new_length +std::bad_array_new_length::_ZTVSt20bad_array_new_length: 5 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 (0x0x7ff7897e4000) 0 nearly-empty + vptr=((& std::bad_array_new_length::_ZTVSt20bad_array_new_length) + 16) + std::bad_alloc (0x0x7ff7897e4068) 0 nearly-empty + primary-for std::bad_array_new_length (0x0x7ff7897e4000) + std::exception (0x0x7ff7897b4e40) 0 nearly-empty + primary-for std::bad_alloc (0x0x7ff7897e4068) + +Class std::nothrow_t + size=1 align=1 + base size=0 base align=1 +std::nothrow_t (0x0x7ff7897eb060) 0 empty + +Class std::__allocator_traits_base + size=1 align=1 + base size=0 base align=1 +std::__allocator_traits_base (0x0x7ff7897eb240) 0 empty + +Class std::__numeric_limits_base + size=1 align=1 + base size=0 base align=1 +std::__numeric_limits_base (0x0x7ff789461720) 0 empty + +Class qIsNull(double)::U + size=8 align=8 + base size=8 base align=8 +qIsNull(double)::U (0x0x7ff7896431e0) 0 + +Class qIsNull(float)::U + size=4 align=4 + base size=4 base align=4 +qIsNull(float)::U (0x0x7ff7896432a0) 0 + +Class QSysInfo + size=1 align=1 + base size=0 base align=1 +QSysInfo (0x0x7ff7890dbc00) 0 empty + +Class QMessageLogContext + size=32 align=8 + base size=32 base align=8 +QMessageLogContext (0x0x7ff7890dbd20) 0 + +Class QMessageLogger + size=32 align=8 + base size=32 base align=8 +QMessageLogger (0x0x7ff7891100c0) 0 + +Class QFlag + size=4 align=4 + base size=4 base align=4 +QFlag (0x0x7ff789110600) 0 + +Class QIncompatibleFlag + size=4 align=4 + base size=4 base align=4 +QIncompatibleFlag (0x0x7ff789153d80) 0 + +Class std::__atomic_flag_base + size=1 align=1 + base size=1 base align=1 +std::__atomic_flag_base (0x0x7ff78920a1e0) 0 + +Class std::atomic_flag + size=1 align=1 + base size=1 base align=1 +std::atomic_flag (0x0x7ff789197ea0) 0 + std::__atomic_flag_base (0x0x7ff78920a240) 0 + +Class QAtomicInt + size=4 align=4 + base size=4 base align=4 +QAtomicInt (0x0x7ff788f2e618) 0 + QAtomicInteger (0x0x7ff788f2e680) 0 + QBasicAtomicInteger (0x0x7ff788d391e0) 0 + +Class QInternal + size=1 align=1 + base size=0 base align=1 +QInternal (0x0x7ff7889584e0) 0 empty + +Class QtPrivate::QSlotObjectBase + size=16 align=8 + base size=16 base align=8 +QtPrivate::QSlotObjectBase (0x0x7ff78898fa80) 0 + +Class QGenericArgument + size=16 align=8 + base size=16 base align=8 +QGenericArgument (0x0x7ff7889d61e0) 0 + +Class QGenericReturnArgument + size=16 align=8 + base size=16 base align=8 +QGenericReturnArgument (0x0x7ff7889d4208) 0 + QGenericArgument (0x0x7ff7889d6480) 0 + +Class QMetaObject + size=48 align=8 + base size=48 base align=8 +QMetaObject (0x0x7ff7889d68a0) 0 + +Class QMetaObject::Connection + size=8 align=8 + base size=8 base align=8 +QMetaObject::Connection (0x0x7ff7889d6cc0) 0 + +Class QLatin1Char + size=1 align=1 + base size=1 base align=1 +QLatin1Char (0x0x7ff78868a7e0) 0 + +Class QChar + size=2 align=2 + base size=2 base align=2 +QChar (0x0x7ff78868aa80) 0 + +Class QtPrivate::RefCount + size=4 align=4 + base size=4 base align=4 +QtPrivate::RefCount (0x0x7ff78875a8a0) 0 + +Class QArrayData + size=24 align=8 + base size=24 base align=8 +QArrayData (0x0x7ff78875ac00) 0 + +Class QtPrivate::QContainerImplHelper + size=1 align=1 + base size=0 base align=1 +QtPrivate::QContainerImplHelper (0x0x7ff7887b3f00) 0 empty + +Class lconv + size=96 align=8 + base size=96 base align=8 +lconv (0x0x7ff788495780) 0 + +Vtable for __cxxabiv1::__forced_unwind +__cxxabiv1::__forced_unwind::_ZTVN10__cxxabiv115__forced_unwindE: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN10__cxxabiv115__forced_unwindE) +16 0 +24 0 +32 (int (*)(...))__cxa_pure_virtual + +Class __cxxabiv1::__forced_unwind + size=8 align=8 + base size=8 base align=8 +__cxxabiv1::__forced_unwind (0x0x7ff788495840) 0 nearly-empty + vptr=((& __cxxabiv1::__forced_unwind::_ZTVN10__cxxabiv115__forced_unwindE) + 16) + +Class sched_param + size=4 align=4 + base size=4 base align=4 +sched_param (0x0x7ff78855c960) 0 + +Class timex + size=208 align=8 + base size=208 base align=8 +timex (0x0x7ff78855ca20) 0 + +Class tm + size=56 align=8 + base size=56 base align=8 +tm (0x0x7ff78855ca80) 0 + +Class itimerspec + size=32 align=8 + base size=32 base align=8 +itimerspec (0x0x7ff78855cae0) 0 + +Class _pthread_cleanup_buffer + size=32 align=8 + base size=32 base align=8 +_pthread_cleanup_buffer (0x0x7ff78855cb40) 0 + +Class __pthread_cleanup_frame + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_frame (0x0x7ff78855cc60) 0 + +Class __pthread_cleanup_class + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_class (0x0x7ff78855ccc0) 0 + +Class _IO_marker + size=24 align=8 + base size=24 base align=8 +_IO_marker (0x0x7ff78829dc60) 0 + +Class _IO_FILE + size=216 align=8 + base size=216 base align=8 +_IO_FILE (0x0x7ff78829dcc0) 0 + +Class std::_Hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Hash_impl (0x0x7ff788459d20) 0 empty + +Class std::_Fnv_hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Fnv_hash_impl (0x0x7ff788459ea0) 0 empty + +Class std::locale + size=8 align=8 + base size=8 base align=8 +std::locale (0x0x7ff788204060) 0 + +Vtable for std::locale::facet +std::locale::facet::_ZTVNSt6locale5facetE: 4 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 (0x0x7ff788204420) 0 + vptr=((& std::locale::facet::_ZTVNSt6locale5facetE) + 16) + +Class std::locale::id + size=8 align=8 + base size=8 base align=8 +std::locale::id (0x0x7ff7882046c0) 0 + +Class std::locale::_Impl + size=40 align=8 + base size=40 base align=8 +std::locale::_Impl (0x0x7ff7882048a0) 0 + +Class std::__cow_string + size=8 align=8 + base size=8 base align=8 +std::__cow_string (0x0x7ff787e668a0) 0 + +Vtable for std::logic_error +std::logic_error::_ZTVSt11logic_error: 5 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 (0x0x7ff787e791a0) 0 + vptr=((& std::logic_error::_ZTVSt11logic_error) + 16) + std::exception (0x0x7ff787e66960) 0 nearly-empty + primary-for std::logic_error (0x0x7ff787e791a0) + +Vtable for std::domain_error +std::domain_error::_ZTVSt12domain_error: 5 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 (0x0x7ff787e79208) 0 + vptr=((& std::domain_error::_ZTVSt12domain_error) + 16) + std::logic_error (0x0x7ff787e79270) 0 + primary-for std::domain_error (0x0x7ff787e79208) + std::exception (0x0x7ff787e669c0) 0 nearly-empty + primary-for std::logic_error (0x0x7ff787e79270) + +Vtable for std::invalid_argument +std::invalid_argument::_ZTVSt16invalid_argument: 5 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 (0x0x7ff787e792d8) 0 + vptr=((& std::invalid_argument::_ZTVSt16invalid_argument) + 16) + std::logic_error (0x0x7ff787e79340) 0 + primary-for std::invalid_argument (0x0x7ff787e792d8) + std::exception (0x0x7ff787e66a20) 0 nearly-empty + primary-for std::logic_error (0x0x7ff787e79340) + +Vtable for std::length_error +std::length_error::_ZTVSt12length_error: 5 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 (0x0x7ff787e793a8) 0 + vptr=((& std::length_error::_ZTVSt12length_error) + 16) + std::logic_error (0x0x7ff787e79410) 0 + primary-for std::length_error (0x0x7ff787e793a8) + std::exception (0x0x7ff787e66a80) 0 nearly-empty + primary-for std::logic_error (0x0x7ff787e79410) + +Vtable for std::out_of_range +std::out_of_range::_ZTVSt12out_of_range: 5 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 (0x0x7ff787e79478) 0 + vptr=((& std::out_of_range::_ZTVSt12out_of_range) + 16) + std::logic_error (0x0x7ff787e794e0) 0 + primary-for std::out_of_range (0x0x7ff787e79478) + std::exception (0x0x7ff787e66ae0) 0 nearly-empty + primary-for std::logic_error (0x0x7ff787e794e0) + +Vtable for std::runtime_error +std::runtime_error::_ZTVSt13runtime_error: 5 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 (0x0x7ff787e79548) 0 + vptr=((& std::runtime_error::_ZTVSt13runtime_error) + 16) + std::exception (0x0x7ff787e66b40) 0 nearly-empty + primary-for std::runtime_error (0x0x7ff787e79548) + +Vtable for std::range_error +std::range_error::_ZTVSt11range_error: 5 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 (0x0x7ff787e795b0) 0 + vptr=((& std::range_error::_ZTVSt11range_error) + 16) + std::runtime_error (0x0x7ff787e79618) 0 + primary-for std::range_error (0x0x7ff787e795b0) + std::exception (0x0x7ff787e66ba0) 0 nearly-empty + primary-for std::runtime_error (0x0x7ff787e79618) + +Vtable for std::overflow_error +std::overflow_error::_ZTVSt14overflow_error: 5 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 (0x0x7ff787e79680) 0 + vptr=((& std::overflow_error::_ZTVSt14overflow_error) + 16) + std::runtime_error (0x0x7ff787e796e8) 0 + primary-for std::overflow_error (0x0x7ff787e79680) + std::exception (0x0x7ff787e66c00) 0 nearly-empty + primary-for std::runtime_error (0x0x7ff787e796e8) + +Vtable for std::underflow_error +std::underflow_error::_ZTVSt15underflow_error: 5 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 (0x0x7ff787e79750) 0 + vptr=((& std::underflow_error::_ZTVSt15underflow_error) + 16) + std::runtime_error (0x0x7ff787e797b8) 0 + primary-for std::underflow_error (0x0x7ff787e79750) + std::exception (0x0x7ff787e66c60) 0 nearly-empty + primary-for std::runtime_error (0x0x7ff787e797b8) + +Vtable for std::_V2::error_category +std::_V2::error_category::_ZTVNSt3_V214error_categoryE: 10 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt3_V214error_categoryE) +16 0 +24 0 +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 (0x0x7ff787e66de0) 0 nearly-empty + vptr=((& std::_V2::error_category::_ZTVNSt3_V214error_categoryE) + 16) + +Class std::error_code + size=16 align=8 + base size=16 base align=8 +std::error_code (0x0x7ff787ebc180) 0 + +Class std::error_condition + size=16 align=8 + base size=16 base align=8 +std::error_condition (0x0x7ff787ebc9c0) 0 + +Vtable for std::system_error +std::system_error::_ZTVSt12system_error: 5 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 (0x0x7ff787e79bc8) 0 + vptr=((& std::system_error::_ZTVSt12system_error) + 16) + std::runtime_error (0x0x7ff787e79c30) 0 + primary-for std::system_error (0x0x7ff787e79bc8) + std::exception (0x0x7ff787eea5a0) 0 nearly-empty + primary-for std::runtime_error (0x0x7ff787e79c30) + +Vtable for std::ios_base::failure +std::ios_base::failure::_ZTVNSt8ios_base7failureB5cxx11E: 5 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 (0x0x7ff787e79ea0) 0 + vptr=((& std::ios_base::failure::_ZTVNSt8ios_base7failureB5cxx11E) + 16) + std::system_error (0x0x7ff787e79f08) 0 + primary-for std::ios_base::failure (0x0x7ff787e79ea0) + std::runtime_error (0x0x7ff787e79f70) 0 + primary-for std::system_error (0x0x7ff787e79f08) + std::exception (0x0x7ff787f20b40) 0 nearly-empty + primary-for std::runtime_error (0x0x7ff787e79f70) + +Class std::ios_base::_Callback_list + size=24 align=8 + base size=24 base align=8 +std::ios_base::_Callback_list (0x0x7ff787f20ba0) 0 + +Class std::ios_base::_Words + size=16 align=8 + base size=16 base align=8 +std::ios_base::_Words (0x0x7ff787f20c00) 0 + +Class std::ios_base::Init + size=1 align=1 + base size=0 base align=1 +std::ios_base::Init (0x0x7ff787f20c60) 0 empty + +Vtable for std::ios_base +std::ios_base::_ZTVSt8ios_base: 4 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 (0x0x7ff787f20ae0) 0 + vptr=((& std::ios_base::_ZTVSt8ios_base) + 16) + +Class std::ctype_base + size=1 align=1 + base size=0 base align=1 +std::ctype_base (0x0x7ff7880175a0) 0 empty + +Class std::__num_base + size=1 align=1 + base size=0 base align=1 +std::__num_base (0x0x7ff787cd2780) 0 empty + +VTT for std::basic_ostream +std::basic_ostream::_ZTTSo: 2 entries +0 ((& std::basic_ostream::_ZTVSo) + 24) +8 ((& std::basic_ostream::_ZTVSo) + 64) + +VTT for std::basic_ostream +std::basic_ostream::_ZTTSt13basic_ostreamIwSt11char_traitsIwEE: 2 entries +0 ((& std::basic_ostream::_ZTVSt13basic_ostreamIwSt11char_traitsIwEE) + 24) +8 ((& std::basic_ostream::_ZTVSt13basic_ostreamIwSt11char_traitsIwEE) + 64) + +VTT for std::basic_istream +std::basic_istream::_ZTTSi: 2 entries +0 ((& std::basic_istream::_ZTVSi) + 24) +8 ((& std::basic_istream::_ZTVSi) + 64) + +VTT for std::basic_istream +std::basic_istream::_ZTTSt13basic_istreamIwSt11char_traitsIwEE: 2 entries +0 ((& std::basic_istream::_ZTVSt13basic_istreamIwSt11char_traitsIwEE) + 24) +8 ((& std::basic_istream::_ZTVSt13basic_istreamIwSt11char_traitsIwEE) + 64) + +Construction vtable for std::basic_istream (0x0x7ff78787e680 instance) in std::basic_iostream +std::basic_iostream::_ZTCSd0_Si: 10 entries +0 24 +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISi) +24 0 +32 0 +40 18446744073709551592 +48 (int (*)(...))-24 +56 (int (*)(...))(& _ZTISi) +64 0 +72 0 + +Construction vtable for std::basic_ostream (0x0x7ff78787e750 instance) in std::basic_iostream +std::basic_iostream::_ZTCSd16_So: 10 entries +0 8 +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISo) +24 0 +32 0 +40 18446744073709551608 +48 (int (*)(...))-8 +56 (int (*)(...))(& _ZTISo) +64 0 +72 0 + +VTT for std::basic_iostream +std::basic_iostream::_ZTTSd: 7 entries +0 ((& std::basic_iostream::_ZTVSd) + 24) +8 ((& std::basic_iostream::_ZTCSd0_Si) + 24) +16 ((& std::basic_iostream::_ZTCSd0_Si) + 64) +24 ((& std::basic_iostream::_ZTCSd16_So) + 24) +32 ((& std::basic_iostream::_ZTCSd16_So) + 64) +40 ((& std::basic_iostream::_ZTVSd) + 104) +48 ((& std::basic_iostream::_ZTVSd) + 64) + +Construction vtable for std::basic_istream (0x0x7ff7878bd410 instance) in std::basic_iostream +std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE0_St13basic_istreamIwS1_E: 10 entries +0 24 +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISt13basic_istreamIwSt11char_traitsIwEE) +24 0 +32 0 +40 18446744073709551592 +48 (int (*)(...))-24 +56 (int (*)(...))(& _ZTISt13basic_istreamIwSt11char_traitsIwEE) +64 0 +72 0 + +Construction vtable for std::basic_ostream (0x0x7ff7878bd4e0 instance) in std::basic_iostream +std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE16_St13basic_ostreamIwS1_E: 10 entries +0 8 +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISt13basic_ostreamIwSt11char_traitsIwEE) +24 0 +32 0 +40 18446744073709551608 +48 (int (*)(...))-8 +56 (int (*)(...))(& _ZTISt13basic_ostreamIwSt11char_traitsIwEE) +64 0 +72 0 + +VTT for std::basic_iostream +std::basic_iostream::_ZTTSt14basic_iostreamIwSt11char_traitsIwEE: 7 entries +0 ((& std::basic_iostream::_ZTVSt14basic_iostreamIwSt11char_traitsIwEE) + 24) +8 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE0_St13basic_istreamIwS1_E) + 24) +16 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE0_St13basic_istreamIwS1_E) + 64) +24 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE16_St13basic_ostreamIwS1_E) + 24) +32 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE16_St13basic_ostreamIwS1_E) + 64) +40 ((& std::basic_iostream::_ZTVSt14basic_iostreamIwSt11char_traitsIwEE) + 104) +48 ((& std::basic_iostream::_ZTVSt14basic_iostreamIwSt11char_traitsIwEE) + 64) + +Class QByteArrayDataPtr + size=8 align=8 + base size=8 base align=8 +QByteArrayDataPtr (0x0x7ff7878f7120) 0 + +Class QByteArray + size=8 align=8 + base size=8 base align=8 +QByteArray (0x0x7ff7878f7180) 0 + +Class QByteRef + size=16 align=8 + base size=12 base align=8 +QByteRef (0x0x7ff787a21540) 0 + +Class QStringDataPtr + size=8 align=8 + base size=8 base align=8 +QStringDataPtr (0x0x7ff7876c13c0) 0 + +Class QStringView + size=16 align=8 + base size=16 base align=8 +QStringView (0x0x7ff7876c1840) 0 + +Class QLatin1String + size=16 align=8 + base size=16 base align=8 +QLatin1String (0x0x7ff787796600) 0 + +Class QString::Null + size=1 align=1 + base size=0 base align=1 +QString::Null (0x0x7ff787834060) 0 empty + +Class QString + size=8 align=8 + base size=8 base align=8 +QString (0x0x7ff787834000) 0 + +Class QCharRef + size=16 align=8 + base size=12 base align=8 +QCharRef (0x0x7ff7876251e0) 0 + +Class QStringRef + size=16 align=8 + base size=16 base align=8 +QStringRef (0x0x7ff787396a20) 0 + +Class QtPrivate::QHashCombine + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombine (0x0x7ff7871a2d20) 0 empty + +Class QtPrivate::QHashCombineCommutative + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombineCommutative (0x0x7ff7871a2de0) 0 empty + +Class std::_Bit_reference + size=16 align=8 + base size=16 base align=8 +std::_Bit_reference (0x0x7ff786e8d300) 0 + +Class std::_Bit_iterator_base + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator_base (0x0x7ff78743b820) 0 + std::iterator (0x0x7ff786e8da20) 0 empty + +Class std::_Bit_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator (0x0x7ff78743b958) 0 + std::_Bit_iterator_base (0x0x7ff78743b9c0) 0 + std::iterator (0x0x7ff786eba0c0) 0 empty + +Class std::_Bit_const_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_const_iterator (0x0x7ff78743ba28) 0 + std::_Bit_iterator_base (0x0x7ff78743ba90) 0 + std::iterator (0x0x7ff786eba8a0) 0 empty + +Class std::__detail::_List_node_base + size=16 align=8 + base size=16 base align=8 +std::__detail::_List_node_base (0x0x7ff786c77f00) 0 + +Class QListData::NotArrayCompatibleLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotArrayCompatibleLayout (0x0x7ff786d7ccc0) 0 empty + +Class QListData::NotIndirectLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotIndirectLayout (0x0x7ff786d7cd20) 0 empty + +Class QListData::ArrayCompatibleLayout + size=1 align=1 + base size=1 base align=1 +QListData::ArrayCompatibleLayout (0x0x7ff786fec4e0) 0 empty + QListData::NotIndirectLayout (0x0x7ff786d7cd80) 0 empty + +Class QListData::InlineWithPaddingLayout + size=1 align=1 + base size=1 base align=1 +QListData::InlineWithPaddingLayout (0x0x7ff786d730e0) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7ff786d7cde0) 0 empty + QListData::NotIndirectLayout (0x0x7ff786d7ce40) 0 empty + +Class QListData::IndirectLayout + size=1 align=1 + base size=1 base align=1 +QListData::IndirectLayout (0x0x7ff786fec548) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7ff786d7cea0) 0 empty + +Class QListData::Data + size=24 align=8 + base size=24 base align=8 +QListData::Data (0x0x7ff786d7cf00) 0 + +Class QListData + size=8 align=8 + base size=8 base align=8 +QListData (0x0x7ff786d7cc60) 0 + +Class QRegExp + size=8 align=8 + base size=8 base align=8 +QRegExp (0x0x7ff786a90120) 0 + +Class QStringMatcher::Data + size=272 align=8 + base size=272 base align=8 +QStringMatcher::Data (0x0x7ff786b63780) 0 + +Class QStringMatcher + size=1048 align=8 + base size=1048 base align=8 +QStringMatcher (0x0x7ff786b63720) 0 + +Class QStringList + size=8 align=8 + base size=8 base align=8 +QStringList (0x0x7ff786b69270) 0 + QList (0x0x7ff786b692d8) 0 + QListSpecialMethods (0x0x7ff786b639c0) 0 empty + +Class QScopedPointerPodDeleter + size=1 align=1 + base size=0 base align=1 +QScopedPointerPodDeleter (0x0x7ff786c29540) 0 empty + +Class std::_Rb_tree_node_base + size=32 align=8 + base size=32 base align=8 +std::_Rb_tree_node_base (0x0x7ff7868b3660) 0 + +Class std::_Rb_tree_header + size=40 align=8 + base size=40 base align=8 +std::_Rb_tree_header (0x0x7ff7868b39c0) 0 + +Class std::__erased_type + size=1 align=1 + base size=0 base align=1 +std::__erased_type (0x0x7ff78668bf60) 0 empty + +Class std::allocator_arg_t + size=1 align=1 + base size=0 base align=1 +std::allocator_arg_t (0x0x7ff7866b1000) 0 empty + +Class std::__uses_alloc_base + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc_base (0x0x7ff7866b1180) 0 empty + +Class std::__uses_alloc0::_Sink + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc0::_Sink (0x0x7ff7866b1240) 0 empty + +Class std::__uses_alloc0 + size=1 align=1 + base size=1 base align=1 +std::__uses_alloc0 (0x0x7ff786a30618) 0 + std::__uses_alloc_base (0x0x7ff7866b11e0) 0 empty + +Class std::_Swallow_assign + size=1 align=1 + base size=0 base align=1 +std::_Swallow_assign (0x0x7ff7868195a0) 0 empty + +Class QtPrivate::AbstractDebugStreamFunction + size=16 align=8 + base size=16 base align=8 +QtPrivate::AbstractDebugStreamFunction (0x0x7ff78643aa20) 0 + +Class QtPrivate::AbstractComparatorFunction + size=24 align=8 + base size=24 base align=8 +QtPrivate::AbstractComparatorFunction (0x0x7ff78643ad80) 0 + +Class QtPrivate::AbstractConverterFunction + size=8 align=8 + base size=8 base align=8 +QtPrivate::AbstractConverterFunction (0x0x7ff78645f300) 0 + +Class QMetaType + size=80 align=8 + base size=80 base align=8 +QMetaType (0x0x7ff78645f840) 0 + +Class QtMetaTypePrivate::VariantData + size=24 align=8 + base size=20 base align=8 +QtMetaTypePrivate::VariantData (0x0x7ff7864c3a20) 0 + +Class QtMetaTypePrivate::VectorBoolElements + size=1 align=1 + base size=0 base align=1 +QtMetaTypePrivate::VectorBoolElements (0x0x7ff7864e1120) 0 empty + +Class QtMetaTypePrivate::QSequentialIterableImpl + size=104 align=8 + base size=104 base align=8 +QtMetaTypePrivate::QSequentialIterableImpl (0x0x7ff7864e1f60) 0 + +Class QtMetaTypePrivate::QAssociativeIterableImpl + size=112 align=8 + base size=112 base align=8 +QtMetaTypePrivate::QAssociativeIterableImpl (0x0x7ff7865d3660) 0 + +Class QtMetaTypePrivate::QPairVariantInterfaceImpl + size=40 align=8 + base size=40 base align=8 +QtMetaTypePrivate::QPairVariantInterfaceImpl (0x0x7ff786229ba0) 0 + +Class std::chrono::_V2::system_clock + size=1 align=1 + base size=0 base align=1 +std::chrono::_V2::system_clock (0x0x7ff7860679c0) 0 empty + +Class std::chrono::_V2::steady_clock + size=1 align=1 + base size=0 base align=1 +std::chrono::_V2::steady_clock (0x0x7ff785d9a480) 0 empty + +Vtable for QObjectData +QObjectData::_ZTV11QObjectData: 4 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 (0x0x7ff785d9a4e0) 0 + vptr=((& QObjectData::_ZTV11QObjectData) + 16) + +Class QObject::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObject::QPrivateSignal (0x0x7ff785d9a6c0) 0 empty + +Vtable for QObject +QObject::_ZTV7QObject: 14 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 (0x0x7ff785d9a660) 0 + vptr=((& QObject::_ZTV7QObject) + 16) + +Vtable for QObjectUserData +QObjectUserData::_ZTV15QObjectUserData: 4 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 (0x0x7ff785e6c4e0) 0 nearly-empty + vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16) + +Class QSignalBlocker + size=16 align=8 + base size=10 base align=8 +QSignalBlocker (0x0x7ff785e6c660) 0 + +Class QAbstractAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractAnimation::QPrivateSignal (0x0x7ff785e6cf00) 0 empty + +Vtable for QAbstractAnimation +QAbstractAnimation::_ZTV18QAbstractAnimation: 18 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QAbstractAnimation) +16 (int (*)(...))QAbstractAnimation::metaObject +24 (int (*)(...))QAbstractAnimation::qt_metacast +32 (int (*)(...))QAbstractAnimation::qt_metacall +40 0 +48 0 +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 (0x0x7ff785e46820) 0 + vptr=((& QAbstractAnimation::_ZTV18QAbstractAnimation) + 16) + QObject (0x0x7ff785e6cea0) 0 + primary-for QAbstractAnimation (0x0x7ff785e46820) + +Class QAnimationDriver::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationDriver::QPrivateSignal (0x0x7ff785ea0300) 0 empty + +Vtable for QAnimationDriver +QAnimationDriver::_ZTV16QAnimationDriver: 18 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 (0x0x7ff785e46888) 0 + vptr=((& QAnimationDriver::_ZTV16QAnimationDriver) + 16) + QObject (0x0x7ff785ea02a0) 0 + primary-for QAnimationDriver (0x0x7ff785e46888) + +Class QEventLoop::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventLoop::QPrivateSignal (0x0x7ff785ea0540) 0 empty + +Vtable for QEventLoop +QEventLoop::_ZTV10QEventLoop: 14 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 (0x0x7ff785e468f0) 0 + vptr=((& QEventLoop::_ZTV10QEventLoop) + 16) + QObject (0x0x7ff785ea04e0) 0 + primary-for QEventLoop (0x0x7ff785e468f0) + +Class QEventLoopLocker + size=8 align=8 + base size=8 base align=8 +QEventLoopLocker (0x0x7ff785ea0de0) 0 + +Class QAbstractEventDispatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractEventDispatcher::QPrivateSignal (0x0x7ff785ea0ea0) 0 empty + +Class QAbstractEventDispatcher::TimerInfo + size=12 align=4 + base size=12 base align=4 +QAbstractEventDispatcher::TimerInfo (0x0x7ff785ea0f00) 0 + +Vtable for QAbstractEventDispatcher +QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher: 28 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI24QAbstractEventDispatcher) +16 (int (*)(...))QAbstractEventDispatcher::metaObject +24 (int (*)(...))QAbstractEventDispatcher::qt_metacast +32 (int (*)(...))QAbstractEventDispatcher::qt_metacall +40 0 +48 0 +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 (0x0x7ff785e46a28) 0 + vptr=((& QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher) + 16) + QObject (0x0x7ff785ea0e40) 0 + primary-for QAbstractEventDispatcher (0x0x7ff785e46a28) + +Vtable for std::bad_function_call +std::bad_function_call::_ZTVSt17bad_function_call: 5 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 (0x0x7ff785b783a8) 0 nearly-empty + vptr=((& std::bad_function_call::_ZTVSt17bad_function_call) + 16) + std::exception (0x0x7ff785b7d5a0) 0 nearly-empty + primary-for std::bad_function_call (0x0x7ff785b783a8) + +Class std::_Nocopy_types + size=16 align=8 + base size=16 base align=8 +std::_Nocopy_types (0x0x7ff785b7d660) 0 + +Class std::_Any_data + size=16 align=8 + base size=16 base align=8 +std::_Any_data (0x0x7ff785b7d6c0) 0 + +Class std::_Function_base + size=24 align=8 + base size=24 base align=8 +std::_Function_base (0x0x7ff785b7d9c0) 0 + +Class QMapNodeBase + size=24 align=8 + base size=24 base align=8 +QMapNodeBase (0x0x7ff785977960) 0 + +Class QMapDataBase + size=40 align=8 + base size=40 base align=8 +QMapDataBase (0x0x7ff7859af600) 0 + +Class QHashData::Node + size=16 align=8 + base size=16 base align=8 +QHashData::Node (0x0x7ff785a73f60) 0 + +Class QHashData + size=48 align=8 + base size=44 base align=8 +QHashData (0x0x7ff785a73f00) 0 + +Class QHashDummyValue + size=1 align=1 + base size=0 base align=1 +QHashDummyValue (0x0x7ff785a9e240) 0 empty + +Class QVariant::PrivateShared + size=16 align=8 + base size=12 base align=8 +QVariant::PrivateShared (0x0x7ff7857a87e0) 0 + +Class QVariant::Private::Data + size=8 align=8 + base size=8 base align=8 +QVariant::Private::Data (0x0x7ff7857a88a0) 0 + +Class QVariant::Private + size=16 align=8 + base size=12 base align=8 +QVariant::Private (0x0x7ff7857a8840) 0 + +Class QVariant::Handler + size=72 align=8 + base size=72 base align=8 +QVariant::Handler (0x0x7ff7857a8900) 0 + +Class QVariant + size=16 align=8 + base size=16 base align=8 +QVariant (0x0x7ff7857a8780) 0 + +Class QVariantComparisonHelper + size=8 align=8 + base size=8 base align=8 +QVariantComparisonHelper (0x0x7ff7858e2ba0) 0 + +Class QSequentialIterable::const_iterator + size=112 align=8 + base size=112 base align=8 +QSequentialIterable::const_iterator (0x0x7ff78555f240) 0 + +Class QSequentialIterable + size=104 align=8 + base size=104 base align=8 +QSequentialIterable (0x0x7ff78555f1e0) 0 + +Class QAssociativeIterable::const_iterator + size=120 align=8 + base size=120 base align=8 +QAssociativeIterable::const_iterator (0x0x7ff78555f360) 0 + +Class QAssociativeIterable + size=112 align=8 + base size=112 base align=8 +QAssociativeIterable (0x0x7ff78555f300) 0 + +Class QModelIndex + size=24 align=8 + base size=24 base align=8 +QModelIndex (0x0x7ff78562b4e0) 0 + +Class QPersistentModelIndex + size=8 align=8 + base size=8 base align=8 +QPersistentModelIndex (0x0x7ff78569d120) 0 + +Class QAbstractItemModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractItemModel::QPrivateSignal (0x0x7ff785753f00) 0 empty + +Vtable for QAbstractItemModel +QAbstractItemModel::_ZTV18QAbstractItemModel: 48 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QAbstractItemModel) +16 (int (*)(...))QAbstractItemModel::metaObject +24 (int (*)(...))QAbstractItemModel::qt_metacast +32 (int (*)(...))QAbstractItemModel::qt_metacall +40 0 +48 0 +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 (0x0x7ff785751f70) 0 + vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16) + QObject (0x0x7ff785753ea0) 0 + primary-for QAbstractItemModel (0x0x7ff785751f70) + +Class QAbstractTableModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTableModel::QPrivateSignal (0x0x7ff785431300) 0 empty + +Vtable for QAbstractTableModel +QAbstractTableModel::_ZTV19QAbstractTableModel: 48 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QAbstractTableModel) +16 (int (*)(...))QAbstractTableModel::metaObject +24 (int (*)(...))QAbstractTableModel::qt_metacast +32 (int (*)(...))QAbstractTableModel::qt_metacall +40 0 +48 0 +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 (0x0x7ff7853985b0) 0 + vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16) + QAbstractItemModel (0x0x7ff785398618) 0 + primary-for QAbstractTableModel (0x0x7ff7853985b0) + QObject (0x0x7ff7854312a0) 0 + primary-for QAbstractItemModel (0x0x7ff785398618) + +Class QAbstractListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractListModel::QPrivateSignal (0x0x7ff785431480) 0 empty + +Vtable for QAbstractListModel +QAbstractListModel::_ZTV18QAbstractListModel: 48 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QAbstractListModel) +16 (int (*)(...))QAbstractListModel::metaObject +24 (int (*)(...))QAbstractListModel::qt_metacast +32 (int (*)(...))QAbstractListModel::qt_metacall +40 0 +48 0 +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 (0x0x7ff785398680) 0 + vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16) + QAbstractItemModel (0x0x7ff7853986e8) 0 + primary-for QAbstractListModel (0x0x7ff785398680) + QObject (0x0x7ff785431420) 0 + primary-for QAbstractItemModel (0x0x7ff7853986e8) + +Vtable for QAbstractNativeEventFilter +QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI26QAbstractNativeEventFilter) +16 0 +24 0 +32 (int (*)(...))__cxa_pure_virtual + +Class QAbstractNativeEventFilter + size=16 align=8 + base size=16 base align=8 +QAbstractNativeEventFilter (0x0x7ff785431ba0) 0 + vptr=((& QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter) + 16) + +Class QAbstractProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractProxyModel::QPrivateSignal (0x0x7ff785431c60) 0 empty + +Vtable for QAbstractProxyModel +QAbstractProxyModel::_ZTV19QAbstractProxyModel: 53 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QAbstractProxyModel) +16 (int (*)(...))QAbstractProxyModel::metaObject +24 (int (*)(...))QAbstractProxyModel::qt_metacast +32 (int (*)(...))QAbstractProxyModel::qt_metacall +40 0 +48 0 +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 (0x0x7ff7853987b8) 0 + vptr=((& QAbstractProxyModel::_ZTV19QAbstractProxyModel) + 16) + QAbstractItemModel (0x0x7ff785398820) 0 + primary-for QAbstractProxyModel (0x0x7ff7853987b8) + QObject (0x0x7ff785431c00) 0 + primary-for QAbstractItemModel (0x0x7ff785398820) + +Class QAbstractState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractState::QPrivateSignal (0x0x7ff785431ea0) 0 empty + +Vtable for QAbstractState +QAbstractState::_ZTV14QAbstractState: 16 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI14QAbstractState) +16 (int (*)(...))QAbstractState::metaObject +24 (int (*)(...))QAbstractState::qt_metacast +32 (int (*)(...))QAbstractState::qt_metacall +40 0 +48 0 +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 (0x0x7ff785398888) 0 + vptr=((& QAbstractState::_ZTV14QAbstractState) + 16) + QObject (0x0x7ff785431e40) 0 + primary-for QAbstractState (0x0x7ff785398888) + +Class QAbstractTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTransition::QPrivateSignal (0x0x7ff7854bc120) 0 empty + +Vtable for QAbstractTransition +QAbstractTransition::_ZTV19QAbstractTransition: 16 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QAbstractTransition) +16 (int (*)(...))QAbstractTransition::metaObject +24 (int (*)(...))QAbstractTransition::qt_metacast +32 (int (*)(...))QAbstractTransition::qt_metacall +40 0 +48 0 +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 (0x0x7ff7853988f0) 0 + vptr=((& QAbstractTransition::_ZTV19QAbstractTransition) + 16) + QObject (0x0x7ff7854bc0c0) 0 + primary-for QAbstractTransition (0x0x7ff7853988f0) + +Class QAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationGroup::QPrivateSignal (0x0x7ff7854bc420) 0 empty + +Vtable for QAnimationGroup +QAnimationGroup::_ZTV15QAnimationGroup: 18 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QAnimationGroup) +16 (int (*)(...))QAnimationGroup::metaObject +24 (int (*)(...))QAnimationGroup::qt_metacast +32 (int (*)(...))QAnimationGroup::qt_metacall +40 0 +48 0 +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 (0x0x7ff785398958) 0 + vptr=((& QAnimationGroup::_ZTV15QAnimationGroup) + 16) + QAbstractAnimation (0x0x7ff7853989c0) 0 + primary-for QAnimationGroup (0x0x7ff785398958) + QObject (0x0x7ff7854bc3c0) 0 + primary-for QAbstractAnimation (0x0x7ff7853989c0) + +Class QBasicTimer + size=4 align=4 + base size=4 base align=4 +QBasicTimer (0x0x7ff78551b780) 0 + +Class QBitArray + size=8 align=8 + base size=8 base align=8 +QBitArray (0x0x7ff785555b40) 0 + +Class QBitRef + size=16 align=8 + base size=12 base align=8 +QBitRef (0x0x7ff7851dc000) 0 + +Class QIODevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIODevice::QPrivateSignal (0x0x7ff7852203c0) 0 empty + +Vtable for QIODevice +QIODevice::_ZTV9QIODevice: 30 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QIODevice) +16 (int (*)(...))QIODevice::metaObject +24 (int (*)(...))QIODevice::qt_metacast +32 (int (*)(...))QIODevice::qt_metacall +40 0 +48 0 +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 (0x0x7ff78520af08) 0 + vptr=((& QIODevice::_ZTV9QIODevice) + 16) + QObject (0x0x7ff785220360) 0 + primary-for QIODevice (0x0x7ff78520af08) + +Class QBuffer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBuffer::QPrivateSignal (0x0x7ff785220d20) 0 empty + +Vtable for QBuffer +QBuffer::_ZTV7QBuffer: 30 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 (0x0x7ff785243068) 0 + vptr=((& QBuffer::_ZTV7QBuffer) + 16) + QIODevice (0x0x7ff7852430d0) 0 + primary-for QBuffer (0x0x7ff785243068) + QObject (0x0x7ff785220cc0) 0 + primary-for QIODevice (0x0x7ff7852430d0) + +Class QByteArrayMatcher::Data + size=272 align=8 + base size=272 base align=8 +QByteArrayMatcher::Data (0x0x7ff78527c000) 0 + +Class QByteArrayMatcher + size=1040 align=8 + base size=1040 base align=8 +QByteArrayMatcher (0x0x7ff785220f60) 0 + +Class QStaticByteArrayMatcherBase::Skiptable + size=256 align=1 + base size=256 base align=1 +QStaticByteArrayMatcherBase::Skiptable (0x0x7ff78527c180) 0 + +Class QStaticByteArrayMatcherBase + size=256 align=16 + base size=256 base align=16 +QStaticByteArrayMatcherBase (0x0x7ff78527c120) 0 + +Class QSharedData + size=4 align=4 + base size=4 base align=4 +QSharedData (0x0x7ff7852ba060) 0 + +Class QDate + size=8 align=8 + base size=8 base align=8 +QDate (0x0x7ff7852ff000) 0 + +Class QTime + size=4 align=4 + base size=4 base align=4 +QTime (0x0x7ff78534e8a0) 0 + +Class QDateTime::ShortData + size=8 align=8 + base size=8 base align=8 +QDateTime::ShortData (0x0x7ff784fb5540) 0 + +Class QDateTime::Data + size=8 align=8 + base size=8 base align=8 +QDateTime::Data (0x0x7ff784fb55a0) 0 + +Class QDateTime + size=8 align=8 + base size=8 base align=8 +QDateTime (0x0x7ff784fb54e0) 0 + +Class QLocale + size=8 align=8 + base size=8 base align=8 +QLocale (0x0x7ff785086c60) 0 + +Vtable for QTextStream +QTextStream::_ZTV11QTextStream: 4 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 (0x0x7ff784da9240) 0 + vptr=((& QTextStream::_ZTV11QTextStream) + 16) + +Class QTextStreamManipulator + size=40 align=8 + base size=38 base align=8 +QTextStreamManipulator (0x0x7ff784da9ae0) 0 + +Class QContiguousCacheData + size=24 align=4 + base size=24 base align=4 +QContiguousCacheData (0x0x7ff784e7e600) 0 + +Class QtSharedPointer::NormalDeleter + size=1 align=1 + base size=0 base align=1 +QtSharedPointer::NormalDeleter (0x0x7ff784ece2a0) 0 empty + +Class QtSharedPointer::ExternalRefCountData + size=16 align=8 + base size=16 base align=8 +QtSharedPointer::ExternalRefCountData (0x0x7ff784ece420) 0 + +Class QDebug::Stream + size=80 align=8 + base size=76 base align=8 +QDebug::Stream (0x0x7ff784b9c060) 0 + +Class QDebug + size=8 align=8 + base size=8 base align=8 +QDebug (0x0x7ff784b9c000) 0 + +Class QDebugStateSaver + size=8 align=8 + base size=8 base align=8 +QDebugStateSaver (0x0x7ff784d1f0c0) 0 + +Class QNoDebug + size=1 align=1 + base size=0 base align=1 +QNoDebug (0x0x7ff784d1f180) 0 empty + +Class QCborError + size=4 align=4 + base size=4 base align=4 +QCborError (0x0x7ff7849a5480) 0 + +Class QRegularExpression + size=8 align=8 + base size=8 base align=8 +QRegularExpression (0x0x7ff7849a5c00) 0 + +Class QRegularExpressionMatch + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatch (0x0x7ff784a5dae0) 0 + +Class QRegularExpressionMatchIterator + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatchIterator (0x0x7ff784ac88a0) 0 + +Class QUrl + size=8 align=8 + base size=8 base align=8 +QUrl (0x0x7ff784b3e300) 0 + +Class QUuid + size=16 align=4 + base size=16 base align=4 +QUuid (0x0x7ff7848922a0) 0 + +Class QCborParserError + size=16 align=8 + base size=12 base align=8 +QCborParserError (0x0x7ff7848f4de0) 0 + +Class QCborValue + size=24 align=8 + base size=20 base align=8 +QCborValue (0x0x7ff7848f4ea0) 0 + +Class QCborValueRef + size=16 align=8 + base size=16 base align=8 +QCborValueRef (0x0x7ff78435dea0) 0 + +Class QCborArray::Iterator + size=16 align=8 + base size=16 base align=8 +QCborArray::Iterator (0x0x7ff7843fc900) 0 + +Class QCborArray::ConstIterator + size=16 align=8 + base size=16 base align=8 +QCborArray::ConstIterator (0x0x7ff7843fc960) 0 + +Class QCborArray + size=8 align=8 + base size=8 base align=8 +QCborArray (0x0x7ff7843fc8a0) 0 + +Class QCborMap::Iterator + size=16 align=8 + base size=16 base align=8 +QCborMap::Iterator (0x0x7ff784511360) 0 + +Class QCborMap::ConstIterator + size=16 align=8 + base size=16 base align=8 +QCborMap::ConstIterator (0x0x7ff7845113c0) 0 + +Class QCborMap + size=8 align=8 + base size=8 base align=8 +QCborMap (0x0x7ff784511300) 0 + +Class qfloat16 + size=2 align=2 + base size=2 base align=2 +qfloat16 (0x0x7ff78430bae0) 0 + +Class QCborStreamWriter + size=8 align=8 + base size=8 base align=8 +QCborStreamWriter (0x0x7ff783fc2a80) 0 + +Class QCborStreamReader + size=24 align=8 + base size=20 base align=8 +QCborStreamReader (0x0x7ff783ff77e0) 0 + +Class QCollatorSortKey + size=8 align=8 + base size=8 base align=8 +QCollatorSortKey (0x0x7ff78407d900) 0 + +Class QCollator + size=8 align=8 + base size=8 base align=8 +QCollator (0x0x7ff78407dae0) 0 + +Class QCommandLineOption + size=8 align=8 + base size=8 base align=8 +QCommandLineOption (0x0x7ff783d910c0) 0 + +Vtable for QEvent +QEvent::_ZTV6QEvent: 4 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 (0x0x7ff783de87e0) 0 + vptr=((& QEvent::_ZTV6QEvent) + 16) + +Vtable for QTimerEvent +QTimerEvent::_ZTV11QTimerEvent: 4 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 (0x0x7ff783de6270) 0 + vptr=((& QTimerEvent::_ZTV11QTimerEvent) + 16) + QEvent (0x0x7ff783de8ba0) 0 + primary-for QTimerEvent (0x0x7ff783de6270) + +Vtable for QChildEvent +QChildEvent::_ZTV11QChildEvent: 4 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 (0x0x7ff783de62d8) 0 + vptr=((& QChildEvent::_ZTV11QChildEvent) + 16) + QEvent (0x0x7ff783de8c60) 0 + primary-for QChildEvent (0x0x7ff783de62d8) + +Vtable for QDynamicPropertyChangeEvent +QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent: 4 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 (0x0x7ff783de6820) 0 + vptr=((& QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent) + 16) + QEvent (0x0x7ff783e32300) 0 + primary-for QDynamicPropertyChangeEvent (0x0x7ff783de6820) + +Vtable for QDeferredDeleteEvent +QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent: 4 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 (0x0x7ff783de6888) 0 + vptr=((& QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent) + 16) + QEvent (0x0x7ff783e323c0) 0 + primary-for QDeferredDeleteEvent (0x0x7ff783de6888) + +Class QCoreApplication::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QCoreApplication::QPrivateSignal (0x0x7ff783e324e0) 0 empty + +Vtable for QCoreApplication +QCoreApplication::_ZTV16QCoreApplication: 16 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 (0x0x7ff783de68f0) 0 + vptr=((& QCoreApplication::_ZTV16QCoreApplication) + 16) + QObject (0x0x7ff783e32480) 0 + primary-for QCoreApplication (0x0x7ff783de68f0) + +Class QCommandLineParser + size=8 align=8 + base size=8 base align=8 +QCommandLineParser (0x0x7ff783e32720) 0 + +Class QConcatenateTablesProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QConcatenateTablesProxyModel::QPrivateSignal (0x0x7ff783e328a0) 0 empty + +Vtable for QConcatenateTablesProxyModel +QConcatenateTablesProxyModel::_ZTV28QConcatenateTablesProxyModel: 48 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI28QConcatenateTablesProxyModel) +16 (int (*)(...))QConcatenateTablesProxyModel::metaObject +24 (int (*)(...))QConcatenateTablesProxyModel::qt_metacast +32 (int (*)(...))QConcatenateTablesProxyModel::qt_metacall +40 (int (*)(...))QConcatenateTablesProxyModel::~QConcatenateTablesProxyModel +48 (int (*)(...))QConcatenateTablesProxyModel::~QConcatenateTablesProxyModel +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 (*)(...))QConcatenateTablesProxyModel::index +120 (int (*)(...))QConcatenateTablesProxyModel::parent +128 (int (*)(...))QAbstractItemModel::sibling +136 (int (*)(...))QConcatenateTablesProxyModel::rowCount +144 (int (*)(...))QConcatenateTablesProxyModel::columnCount +152 (int (*)(...))QAbstractItemModel::hasChildren +160 (int (*)(...))QConcatenateTablesProxyModel::data +168 (int (*)(...))QConcatenateTablesProxyModel::setData +176 (int (*)(...))QConcatenateTablesProxyModel::headerData +184 (int (*)(...))QAbstractItemModel::setHeaderData +192 (int (*)(...))QConcatenateTablesProxyModel::itemData +200 (int (*)(...))QConcatenateTablesProxyModel::setItemData +208 (int (*)(...))QConcatenateTablesProxyModel::mimeTypes +216 (int (*)(...))QConcatenateTablesProxyModel::mimeData +224 (int (*)(...))QConcatenateTablesProxyModel::canDropMimeData +232 (int (*)(...))QConcatenateTablesProxyModel::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 (*)(...))QConcatenateTablesProxyModel::flags +328 (int (*)(...))QAbstractItemModel::sort +336 (int (*)(...))QAbstractItemModel::buddy +344 (int (*)(...))QAbstractItemModel::match +352 (int (*)(...))QConcatenateTablesProxyModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractItemModel::submit +376 (int (*)(...))QAbstractItemModel::revert + +Class QConcatenateTablesProxyModel + size=16 align=8 + base size=16 base align=8 +QConcatenateTablesProxyModel (0x0x7ff783de6958) 0 + vptr=((& QConcatenateTablesProxyModel::_ZTV28QConcatenateTablesProxyModel) + 16) + QAbstractItemModel (0x0x7ff783de69c0) 0 + primary-for QConcatenateTablesProxyModel (0x0x7ff783de6958) + QObject (0x0x7ff783e32840) 0 + primary-for QAbstractItemModel (0x0x7ff783de69c0) + +Class QCryptographicHash + size=8 align=8 + base size=8 base align=8 +QCryptographicHash (0x0x7ff783e32a80) 0 + +Class QDataStream + size=32 align=8 + base size=32 base align=8 +QDataStream (0x0x7ff783e32ba0) 0 + +Class QtPrivate::StreamStateSaver + size=16 align=8 + base size=12 base align=8 +QtPrivate::StreamStateSaver (0x0x7ff783e32d20) 0 + +Class QElapsedTimer + size=16 align=8 + base size=16 base align=8 +QElapsedTimer (0x0x7ff783ef6480) 0 + +Class QDeadlineTimer + size=16 align=8 + base size=16 base align=8 +QDeadlineTimer (0x0x7ff783ef6ba0) 0 + +Class QFileDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileDevice::QPrivateSignal (0x0x7ff783c43900) 0 empty + +Vtable for QFileDevice +QFileDevice::_ZTV11QFileDevice: 34 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 (0x0x7ff783c35bc8) 0 + vptr=((& QFileDevice::_ZTV11QFileDevice) + 16) + QIODevice (0x0x7ff783c35c30) 0 + primary-for QFileDevice (0x0x7ff783c35bc8) + QObject (0x0x7ff783c438a0) 0 + primary-for QIODevice (0x0x7ff783c35c30) + +Class QFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFile::QPrivateSignal (0x0x7ff783c8e240) 0 empty + +Vtable for QFile +QFile::_ZTV5QFile: 34 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 (0x0x7ff783c35d68) 0 + vptr=((& QFile::_ZTV5QFile) + 16) + QFileDevice (0x0x7ff783c35dd0) 0 + primary-for QFile (0x0x7ff783c35d68) + QIODevice (0x0x7ff783c35e38) 0 + primary-for QFileDevice (0x0x7ff783c35dd0) + QObject (0x0x7ff783c8e1e0) 0 + primary-for QIODevice (0x0x7ff783c35e38) + +Class QFileInfo + size=8 align=8 + base size=8 base align=8 +QFileInfo (0x0x7ff783c8e8a0) 0 + +Class QDir + size=8 align=8 + base size=8 base align=8 +QDir (0x0x7ff783d09c60) 0 + +Class QDirIterator + size=8 align=8 + base size=8 base align=8 +QDirIterator (0x0x7ff7839a9000) 0 + +Class QEasingCurve + size=8 align=8 + base size=8 base align=8 +QEasingCurve (0x0x7ff7839a9780) 0 + +Class QEventTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventTransition::QPrivateSignal (0x0x7ff783ad28a0) 0 empty + +Vtable for QEventTransition +QEventTransition::_ZTV16QEventTransition: 16 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 (0x0x7ff783ade0d0) 0 + vptr=((& QEventTransition::_ZTV16QEventTransition) + 16) + QAbstractTransition (0x0x7ff783ade138) 0 + primary-for QEventTransition (0x0x7ff783ade0d0) + QObject (0x0x7ff783ad2840) 0 + primary-for QAbstractTransition (0x0x7ff783ade138) + +Vtable for QException +QException::_ZTV10QException: 7 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 (0x0x7ff783ade1a0) 0 nearly-empty + vptr=((& QException::_ZTV10QException) + 16) + std::exception (0x0x7ff783ad2a80) 0 nearly-empty + primary-for QException (0x0x7ff783ade1a0) + +Vtable for QUnhandledException +QUnhandledException::_ZTV19QUnhandledException: 7 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 (0x0x7ff783ade208) 0 nearly-empty + vptr=((& QUnhandledException::_ZTV19QUnhandledException) + 16) + QException (0x0x7ff783ade270) 0 nearly-empty + primary-for QUnhandledException (0x0x7ff783ade208) + std::exception (0x0x7ff783ad2ae0) 0 nearly-empty + primary-for QException (0x0x7ff783ade270) + +Class QtPrivate::ExceptionHolder + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionHolder (0x0x7ff783ad2b40) 0 + +Class QtPrivate::ExceptionStore + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionStore (0x0x7ff783ad2c00) 0 + +Vtable for QFactoryInterface +QFactoryInterface::_ZTV17QFactoryInterface: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QFactoryInterface) +16 0 +24 0 +32 (int (*)(...))__cxa_pure_virtual + +Class QFactoryInterface + size=8 align=8 + base size=8 base align=8 +QFactoryInterface (0x0x7ff783ad2c60) 0 nearly-empty + vptr=((& QFactoryInterface::_ZTV17QFactoryInterface) + 16) + +Class QFileSelector::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSelector::QPrivateSignal (0x0x7ff783ad2ea0) 0 empty + +Vtable for QFileSelector +QFileSelector::_ZTV13QFileSelector: 14 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 (0x0x7ff783ade2d8) 0 + vptr=((& QFileSelector::_ZTV13QFileSelector) + 16) + QObject (0x0x7ff783ad2e40) 0 + primary-for QFileSelector (0x0x7ff783ade2d8) + +Class QFileSystemWatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSystemWatcher::QPrivateSignal (0x0x7ff78371f120) 0 empty + +Vtable for QFileSystemWatcher +QFileSystemWatcher::_ZTV18QFileSystemWatcher: 14 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 (0x0x7ff783ade340) 0 + vptr=((& QFileSystemWatcher::_ZTV18QFileSystemWatcher) + 16) + QObject (0x0x7ff78371f0c0) 0 + primary-for QFileSystemWatcher (0x0x7ff783ade340) + +Class QFinalState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFinalState::QPrivateSignal (0x0x7ff78371f360) 0 empty + +Vtable for QFinalState +QFinalState::_ZTV11QFinalState: 16 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 (0x0x7ff783ade3a8) 0 + vptr=((& QFinalState::_ZTV11QFinalState) + 16) + QAbstractState (0x0x7ff783ade410) 0 + primary-for QFinalState (0x0x7ff783ade3a8) + QObject (0x0x7ff78371f300) 0 + primary-for QAbstractState (0x0x7ff783ade410) + +Vtable for QRunnable +QRunnable::_ZTV9QRunnable: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QRunnable) +16 (int (*)(...))__cxa_pure_virtual +24 0 +32 0 + +Class QRunnable + size=16 align=8 + base size=12 base align=8 +QRunnable (0x0x7ff78371f540) 0 + vptr=((& QRunnable::_ZTV9QRunnable) + 16) + +Class QBasicMutex + size=8 align=8 + base size=8 base align=8 +QBasicMutex (0x0x7ff78371f7e0) 0 + +Class QMutex + size=8 align=8 + base size=8 base align=8 +QMutex (0x0x7ff783ade4e0) 0 + QBasicMutex (0x0x7ff7837ae480) 0 + +Class QMutexLocker + size=8 align=8 + base size=8 base align=8 +QMutexLocker (0x0x7ff7837ae6c0) 0 + +Class QtPrivate::ResultItem + size=16 align=8 + base size=16 base align=8 +QtPrivate::ResultItem (0x0x7ff7837aeb40) 0 + +Class QtPrivate::ResultIteratorBase + size=16 align=8 + base size=12 base align=8 +QtPrivate::ResultIteratorBase (0x0x7ff7837d8180) 0 + +Vtable for QtPrivate::ResultStoreBase +QtPrivate::ResultStoreBase::_ZTVN9QtPrivate15ResultStoreBaseE: 4 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 (0x0x7ff7837d8360) 0 + vptr=((& QtPrivate::ResultStoreBase::_ZTVN9QtPrivate15ResultStoreBaseE) + 16) + +Vtable for QFutureInterfaceBase +QFutureInterfaceBase::_ZTV20QFutureInterfaceBase: 4 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 (0x0x7ff78384eb40) 0 + vptr=((& QFutureInterfaceBase::_ZTV20QFutureInterfaceBase) + 16) + +Class QFutureWatcherBase::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFutureWatcherBase::QPrivateSignal (0x0x7ff7838ede40) 0 empty + +Vtable for QFutureWatcherBase +QFutureWatcherBase::_ZTV18QFutureWatcherBase: 16 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QFutureWatcherBase) +16 (int (*)(...))QFutureWatcherBase::metaObject +24 (int (*)(...))QFutureWatcherBase::qt_metacast +32 (int (*)(...))QFutureWatcherBase::qt_metacall +40 0 +48 0 +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 (0x0x7ff783884af8) 0 + vptr=((& QFutureWatcherBase::_ZTV18QFutureWatcherBase) + 16) + QObject (0x0x7ff7838edde0) 0 + primary-for QFutureWatcherBase (0x0x7ff783884af8) + +Class QHistoryState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QHistoryState::QPrivateSignal (0x0x7ff7835371e0) 0 empty + +Vtable for QHistoryState +QHistoryState::_ZTV13QHistoryState: 16 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 (0x0x7ff783534340) 0 + vptr=((& QHistoryState::_ZTV13QHistoryState) + 16) + QAbstractState (0x0x7ff7835343a8) 0 + primary-for QHistoryState (0x0x7ff783534340) + QObject (0x0x7ff783537180) 0 + primary-for QAbstractState (0x0x7ff7835343a8) + +Class QIdentityProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIdentityProxyModel::QPrivateSignal (0x0x7ff7835374e0) 0 empty + +Vtable for QIdentityProxyModel +QIdentityProxyModel::_ZTV19QIdentityProxyModel: 53 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 (0x0x7ff783534410) 0 + vptr=((& QIdentityProxyModel::_ZTV19QIdentityProxyModel) + 16) + QAbstractProxyModel (0x0x7ff783534478) 0 + primary-for QIdentityProxyModel (0x0x7ff783534410) + QAbstractItemModel (0x0x7ff7835344e0) 0 + primary-for QAbstractProxyModel (0x0x7ff783534478) + QObject (0x0x7ff783537480) 0 + primary-for QAbstractItemModel (0x0x7ff7835344e0) + +Class QItemSelectionRange + size=16 align=8 + base size=16 base align=8 +QItemSelectionRange (0x0x7ff7835376c0) 0 + +Class QItemSelectionModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QItemSelectionModel::QPrivateSignal (0x0x7ff783621000) 0 empty + +Vtable for QItemSelectionModel +QItemSelectionModel::_ZTV19QItemSelectionModel: 20 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 (0x0x7ff783605e38) 0 + vptr=((& QItemSelectionModel::_ZTV19QItemSelectionModel) + 16) + QObject (0x0x7ff783602f60) 0 + primary-for QItemSelectionModel (0x0x7ff783605e38) + +Class QItemSelection + size=8 align=8 + base size=8 base align=8 +QItemSelection (0x0x7ff783686000) 0 + QList (0x0x7ff783686068) 0 + QListSpecialMethods (0x0x7ff783621ae0) 0 empty + +Class QJsonValue + size=24 align=8 + base size=20 base align=8 +QJsonValue (0x0x7ff7836ca420) 0 + +Class QJsonValueRef + size=16 align=8 + base size=12 base align=8 +QJsonValueRef (0x0x7ff78341f600) 0 + +Class QJsonValuePtr + size=24 align=8 + base size=24 base align=8 +QJsonValuePtr (0x0x7ff7834725a0) 0 + +Class QJsonValueRefPtr + size=16 align=8 + base size=16 base align=8 +QJsonValueRefPtr (0x0x7ff783472840) 0 + +Class QJsonArray::iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::iterator (0x0x7ff7834b2ba0) 0 + +Class QJsonArray::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::const_iterator (0x0x7ff7834b2c00) 0 + +Class QJsonArray + size=16 align=8 + base size=16 base align=8 +QJsonArray (0x0x7ff7834b2b40) 0 + +Class QJsonParseError + size=8 align=4 + base size=8 base align=4 +QJsonParseError (0x0x7ff7831deae0) 0 + +Class QJsonDocument + size=8 align=8 + base size=8 base align=8 +QJsonDocument (0x0x7ff7831deb40) 0 + +Class QJsonObject::iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::iterator (0x0x7ff78324f360) 0 + +Class QJsonObject::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::const_iterator (0x0x7ff78324f3c0) 0 + +Class QJsonObject + size=16 align=8 + base size=16 base align=8 +QJsonObject (0x0x7ff78324f300) 0 + +Class QLibrary::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLibrary::QPrivateSignal (0x0x7ff782f61720) 0 empty + +Vtable for QLibrary +QLibrary::_ZTV8QLibrary: 14 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 (0x0x7ff782f6b0d0) 0 + vptr=((& QLibrary::_ZTV8QLibrary) + 16) + QObject (0x0x7ff782f616c0) 0 + primary-for QLibrary (0x0x7ff782f6b0d0) + +Class QVersionNumber::SegmentStorage + size=8 align=8 + base size=8 base align=8 +QVersionNumber::SegmentStorage (0x0x7ff782fad5a0) 0 + +Class QVersionNumber + size=8 align=8 + base size=8 base align=8 +QVersionNumber (0x0x7ff782fad0c0) 0 + +Class QLibraryInfo + size=1 align=1 + base size=0 base align=1 +QLibraryInfo (0x0x7ff783044cc0) 0 empty + +Class QPoint + size=8 align=4 + base size=8 base align=4 +QPoint (0x0x7ff783044d20) 0 + +Class QPointF + size=16 align=8 + base size=16 base align=8 +QPointF (0x0x7ff7830b3b40) 0 + +Class QLine + size=16 align=4 + base size=16 base align=4 +QLine (0x0x7ff782d27cc0) 0 + +Class QLineF + size=32 align=8 + base size=32 base align=8 +QLineF (0x0x7ff782dbb0c0) 0 + +Class QLinkedListData + size=32 align=8 + base size=25 base align=8 +QLinkedListData (0x0x7ff782e37360) 0 + +Class QLockFile + size=8 align=8 + base size=8 base align=8 +QLockFile (0x0x7ff782ed54e0) 0 + +Class QLoggingCategory::AtomicBools + size=4 align=1 + base size=4 base align=1 +QLoggingCategory::AtomicBools (0x0x7ff782ed5720) 0 + +Class QLoggingCategory + size=24 align=8 + base size=24 base align=8 +QLoggingCategory (0x0x7ff782ed56c0) 0 + +Class QMargins + size=16 align=4 + base size=16 base align=4 +QMargins (0x0x7ff782ed5b40) 0 + +Class QMarginsF + size=32 align=8 + base size=32 base align=8 +QMarginsF (0x0x7ff782b87a80) 0 + +Class QMessageAuthenticationCode + size=8 align=8 + base size=8 base align=8 +QMessageAuthenticationCode (0x0x7ff7829f82a0) 0 + +Class QMetaMethod + size=16 align=8 + base size=12 base align=8 +QMetaMethod (0x0x7ff7829f8300) 0 + +Class QMetaEnum + size=16 align=8 + base size=12 base align=8 +QMetaEnum (0x0x7ff782a5eb40) 0 + +Class QMetaProperty + size=32 align=8 + base size=32 base align=8 +QMetaProperty (0x0x7ff782a9ed80) 0 + +Class QMetaClassInfo + size=16 align=8 + base size=12 base align=8 +QMetaClassInfo (0x0x7ff782a9eea0) 0 + +Class QMimeData::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QMimeData::QPrivateSignal (0x0x7ff782afb480) 0 empty + +Vtable for QMimeData +QMimeData::_ZTV9QMimeData: 17 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 (0x0x7ff782aebd00) 0 + vptr=((& QMimeData::_ZTV9QMimeData) + 16) + QObject (0x0x7ff782afb420) 0 + primary-for QMimeData (0x0x7ff782aebd00) + +Class QMimeType + size=8 align=8 + base size=8 base align=8 +QMimeType (0x0x7ff782afb660) 0 + +Class QMimeDatabase + size=8 align=8 + base size=8 base align=8 +QMimeDatabase (0x0x7ff78275b780) 0 + +Class QObjectCleanupHandler::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObjectCleanupHandler::QPrivateSignal (0x0x7ff78275b840) 0 empty + +Vtable for QObjectCleanupHandler +QObjectCleanupHandler::_ZTV21QObjectCleanupHandler: 14 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 (0x0x7ff782767068) 0 + vptr=((& QObjectCleanupHandler::_ZTV21QObjectCleanupHandler) + 16) + QObject (0x0x7ff78275b7e0) 0 + primary-for QObjectCleanupHandler (0x0x7ff782767068) + +Class QOperatingSystemVersion + size=16 align=4 + base size=16 base align=4 +QOperatingSystemVersion (0x0x7ff78275b960) 0 + +Class QParallelAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QParallelAnimationGroup::QPrivateSignal (0x0x7ff7827e7120) 0 empty + +Vtable for QParallelAnimationGroup +QParallelAnimationGroup::_ZTV23QParallelAnimationGroup: 18 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 (0x0x7ff7827de8f0) 0 + vptr=((& QParallelAnimationGroup::_ZTV23QParallelAnimationGroup) + 16) + QAnimationGroup (0x0x7ff7827de958) 0 + primary-for QParallelAnimationGroup (0x0x7ff7827de8f0) + QAbstractAnimation (0x0x7ff7827de9c0) 0 + primary-for QAnimationGroup (0x0x7ff7827de958) + QObject (0x0x7ff7827e70c0) 0 + primary-for QAbstractAnimation (0x0x7ff7827de9c0) + +Class QPauseAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPauseAnimation::QPrivateSignal (0x0x7ff7827e7360) 0 empty + +Vtable for QPauseAnimation +QPauseAnimation::_ZTV15QPauseAnimation: 18 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 (0x0x7ff7827dea28) 0 + vptr=((& QPauseAnimation::_ZTV15QPauseAnimation) + 16) + QAbstractAnimation (0x0x7ff7827dea90) 0 + primary-for QPauseAnimation (0x0x7ff7827dea28) + QObject (0x0x7ff7827e7300) 0 + primary-for QAbstractAnimation (0x0x7ff7827dea90) + +Class QStaticPlugin + size=16 align=8 + base size=16 base align=8 +QStaticPlugin (0x0x7ff7827e7f60) 0 + +Class QPluginLoader::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPluginLoader::QPrivateSignal (0x0x7ff78285e120) 0 empty + +Vtable for QPluginLoader +QPluginLoader::_ZTV13QPluginLoader: 14 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 (0x0x7ff782849dd0) 0 + vptr=((& QPluginLoader::_ZTV13QPluginLoader) + 16) + QObject (0x0x7ff78285e0c0) 0 + primary-for QPluginLoader (0x0x7ff782849dd0) + +Class QProcessEnvironment + size=8 align=8 + base size=8 base align=8 +QProcessEnvironment (0x0x7ff78285e240) 0 + +Class QProcess::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QProcess::QPrivateSignal (0x0x7ff7828ba8a0) 0 empty + +Vtable for QProcess +QProcess::_ZTV8QProcess: 31 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 (0x0x7ff7828b9a28) 0 + vptr=((& QProcess::_ZTV8QProcess) + 16) + QIODevice (0x0x7ff7828b9a90) 0 + primary-for QProcess (0x0x7ff7828b9a28) + QObject (0x0x7ff7828ba840) 0 + primary-for QIODevice (0x0x7ff7828b9a90) + +Class QVariantAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QVariantAnimation::QPrivateSignal (0x0x7ff7828baf60) 0 empty + +Vtable for QVariantAnimation +QVariantAnimation::_ZTV17QVariantAnimation: 20 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 (0x0x7ff7828b9af8) 0 + vptr=((& QVariantAnimation::_ZTV17QVariantAnimation) + 16) + QAbstractAnimation (0x0x7ff7828b9b60) 0 + primary-for QVariantAnimation (0x0x7ff7828b9af8) + QObject (0x0x7ff7828baf00) 0 + primary-for QAbstractAnimation (0x0x7ff7828b9b60) + +Class QPropertyAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPropertyAnimation::QPrivateSignal (0x0x7ff78290a240) 0 empty + +Vtable for QPropertyAnimation +QPropertyAnimation::_ZTV18QPropertyAnimation: 20 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 (0x0x7ff7828b9c30) 0 + vptr=((& QPropertyAnimation::_ZTV18QPropertyAnimation) + 16) + QVariantAnimation (0x0x7ff7828b9c98) 0 + primary-for QPropertyAnimation (0x0x7ff7828b9c30) + QAbstractAnimation (0x0x7ff7828b9d00) 0 + primary-for QVariantAnimation (0x0x7ff7828b9c98) + QObject (0x0x7ff78290a1e0) 0 + primary-for QAbstractAnimation (0x0x7ff7828b9d00) + +Class std::random_device + size=5000 align=8 + base size=5000 base align=8 +std::random_device (0x0x7ff78257f960) 0 + +Class std::bernoulli_distribution::param_type + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution::param_type (0x0x7ff78268e6c0) 0 + +Class std::bernoulli_distribution + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution (0x0x7ff78268e660) 0 + +Class std::seed_seq + size=24 align=8 + base size=24 base align=8 +std::seed_seq (0x0x7ff782478420) 0 + +Class QRandomGenerator::Storage + size=2504 align=8 + base size=2504 base align=8 +QRandomGenerator::Storage (0x0x7ff7822b30c0) 0 + +Class QRandomGenerator + size=2512 align=8 + base size=2512 base align=8 +QRandomGenerator (0x0x7ff7822b3060) 0 + +Class QRandomGenerator64 + size=2512 align=8 + base size=2512 base align=8 +QRandomGenerator64 (0x0x7ff7823159c0) 0 + QRandomGenerator (0x0x7ff781eaaba0) 0 + +Class QReadWriteLock + size=8 align=8 + base size=8 base align=8 +QReadWriteLock (0x0x7ff781ed1780) 0 + +Class QReadLocker + size=8 align=8 + base size=8 base align=8 +QReadLocker (0x0x7ff781ed1a20) 0 + +Class QWriteLocker + size=8 align=8 + base size=8 base align=8 +QWriteLocker (0x0x7ff781ed1f00) 0 + +Class QSize + size=8 align=4 + base size=8 base align=4 +QSize (0x0x7ff781f52420) 0 + +Class QSizeF + size=16 align=8 + base size=16 base align=8 +QSizeF (0x0x7ff781fc2240) 0 + +Class QRect + size=16 align=4 + base size=16 base align=4 +QRect (0x0x7ff78203d1e0) 0 + +Class QRectF + size=32 align=8 + base size=32 base align=8 +QRectF (0x0x7ff781cf9240) 0 + +Class QResource + size=8 align=8 + base size=8 base align=8 +QResource (0x0x7ff781db1360) 0 + +Class QSaveFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSaveFile::QPrivateSignal (0x0x7ff781db1600) 0 empty + +Vtable for QSaveFile +QSaveFile::_ZTV9QSaveFile: 34 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 (0x0x7ff781d623a8) 0 + vptr=((& QSaveFile::_ZTV9QSaveFile) + 16) + QFileDevice (0x0x7ff781d62410) 0 + primary-for QSaveFile (0x0x7ff781d623a8) + QIODevice (0x0x7ff781d62478) 0 + primary-for QFileDevice (0x0x7ff781d62410) + QObject (0x0x7ff781db15a0) 0 + primary-for QIODevice (0x0x7ff781d62478) + +Class QSemaphore + size=8 align=8 + base size=8 base align=8 +QSemaphore (0x0x7ff781db1c00) 0 + +Class QSemaphoreReleaser + size=16 align=8 + base size=12 base align=8 +QSemaphoreReleaser (0x0x7ff781db1d80) 0 + +Class QSequentialAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSequentialAnimationGroup::QPrivateSignal (0x0x7ff781b06060) 0 empty + +Vtable for QSequentialAnimationGroup +QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup: 18 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 (0x0x7ff781b031a0) 0 + vptr=((& QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup) + 16) + QAnimationGroup (0x0x7ff781b03208) 0 + primary-for QSequentialAnimationGroup (0x0x7ff781b031a0) + QAbstractAnimation (0x0x7ff781b03270) 0 + primary-for QAnimationGroup (0x0x7ff781b03208) + QObject (0x0x7ff781b06000) 0 + primary-for QAbstractAnimation (0x0x7ff781b03270) + +Class QSettings::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSettings::QPrivateSignal (0x0x7ff781b062a0) 0 empty + +Vtable for QSettings +QSettings::_ZTV9QSettings: 14 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 (0x0x7ff781b032d8) 0 + vptr=((& QSettings::_ZTV9QSettings) + 16) + QObject (0x0x7ff781b06240) 0 + primary-for QSettings (0x0x7ff781b032d8) + +Class QSharedMemory::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSharedMemory::QPrivateSignal (0x0x7ff781b06720) 0 empty + +Vtable for QSharedMemory +QSharedMemory::_ZTV13QSharedMemory: 14 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 (0x0x7ff781b03340) 0 + vptr=((& QSharedMemory::_ZTV13QSharedMemory) + 16) + QObject (0x0x7ff781b066c0) 0 + primary-for QSharedMemory (0x0x7ff781b03340) + +Class QSignalMapper::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalMapper::QPrivateSignal (0x0x7ff781b06960) 0 empty + +Vtable for QSignalMapper +QSignalMapper::_ZTV13QSignalMapper: 14 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 (0x0x7ff781b033a8) 0 + vptr=((& QSignalMapper::_ZTV13QSignalMapper) + 16) + QObject (0x0x7ff781b06900) 0 + primary-for QSignalMapper (0x0x7ff781b033a8) + +Class QSignalTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalTransition::QPrivateSignal (0x0x7ff781b06ba0) 0 empty + +Vtable for QSignalTransition +QSignalTransition::_ZTV17QSignalTransition: 16 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 (0x0x7ff781b03410) 0 + vptr=((& QSignalTransition::_ZTV17QSignalTransition) + 16) + QAbstractTransition (0x0x7ff781b03478) 0 + primary-for QSignalTransition (0x0x7ff781b03410) + QObject (0x0x7ff781b06b40) 0 + primary-for QAbstractTransition (0x0x7ff781b03478) + +Class QSocketNotifier::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSocketNotifier::QPrivateSignal (0x0x7ff781b06e40) 0 empty + +Vtable for QSocketNotifier +QSocketNotifier::_ZTV15QSocketNotifier: 14 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 (0x0x7ff781b034e0) 0 + vptr=((& QSocketNotifier::_ZTV15QSocketNotifier) + 16) + QObject (0x0x7ff781b06de0) 0 + primary-for QSocketNotifier (0x0x7ff781b034e0) + +Class QSortFilterProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSortFilterProxyModel::QPrivateSignal (0x0x7ff781b7b0c0) 0 empty + +Vtable for QSortFilterProxyModel +QSortFilterProxyModel::_ZTV21QSortFilterProxyModel: 56 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 (0x0x7ff781b03548) 0 + vptr=((& QSortFilterProxyModel::_ZTV21QSortFilterProxyModel) + 16) + QAbstractProxyModel (0x0x7ff781b035b0) 0 + primary-for QSortFilterProxyModel (0x0x7ff781b03548) + QAbstractItemModel (0x0x7ff781b03618) 0 + primary-for QAbstractProxyModel (0x0x7ff781b035b0) + QObject (0x0x7ff781b7b060) 0 + primary-for QAbstractItemModel (0x0x7ff781b03618) + +Class QStandardPaths + size=1 align=1 + base size=0 base align=1 +QStandardPaths (0x0x7ff781b7b4e0) 0 empty + +Class QState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QState::QPrivateSignal (0x0x7ff781b7bde0) 0 empty + +Vtable for QState +QState::_ZTV6QState: 16 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 (0x0x7ff781b037b8) 0 + vptr=((& QState::_ZTV6QState) + 16) + QAbstractState (0x0x7ff781b03820) 0 + primary-for QState (0x0x7ff781b037b8) + QObject (0x0x7ff781b7bd80) 0 + primary-for QAbstractState (0x0x7ff781b03820) + +Class QStateMachine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStateMachine::QPrivateSignal (0x0x7ff781bee2a0) 0 empty + +Vtable for QStateMachine::SignalEvent +QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE: 4 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 (0x0x7ff781b039c0) 0 + vptr=((& QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE) + 16) + QEvent (0x0x7ff781bee300) 0 + primary-for QStateMachine::SignalEvent (0x0x7ff781b039c0) + +Vtable for QStateMachine::WrappedEvent +QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE: 4 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 (0x0x7ff781b03a28) 0 + vptr=((& QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE) + 16) + QEvent (0x0x7ff781bee360) 0 + primary-for QStateMachine::WrappedEvent (0x0x7ff781b03a28) + +Vtable for QStateMachine +QStateMachine::_ZTV13QStateMachine: 20 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 (0x0x7ff781b03888) 0 + vptr=((& QStateMachine::_ZTV13QStateMachine) + 16) + QState (0x0x7ff781b038f0) 0 + primary-for QStateMachine (0x0x7ff781b03888) + QAbstractState (0x0x7ff781b03958) 0 + primary-for QState (0x0x7ff781b038f0) + QObject (0x0x7ff781bee240) 0 + primary-for QAbstractState (0x0x7ff781b03958) + +Class QStorageInfo + size=8 align=8 + base size=8 base align=8 +QStorageInfo (0x0x7ff781bee720) 0 + +Class QAbstractConcatenable + size=1 align=1 + base size=0 base align=1 +QAbstractConcatenable (0x0x7ff781c8e720) 0 empty + +Class QStringListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStringListModel::QPrivateSignal (0x0x7ff781917a80) 0 empty + +Vtable for QStringListModel +QStringListModel::_ZTV16QStringListModel: 48 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 (*)(...))QStringListModel::itemData +200 (int (*)(...))QStringListModel::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 (*)(...))QStringListModel::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 (0x0x7ff781906b60) 0 + vptr=((& QStringListModel::_ZTV16QStringListModel) + 16) + QAbstractListModel (0x0x7ff781906bc8) 0 + primary-for QStringListModel (0x0x7ff781906b60) + QAbstractItemModel (0x0x7ff781906c30) 0 + primary-for QAbstractListModel (0x0x7ff781906bc8) + QObject (0x0x7ff781917a20) 0 + primary-for QAbstractItemModel (0x0x7ff781906c30) + +Class QSystemSemaphore + size=8 align=8 + base size=8 base align=8 +QSystemSemaphore (0x0x7ff781917ba0) 0 + +Class QTemporaryDir + size=8 align=8 + base size=8 base align=8 +QTemporaryDir (0x0x7ff781917c60) 0 + +Class QTemporaryFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTemporaryFile::QPrivateSignal (0x0x7ff781917d80) 0 empty + +Vtable for QTemporaryFile +QTemporaryFile::_ZTV14QTemporaryFile: 34 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 (0x0x7ff781906c98) 0 + vptr=((& QTemporaryFile::_ZTV14QTemporaryFile) + 16) + QFile (0x0x7ff781906d00) 0 + primary-for QTemporaryFile (0x0x7ff781906c98) + QFileDevice (0x0x7ff781906d68) 0 + primary-for QFile (0x0x7ff781906d00) + QIODevice (0x0x7ff781906dd0) 0 + primary-for QFileDevice (0x0x7ff781906d68) + QObject (0x0x7ff781917d20) 0 + primary-for QIODevice (0x0x7ff781906dd0) + +Class QTextBoundaryFinder + size=48 align=8 + base size=48 base align=8 +QTextBoundaryFinder (0x0x7ff781974120) 0 + +Class QTextCodec::ConverterState + size=32 align=8 + base size=32 base align=8 +QTextCodec::ConverterState (0x0x7ff781974960) 0 + +Vtable for QTextCodec +QTextCodec::_ZTV10QTextCodec: 9 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 0 +64 0 + +Class QTextCodec + size=8 align=8 + base size=8 base align=8 +QTextCodec (0x0x7ff781974900) 0 nearly-empty + vptr=((& QTextCodec::_ZTV10QTextCodec) + 16) + +Class QTextEncoder + size=40 align=8 + base size=40 base align=8 +QTextEncoder (0x0x7ff7819e0360) 0 + +Class QTextDecoder + size=40 align=8 + base size=40 base align=8 +QTextDecoder (0x0x7ff7819e0540) 0 + +Class std::__mutex_base + size=40 align=8 + base size=40 base align=8 +std::__mutex_base (0x0x7ff7819e0720) 0 + +Class std::mutex + size=40 align=8 + base size=40 base align=8 +std::mutex (0x0x7ff781a04000) 0 + std::__mutex_base (0x0x7ff7819e0780) 0 + +Class std::defer_lock_t + size=1 align=1 + base size=0 base align=1 +std::defer_lock_t (0x0x7ff7819e0960) 0 empty + +Class std::try_to_lock_t + size=1 align=1 + base size=0 base align=1 +std::try_to_lock_t (0x0x7ff7819e09c0) 0 empty + +Class std::adopt_lock_t + size=1 align=1 + base size=0 base align=1 +std::adopt_lock_t (0x0x7ff7819e0a20) 0 empty + +Class std::__recursive_mutex_base + size=40 align=8 + base size=40 base align=8 +std::__recursive_mutex_base (0x0x7ff781a2a480) 0 + +Class std::recursive_mutex + size=40 align=8 + base size=40 base align=8 +std::recursive_mutex (0x0x7ff781a04068) 0 + std::__recursive_mutex_base (0x0x7ff781a2a4e0) 0 + +Class std::timed_mutex + size=40 align=8 + base size=40 base align=8 +std::timed_mutex (0x0x7ff7819e4ee0) 0 + std::__mutex_base (0x0x7ff781a2a8a0) 0 + std::__timed_mutex_impl (0x0x7ff781a2a900) 0 empty + +Class std::recursive_timed_mutex + size=40 align=8 + base size=40 base align=8 +std::recursive_timed_mutex (0x0x7ff781a50230) 0 + std::__recursive_mutex_base (0x0x7ff781a2ac60) 0 + std::__timed_mutex_impl (0x0x7ff781a2acc0) 0 empty + +Class std::once_flag + size=4 align=4 + base size=4 base align=4 +std::once_flag (0x0x7ff781a68420) 0 + +Vtable for __gnu_cxx::__concurrence_lock_error +__gnu_cxx::__concurrence_lock_error::_ZTVN9__gnu_cxx24__concurrence_lock_errorE: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx24__concurrence_lock_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_lock_error::~__concurrence_lock_error +24 (int (*)(...))__gnu_cxx::__concurrence_lock_error::~__concurrence_lock_error +32 (int (*)(...))__gnu_cxx::__concurrence_lock_error::what + +Class __gnu_cxx::__concurrence_lock_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_lock_error (0x0x7ff781a041a0) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_lock_error::_ZTVN9__gnu_cxx24__concurrence_lock_errorE) + 16) + std::exception (0x0x7ff781a68960) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_lock_error (0x0x7ff781a041a0) + +Vtable for __gnu_cxx::__concurrence_unlock_error +__gnu_cxx::__concurrence_unlock_error::_ZTVN9__gnu_cxx26__concurrence_unlock_errorE: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx26__concurrence_unlock_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::~__concurrence_unlock_error +24 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::~__concurrence_unlock_error +32 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::what + +Class __gnu_cxx::__concurrence_unlock_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_unlock_error (0x0x7ff781a04208) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_unlock_error::_ZTVN9__gnu_cxx26__concurrence_unlock_errorE) + 16) + std::exception (0x0x7ff781a68a80) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_unlock_error (0x0x7ff781a04208) + +Vtable for __gnu_cxx::__concurrence_broadcast_error +__gnu_cxx::__concurrence_broadcast_error::_ZTVN9__gnu_cxx29__concurrence_broadcast_errorE: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx29__concurrence_broadcast_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::~__concurrence_broadcast_error +24 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::~__concurrence_broadcast_error +32 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::what + +Class __gnu_cxx::__concurrence_broadcast_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_broadcast_error (0x0x7ff781a04270) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_broadcast_error::_ZTVN9__gnu_cxx29__concurrence_broadcast_errorE) + 16) + std::exception (0x0x7ff781a68ba0) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_broadcast_error (0x0x7ff781a04270) + +Vtable for __gnu_cxx::__concurrence_wait_error +__gnu_cxx::__concurrence_wait_error::_ZTVN9__gnu_cxx24__concurrence_wait_errorE: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx24__concurrence_wait_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_wait_error::~__concurrence_wait_error +24 (int (*)(...))__gnu_cxx::__concurrence_wait_error::~__concurrence_wait_error +32 (int (*)(...))__gnu_cxx::__concurrence_wait_error::what + +Class __gnu_cxx::__concurrence_wait_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_wait_error (0x0x7ff781a04340) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_wait_error::_ZTVN9__gnu_cxx24__concurrence_wait_errorE) + 16) + std::exception (0x0x7ff781a68cc0) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_wait_error (0x0x7ff781a04340) + +Class __gnu_cxx::__mutex + size=40 align=8 + base size=40 base align=8 +__gnu_cxx::__mutex (0x0x7ff78169dd20) 0 + +Class __gnu_cxx::__recursive_mutex + size=40 align=8 + base size=40 base align=8 +__gnu_cxx::__recursive_mutex (0x0x7ff7816bd060) 0 + +Class __gnu_cxx::__scoped_lock + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__scoped_lock (0x0x7ff7816bd360) 0 + +Class __gnu_cxx::__cond + size=48 align=8 + base size=48 base align=8 +__gnu_cxx::__cond (0x0x7ff7816bd6c0) 0 + +Vtable for std::bad_weak_ptr +std::bad_weak_ptr::_ZTVSt12bad_weak_ptr: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt12bad_weak_ptr) +16 (int (*)(...))std::bad_weak_ptr::~bad_weak_ptr +24 (int (*)(...))std::bad_weak_ptr::~bad_weak_ptr +32 (int (*)(...))std::bad_weak_ptr::what + +Class std::bad_weak_ptr + size=8 align=8 + base size=8 base align=8 +std::bad_weak_ptr (0x0x7ff781a043a8) 0 nearly-empty + vptr=((& std::bad_weak_ptr::_ZTVSt12bad_weak_ptr) + 16) + std::exception (0x0x7ff7817348a0) 0 nearly-empty + primary-for std::bad_weak_ptr (0x0x7ff781a043a8) + +Class std::_Sp_make_shared_tag + size=1 align=1 + base size=0 base align=1 +std::_Sp_make_shared_tag (0x0x7ff7817a2840) 0 empty + +Class std::__sp_array_delete + size=1 align=1 + base size=0 base align=1 +std::__sp_array_delete (0x0x7ff7817a2c60) 0 empty + +Class std::_Sp_locker + size=2 align=1 + base size=2 base align=1 +std::_Sp_locker (0x0x7ff7814e1ae0) 0 + +Vtable for std::thread::_State +std::thread::_State::_ZTVNSt6thread6_StateE: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt6thread6_StateE) +16 0 +24 0 +32 (int (*)(...))__cxa_pure_virtual + +Class std::thread::_State + size=8 align=8 + base size=8 base align=8 +std::thread::_State (0x0x7ff781514f60) 0 nearly-empty + vptr=((& std::thread::_State::_ZTVNSt6thread6_StateE) + 16) + +Class std::thread::id + size=8 align=8 + base size=8 base align=8 +std::thread::id (0x0x7ff78153f000) 0 + +Class std::thread + size=8 align=8 + base size=8 base align=8 +std::thread (0x0x7ff781514f00) 0 + +Class std::condition_variable + size=48 align=8 + base size=48 base align=8 +std::condition_variable (0x0x7ff7813d63c0) 0 + +Class std::__at_thread_exit_elt + size=16 align=8 + base size=16 base align=8 +std::__at_thread_exit_elt (0x0x7ff7813d6780) 0 + +Class std::_V2::condition_variable_any + size=64 align=8 + base size=64 base align=8 +std::_V2::condition_variable_any (0x0x7ff7813d67e0) 0 + +Class std::__atomic_futex_unsigned_base + size=1 align=1 + base size=0 base align=1 +std::__atomic_futex_unsigned_base (0x0x7ff781161ae0) 0 empty + +Vtable for std::future_error +std::future_error::_ZTVSt12future_error: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt12future_error) +16 (int (*)(...))std::future_error::~future_error +24 (int (*)(...))std::future_error::~future_error +32 (int (*)(...))std::future_error::what + +Class std::future_error + size=32 align=8 + base size=32 base align=8 +std::future_error (0x0x7ff781160c30) 0 + vptr=((& std::future_error::_ZTVSt12future_error) + 16) + std::logic_error (0x0x7ff781160c98) 0 + primary-for std::future_error (0x0x7ff781160c30) + std::exception (0x0x7ff78118d240) 0 nearly-empty + primary-for std::logic_error (0x0x7ff781160c98) + +Class std::__future_base::_Result_base::_Deleter + size=1 align=1 + base size=0 base align=1 +std::__future_base::_Result_base::_Deleter (0x0x7ff78118d960) 0 empty + +Vtable for std::__future_base::_Result_base +std::__future_base::_Result_base::_ZTVNSt13__future_base12_Result_baseE: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt13__future_base12_Result_baseE) +16 (int (*)(...))__cxa_pure_virtual +24 0 +32 0 + +Class std::__future_base::_Result_base + size=16 align=8 + base size=16 base align=8 +std::__future_base::_Result_base (0x0x7ff78118d900) 0 + vptr=((& std::__future_base::_Result_base::_ZTVNSt13__future_base12_Result_baseE) + 16) + +Class std::__future_base::_State_baseV2::__exception_ptr_tag + size=1 align=1 + base size=0 base align=1 +std::__future_base::_State_baseV2::__exception_ptr_tag (0x0x7ff780fa60c0) 0 empty + +Class std::__future_base::_State_baseV2::_Make_ready + size=32 align=8 + base size=32 base align=8 +std::__future_base::_State_baseV2::_Make_ready (0x0x7ff780f844e0) 0 + std::__at_thread_exit_elt (0x0x7ff780fa6180) 0 + +Vtable for std::__future_base::_State_baseV2 +std::__future_base::_State_baseV2::_ZTVNSt13__future_base13_State_baseV2E: 6 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt13__future_base13_State_baseV2E) +16 (int (*)(...))std::__future_base::_State_baseV2::~_State_baseV2 +24 (int (*)(...))std::__future_base::_State_baseV2::~_State_baseV2 +32 (int (*)(...))std::__future_base::_State_baseV2::_M_complete_async +40 (int (*)(...))std::__future_base::_State_baseV2::_M_is_deferred_future + +Class std::__future_base::_State_baseV2 + size=32 align=8 + base size=28 base align=8 +std::__future_base::_State_baseV2 (0x0x7ff78118dae0) 0 + vptr=((& std::__future_base::_State_baseV2::_ZTVNSt13__future_base13_State_baseV2E) + 16) + +Class std::__future_base + size=1 align=1 + base size=0 base align=1 +std::__future_base (0x0x7ff78118d8a0) 0 empty + +Vtable for std::__future_base::_Async_state_commonV2 +std::__future_base::_Async_state_commonV2::_ZTVNSt13__future_base21_Async_state_commonV2E: 6 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt13__future_base21_Async_state_commonV2E) +16 (int (*)(...))std::__future_base::_Async_state_commonV2::~_Async_state_commonV2 +24 (int (*)(...))std::__future_base::_Async_state_commonV2::~_Async_state_commonV2 +32 (int (*)(...))std::__future_base::_Async_state_commonV2::_M_complete_async +40 (int (*)(...))std::__future_base::_State_baseV2::_M_is_deferred_future + +Class std::__future_base::_Async_state_commonV2 + size=48 align=8 + base size=44 base align=8 +std::__future_base::_Async_state_commonV2 (0x0x7ff78073f208) 0 + vptr=((& std::__future_base::_Async_state_commonV2::_ZTVNSt13__future_base21_Async_state_commonV2E) + 16) + std::__future_base::_State_baseV2 (0x0x7ff780743180) 0 + primary-for std::__future_base::_Async_state_commonV2 (0x0x7ff78073f208) + +Class QThread::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThread::QPrivateSignal (0x0x7ff780743a20) 0 empty + +Vtable for QThread +QThread::_ZTV7QThread: 15 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 (0x0x7ff78073f548) 0 + vptr=((& QThread::_ZTV7QThread) + 16) + QObject (0x0x7ff7807439c0) 0 + primary-for QThread (0x0x7ff78073f548) + +Class QThreadPool::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThreadPool::QPrivateSignal (0x0x7ff780743de0) 0 empty + +Vtable for QThreadPool +QThreadPool::_ZTV11QThreadPool: 14 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 (0x0x7ff78073f5b0) 0 + vptr=((& QThreadPool::_ZTV11QThreadPool) + 16) + QObject (0x0x7ff780743d80) 0 + primary-for QThreadPool (0x0x7ff78073f5b0) + +Class QThreadStorageData + size=4 align=4 + base size=4 base align=4 +QThreadStorageData (0x0x7ff780788000) 0 + +Class QTimeLine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimeLine::QPrivateSignal (0x0x7ff7807886c0) 0 empty + +Vtable for QTimeLine +QTimeLine::_ZTV9QTimeLine: 15 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 (0x0x7ff78073f618) 0 + vptr=((& QTimeLine::_ZTV9QTimeLine) + 16) + QObject (0x0x7ff780788660) 0 + primary-for QTimeLine (0x0x7ff78073f618) + +Class QTimer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimer::QPrivateSignal (0x0x7ff780788900) 0 empty + +Vtable for QTimer +QTimer::_ZTV6QTimer: 14 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 (0x0x7ff78073f680) 0 + vptr=((& QTimer::_ZTV6QTimer) + 16) + QObject (0x0x7ff7807888a0) 0 + primary-for QTimer (0x0x7ff78073f680) + +Class QTimeZone::OffsetData + size=32 align=8 + base size=28 base align=8 +QTimeZone::OffsetData (0x0x7ff7807fa2a0) 0 + +Class QTimeZone + size=8 align=8 + base size=8 base align=8 +QTimeZone (0x0x7ff7807fa240) 0 + +Class QTranslator::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTranslator::QPrivateSignal (0x0x7ff780895360) 0 empty + +Vtable for QTranslator +QTranslator::_ZTV11QTranslator: 16 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 (0x0x7ff780882d68) 0 + vptr=((& QTranslator::_ZTV11QTranslator) + 16) + QObject (0x0x7ff780895300) 0 + primary-for QTranslator (0x0x7ff780882d68) + +Class QTransposeProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTransposeProxyModel::QPrivateSignal (0x0x7ff7808955a0) 0 empty + +Vtable for QTransposeProxyModel +QTransposeProxyModel::_ZTV20QTransposeProxyModel: 53 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI20QTransposeProxyModel) +16 (int (*)(...))QTransposeProxyModel::metaObject +24 (int (*)(...))QTransposeProxyModel::qt_metacast +32 (int (*)(...))QTransposeProxyModel::qt_metacall +40 (int (*)(...))QTransposeProxyModel::~QTransposeProxyModel +48 (int (*)(...))QTransposeProxyModel::~QTransposeProxyModel +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 (*)(...))QTransposeProxyModel::index +120 (int (*)(...))QTransposeProxyModel::parent +128 (int (*)(...))QAbstractProxyModel::sibling +136 (int (*)(...))QTransposeProxyModel::rowCount +144 (int (*)(...))QTransposeProxyModel::columnCount +152 (int (*)(...))QAbstractProxyModel::hasChildren +160 (int (*)(...))QAbstractProxyModel::data +168 (int (*)(...))QAbstractProxyModel::setData +176 (int (*)(...))QTransposeProxyModel::headerData +184 (int (*)(...))QTransposeProxyModel::setHeaderData +192 (int (*)(...))QTransposeProxyModel::itemData +200 (int (*)(...))QTransposeProxyModel::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 (*)(...))QTransposeProxyModel::insertRows +264 (int (*)(...))QTransposeProxyModel::insertColumns +272 (int (*)(...))QTransposeProxyModel::removeRows +280 (int (*)(...))QTransposeProxyModel::removeColumns +288 (int (*)(...))QTransposeProxyModel::moveRows +296 (int (*)(...))QTransposeProxyModel::moveColumns +304 (int (*)(...))QAbstractProxyModel::fetchMore +312 (int (*)(...))QAbstractProxyModel::canFetchMore +320 (int (*)(...))QAbstractProxyModel::flags +328 (int (*)(...))QTransposeProxyModel::sort +336 (int (*)(...))QAbstractProxyModel::buddy +344 (int (*)(...))QAbstractItemModel::match +352 (int (*)(...))QTransposeProxyModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractProxyModel::submit +376 (int (*)(...))QAbstractProxyModel::revert +384 (int (*)(...))QTransposeProxyModel::setSourceModel +392 (int (*)(...))QTransposeProxyModel::mapToSource +400 (int (*)(...))QTransposeProxyModel::mapFromSource +408 (int (*)(...))QAbstractProxyModel::mapSelectionToSource +416 (int (*)(...))QAbstractProxyModel::mapSelectionFromSource + +Class QTransposeProxyModel + size=16 align=8 + base size=16 base align=8 +QTransposeProxyModel (0x0x7ff780882dd0) 0 + vptr=((& QTransposeProxyModel::_ZTV20QTransposeProxyModel) + 16) + QAbstractProxyModel (0x0x7ff780882e38) 0 + primary-for QTransposeProxyModel (0x0x7ff780882dd0) + QAbstractItemModel (0x0x7ff780882ea0) 0 + primary-for QAbstractProxyModel (0x0x7ff780882e38) + QObject (0x0x7ff780895540) 0 + primary-for QAbstractItemModel (0x0x7ff780882ea0) + +Class QUrlQuery + size=8 align=8 + base size=8 base align=8 +QUrlQuery (0x0x7ff780895780) 0 + +Class QWaitCondition + size=8 align=8 + base size=8 base align=8 +QWaitCondition (0x0x7ff78053b180) 0 + +Class QXmlStreamStringRef + size=16 align=8 + base size=16 base align=8 +QXmlStreamStringRef (0x0x7ff78053b2a0) 0 + +Class QXmlStreamAttribute + size=80 align=8 + base size=73 base align=8 +QXmlStreamAttribute (0x0x7ff7805c9660) 0 + +Class QXmlStreamAttributes + size=8 align=8 + base size=8 base align=8 +QXmlStreamAttributes (0x0x7ff780638548) 0 + QVector (0x0x7ff780629d80) 0 + +Class QXmlStreamNamespaceDeclaration + size=40 align=8 + base size=40 base align=8 +QXmlStreamNamespaceDeclaration (0x0x7ff7806730c0) 0 + +Class QXmlStreamNotationDeclaration + size=56 align=8 + base size=56 base align=8 +QXmlStreamNotationDeclaration (0x0x7ff7802cb060) 0 + +Class QXmlStreamEntityDeclaration + size=88 align=8 + base size=88 base align=8 +QXmlStreamEntityDeclaration (0x0x7ff780328060) 0 + +Vtable for QXmlStreamEntityResolver +QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver: 6 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 (0x0x7ff780391120) 0 nearly-empty + vptr=((& QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver) + 16) + +Class QXmlStreamReader + size=8 align=8 + base size=8 base align=8 +QXmlStreamReader (0x0x7ff780391180) 0 + +Class QXmlStreamWriter + size=8 align=8 + base size=8 base align=8 +QXmlStreamWriter (0x0x7ff7803f1060) 0 + +Class QNdefRecord + size=8 align=8 + base size=8 base align=8 +QNdefRecord (0x0x7ff7803f1240) 0 + +Class QNdefFilter::Record + size=24 align=8 + base size=24 base align=8 +QNdefFilter::Record (0x0x7ff7803f1420) 0 + +Class QNdefFilter + size=8 align=8 + base size=8 base align=8 +QNdefFilter (0x0x7ff7803f13c0) 0 + +Class QNdefMessage + size=8 align=8 + base size=8 base align=8 +QNdefMessage (0x0x7ff7803eb270) 0 + QList (0x0x7ff7803eb2d8) 0 + QListSpecialMethods (0x0x7ff7803f1660) 0 empty + +Class QNdefNfcTextRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcTextRecord (0x0x7ff7803eb340) 0 + QNdefRecord (0x0x7ff7803f1f00) 0 + +Class QNdefNfcUriRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcUriRecord (0x0x7ff7803eb888) 0 + QNdefRecord (0x0x7ff780477780) 0 + +Class QNdefNfcIconRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcIconRecord (0x0x7ff7803eb8f0) 0 + QNdefRecord (0x0x7ff780477b40) 0 + +Class QNdefNfcSmartPosterRecord + size=16 align=8 + base size=16 base align=8 +QNdefNfcSmartPosterRecord (0x0x7ff7803eb958) 0 + QNdefRecord (0x0x7ff780477ea0) 0 + +Class QNearFieldTarget::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldTarget::QPrivateSignal (0x0x7ff7800dd0c0) 0 empty + +Class QNearFieldTarget::RequestId + size=8 align=8 + base size=8 base align=8 +QNearFieldTarget::RequestId (0x0x7ff7800dd120) 0 + +Vtable for QNearFieldTarget +QNearFieldTarget::_ZTV16QNearFieldTarget: 25 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QNearFieldTarget) +16 (int (*)(...))QNearFieldTarget::metaObject +24 (int (*)(...))QNearFieldTarget::qt_metacast +32 (int (*)(...))QNearFieldTarget::qt_metacall +40 0 +48 0 +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 (*)(...))QNearFieldTarget::url +128 (int (*)(...))__cxa_pure_virtual +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))QNearFieldTarget::hasNdefMessage +152 (int (*)(...))QNearFieldTarget::readNdefMessages +160 (int (*)(...))QNearFieldTarget::writeNdefMessages +168 (int (*)(...))QNearFieldTarget::sendCommand +176 (int (*)(...))QNearFieldTarget::sendCommands +184 (int (*)(...))QNearFieldTarget::waitForRequestCompleted +192 (int (*)(...))QNearFieldTarget::handleResponse + +Class QNearFieldTarget + size=24 align=8 + base size=24 base align=8 +QNearFieldTarget (0x0x7ff7803eb9c0) 0 + vptr=((& QNearFieldTarget::_ZTV16QNearFieldTarget) + 16) + QObject (0x0x7ff7800dd060) 0 + primary-for QNearFieldTarget (0x0x7ff7803eb9c0) + +Class QNearFieldManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldManager::QPrivateSignal (0x0x7ff7800ddea0) 0 empty + +Vtable for QNearFieldManager +QNearFieldManager::_ZTV17QNearFieldManager: 14 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QNearFieldManager) +16 (int (*)(...))QNearFieldManager::metaObject +24 (int (*)(...))QNearFieldManager::qt_metacast +32 (int (*)(...))QNearFieldManager::qt_metacall +40 (int (*)(...))QNearFieldManager::~QNearFieldManager +48 (int (*)(...))QNearFieldManager::~QNearFieldManager +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 QNearFieldManager + size=24 align=8 + base size=24 base align=8 +QNearFieldManager (0x0x7ff7803ebaf8) 0 + vptr=((& QNearFieldManager::_ZTV17QNearFieldManager) + 16) + QObject (0x0x7ff7800dde40) 0 + primary-for QNearFieldManager (0x0x7ff7803ebaf8) + +Class QNearFieldShareManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldShareManager::QPrivateSignal (0x0x7ff78014c960) 0 empty + +Vtable for QNearFieldShareManager +QNearFieldShareManager::_ZTV22QNearFieldShareManager: 14 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI22QNearFieldShareManager) +16 (int (*)(...))QNearFieldShareManager::metaObject +24 (int (*)(...))QNearFieldShareManager::qt_metacast +32 (int (*)(...))QNearFieldShareManager::qt_metacall +40 (int (*)(...))QNearFieldShareManager::~QNearFieldShareManager +48 (int (*)(...))QNearFieldShareManager::~QNearFieldShareManager +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 QNearFieldShareManager + size=24 align=8 + base size=24 base align=8 +QNearFieldShareManager (0x0x7ff7803ebc30) 0 + vptr=((& QNearFieldShareManager::_ZTV22QNearFieldShareManager) + 16) + QObject (0x0x7ff78014c900) 0 + primary-for QNearFieldShareManager (0x0x7ff7803ebc30) + +Class QNearFieldShareTarget::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldShareTarget::QPrivateSignal (0x0x7ff7801ae4e0) 0 empty + +Vtable for QNearFieldShareTarget +QNearFieldShareTarget::_ZTV21QNearFieldShareTarget: 14 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QNearFieldShareTarget) +16 (int (*)(...))QNearFieldShareTarget::metaObject +24 (int (*)(...))QNearFieldShareTarget::qt_metacast +32 (int (*)(...))QNearFieldShareTarget::qt_metacall +40 (int (*)(...))QNearFieldShareTarget::~QNearFieldShareTarget +48 (int (*)(...))QNearFieldShareTarget::~QNearFieldShareTarget +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 QNearFieldShareTarget + size=24 align=8 + base size=24 base align=8 +QNearFieldShareTarget (0x0x7ff7803ebd68) 0 + vptr=((& QNearFieldShareTarget::_ZTV21QNearFieldShareTarget) + 16) + QObject (0x0x7ff7801ae480) 0 + primary-for QNearFieldShareTarget (0x0x7ff7803ebd68) + +Class QQmlNdefRecord::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QQmlNdefRecord::QPrivateSignal (0x0x7ff7801ae720) 0 empty + +Vtable for QQmlNdefRecord +QQmlNdefRecord::_ZTV14QQmlNdefRecord: 14 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI14QQmlNdefRecord) +16 (int (*)(...))QQmlNdefRecord::metaObject +24 (int (*)(...))QQmlNdefRecord::qt_metacast +32 (int (*)(...))QQmlNdefRecord::qt_metacall +40 (int (*)(...))QQmlNdefRecord::~QQmlNdefRecord +48 (int (*)(...))QQmlNdefRecord::~QQmlNdefRecord +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 QQmlNdefRecord + size=24 align=8 + base size=24 base align=8 +QQmlNdefRecord (0x0x7ff7803ebdd0) 0 + vptr=((& QQmlNdefRecord::_ZTV14QQmlNdefRecord) + 16) + QObject (0x0x7ff7801ae6c0) 0 + primary-for QQmlNdefRecord (0x0x7ff7803ebdd0) + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff7801fecc0) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff78021d060) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff78021d240) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff78021d5a0) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff78021d780) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff78021dae0) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff78021dcc0) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff78025c060) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff78025c240) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff78025c5a0) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff78025c780) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff78025cae0) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff78025ccc0) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff780291060) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff780291240) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff7802915a0) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff77fec4a80) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff77fec4de0) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff77fec4f60) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff77fef3300) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff77fef3480) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff77fef37e0) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff77fef3960) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff77fef3cc0) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff77fef3e40) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff77ff221e0) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff77ff22360) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff77ff226c0) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff77ff22840) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff77ff22ba0) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7ff77ff22d20) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7ff77ff500c0) 0 empty + diff --git a/tests/auto/bic/data/QtNfc.5.14.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtNfc.5.14.0.linux-gcc-amd64.txt new file mode 100644 index 0000000..ce605a5 --- /dev/null +++ b/tests/auto/bic/data/QtNfc.5.14.0.linux-gcc-amd64.txt @@ -0,0 +1,5228 @@ +Class std::__failure_type + size=1 align=1 + base size=0 base align=1 +std::__failure_type (0x0x7fb80aaea0c0) 0 empty + +Class std::__do_is_destructible_impl + size=1 align=1 + base size=0 base align=1 +std::__do_is_destructible_impl (0x0x7fb80ab30840) 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 (0x0x7fb80ab30a80) 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 (0x0x7fb80ab30cc0) 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 (0x0x7fb80ab30f00) 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 (0x0x7fb80ab600c0) 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 (0x0x7fb80ab60480) 0 empty + +Class std::__do_is_implicitly_default_constructible_impl + size=1 align=1 + base size=0 base align=1 +std::__do_is_implicitly_default_constructible_impl (0x0x7fb80ab9b5a0) 0 empty + +Class std::__do_common_type_impl + size=1 align=1 + base size=0 base align=1 +std::__do_common_type_impl (0x0x7fb80abf1c60) 0 empty + +Class std::__do_member_type_wrapper + size=1 align=1 + base size=0 base align=1 +std::__do_member_type_wrapper (0x0x7fb80abf1d20) 0 empty + +Class std::__invoke_memfun_ref + size=1 align=1 + base size=0 base align=1 +std::__invoke_memfun_ref (0x0x7fb80ac21120) 0 empty + +Class std::__invoke_memfun_deref + size=1 align=1 + base size=0 base align=1 +std::__invoke_memfun_deref (0x0x7fb80ac21180) 0 empty + +Class std::__invoke_memobj_ref + size=1 align=1 + base size=0 base align=1 +std::__invoke_memobj_ref (0x0x7fb80ac211e0) 0 empty + +Class std::__invoke_memobj_deref + size=1 align=1 + base size=0 base align=1 +std::__invoke_memobj_deref (0x0x7fb80ac21240) 0 empty + +Class std::__invoke_other + size=1 align=1 + base size=0 base align=1 +std::__invoke_other (0x0x7fb80ac212a0) 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 (0x0x7fb80ac21360) 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 (0x0x7fb80ac21420) 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 (0x0x7fb80ac214e0) 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 (0x0x7fb80ac215a0) 0 empty + +Class std::__result_of_other_impl + size=1 align=1 + base size=0 base align=1 +std::__result_of_other_impl (0x0x7fb80ac21900) 0 empty + +Class std::__swappable_details::__do_is_swappable_impl + size=1 align=1 + base size=0 base align=1 +std::__swappable_details::__do_is_swappable_impl (0x0x7fb80ac21c60) 0 empty + +Class std::__swappable_details::__do_is_nothrow_swappable_impl + size=1 align=1 + base size=0 base align=1 +std::__swappable_details::__do_is_nothrow_swappable_impl (0x0x7fb80ac21cc0) 0 empty + +Class std::__nonesuch + size=1 align=1 + base size=0 base align=1 +std::__nonesuch (0x0x7fb80a8682a0) 0 empty + +Class std::piecewise_construct_t + size=1 align=1 + base size=0 base align=1 +std::piecewise_construct_t (0x0x7fb80a868900) 0 empty + +Class std::__nonesuch_no_braces + size=1 align=1 + base size=1 base align=1 +std::__nonesuch_no_braces (0x0x7fb80a85f3a8) 0 empty + std::__nonesuch (0x0x7fb80a868de0) 0 empty + +Class std::__true_type + size=1 align=1 + base size=0 base align=1 +std::__true_type (0x0x7fb80a8ec780) 0 empty + +Class std::__false_type + size=1 align=1 + base size=0 base align=1 +std::__false_type (0x0x7fb80a8ec7e0) 0 empty + +Class std::input_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::input_iterator_tag (0x0x7fb80a9464e0) 0 empty + +Class std::output_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::output_iterator_tag (0x0x7fb80a946540) 0 empty + +Class std::forward_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::forward_iterator_tag (0x0x7fb80a85f888) 0 empty + std::input_iterator_tag (0x0x7fb80a9465a0) 0 empty + +Class std::bidirectional_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::bidirectional_iterator_tag (0x0x7fb80a85f8f0) 0 empty + std::forward_iterator_tag (0x0x7fb80a85f958) 0 empty + std::input_iterator_tag (0x0x7fb80a946600) 0 empty + +Class std::random_access_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::random_access_iterator_tag (0x0x7fb80a85f9c0) 0 empty + std::bidirectional_iterator_tag (0x0x7fb80a85fa28) 0 empty + std::forward_iterator_tag (0x0x7fb80a85fa90) 0 empty + std::input_iterator_tag (0x0x7fb80a946660) 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 (0x0x7fb80a9fe180) 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 (0x0x7fb80a9fe2a0) 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 (0x0x7fb80a9fe5a0) 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 (0x0x7fb80a9fe8a0) 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 (0x0x7fb80a9fe9c0) 0 empty + +Class __locale_struct + size=232 align=8 + base size=232 base align=8 +__locale_struct (0x0x7fb80a687cc0) 0 + +Class timeval + size=16 align=8 + base size=16 base align=8 +timeval (0x0x7fb80a6cf000) 0 + +Class timespec + size=16 align=8 + base size=16 base align=8 +timespec (0x0x7fb80a6cf060) 0 + +Class __pthread_rwlock_arch_t + size=56 align=8 + base size=56 base align=8 +__pthread_rwlock_arch_t (0x0x7fb80a6cf120) 0 + +Class __pthread_internal_list + size=16 align=8 + base size=16 base align=8 +__pthread_internal_list (0x0x7fb80a6cf180) 0 + +Class __pthread_mutex_s + size=40 align=8 + base size=40 base align=8 +__pthread_mutex_s (0x0x7fb80a6cf1e0) 0 + +Class __pthread_cond_s + size=48 align=8 + base size=48 base align=8 +__pthread_cond_s (0x0x7fb80a6cf240) 0 + +Class pthread_attr_t + size=56 align=8 + base size=56 base align=8 +pthread_attr_t (0x0x7fb80a6cf4e0) 0 + +Class random_data + size=48 align=8 + base size=48 base align=8 +random_data (0x0x7fb80a6cf780) 0 + +Class drand48_data + size=24 align=8 + base size=24 base align=8 +drand48_data (0x0x7fb80a6cf7e0) 0 + +Vtable for std::exception +std::exception::_ZTVSt9exception: 5 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 (0x0x7fb80a7865a0) 0 nearly-empty + vptr=((& std::exception::_ZTVSt9exception) + 16) + +Vtable for std::bad_exception +std::bad_exception::_ZTVSt13bad_exception: 5 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 (0x0x7fb80a85fdd0) 0 nearly-empty + vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16) + std::exception (0x0x7fb80a786780) 0 nearly-empty + primary-for std::bad_exception (0x0x7fb80a85fdd0) + +Vtable for std::type_info +std::type_info::_ZTVSt9type_info: 8 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 (0x0x7fb80a786960) 0 + vptr=((& std::type_info::_ZTVSt9type_info) + 16) + +Vtable for std::bad_cast +std::bad_cast::_ZTVSt8bad_cast: 5 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 (0x0x7fb80a85fe38) 0 nearly-empty + vptr=((& std::bad_cast::_ZTVSt8bad_cast) + 16) + std::exception (0x0x7fb80a786d20) 0 nearly-empty + primary-for std::bad_cast (0x0x7fb80a85fe38) + +Vtable for std::bad_typeid +std::bad_typeid::_ZTVSt10bad_typeid: 5 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 (0x0x7fb80a85fea0) 0 nearly-empty + vptr=((& std::bad_typeid::_ZTVSt10bad_typeid) + 16) + std::exception (0x0x7fb80a786f00) 0 nearly-empty + primary-for std::bad_typeid (0x0x7fb80a85fea0) + +Class std::__exception_ptr::exception_ptr + size=8 align=8 + base size=8 base align=8 +std::__exception_ptr::exception_ptr (0x0x7fb80a7b6120) 0 + +Vtable for std::nested_exception +std::nested_exception::_ZTVSt16nested_exception: 4 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 (0x0x7fb80a7b66c0) 0 + vptr=((& std::nested_exception::_ZTVSt16nested_exception) + 16) + +Vtable for std::bad_alloc +std::bad_alloc::_ZTVSt9bad_alloc: 5 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 (0x0x7fb80a85ff08) 0 nearly-empty + vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16) + std::exception (0x0x7fb80a7b6d80) 0 nearly-empty + primary-for std::bad_alloc (0x0x7fb80a85ff08) + +Vtable for std::bad_array_new_length +std::bad_array_new_length::_ZTVSt20bad_array_new_length: 5 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 (0x0x7fb80a85ff70) 0 nearly-empty + vptr=((& std::bad_array_new_length::_ZTVSt20bad_array_new_length) + 16) + std::bad_alloc (0x0x7fb80a7e9000) 0 nearly-empty + primary-for std::bad_array_new_length (0x0x7fb80a85ff70) + std::exception (0x0x7fb80a7b6f60) 0 nearly-empty + primary-for std::bad_alloc (0x0x7fb80a7e9000) + +Class std::nothrow_t + size=1 align=1 + base size=0 base align=1 +std::nothrow_t (0x0x7fb80a7ef180) 0 empty + +Class std::__allocator_traits_base + size=1 align=1 + base size=0 base align=1 +std::__allocator_traits_base (0x0x7fb80a7ef360) 0 empty + +Class std::__numeric_limits_base + size=1 align=1 + base size=0 base align=1 +std::__numeric_limits_base (0x0x7fb80a464840) 0 empty + +Class QSysInfo + size=1 align=1 + base size=0 base align=1 +QSysInfo (0x0x7fb80a0dcd80) 0 empty + +Class QMessageLogContext + size=32 align=8 + base size=32 base align=8 +QMessageLogContext (0x0x7fb80a0dcea0) 0 + +Class QMessageLogger + size=32 align=8 + base size=32 base align=8 +QMessageLogger (0x0x7fb80a1120c0) 0 + +Class QFlag + size=4 align=4 + base size=4 base align=4 +QFlag (0x0x7fb80a112780) 0 + +Class QIncompatibleFlag + size=4 align=4 + base size=4 base align=4 +QIncompatibleFlag (0x0x7fb80a159f00) 0 + +Class std::__atomic_flag_base + size=1 align=1 + base size=1 base align=1 +std::__atomic_flag_base (0x0x7fb80a208420) 0 + +Class std::atomic_flag + size=1 align=1 + base size=1 base align=1 +std::atomic_flag (0x0x7fb80a19be38) 0 + std::__atomic_flag_base (0x0x7fb80a208480) 0 + +Class QAtomicInt + size=4 align=4 + base size=4 base align=4 +QAtomicInt (0x0x7fb809f515b0) 0 + QAtomicInteger (0x0x7fb809f51618) 0 + QBasicAtomicInteger (0x0x7fb809d3d6c0) 0 + +Class QInternal + size=1 align=1 + base size=0 base align=1 +QInternal (0x0x7fb809998240) 0 empty + +Class QtPrivate::QSlotObjectBase + size=16 align=8 + base size=16 base align=8 +QtPrivate::QSlotObjectBase (0x0x7fb8099db7e0) 0 + +Class QGenericArgument + size=16 align=8 + base size=16 base align=8 +QGenericArgument (0x0x7fb8099dbf00) 0 + +Class QGenericReturnArgument + size=16 align=8 + base size=16 base align=8 +QGenericReturnArgument (0x0x7fb809a0d270) 0 + QGenericArgument (0x0x7fb809a1b1e0) 0 + +Class QMetaObject::SuperData + size=8 align=8 + base size=8 base align=8 +QMetaObject::SuperData (0x0x7fb809a1b660) 0 + +Class QMetaObject + size=48 align=8 + base size=48 base align=8 +QMetaObject (0x0x7fb809a1b600) 0 + +Class QMetaObject::Connection + size=8 align=8 + base size=8 base align=8 +QMetaObject::Connection (0x0x7fb809a1bf00) 0 + +Class QLatin1Char + size=1 align=1 + base size=1 base align=1 +QLatin1Char (0x0x7fb8096caa20) 0 + +Class QChar + size=2 align=2 + base size=2 base align=2 +QChar (0x0x7fb8096ee180) 0 + +Class QtPrivate::RefCount + size=4 align=4 + base size=4 base align=4 +QtPrivate::RefCount (0x0x7fb80979ef60) 0 + +Class QArrayData + size=24 align=8 + base size=24 base align=8 +QArrayData (0x0x7fb8097c4300) 0 + +Class QtPrivate::QContainerImplHelper + size=1 align=1 + base size=0 base align=1 +QtPrivate::QContainerImplHelper (0x0x7fb809826600) 0 empty + +Class lconv + size=96 align=8 + base size=96 base align=8 +lconv (0x0x7fb8094d6e40) 0 + +Vtable for __cxxabiv1::__forced_unwind +__cxxabiv1::__forced_unwind::_ZTVN10__cxxabiv115__forced_unwindE: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN10__cxxabiv115__forced_unwindE) +16 0 +24 0 +32 (int (*)(...))__cxa_pure_virtual + +Class __cxxabiv1::__forced_unwind + size=8 align=8 + base size=8 base align=8 +__cxxabiv1::__forced_unwind (0x0x7fb8094d6f00) 0 nearly-empty + vptr=((& __cxxabiv1::__forced_unwind::_ZTVN10__cxxabiv115__forced_unwindE) + 16) + +Class sched_param + size=4 align=4 + base size=4 base align=4 +sched_param (0x0x7fb8095ca060) 0 + +Class timex + size=208 align=8 + base size=208 base align=8 +timex (0x0x7fb8095ca120) 0 + +Class tm + size=56 align=8 + base size=56 base align=8 +tm (0x0x7fb8095ca180) 0 + +Class itimerspec + size=32 align=8 + base size=32 base align=8 +itimerspec (0x0x7fb8095ca1e0) 0 + +Class _pthread_cleanup_buffer + size=32 align=8 + base size=32 base align=8 +_pthread_cleanup_buffer (0x0x7fb8095ca240) 0 + +Class __pthread_cleanup_frame + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_frame (0x0x7fb8095ca360) 0 + +Class __pthread_cleanup_class + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_class (0x0x7fb8095ca3c0) 0 + +Class _IO_marker + size=24 align=8 + base size=24 base align=8 +_IO_marker (0x0x7fb80930f360) 0 + +Class _IO_FILE + size=216 align=8 + base size=216 base align=8 +_IO_FILE (0x0x7fb80930f3c0) 0 + +Class std::_Hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Hash_impl (0x0x7fb8090c1420) 0 empty + +Class std::_Fnv_hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Fnv_hash_impl (0x0x7fb8090c15a0) 0 empty + +Class std::locale + size=8 align=8 + base size=8 base align=8 +std::locale (0x0x7fb80923b720) 0 + +Vtable for std::locale::facet +std::locale::facet::_ZTVNSt6locale5facetE: 4 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 (0x0x7fb80923bae0) 0 + vptr=((& std::locale::facet::_ZTVNSt6locale5facetE) + 16) + +Class std::locale::id + size=8 align=8 + base size=8 base align=8 +std::locale::id (0x0x7fb80923bd80) 0 + +Class std::locale::_Impl + size=40 align=8 + base size=40 base align=8 +std::locale::_Impl (0x0x7fb80923bf60) 0 + +Class std::__cow_string + size=8 align=8 + base size=8 base align=8 +std::__cow_string (0x0x7fb808e95f60) 0 + +Vtable for std::logic_error +std::logic_error::_ZTVSt11logic_error: 5 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 (0x0x7fb808ec8208) 0 + vptr=((& std::logic_error::_ZTVSt11logic_error) + 16) + std::exception (0x0x7fb808edb060) 0 nearly-empty + primary-for std::logic_error (0x0x7fb808ec8208) + +Vtable for std::domain_error +std::domain_error::_ZTVSt12domain_error: 5 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 (0x0x7fb808ec8270) 0 + vptr=((& std::domain_error::_ZTVSt12domain_error) + 16) + std::logic_error (0x0x7fb808ec82d8) 0 + primary-for std::domain_error (0x0x7fb808ec8270) + std::exception (0x0x7fb808edb0c0) 0 nearly-empty + primary-for std::logic_error (0x0x7fb808ec82d8) + +Vtable for std::invalid_argument +std::invalid_argument::_ZTVSt16invalid_argument: 5 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 (0x0x7fb808ec8340) 0 + vptr=((& std::invalid_argument::_ZTVSt16invalid_argument) + 16) + std::logic_error (0x0x7fb808ec83a8) 0 + primary-for std::invalid_argument (0x0x7fb808ec8340) + std::exception (0x0x7fb808edb120) 0 nearly-empty + primary-for std::logic_error (0x0x7fb808ec83a8) + +Vtable for std::length_error +std::length_error::_ZTVSt12length_error: 5 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 (0x0x7fb808ec8410) 0 + vptr=((& std::length_error::_ZTVSt12length_error) + 16) + std::logic_error (0x0x7fb808ec8478) 0 + primary-for std::length_error (0x0x7fb808ec8410) + std::exception (0x0x7fb808edb180) 0 nearly-empty + primary-for std::logic_error (0x0x7fb808ec8478) + +Vtable for std::out_of_range +std::out_of_range::_ZTVSt12out_of_range: 5 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 (0x0x7fb808ec84e0) 0 + vptr=((& std::out_of_range::_ZTVSt12out_of_range) + 16) + std::logic_error (0x0x7fb808ec8548) 0 + primary-for std::out_of_range (0x0x7fb808ec84e0) + std::exception (0x0x7fb808edb1e0) 0 nearly-empty + primary-for std::logic_error (0x0x7fb808ec8548) + +Vtable for std::runtime_error +std::runtime_error::_ZTVSt13runtime_error: 5 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 (0x0x7fb808ec85b0) 0 + vptr=((& std::runtime_error::_ZTVSt13runtime_error) + 16) + std::exception (0x0x7fb808edb240) 0 nearly-empty + primary-for std::runtime_error (0x0x7fb808ec85b0) + +Vtable for std::range_error +std::range_error::_ZTVSt11range_error: 5 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 (0x0x7fb808ec8618) 0 + vptr=((& std::range_error::_ZTVSt11range_error) + 16) + std::runtime_error (0x0x7fb808ec8680) 0 + primary-for std::range_error (0x0x7fb808ec8618) + std::exception (0x0x7fb808edb2a0) 0 nearly-empty + primary-for std::runtime_error (0x0x7fb808ec8680) + +Vtable for std::overflow_error +std::overflow_error::_ZTVSt14overflow_error: 5 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 (0x0x7fb808ec86e8) 0 + vptr=((& std::overflow_error::_ZTVSt14overflow_error) + 16) + std::runtime_error (0x0x7fb808ec8750) 0 + primary-for std::overflow_error (0x0x7fb808ec86e8) + std::exception (0x0x7fb808edb300) 0 nearly-empty + primary-for std::runtime_error (0x0x7fb808ec8750) + +Vtable for std::underflow_error +std::underflow_error::_ZTVSt15underflow_error: 5 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 (0x0x7fb808ec87b8) 0 + vptr=((& std::underflow_error::_ZTVSt15underflow_error) + 16) + std::runtime_error (0x0x7fb808ec8820) 0 + primary-for std::underflow_error (0x0x7fb808ec87b8) + std::exception (0x0x7fb808edb360) 0 nearly-empty + primary-for std::runtime_error (0x0x7fb808ec8820) + +Vtable for std::_V2::error_category +std::_V2::error_category::_ZTVNSt3_V214error_categoryE: 10 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt3_V214error_categoryE) +16 0 +24 0 +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 (0x0x7fb808edb4e0) 0 nearly-empty + vptr=((& std::_V2::error_category::_ZTVNSt3_V214error_categoryE) + 16) + +Class std::error_code + size=16 align=8 + base size=16 base align=8 +std::error_code (0x0x7fb808edb840) 0 + +Class std::error_condition + size=16 align=8 + base size=16 base align=8 +std::error_condition (0x0x7fb808f2b0c0) 0 + +Vtable for std::system_error +std::system_error::_ZTVSt12system_error: 5 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 (0x0x7fb808ec8c30) 0 + vptr=((& std::system_error::_ZTVSt12system_error) + 16) + std::runtime_error (0x0x7fb808ec8c98) 0 + primary-for std::system_error (0x0x7fb808ec8c30) + std::exception (0x0x7fb808f2bc60) 0 nearly-empty + primary-for std::runtime_error (0x0x7fb808ec8c98) + +Vtable for std::ios_base::failure +std::ios_base::failure::_ZTVNSt8ios_base7failureB5cxx11E: 5 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 (0x0x7fb808ec8f08) 0 + vptr=((& std::ios_base::failure::_ZTVNSt8ios_base7failureB5cxx11E) + 16) + std::system_error (0x0x7fb808ec8f70) 0 + primary-for std::ios_base::failure (0x0x7fb808ec8f08) + std::runtime_error (0x0x7fb808f8e000) 0 + primary-for std::system_error (0x0x7fb808ec8f70) + std::exception (0x0x7fb808f86240) 0 nearly-empty + primary-for std::runtime_error (0x0x7fb808f8e000) + +Class std::ios_base::_Callback_list + size=24 align=8 + base size=24 base align=8 +std::ios_base::_Callback_list (0x0x7fb808f862a0) 0 + +Class std::ios_base::_Words + size=16 align=8 + base size=16 base align=8 +std::ios_base::_Words (0x0x7fb808f86300) 0 + +Class std::ios_base::Init + size=1 align=1 + base size=0 base align=1 +std::ios_base::Init (0x0x7fb808f86360) 0 empty + +Vtable for std::ios_base +std::ios_base::_ZTVSt8ios_base: 4 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 (0x0x7fb808f861e0) 0 + vptr=((& std::ios_base::_ZTVSt8ios_base) + 16) + +Class std::ctype_base + size=1 align=1 + base size=0 base align=1 +std::ctype_base (0x0x7fb809056c60) 0 empty + +Class std::__num_base + size=1 align=1 + base size=0 base align=1 +std::__num_base (0x0x7fb808cffe40) 0 empty + +VTT for std::basic_ostream +std::basic_ostream::_ZTTSo: 2 entries +0 ((& std::basic_ostream::_ZTVSo) + 24) +8 ((& std::basic_ostream::_ZTVSo) + 64) + +VTT for std::basic_ostream +std::basic_ostream::_ZTTSt13basic_ostreamIwSt11char_traitsIwEE: 2 entries +0 ((& std::basic_ostream::_ZTVSt13basic_ostreamIwSt11char_traitsIwEE) + 24) +8 ((& std::basic_ostream::_ZTVSt13basic_ostreamIwSt11char_traitsIwEE) + 64) + +VTT for std::basic_istream +std::basic_istream::_ZTTSi: 2 entries +0 ((& std::basic_istream::_ZTVSi) + 24) +8 ((& std::basic_istream::_ZTVSi) + 64) + +VTT for std::basic_istream +std::basic_istream::_ZTTSt13basic_istreamIwSt11char_traitsIwEE: 2 entries +0 ((& std::basic_istream::_ZTVSt13basic_istreamIwSt11char_traitsIwEE) + 24) +8 ((& std::basic_istream::_ZTVSt13basic_istreamIwSt11char_traitsIwEE) + 64) + +Construction vtable for std::basic_istream (0x0x7fb8088d06e8 instance) in std::basic_iostream +std::basic_iostream::_ZTCSd0_Si: 10 entries +0 24 +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISi) +24 0 +32 0 +40 18446744073709551592 +48 (int (*)(...))-24 +56 (int (*)(...))(& _ZTISi) +64 0 +72 0 + +Construction vtable for std::basic_ostream (0x0x7fb8088d07b8 instance) in std::basic_iostream +std::basic_iostream::_ZTCSd16_So: 10 entries +0 8 +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISo) +24 0 +32 0 +40 18446744073709551608 +48 (int (*)(...))-8 +56 (int (*)(...))(& _ZTISo) +64 0 +72 0 + +VTT for std::basic_iostream +std::basic_iostream::_ZTTSd: 7 entries +0 ((& std::basic_iostream::_ZTVSd) + 24) +8 ((& std::basic_iostream::_ZTCSd0_Si) + 24) +16 ((& std::basic_iostream::_ZTCSd0_Si) + 64) +24 ((& std::basic_iostream::_ZTCSd16_So) + 24) +32 ((& std::basic_iostream::_ZTCSd16_So) + 64) +40 ((& std::basic_iostream::_ZTVSd) + 104) +48 ((& std::basic_iostream::_ZTVSd) + 64) + +Construction vtable for std::basic_istream (0x0x7fb80890e478 instance) in std::basic_iostream +std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE0_St13basic_istreamIwS1_E: 10 entries +0 24 +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISt13basic_istreamIwSt11char_traitsIwEE) +24 0 +32 0 +40 18446744073709551592 +48 (int (*)(...))-24 +56 (int (*)(...))(& _ZTISt13basic_istreamIwSt11char_traitsIwEE) +64 0 +72 0 + +Construction vtable for std::basic_ostream (0x0x7fb80890e548 instance) in std::basic_iostream +std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE16_St13basic_ostreamIwS1_E: 10 entries +0 8 +8 (int (*)(...))0 +16 (int (*)(...))(& _ZTISt13basic_ostreamIwSt11char_traitsIwEE) +24 0 +32 0 +40 18446744073709551608 +48 (int (*)(...))-8 +56 (int (*)(...))(& _ZTISt13basic_ostreamIwSt11char_traitsIwEE) +64 0 +72 0 + +VTT for std::basic_iostream +std::basic_iostream::_ZTTSt14basic_iostreamIwSt11char_traitsIwEE: 7 entries +0 ((& std::basic_iostream::_ZTVSt14basic_iostreamIwSt11char_traitsIwEE) + 24) +8 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE0_St13basic_istreamIwS1_E) + 24) +16 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE0_St13basic_istreamIwS1_E) + 64) +24 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE16_St13basic_ostreamIwS1_E) + 24) +32 ((& std::basic_iostream::_ZTCSt14basic_iostreamIwSt11char_traitsIwEE16_St13basic_ostreamIwS1_E) + 64) +40 ((& std::basic_iostream::_ZTVSt14basic_iostreamIwSt11char_traitsIwEE) + 104) +48 ((& std::basic_iostream::_ZTVSt14basic_iostreamIwSt11char_traitsIwEE) + 64) + +Class QByteArrayDataPtr + size=8 align=8 + base size=8 base align=8 +QByteArrayDataPtr (0x0x7fb8089377e0) 0 + +Class QByteArray + size=8 align=8 + base size=8 base align=8 +QByteArray (0x0x7fb808937840) 0 + +Class QByteRef + size=16 align=8 + base size=12 base align=8 +QByteRef (0x0x7fb808663c00) 0 + +Class QStringDataPtr + size=8 align=8 + base size=8 base align=8 +QStringDataPtr (0x0x7fb80870aa80) 0 + +Class QStringView + size=16 align=8 + base size=16 base align=8 +QStringView (0x0x7fb80870af00) 0 + +Class QLatin1String + size=16 align=8 + base size=16 base align=8 +QLatin1String (0x0x7fb80880d000) 0 + +Class QString::Null + size=1 align=1 + base size=0 base align=1 +QString::Null (0x0x7fb80849ff60) 0 empty + +Class QString + size=8 align=8 + base size=8 base align=8 +QString (0x0x7fb80849fe40) 0 + +Class QCharRef + size=16 align=8 + base size=12 base align=8 +QCharRef (0x0x7fb80835fde0) 0 + +Class QStringRef + size=16 align=8 + base size=16 base align=8 +QStringRef (0x0x7fb8080f79c0) 0 + +Class QtPrivate::ArgBase + size=1 align=1 + base size=1 base align=1 +QtPrivate::ArgBase (0x0x7fb807d807e0) 0 + +Class QtPrivate::QStringViewArg + size=24 align=8 + base size=24 base align=8 +QtPrivate::QStringViewArg (0x0x7fb80819d3a8) 0 + QtPrivate::ArgBase (0x0x7fb807d80840) 0 + +Class QtPrivate::QLatin1StringArg + size=24 align=8 + base size=24 base align=8 +QtPrivate::QLatin1StringArg (0x0x7fb80819d410) 0 + QtPrivate::ArgBase (0x0x7fb807d80a20) 0 + +Class std::__erased_type + size=1 align=1 + base size=0 base align=1 +std::__erased_type (0x0x7fb807e56960) 0 empty + +Class std::allocator_arg_t + size=1 align=1 + base size=0 base align=1 +std::allocator_arg_t (0x0x7fb807e569c0) 0 empty + +Class std::__uses_alloc_base + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc_base (0x0x7fb807e56b40) 0 empty + +Class std::__uses_alloc0::_Sink + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc0::_Sink (0x0x7fb807e56c00) 0 empty + +Class std::__uses_alloc0 + size=1 align=1 + base size=1 base align=1 +std::__uses_alloc0 (0x0x7fb80819d7b8) 0 + std::__uses_alloc_base (0x0x7fb807e56ba0) 0 empty + +Class std::_Swallow_assign + size=1 align=1 + base size=0 base align=1 +std::_Swallow_assign (0x0x7fb807badf60) 0 empty + +Vtable for std::bad_function_call +std::bad_function_call::_ZTVSt17bad_function_call: 5 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 (0x0x7fb807bd5a28) 0 nearly-empty + vptr=((& std::bad_function_call::_ZTVSt17bad_function_call) + 16) + std::exception (0x0x7fb807c298a0) 0 nearly-empty + primary-for std::bad_function_call (0x0x7fb807bd5a28) + +Class std::_Nocopy_types + size=16 align=8 + base size=16 base align=8 +std::_Nocopy_types (0x0x7fb807c29960) 0 + +Class std::_Any_data + size=16 align=8 + base size=16 base align=8 +std::_Any_data (0x0x7fb807c299c0) 0 + +Class std::_Function_base + size=24 align=8 + base size=24 base align=8 +std::_Function_base (0x0x7fb807c29cc0) 0 + +Class QtPrivate::QHashCombine + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombine (0x0x7fb807a5a180) 0 empty + +Class QtPrivate::QHashCombineCommutative + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombineCommutative (0x0x7fb807a5a240) 0 empty + +Class std::_Bit_reference + size=16 align=8 + base size=16 base align=8 +std::_Bit_reference (0x0x7fb807760960) 0 + +Class std::_Bit_iterator_base + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator_base (0x0x7fb807a9c5b0) 0 + std::iterator (0x0x7fb8077820c0) 0 empty + +Class std::_Bit_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator (0x0x7fb807a9c6e8) 0 + std::_Bit_iterator_base (0x0x7fb807a9c750) 0 + std::iterator (0x0x7fb807782720) 0 empty + +Class std::_Bit_const_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_const_iterator (0x0x7fb807a9c7b8) 0 + std::_Bit_iterator_base (0x0x7fb807a9c820) 0 + std::iterator (0x0x7fb807782f00) 0 empty + +Class std::__detail::_List_node_base + size=16 align=8 + base size=16 base align=8 +std::__detail::_List_node_base (0x0x7fb8075d7a80) 0 + +Class QListData::NotArrayCompatibleLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotArrayCompatibleLayout (0x0x7fb8076ab840) 0 empty + +Class QListData::NotIndirectLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotIndirectLayout (0x0x7fb8076ab8a0) 0 empty + +Class QListData::ArrayCompatibleLayout + size=1 align=1 + base size=1 base align=1 +QListData::ArrayCompatibleLayout (0x0x7fb80757f340) 0 empty + QListData::NotIndirectLayout (0x0x7fb8076ab900) 0 empty + +Class QListData::InlineWithPaddingLayout + size=1 align=1 + base size=1 base align=1 +QListData::InlineWithPaddingLayout (0x0x7fb80760d8c0) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7fb8076ab960) 0 empty + QListData::NotIndirectLayout (0x0x7fb8076ab9c0) 0 empty + +Class QListData::IndirectLayout + size=1 align=1 + base size=1 base align=1 +QListData::IndirectLayout (0x0x7fb80757f3a8) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7fb8076aba20) 0 empty + +Class QListData::Data + size=24 align=8 + base size=24 base align=8 +QListData::Data (0x0x7fb8076aba80) 0 + +Class QListData + size=8 align=8 + base size=8 base align=8 +QListData (0x0x7fb8076ab7e0) 0 + +Class QRegExp + size=8 align=8 + base size=8 base align=8 +QRegExp (0x0x7fb80739dc00) 0 + +Class QStringMatcher::Data + size=272 align=8 + base size=272 base align=8 +QStringMatcher::Data (0x0x7fb807497180) 0 + +Class QStringMatcher + size=1048 align=8 + base size=1048 base align=8 +QStringMatcher (0x0x7fb807497120) 0 + +Class QStringList + size=8 align=8 + base size=8 base align=8 +QStringList (0x0x7fb8074af068) 0 + QList (0x0x7fb8074af0d0) 0 + QListSpecialMethods (0x0x7fb8074973c0) 0 empty + +Class QScopedPointerPodDeleter + size=1 align=1 + base size=0 base align=1 +QScopedPointerPodDeleter (0x0x7fb807178300) 0 empty + +Class std::_Rb_tree_node_base + size=32 align=8 + base size=32 base align=8 +std::_Rb_tree_node_base (0x0x7fb807200540) 0 + +Class std::_Rb_tree_header + size=40 align=8 + base size=40 base align=8 +std::_Rb_tree_header (0x0x7fb8072008a0) 0 + +Class QtPrivate::AbstractDebugStreamFunction + size=16 align=8 + base size=16 base align=8 +QtPrivate::AbstractDebugStreamFunction (0x0x7fb806f47ea0) 0 + +Class QtPrivate::AbstractComparatorFunction + size=24 align=8 + base size=24 base align=8 +QtPrivate::AbstractComparatorFunction (0x0x7fb806f63240) 0 + +Class QtPrivate::AbstractConverterFunction + size=8 align=8 + base size=8 base align=8 +QtPrivate::AbstractConverterFunction (0x0x7fb806f63780) 0 + +Class QMetaType + size=80 align=8 + base size=80 base align=8 +QMetaType (0x0x7fb806f63cc0) 0 + +Class QtMetaTypePrivate::VariantData + size=24 align=8 + base size=20 base align=8 +QtMetaTypePrivate::VariantData (0x0x7fb806fb4ea0) 0 + +Class QtMetaTypePrivate::VectorBoolElements + size=1 align=1 + base size=0 base align=1 +QtMetaTypePrivate::VectorBoolElements (0x0x7fb806fed5a0) 0 empty + +Class QtMetaTypePrivate::QSequentialIterableImpl + size=104 align=8 + base size=104 base align=8 +QtMetaTypePrivate::QSequentialIterableImpl (0x0x7fb806c86420) 0 + +Class QtMetaTypePrivate::QAssociativeIterableImpl + size=112 align=8 + base size=112 base align=8 +QtMetaTypePrivate::QAssociativeIterableImpl (0x0x7fb806ce0ae0) 0 + +Class QtMetaTypePrivate::QPairVariantInterfaceImpl + size=40 align=8 + base size=40 base align=8 +QtMetaTypePrivate::QPairVariantInterfaceImpl (0x0x7fb806d57060) 0 + +Class std::chrono::_V2::system_clock + size=1 align=1 + base size=0 base align=1 +std::chrono::_V2::system_clock (0x0x7fb806bfe600) 0 empty + +Class std::chrono::_V2::steady_clock + size=1 align=1 + base size=0 base align=1 +std::chrono::_V2::steady_clock (0x0x7fb80692a0c0) 0 empty + +Vtable for QObjectData +QObjectData::_ZTV11QObjectData: 4 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 (0x0x7fb80692a120) 0 + vptr=((& QObjectData::_ZTV11QObjectData) + 16) + +Class QObject::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObject::QPrivateSignal (0x0x7fb80692a300) 0 empty + +Vtable for QObject +QObject::_ZTV7QObject: 14 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 (0x0x7fb80692a2a0) 0 + vptr=((& QObject::_ZTV7QObject) + 16) + +Vtable for QObjectUserData +QObjectUserData::_ZTV15QObjectUserData: 4 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 (0x0x7fb8069fb120) 0 nearly-empty + vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16) + +Class QSignalBlocker + size=16 align=8 + base size=10 base align=8 +QSignalBlocker (0x0x7fb8069fb2a0) 0 + +Class QAbstractAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractAnimation::QPrivateSignal (0x0x7fb8069fbb40) 0 empty + +Vtable for QAbstractAnimation +QAbstractAnimation::_ZTV18QAbstractAnimation: 18 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QAbstractAnimation) +16 (int (*)(...))QAbstractAnimation::metaObject +24 (int (*)(...))QAbstractAnimation::qt_metacast +32 (int (*)(...))QAbstractAnimation::qt_metacall +40 0 +48 0 +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 (0x0x7fb8069f8208) 0 + vptr=((& QAbstractAnimation::_ZTV18QAbstractAnimation) + 16) + QObject (0x0x7fb8069fbae0) 0 + primary-for QAbstractAnimation (0x0x7fb8069f8208) + +Class QAnimationDriver::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationDriver::QPrivateSignal (0x0x7fb8069fbf00) 0 empty + +Vtable for QAnimationDriver +QAnimationDriver::_ZTV16QAnimationDriver: 18 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 (0x0x7fb8069f8270) 0 + vptr=((& QAnimationDriver::_ZTV16QAnimationDriver) + 16) + QObject (0x0x7fb8069fbea0) 0 + primary-for QAnimationDriver (0x0x7fb8069f8270) + +Class QEventLoop::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventLoop::QPrivateSignal (0x0x7fb806a3f180) 0 empty + +Vtable for QEventLoop +QEventLoop::_ZTV10QEventLoop: 14 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 (0x0x7fb8069f82d8) 0 + vptr=((& QEventLoop::_ZTV10QEventLoop) + 16) + QObject (0x0x7fb806a3f120) 0 + primary-for QEventLoop (0x0x7fb8069f82d8) + +Class QEventLoopLocker + size=8 align=8 + base size=8 base align=8 +QEventLoopLocker (0x0x7fb806a3fa20) 0 + +Class QAbstractEventDispatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractEventDispatcher::QPrivateSignal (0x0x7fb806a3fae0) 0 empty + +Class QAbstractEventDispatcher::TimerInfo + size=12 align=4 + base size=12 base align=4 +QAbstractEventDispatcher::TimerInfo (0x0x7fb806a3fb40) 0 + +Vtable for QAbstractEventDispatcher +QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher: 28 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI24QAbstractEventDispatcher) +16 (int (*)(...))QAbstractEventDispatcher::metaObject +24 (int (*)(...))QAbstractEventDispatcher::qt_metacast +32 (int (*)(...))QAbstractEventDispatcher::qt_metacall +40 0 +48 0 +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 (0x0x7fb8069f8410) 0 + vptr=((& QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher) + 16) + QObject (0x0x7fb806a3fa80) 0 + primary-for QAbstractEventDispatcher (0x0x7fb8069f8410) + +Class QMapNodeBase + size=24 align=8 + base size=24 base align=8 +QMapNodeBase (0x0x7fb8066b7b40) 0 + +Class QMapDataBase + size=40 align=8 + base size=40 base align=8 +QMapDataBase (0x0x7fb8066e07e0) 0 + +Class QHashData::Node + size=16 align=8 + base size=16 base align=8 +QHashData::Node (0x0x7fb8067cd180) 0 + +Class QHashData + size=48 align=8 + base size=44 base align=8 +QHashData (0x0x7fb8067cd120) 0 + +Class QHashDummyValue + size=1 align=1 + base size=0 base align=1 +QHashDummyValue (0x0x7fb8067cd420) 0 empty + +Class QVariant::PrivateShared + size=16 align=8 + base size=12 base align=8 +QVariant::PrivateShared (0x0x7fb8064dab40) 0 + +Class QVariant::Private::Data + size=8 align=8 + base size=8 base align=8 +QVariant::Private::Data (0x0x7fb8064dac00) 0 + +Class QVariant::Private + size=16 align=8 + base size=12 base align=8 +QVariant::Private (0x0x7fb8064daba0) 0 + +Class QVariant::Handler + size=72 align=8 + base size=72 base align=8 +QVariant::Handler (0x0x7fb8064dac60) 0 + +Class QVariant + size=16 align=8 + base size=16 base align=8 +QVariant (0x0x7fb8064daae0) 0 + +Class QVariantComparisonHelper + size=8 align=8 + base size=8 base align=8 +QVariantComparisonHelper (0x0x7fb8065d3f00) 0 + +Class QSequentialIterable::const_iterator + size=112 align=8 + base size=112 base align=8 +QSequentialIterable::const_iterator (0x0x7fb8062a15a0) 0 + +Class QSequentialIterable + size=104 align=8 + base size=104 base align=8 +QSequentialIterable (0x0x7fb8062a1540) 0 + +Class QAssociativeIterable::const_iterator + size=120 align=8 + base size=120 base align=8 +QAssociativeIterable::const_iterator (0x0x7fb8062a16c0) 0 + +Class QAssociativeIterable + size=112 align=8 + base size=112 base align=8 +QAssociativeIterable (0x0x7fb8062a1660) 0 + +Class QModelIndex + size=24 align=8 + base size=24 base align=8 +QModelIndex (0x0x7fb80636b840) 0 + +Class QPersistentModelIndex + size=8 align=8 + base size=8 base align=8 +QPersistentModelIndex (0x0x7fb8063e0480) 0 + +Class QAbstractItemModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractItemModel::QPrivateSignal (0x0x7fb8060b02a0) 0 empty + +Vtable for QAbstractItemModel +QAbstractItemModel::_ZTV18QAbstractItemModel: 48 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QAbstractItemModel) +16 (int (*)(...))QAbstractItemModel::metaObject +24 (int (*)(...))QAbstractItemModel::qt_metacast +32 (int (*)(...))QAbstractItemModel::qt_metacall +40 0 +48 0 +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 (0x0x7fb8060af5b0) 0 + vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16) + QObject (0x0x7fb8060b0240) 0 + primary-for QAbstractItemModel (0x0x7fb8060af5b0) + +Class QAbstractTableModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTableModel::QPrivateSignal (0x0x7fb806176660) 0 empty + +Vtable for QAbstractTableModel +QAbstractTableModel::_ZTV19QAbstractTableModel: 48 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QAbstractTableModel) +16 (int (*)(...))QAbstractTableModel::metaObject +24 (int (*)(...))QAbstractTableModel::qt_metacast +32 (int (*)(...))QAbstractTableModel::qt_metacall +40 0 +48 0 +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 (0x0x7fb8060afbc8) 0 + vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16) + QAbstractItemModel (0x0x7fb8060afc30) 0 + primary-for QAbstractTableModel (0x0x7fb8060afbc8) + QObject (0x0x7fb806176600) 0 + primary-for QAbstractItemModel (0x0x7fb8060afc30) + +Class QAbstractListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractListModel::QPrivateSignal (0x0x7fb8061767e0) 0 empty + +Vtable for QAbstractListModel +QAbstractListModel::_ZTV18QAbstractListModel: 48 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QAbstractListModel) +16 (int (*)(...))QAbstractListModel::metaObject +24 (int (*)(...))QAbstractListModel::qt_metacast +32 (int (*)(...))QAbstractListModel::qt_metacall +40 0 +48 0 +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 (0x0x7fb8060afc98) 0 + vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16) + QAbstractItemModel (0x0x7fb8060afd00) 0 + primary-for QAbstractListModel (0x0x7fb8060afc98) + QObject (0x0x7fb806176780) 0 + primary-for QAbstractItemModel (0x0x7fb8060afd00) + +Vtable for QAbstractNativeEventFilter +QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI26QAbstractNativeEventFilter) +16 0 +24 0 +32 (int (*)(...))__cxa_pure_virtual + +Class QAbstractNativeEventFilter + size=16 align=8 + base size=16 base align=8 +QAbstractNativeEventFilter (0x0x7fb806176f00) 0 + vptr=((& QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter) + 16) + +Class QAbstractProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractProxyModel::QPrivateSignal (0x0x7fb8061e8000) 0 empty + +Vtable for QAbstractProxyModel +QAbstractProxyModel::_ZTV19QAbstractProxyModel: 53 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QAbstractProxyModel) +16 (int (*)(...))QAbstractProxyModel::metaObject +24 (int (*)(...))QAbstractProxyModel::qt_metacast +32 (int (*)(...))QAbstractProxyModel::qt_metacall +40 0 +48 0 +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 (0x0x7fb8060afdd0) 0 + vptr=((& QAbstractProxyModel::_ZTV19QAbstractProxyModel) + 16) + QAbstractItemModel (0x0x7fb8060afe38) 0 + primary-for QAbstractProxyModel (0x0x7fb8060afdd0) + QObject (0x0x7fb806176f60) 0 + primary-for QAbstractItemModel (0x0x7fb8060afe38) + +Class QAbstractState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractState::QPrivateSignal (0x0x7fb8061e8240) 0 empty + +Vtable for QAbstractState +QAbstractState::_ZTV14QAbstractState: 16 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI14QAbstractState) +16 (int (*)(...))QAbstractState::metaObject +24 (int (*)(...))QAbstractState::qt_metacast +32 (int (*)(...))QAbstractState::qt_metacall +40 0 +48 0 +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 (0x0x7fb8060afea0) 0 + vptr=((& QAbstractState::_ZTV14QAbstractState) + 16) + QObject (0x0x7fb8061e81e0) 0 + primary-for QAbstractState (0x0x7fb8060afea0) + +Class QAbstractTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTransition::QPrivateSignal (0x0x7fb8061e8480) 0 empty + +Vtable for QAbstractTransition +QAbstractTransition::_ZTV19QAbstractTransition: 16 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI19QAbstractTransition) +16 (int (*)(...))QAbstractTransition::metaObject +24 (int (*)(...))QAbstractTransition::qt_metacast +32 (int (*)(...))QAbstractTransition::qt_metacall +40 0 +48 0 +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 (0x0x7fb8060aff08) 0 + vptr=((& QAbstractTransition::_ZTV19QAbstractTransition) + 16) + QObject (0x0x7fb8061e8420) 0 + primary-for QAbstractTransition (0x0x7fb8060aff08) + +Class QAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationGroup::QPrivateSignal (0x0x7fb8061e8780) 0 empty + +Vtable for QAnimationGroup +QAnimationGroup::_ZTV15QAnimationGroup: 18 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI15QAnimationGroup) +16 (int (*)(...))QAnimationGroup::metaObject +24 (int (*)(...))QAnimationGroup::qt_metacast +32 (int (*)(...))QAnimationGroup::qt_metacall +40 0 +48 0 +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 (0x0x7fb8060aff70) 0 + vptr=((& QAnimationGroup::_ZTV15QAnimationGroup) + 16) + QAbstractAnimation (0x0x7fb80621e000) 0 + primary-for QAnimationGroup (0x0x7fb8060aff70) + QObject (0x0x7fb8061e8720) 0 + primary-for QAbstractAnimation (0x0x7fb80621e000) + +Class QBasicTimer + size=4 align=4 + base size=4 base align=4 +QBasicTimer (0x0x7fb805e6aa80) 0 + +Class QBitArray + size=8 align=8 + base size=8 base align=8 +QBitArray (0x0x7fb805f00420) 0 + +Class QBitRef + size=16 align=8 + base size=12 base align=8 +QBitRef (0x0x7fb805f548a0) 0 + +Class QIODevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIODevice::QPrivateSignal (0x0x7fb805fa7b40) 0 empty + +Vtable for QIODevice +QIODevice::_ZTV9QIODevice: 30 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QIODevice) +16 (int (*)(...))QIODevice::metaObject +24 (int (*)(...))QIODevice::qt_metacast +32 (int (*)(...))QIODevice::qt_metacall +40 0 +48 0 +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 (0x0x7fb805fb45b0) 0 + vptr=((& QIODevice::_ZTV9QIODevice) + 16) + QObject (0x0x7fb805fa7ae0) 0 + primary-for QIODevice (0x0x7fb805fb45b0) + +Class QBuffer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBuffer::QPrivateSignal (0x0x7fb805ff04e0) 0 empty + +Vtable for QBuffer +QBuffer::_ZTV7QBuffer: 30 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 (0x0x7fb805fb46e8) 0 + vptr=((& QBuffer::_ZTV7QBuffer) + 16) + QIODevice (0x0x7fb805fb4750) 0 + primary-for QBuffer (0x0x7fb805fb46e8) + QObject (0x0x7fb805ff0480) 0 + primary-for QIODevice (0x0x7fb805fb4750) + +Class QByteArrayMatcher::Data + size=272 align=8 + base size=272 base align=8 +QByteArrayMatcher::Data (0x0x7fb805ff0780) 0 + +Class QByteArrayMatcher + size=1040 align=8 + base size=1040 base align=8 +QByteArrayMatcher (0x0x7fb805ff0720) 0 + +Class QStaticByteArrayMatcherBase::Skiptable + size=256 align=1 + base size=256 base align=1 +QStaticByteArrayMatcherBase::Skiptable (0x0x7fb805ff0900) 0 + +Class QStaticByteArrayMatcherBase + size=256 align=16 + base size=256 base align=16 +QStaticByteArrayMatcherBase (0x0x7fb805ff08a0) 0 + +Class QSharedData + size=4 align=4 + base size=4 base align=4 +QSharedData (0x0x7fb8060437e0) 0 + +Class QLocale + size=8 align=8 + base size=8 base align=8 +QLocale (0x0x7fb805c866c0) 0 + +Class QCalendar::YearMonthDay + size=12 align=4 + base size=12 base align=4 +QCalendar::YearMonthDay (0x0x7fb805de0ba0) 0 + +Class QCalendar + size=8 align=8 + base size=8 base align=8 +QCalendar (0x0x7fb805de0b40) 0 + +Class QDate + size=8 align=8 + base size=8 base align=8 +QDate (0x0x7fb805e2a3c0) 0 + +Class QTime + size=4 align=4 + base size=4 base align=4 +QTime (0x0x7fb805a81c60) 0 + +Class QDateTime::ShortData + size=8 align=8 + base size=8 base align=8 +QDateTime::ShortData (0x0x7fb805aed900) 0 + +Class QDateTime::Data + size=8 align=8 + base size=8 base align=8 +QDateTime::Data (0x0x7fb805aed960) 0 + +Class QDateTime + size=8 align=8 + base size=8 base align=8 +QDateTime (0x0x7fb805aed8a0) 0 + +Vtable for QTextStream +QTextStream::_ZTV11QTextStream: 4 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 (0x0x7fb805bdc060) 0 + vptr=((& QTextStream::_ZTV11QTextStream) + 16) + +Class QTextStreamManipulator + size=40 align=8 + base size=38 base align=8 +QTextStreamManipulator (0x0x7fb805bdc900) 0 + +Class QContiguousCacheData + size=24 align=4 + base size=24 base align=4 +QContiguousCacheData (0x0x7fb8058b45a0) 0 + +Vtable for __gnu_cxx::__concurrence_lock_error +__gnu_cxx::__concurrence_lock_error::_ZTVN9__gnu_cxx24__concurrence_lock_errorE: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx24__concurrence_lock_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_lock_error::~__concurrence_lock_error +24 (int (*)(...))__gnu_cxx::__concurrence_lock_error::~__concurrence_lock_error +32 (int (*)(...))__gnu_cxx::__concurrence_lock_error::what + +Class __gnu_cxx::__concurrence_lock_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_lock_error (0x0x7fb805bd3750) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_lock_error::_ZTVN9__gnu_cxx24__concurrence_lock_errorE) + 16) + std::exception (0x0x7fb805903420) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_lock_error (0x0x7fb805bd3750) + +Vtable for __gnu_cxx::__concurrence_unlock_error +__gnu_cxx::__concurrence_unlock_error::_ZTVN9__gnu_cxx26__concurrence_unlock_errorE: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx26__concurrence_unlock_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::~__concurrence_unlock_error +24 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::~__concurrence_unlock_error +32 (int (*)(...))__gnu_cxx::__concurrence_unlock_error::what + +Class __gnu_cxx::__concurrence_unlock_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_unlock_error (0x0x7fb805bd37b8) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_unlock_error::_ZTVN9__gnu_cxx26__concurrence_unlock_errorE) + 16) + std::exception (0x0x7fb805903540) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_unlock_error (0x0x7fb805bd37b8) + +Vtable for __gnu_cxx::__concurrence_broadcast_error +__gnu_cxx::__concurrence_broadcast_error::_ZTVN9__gnu_cxx29__concurrence_broadcast_errorE: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx29__concurrence_broadcast_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::~__concurrence_broadcast_error +24 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::~__concurrence_broadcast_error +32 (int (*)(...))__gnu_cxx::__concurrence_broadcast_error::what + +Class __gnu_cxx::__concurrence_broadcast_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_broadcast_error (0x0x7fb805bd3820) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_broadcast_error::_ZTVN9__gnu_cxx29__concurrence_broadcast_errorE) + 16) + std::exception (0x0x7fb805903660) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_broadcast_error (0x0x7fb805bd3820) + +Vtable for __gnu_cxx::__concurrence_wait_error +__gnu_cxx::__concurrence_wait_error::_ZTVN9__gnu_cxx24__concurrence_wait_errorE: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTIN9__gnu_cxx24__concurrence_wait_errorE) +16 (int (*)(...))__gnu_cxx::__concurrence_wait_error::~__concurrence_wait_error +24 (int (*)(...))__gnu_cxx::__concurrence_wait_error::~__concurrence_wait_error +32 (int (*)(...))__gnu_cxx::__concurrence_wait_error::what + +Class __gnu_cxx::__concurrence_wait_error + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__concurrence_wait_error (0x0x7fb805bd38f0) 0 nearly-empty + vptr=((& __gnu_cxx::__concurrence_wait_error::_ZTVN9__gnu_cxx24__concurrence_wait_errorE) + 16) + std::exception (0x0x7fb805903780) 0 nearly-empty + primary-for __gnu_cxx::__concurrence_wait_error (0x0x7fb805bd38f0) + +Class __gnu_cxx::__mutex + size=40 align=8 + base size=40 base align=8 +__gnu_cxx::__mutex (0x0x7fb8059277e0) 0 + +Class __gnu_cxx::__recursive_mutex + size=40 align=8 + base size=40 base align=8 +__gnu_cxx::__recursive_mutex (0x0x7fb805927ae0) 0 + +Class __gnu_cxx::__scoped_lock + size=8 align=8 + base size=8 base align=8 +__gnu_cxx::__scoped_lock (0x0x7fb805927de0) 0 + +Class __gnu_cxx::__cond + size=48 align=8 + base size=48 base align=8 +__gnu_cxx::__cond (0x0x7fb80594e180) 0 + +Vtable for std::bad_weak_ptr +std::bad_weak_ptr::_ZTVSt12bad_weak_ptr: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt12bad_weak_ptr) +16 (int (*)(...))std::bad_weak_ptr::~bad_weak_ptr +24 (int (*)(...))std::bad_weak_ptr::~bad_weak_ptr +32 (int (*)(...))std::bad_weak_ptr::what + +Class std::bad_weak_ptr + size=8 align=8 + base size=8 base align=8 +std::bad_weak_ptr (0x0x7fb805bd3958) 0 nearly-empty + vptr=((& std::bad_weak_ptr::_ZTVSt12bad_weak_ptr) + 16) + std::exception (0x0x7fb8059c8360) 0 nearly-empty + primary-for std::bad_weak_ptr (0x0x7fb805bd3958) + +Class std::_Sp_make_shared_tag + size=1 align=1 + base size=0 base align=1 +std::_Sp_make_shared_tag (0x0x7fb805a34300) 0 empty + +Class std::__sp_array_delete + size=1 align=1 + base size=0 base align=1 +std::__sp_array_delete (0x0x7fb805a34720) 0 empty + +Class std::_Sp_locker + size=2 align=1 + base size=2 base align=1 +std::_Sp_locker (0x0x7fb8057735a0) 0 + +Class QtSharedPointer::NormalDeleter + size=1 align=1 + base size=0 base align=1 +QtSharedPointer::NormalDeleter (0x0x7fb8057aaa80) 0 empty + +Class QtSharedPointer::ExternalRefCountData + size=16 align=8 + base size=16 base align=8 +QtSharedPointer::ExternalRefCountData (0x0x7fb8057aac00) 0 + +Class QtPrivate::EnableInternalData + size=1 align=1 + base size=0 base align=1 +QtPrivate::EnableInternalData (0x0x7fb805833540) 0 empty + +Class QDebug::Stream + size=80 align=8 + base size=76 base align=8 +QDebug::Stream (0x0x7fb80545bc00) 0 + +Class QDebug + size=8 align=8 + base size=8 base align=8 +QDebug (0x0x7fb80545bba0) 0 + +Class QDebugStateSaver + size=8 align=8 + base size=8 base align=8 +QDebugStateSaver (0x0x7fb8055f0540) 0 + +Class QNoDebug + size=1 align=1 + base size=0 base align=1 +QNoDebug (0x0x7fb8055f0600) 0 empty + +Class QCborError + size=4 align=4 + base size=4 base align=4 +QCborError (0x0x7fb805270840) 0 + +Class QRegularExpression + size=8 align=8 + base size=8 base align=8 +QRegularExpression (0x0x7fb8052a8000) 0 + +Class QRegularExpressionMatch + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatch (0x0x7fb80532cea0) 0 + +Class QRegularExpressionMatchIterator + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatchIterator (0x0x7fb805392c60) 0 + +Class QUrl + size=8 align=8 + base size=8 base align=8 +QUrl (0x0x7fb8054146c0) 0 + +Class QUuid + size=16 align=4 + base size=16 base align=4 +QUuid (0x0x7fb80515c660) 0 + +Class QCborParserError + size=16 align=8 + base size=12 base align=8 +QCborParserError (0x0x7fb8051df1e0) 0 + +Class QCborValue + size=24 align=8 + base size=20 base align=8 +QCborValue (0x0x7fb8051df2a0) 0 + +Class QCborValueRef + size=16 align=8 + base size=16 base align=8 +QCborValueRef (0x0x7fb80501de40) 0 + +Class QCborArray::Iterator + size=16 align=8 + base size=16 base align=8 +QCborArray::Iterator (0x0x7fb804cd58a0) 0 + +Class QCborArray::ConstIterator + size=16 align=8 + base size=16 base align=8 +QCborArray::ConstIterator (0x0x7fb804cd5900) 0 + +Class QCborArray + size=8 align=8 + base size=8 base align=8 +QCborArray (0x0x7fb804cd5840) 0 + +Class QCborMap::Iterator + size=16 align=8 + base size=16 base align=8 +QCborMap::Iterator (0x0x7fb804e564e0) 0 + +Class QCborMap::ConstIterator + size=16 align=8 + base size=16 base align=8 +QCborMap::ConstIterator (0x0x7fb804e56540) 0 + +Class QCborMap + size=8 align=8 + base size=8 base align=8 +QCborMap (0x0x7fb804e56480) 0 + +Class qfloat16::Wrap + size=2 align=2 + base size=2 base align=2 +qfloat16::Wrap (0x0x7fb80485bcc0) 0 + +Class qfloat16 + size=2 align=2 + base size=2 base align=2 +qfloat16 (0x0x7fb80485bc60) 0 + +Class QCborStreamWriter + size=8 align=8 + base size=8 base align=8 +QCborStreamWriter (0x0x7fb80493e960) 0 + +Class QCborStreamReader + size=24 align=8 + base size=20 base align=8 +QCborStreamReader (0x0x7fb8049756c0) 0 + +Class QCollatorSortKey + size=8 align=8 + base size=8 base align=8 +QCollatorSortKey (0x0x7fb8049fb7e0) 0 + +Class QCollator + size=8 align=8 + base size=8 base align=8 +QCollator (0x0x7fb8049fb9c0) 0 + +Class QCommandLineOption + size=8 align=8 + base size=8 base align=8 +QCommandLineOption (0x0x7fb804711000) 0 + +Vtable for QEvent +QEvent::_ZTV6QEvent: 4 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 (0x0x7fb8047ed540) 0 + vptr=((& QEvent::_ZTV6QEvent) + 16) + +Vtable for QTimerEvent +QTimerEvent::_ZTV11QTimerEvent: 4 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 (0x0x7fb8047cd3a8) 0 + vptr=((& QTimerEvent::_ZTV11QTimerEvent) + 16) + QEvent (0x0x7fb8047ed900) 0 + primary-for QTimerEvent (0x0x7fb8047cd3a8) + +Vtable for QChildEvent +QChildEvent::_ZTV11QChildEvent: 4 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 (0x0x7fb8047cd410) 0 + vptr=((& QChildEvent::_ZTV11QChildEvent) + 16) + QEvent (0x0x7fb8047ed9c0) 0 + primary-for QChildEvent (0x0x7fb8047cd410) + +Vtable for QDynamicPropertyChangeEvent +QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent: 4 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 (0x0x7fb8047cd958) 0 + vptr=((& QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent) + 16) + QEvent (0x0x7fb804829060) 0 + primary-for QDynamicPropertyChangeEvent (0x0x7fb8047cd958) + +Vtable for QDeferredDeleteEvent +QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent: 4 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 (0x0x7fb8047cd9c0) 0 + vptr=((& QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent) + 16) + QEvent (0x0x7fb804829120) 0 + primary-for QDeferredDeleteEvent (0x0x7fb8047cd9c0) + +Class QCoreApplication::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QCoreApplication::QPrivateSignal (0x0x7fb804829240) 0 empty + +Vtable for QCoreApplication +QCoreApplication::_ZTV16QCoreApplication: 16 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 (0x0x7fb8047cda28) 0 + vptr=((& QCoreApplication::_ZTV16QCoreApplication) + 16) + QObject (0x0x7fb8048291e0) 0 + primary-for QCoreApplication (0x0x7fb8047cda28) + +Class QCommandLineParser + size=8 align=8 + base size=8 base align=8 +QCommandLineParser (0x0x7fb804829480) 0 + +Class QConcatenateTablesProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QConcatenateTablesProxyModel::QPrivateSignal (0x0x7fb804829600) 0 empty + +Vtable for QConcatenateTablesProxyModel +QConcatenateTablesProxyModel::_ZTV28QConcatenateTablesProxyModel: 48 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI28QConcatenateTablesProxyModel) +16 (int (*)(...))QConcatenateTablesProxyModel::metaObject +24 (int (*)(...))QConcatenateTablesProxyModel::qt_metacast +32 (int (*)(...))QConcatenateTablesProxyModel::qt_metacall +40 (int (*)(...))QConcatenateTablesProxyModel::~QConcatenateTablesProxyModel +48 (int (*)(...))QConcatenateTablesProxyModel::~QConcatenateTablesProxyModel +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 (*)(...))QConcatenateTablesProxyModel::index +120 (int (*)(...))QConcatenateTablesProxyModel::parent +128 (int (*)(...))QAbstractItemModel::sibling +136 (int (*)(...))QConcatenateTablesProxyModel::rowCount +144 (int (*)(...))QConcatenateTablesProxyModel::columnCount +152 (int (*)(...))QAbstractItemModel::hasChildren +160 (int (*)(...))QConcatenateTablesProxyModel::data +168 (int (*)(...))QConcatenateTablesProxyModel::setData +176 (int (*)(...))QConcatenateTablesProxyModel::headerData +184 (int (*)(...))QAbstractItemModel::setHeaderData +192 (int (*)(...))QConcatenateTablesProxyModel::itemData +200 (int (*)(...))QConcatenateTablesProxyModel::setItemData +208 (int (*)(...))QConcatenateTablesProxyModel::mimeTypes +216 (int (*)(...))QConcatenateTablesProxyModel::mimeData +224 (int (*)(...))QConcatenateTablesProxyModel::canDropMimeData +232 (int (*)(...))QConcatenateTablesProxyModel::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 (*)(...))QConcatenateTablesProxyModel::flags +328 (int (*)(...))QAbstractItemModel::sort +336 (int (*)(...))QAbstractItemModel::buddy +344 (int (*)(...))QAbstractItemModel::match +352 (int (*)(...))QConcatenateTablesProxyModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractItemModel::submit +376 (int (*)(...))QAbstractItemModel::revert + +Class QConcatenateTablesProxyModel + size=16 align=8 + base size=16 base align=8 +QConcatenateTablesProxyModel (0x0x7fb8047cda90) 0 + vptr=((& QConcatenateTablesProxyModel::_ZTV28QConcatenateTablesProxyModel) + 16) + QAbstractItemModel (0x0x7fb8047cdaf8) 0 + primary-for QConcatenateTablesProxyModel (0x0x7fb8047cda90) + QObject (0x0x7fb8048295a0) 0 + primary-for QAbstractItemModel (0x0x7fb8047cdaf8) + +Class QCryptographicHash + size=8 align=8 + base size=8 base align=8 +QCryptographicHash (0x0x7fb8048297e0) 0 + +Class QDataStream + size=32 align=8 + base size=32 base align=8 +QDataStream (0x0x7fb804829900) 0 + +Class QtPrivate::StreamStateSaver + size=16 align=8 + base size=12 base align=8 +QtPrivate::StreamStateSaver (0x0x7fb804829a80) 0 + +Class QElapsedTimer + size=16 align=8 + base size=16 base align=8 +QElapsedTimer (0x0x7fb8044ef1e0) 0 + +Class QDeadlineTimer + size=16 align=8 + base size=16 base align=8 +QDeadlineTimer (0x0x7fb8044ef900) 0 + +Class QFileDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileDevice::QPrivateSignal (0x0x7fb804630600) 0 empty + +Vtable for QFileDevice +QFileDevice::_ZTV11QFileDevice: 34 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 (0x0x7fb804620d00) 0 + vptr=((& QFileDevice::_ZTV11QFileDevice) + 16) + QIODevice (0x0x7fb804620d68) 0 + primary-for QFileDevice (0x0x7fb804620d00) + QObject (0x0x7fb8046305a0) 0 + primary-for QIODevice (0x0x7fb804620d68) + +Class QFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFile::QPrivateSignal (0x0x7fb804630f00) 0 empty + +Vtable for QFile +QFile::_ZTV5QFile: 34 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 (0x0x7fb804620ea0) 0 + vptr=((& QFile::_ZTV5QFile) + 16) + QFileDevice (0x0x7fb804620f08) 0 + primary-for QFile (0x0x7fb804620ea0) + QIODevice (0x0x7fb804620f70) 0 + primary-for QFileDevice (0x0x7fb804620f08) + QObject (0x0x7fb804630ea0) 0 + primary-for QIODevice (0x0x7fb804620f70) + +Class QFileInfo + size=8 align=8 + base size=8 base align=8 +QFileInfo (0x0x7fb8042955a0) 0 + +Class QDir + size=8 align=8 + base size=8 base align=8 +QDir (0x0x7fb804372480) 0 + +Class QDirIterator + size=8 align=8 + base size=8 base align=8 +QDirIterator (0x0x7fb804089480) 0 + +Class QEasingCurve + size=8 align=8 + base size=8 base align=8 +QEasingCurve (0x0x7fb804089c00) 0 + +Class QEventTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventTransition::QPrivateSignal (0x0x7fb8041c7d20) 0 empty + +Vtable for QEventTransition +QEventTransition::_ZTV16QEventTransition: 16 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 (0x0x7fb80418dc30) 0 + vptr=((& QEventTransition::_ZTV16QEventTransition) + 16) + QAbstractTransition (0x0x7fb80418dc98) 0 + primary-for QEventTransition (0x0x7fb80418dc30) + QObject (0x0x7fb8041c7cc0) 0 + primary-for QAbstractTransition (0x0x7fb80418dc98) + +Vtable for QException +QException::_ZTV10QException: 7 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 (0x0x7fb80418dd00) 0 nearly-empty + vptr=((& QException::_ZTV10QException) + 16) + std::exception (0x0x7fb8041c7f00) 0 nearly-empty + primary-for QException (0x0x7fb80418dd00) + +Vtable for QUnhandledException +QUnhandledException::_ZTV19QUnhandledException: 7 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 (0x0x7fb80418dd68) 0 nearly-empty + vptr=((& QUnhandledException::_ZTV19QUnhandledException) + 16) + QException (0x0x7fb80418ddd0) 0 nearly-empty + primary-for QUnhandledException (0x0x7fb80418dd68) + std::exception (0x0x7fb8041c7f60) 0 nearly-empty + primary-for QException (0x0x7fb80418ddd0) + +Class QtPrivate::ExceptionHolder + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionHolder (0x0x7fb8041fe000) 0 + +Class QtPrivate::ExceptionStore + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionStore (0x0x7fb8041fe0c0) 0 + +Vtable for QFactoryInterface +QFactoryInterface::_ZTV17QFactoryInterface: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QFactoryInterface) +16 0 +24 0 +32 (int (*)(...))__cxa_pure_virtual + +Class QFactoryInterface + size=8 align=8 + base size=8 base align=8 +QFactoryInterface (0x0x7fb8041fe120) 0 nearly-empty + vptr=((& QFactoryInterface::_ZTV17QFactoryInterface) + 16) + +Class QFileSelector::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSelector::QPrivateSignal (0x0x7fb8041fe360) 0 empty + +Vtable for QFileSelector +QFileSelector::_ZTV13QFileSelector: 14 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 (0x0x7fb80418de38) 0 + vptr=((& QFileSelector::_ZTV13QFileSelector) + 16) + QObject (0x0x7fb8041fe300) 0 + primary-for QFileSelector (0x0x7fb80418de38) + +Class QFileSystemWatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSystemWatcher::QPrivateSignal (0x0x7fb8041fe5a0) 0 empty + +Vtable for QFileSystemWatcher +QFileSystemWatcher::_ZTV18QFileSystemWatcher: 14 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 (0x0x7fb80418dea0) 0 + vptr=((& QFileSystemWatcher::_ZTV18QFileSystemWatcher) + 16) + QObject (0x0x7fb8041fe540) 0 + primary-for QFileSystemWatcher (0x0x7fb80418dea0) + +Class QFinalState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFinalState::QPrivateSignal (0x0x7fb8041fe7e0) 0 empty + +Vtable for QFinalState +QFinalState::_ZTV11QFinalState: 16 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 (0x0x7fb80418df08) 0 + vptr=((& QFinalState::_ZTV11QFinalState) + 16) + QAbstractState (0x0x7fb80418df70) 0 + primary-for QFinalState (0x0x7fb80418df08) + QObject (0x0x7fb8041fe780) 0 + primary-for QAbstractState (0x0x7fb80418df70) + +Vtable for QRunnable +QRunnable::_ZTV9QRunnable: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI9QRunnable) +16 (int (*)(...))__cxa_pure_virtual +24 0 +32 0 + +Class QRunnable + size=16 align=8 + base size=12 base align=8 +QRunnable (0x0x7fb8041fe9c0) 0 + vptr=((& QRunnable::_ZTV9QRunnable) + 16) + +Class QBasicMutex + size=8 align=8 + base size=8 base align=8 +QBasicMutex (0x0x7fb8041fec60) 0 + +Class QMutex + size=8 align=8 + base size=8 base align=8 +QMutex (0x0x7fb803e34068) 0 + QBasicMutex (0x0x7fb803e6d900) 0 + +Class QRecursiveMutex + size=8 align=8 + base size=8 base align=8 +QRecursiveMutex (0x0x7fb803e340d0) 0 + QMutex (0x0x7fb803e34138) 0 + QBasicMutex (0x0x7fb803e6db40) 0 + +Class QMutexLocker + size=8 align=8 + base size=8 base align=8 +QMutexLocker (0x0x7fb803e6dba0) 0 + +Class QtPrivate::ResultItem + size=16 align=8 + base size=16 base align=8 +QtPrivate::ResultItem (0x0x7fb803e941e0) 0 + +Class QtPrivate::ResultIteratorBase + size=16 align=8 + base size=12 base align=8 +QtPrivate::ResultIteratorBase (0x0x7fb803e947e0) 0 + +Vtable for QtPrivate::ResultStoreBase +QtPrivate::ResultStoreBase::_ZTVN9QtPrivate15ResultStoreBaseE: 4 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 (0x0x7fb803e949c0) 0 + vptr=((& QtPrivate::ResultStoreBase::_ZTVN9QtPrivate15ResultStoreBaseE) + 16) + +Class std::__mutex_base + size=40 align=8 + base size=40 base align=8 +std::__mutex_base (0x0x7fb803f281e0) 0 + +Class std::mutex + size=40 align=8 + base size=40 base align=8 +std::mutex (0x0x7fb803f13a28) 0 + std::__mutex_base (0x0x7fb803f28240) 0 + +Class std::defer_lock_t + size=1 align=1 + base size=0 base align=1 +std::defer_lock_t (0x0x7fb803f28420) 0 empty + +Class std::try_to_lock_t + size=1 align=1 + base size=0 base align=1 +std::try_to_lock_t (0x0x7fb803f28480) 0 empty + +Class std::adopt_lock_t + size=1 align=1 + base size=0 base align=1 +std::adopt_lock_t (0x0x7fb803f284e0) 0 empty + +Class std::__recursive_mutex_base + size=40 align=8 + base size=40 base align=8 +std::__recursive_mutex_base (0x0x7fb803f28f00) 0 + +Class std::recursive_mutex + size=40 align=8 + base size=40 base align=8 +std::recursive_mutex (0x0x7fb803f13a90) 0 + std::__recursive_mutex_base (0x0x7fb803f28f60) 0 + +Class std::timed_mutex + size=40 align=8 + base size=40 base align=8 +std::timed_mutex (0x0x7fb803f33af0) 0 + std::__mutex_base (0x0x7fb803f64360) 0 + std::__timed_mutex_impl (0x0x7fb803f643c0) 0 empty + +Class std::recursive_timed_mutex + size=40 align=8 + base size=40 base align=8 +std::recursive_timed_mutex (0x0x7fb803f33e70) 0 + std::__recursive_mutex_base (0x0x7fb803f64720) 0 + std::__timed_mutex_impl (0x0x7fb803f64780) 0 empty + +Class std::once_flag + size=4 align=4 + base size=4 base align=4 +std::once_flag (0x0x7fb803f64ea0) 0 + +Vtable for QFutureInterfaceBase +QFutureInterfaceBase::_ZTV20QFutureInterfaceBase: 4 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 (0x0x7fb803fab120) 0 + vptr=((& QFutureInterfaceBase::_ZTV20QFutureInterfaceBase) + 16) + +Class QFutureWatcherBase::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFutureWatcherBase::QPrivateSignal (0x0x7fb803c53480) 0 empty + +Vtable for QFutureWatcherBase +QFutureWatcherBase::_ZTV18QFutureWatcherBase: 16 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI18QFutureWatcherBase) +16 (int (*)(...))QFutureWatcherBase::metaObject +24 (int (*)(...))QFutureWatcherBase::qt_metacast +32 (int (*)(...))QFutureWatcherBase::qt_metacall +40 0 +48 0 +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 (0x0x7fb803fd9888) 0 + vptr=((& QFutureWatcherBase::_ZTV18QFutureWatcherBase) + 16) + QObject (0x0x7fb803c53420) 0 + primary-for QFutureWatcherBase (0x0x7fb803fd9888) + +Class QHistoryState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QHistoryState::QPrivateSignal (0x0x7fb803c7d7e0) 0 empty + +Vtable for QHistoryState +QHistoryState::_ZTV13QHistoryState: 16 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 (0x0x7fb803c890d0) 0 + vptr=((& QHistoryState::_ZTV13QHistoryState) + 16) + QAbstractState (0x0x7fb803c89138) 0 + primary-for QHistoryState (0x0x7fb803c890d0) + QObject (0x0x7fb803c7d780) 0 + primary-for QAbstractState (0x0x7fb803c89138) + +Class QIdentityProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIdentityProxyModel::QPrivateSignal (0x0x7fb803c7dae0) 0 empty + +Vtable for QIdentityProxyModel +QIdentityProxyModel::_ZTV19QIdentityProxyModel: 53 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 (0x0x7fb803c891a0) 0 + vptr=((& QIdentityProxyModel::_ZTV19QIdentityProxyModel) + 16) + QAbstractProxyModel (0x0x7fb803c89208) 0 + primary-for QIdentityProxyModel (0x0x7fb803c891a0) + QAbstractItemModel (0x0x7fb803c89270) 0 + primary-for QAbstractProxyModel (0x0x7fb803c89208) + QObject (0x0x7fb803c7da80) 0 + primary-for QAbstractItemModel (0x0x7fb803c89270) + +Class QItemSelectionRange + size=16 align=8 + base size=16 base align=8 +QItemSelectionRange (0x0x7fb803c7dcc0) 0 + +Class QItemSelectionModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QItemSelectionModel::QPrivateSignal (0x0x7fb803d64600) 0 empty + +Vtable for QItemSelectionModel +QItemSelectionModel::_ZTV19QItemSelectionModel: 20 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 (0x0x7fb803d59bc8) 0 + vptr=((& QItemSelectionModel::_ZTV19QItemSelectionModel) + 16) + QObject (0x0x7fb803d645a0) 0 + primary-for QItemSelectionModel (0x0x7fb803d59bc8) + +Class QItemSelection + size=8 align=8 + base size=8 base align=8 +QItemSelection (0x0x7fb803d59d68) 0 + QList (0x0x7fb803d59dd0) 0 + QListSpecialMethods (0x0x7fb803dab120) 0 empty + +Class QJsonValue + size=24 align=8 + base size=20 base align=8 +QJsonValue (0x0x7fb803e12a20) 0 + +Class QJsonValueRef + size=16 align=8 + base size=12 base align=8 +QJsonValueRef (0x0x7fb803b696c0) 0 + +Class QJsonValuePtr + size=24 align=8 + base size=24 base align=8 +QJsonValuePtr (0x0x7fb803bba660) 0 + +Class QJsonValueRefPtr + size=16 align=8 + base size=16 base align=8 +QJsonValueRefPtr (0x0x7fb803bba900) 0 + +Class QJsonArray::iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::iterator (0x0x7fb803bfdc60) 0 + +Class QJsonArray::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::const_iterator (0x0x7fb803bfdcc0) 0 + +Class QJsonArray + size=16 align=8 + base size=16 base align=8 +QJsonArray (0x0x7fb803bfdc00) 0 + +Class QJsonParseError + size=8 align=4 + base size=8 base align=4 +QJsonParseError (0x0x7fb80392aba0) 0 + +Class QJsonDocument + size=8 align=8 + base size=8 base align=8 +QJsonDocument (0x0x7fb80392ac00) 0 + +Class QJsonObject::iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::iterator (0x0x7fb803998420) 0 + +Class QJsonObject::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::const_iterator (0x0x7fb803998480) 0 + +Class QJsonObject + size=16 align=8 + base size=16 base align=8 +QJsonObject (0x0x7fb8039983c0) 0 + +Class QLibrary::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLibrary::QPrivateSignal (0x0x7fb8036bc8a0) 0 empty + +Vtable for QLibrary +QLibrary::_ZTV8QLibrary: 14 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 (0x0x7fb8036b6a28) 0 + vptr=((& QLibrary::_ZTV8QLibrary) + 16) + QObject (0x0x7fb8036bc840) 0 + primary-for QLibrary (0x0x7fb8036b6a28) + +Class QVersionNumber::SegmentStorage + size=8 align=8 + base size=8 base align=8 +QVersionNumber::SegmentStorage (0x0x7fb8036ff720) 0 + +Class QVersionNumber + size=8 align=8 + base size=8 base align=8 +QVersionNumber (0x0x7fb8036ff240) 0 + +Class QLibraryInfo + size=1 align=1 + base size=0 base align=1 +QLibraryInfo (0x0x7fb80379aea0) 0 empty + +Class QPoint + size=8 align=4 + base size=8 base align=4 +QPoint (0x0x7fb80379af00) 0 + +Class QPointF + size=16 align=8 + base size=16 base align=8 +QPointF (0x0x7fb803811d80) 0 + +Class QLine + size=16 align=4 + base size=16 base align=4 +QLine (0x0x7fb803482f60) 0 + +Class QLineF + size=32 align=8 + base size=32 base align=8 +QLineF (0x0x7fb803512360) 0 + +Class QLinkedListData + size=32 align=8 + base size=25 base align=8 +QLinkedListData (0x0x7fb803589600) 0 + +Class QLockFile + size=8 align=8 + base size=8 base align=8 +QLockFile (0x0x7fb803233b40) 0 + +Class QLoggingCategory::AtomicBools + size=4 align=1 + base size=4 base align=1 +QLoggingCategory::AtomicBools (0x0x7fb803233d80) 0 + +Class QLoggingCategory + size=24 align=8 + base size=24 base align=8 +QLoggingCategory (0x0x7fb803233d20) 0 + +Class QMargins + size=16 align=4 + base size=16 base align=4 +QMargins (0x0x7fb8032a41e0) 0 + +Class QMarginsF + size=32 align=8 + base size=32 base align=8 +QMarginsF (0x0x7fb803323120) 0 + +Class QMessageAuthenticationCode + size=8 align=8 + base size=8 base align=8 +QMessageAuthenticationCode (0x0x7fb80315c900) 0 + +Class QMetaMethod + size=16 align=8 + base size=12 base align=8 +QMetaMethod (0x0x7fb80315c960) 0 + +Class QMetaEnum + size=16 align=8 + base size=12 base align=8 +QMetaEnum (0x0x7fb8031e31e0) 0 + +Class QMetaProperty + size=32 align=8 + base size=32 base align=8 +QMetaProperty (0x0x7fb802da63c0) 0 + +Class QMetaClassInfo + size=16 align=8 + base size=12 base align=8 +QMetaClassInfo (0x0x7fb802da64e0) 0 + +Class QMimeData::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QMimeData::QPrivateSignal (0x0x7fb802de5a80) 0 empty + +Vtable for QMimeData +QMimeData::_ZTV9QMimeData: 17 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 (0x0x7fb802dec680) 0 + vptr=((& QMimeData::_ZTV9QMimeData) + 16) + QObject (0x0x7fb802de5a20) 0 + primary-for QMimeData (0x0x7fb802dec680) + +Class QMimeType + size=8 align=8 + base size=8 base align=8 +QMimeType (0x0x7fb802de5c60) 0 + +Class QMimeDatabase + size=8 align=8 + base size=8 base align=8 +QMimeDatabase (0x0x7fb802eb1ba0) 0 + +Class QObjectCleanupHandler::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObjectCleanupHandler::QPrivateSignal (0x0x7fb802eb1c60) 0 empty + +Vtable for QObjectCleanupHandler +QObjectCleanupHandler::_ZTV21QObjectCleanupHandler: 14 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 (0x0x7fb802ec4208) 0 + vptr=((& QObjectCleanupHandler::_ZTV21QObjectCleanupHandler) + 16) + QObject (0x0x7fb802eb1c00) 0 + primary-for QObjectCleanupHandler (0x0x7fb802ec4208) + +Class QOperatingSystemVersion + size=16 align=4 + base size=16 base align=4 +QOperatingSystemVersion (0x0x7fb802eb1d80) 0 + +Class QParallelAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QParallelAnimationGroup::QPrivateSignal (0x0x7fb802f3f540) 0 empty + +Vtable for QParallelAnimationGroup +QParallelAnimationGroup::_ZTV23QParallelAnimationGroup: 18 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 (0x0x7fb802f3ca90) 0 + vptr=((& QParallelAnimationGroup::_ZTV23QParallelAnimationGroup) + 16) + QAnimationGroup (0x0x7fb802f3caf8) 0 + primary-for QParallelAnimationGroup (0x0x7fb802f3ca90) + QAbstractAnimation (0x0x7fb802f3cb60) 0 + primary-for QAnimationGroup (0x0x7fb802f3caf8) + QObject (0x0x7fb802f3f4e0) 0 + primary-for QAbstractAnimation (0x0x7fb802f3cb60) + +Class QPauseAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPauseAnimation::QPrivateSignal (0x0x7fb802f3f780) 0 empty + +Vtable for QPauseAnimation +QPauseAnimation::_ZTV15QPauseAnimation: 18 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 (0x0x7fb802f3cbc8) 0 + vptr=((& QPauseAnimation::_ZTV15QPauseAnimation) + 16) + QAbstractAnimation (0x0x7fb802f3cc30) 0 + primary-for QPauseAnimation (0x0x7fb802f3cbc8) + QObject (0x0x7fb802f3f720) 0 + primary-for QAbstractAnimation (0x0x7fb802f3cc30) + +Class QStaticPlugin + size=16 align=8 + base size=16 base align=8 +QStaticPlugin (0x0x7fb802f78300) 0 + +Class QPluginLoader::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPluginLoader::QPrivateSignal (0x0x7fb802bb6480) 0 empty + +Vtable for QPluginLoader +QPluginLoader::_ZTV13QPluginLoader: 14 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 (0x0x7fb802ba6f70) 0 + vptr=((& QPluginLoader::_ZTV13QPluginLoader) + 16) + QObject (0x0x7fb802bb6420) 0 + primary-for QPluginLoader (0x0x7fb802ba6f70) + +Class QProcessEnvironment + size=8 align=8 + base size=8 base align=8 +QProcessEnvironment (0x0x7fb802bb65a0) 0 + +Class QProcess::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QProcess::QPrivateSignal (0x0x7fb802c88a20) 0 empty + +Vtable for QProcess +QProcess::_ZTV8QProcess: 31 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 (0x0x7fb802c8e410) 0 + vptr=((& QProcess::_ZTV8QProcess) + 16) + QIODevice (0x0x7fb802c8e478) 0 + primary-for QProcess (0x0x7fb802c8e410) + QObject (0x0x7fb802c889c0) 0 + primary-for QIODevice (0x0x7fb802c8e478) + +Class QVariantAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QVariantAnimation::QPrivateSignal (0x0x7fb802cc6120) 0 empty + +Vtable for QVariantAnimation +QVariantAnimation::_ZTV17QVariantAnimation: 20 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 (0x0x7fb802c8e4e0) 0 + vptr=((& QVariantAnimation::_ZTV17QVariantAnimation) + 16) + QAbstractAnimation (0x0x7fb802c8e548) 0 + primary-for QVariantAnimation (0x0x7fb802c8e4e0) + QObject (0x0x7fb802cc60c0) 0 + primary-for QAbstractAnimation (0x0x7fb802c8e548) + +Class QPropertyAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPropertyAnimation::QPrivateSignal (0x0x7fb802cc63c0) 0 empty + +Vtable for QPropertyAnimation +QPropertyAnimation::_ZTV18QPropertyAnimation: 20 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 (0x0x7fb802c8e618) 0 + vptr=((& QPropertyAnimation::_ZTV18QPropertyAnimation) + 16) + QVariantAnimation (0x0x7fb802c8e680) 0 + primary-for QPropertyAnimation (0x0x7fb802c8e618) + QAbstractAnimation (0x0x7fb802c8e6e8) 0 + primary-for QVariantAnimation (0x0x7fb802c8e680) + QObject (0x0x7fb802cc6360) 0 + primary-for QAbstractAnimation (0x0x7fb802c8e6e8) + +Class std::random_device + size=5000 align=8 + base size=5000 base align=8 +std::random_device (0x0x7fb802d4dae0) 0 + +Class std::bernoulli_distribution::param_type + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution::param_type (0x0x7fb802a44840) 0 + +Class std::bernoulli_distribution + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution (0x0x7fb802a447e0) 0 + +Class std::seed_seq + size=24 align=8 + base size=24 base align=8 +std::seed_seq (0x0x7fb80284b5a0) 0 + +Class QRandomGenerator::Storage + size=2504 align=8 + base size=2504 base align=8 +QRandomGenerator::Storage (0x0x7fb80267f240) 0 + +Class QRandomGenerator + size=2512 align=8 + base size=2512 base align=8 +QRandomGenerator (0x0x7fb80267f1e0) 0 + +Class QRandomGenerator64 + size=2512 align=8 + base size=2512 base align=8 +QRandomGenerator64 (0x0x7fb8027003a8) 0 + QRandomGenerator (0x0x7fb8026f8d20) 0 + +Class QReadWriteLock + size=8 align=8 + base size=8 base align=8 +QReadWriteLock (0x0x7fb802724900) 0 + +Class QReadLocker + size=8 align=8 + base size=8 base align=8 +QReadLocker (0x0x7fb802724ba0) 0 + +Class QWriteLocker + size=8 align=8 + base size=8 base align=8 +QWriteLocker (0x0x7fb8023a80c0) 0 + +Class QSize + size=8 align=4 + base size=8 base align=4 +QSize (0x0x7fb8023a85a0) 0 + +Class QSizeF + size=16 align=8 + base size=16 base align=8 +QSizeF (0x0x7fb802419480) 0 + +Class QRect + size=16 align=4 + base size=16 base align=4 +QRect (0x0x7fb8024924e0) 0 + +Class QRectF + size=32 align=8 + base size=32 base align=8 +QRectF (0x0x7fb80254c540) 0 + +Class QResource + size=8 align=8 + base size=8 base align=8 +QResource (0x0x7fb802208660) 0 + +Class QSaveFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSaveFile::QPrivateSignal (0x0x7fb802208900) 0 empty + +Vtable for QSaveFile +QSaveFile::_ZTV9QSaveFile: 34 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 (0x0x7fb8021b2d68) 0 + vptr=((& QSaveFile::_ZTV9QSaveFile) + 16) + QFileDevice (0x0x7fb8021b2dd0) 0 + primary-for QSaveFile (0x0x7fb8021b2d68) + QIODevice (0x0x7fb8021b2e38) 0 + primary-for QFileDevice (0x0x7fb8021b2dd0) + QObject (0x0x7fb8022088a0) 0 + primary-for QIODevice (0x0x7fb8021b2e38) + +Class QSemaphore + size=8 align=8 + base size=8 base align=8 +QSemaphore (0x0x7fb802208f00) 0 + +Class QSemaphoreReleaser + size=16 align=8 + base size=12 base align=8 +QSemaphoreReleaser (0x0x7fb8022600c0) 0 + +Class QSequentialAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSequentialAnimationGroup::QPrivateSignal (0x0x7fb80230bcc0) 0 empty + +Vtable for QSequentialAnimationGroup +QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup: 18 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 (0x0x7fb80231f618) 0 + vptr=((& QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup) + 16) + QAnimationGroup (0x0x7fb80231f680) 0 + primary-for QSequentialAnimationGroup (0x0x7fb80231f618) + QAbstractAnimation (0x0x7fb80231f6e8) 0 + primary-for QAnimationGroup (0x0x7fb80231f680) + QObject (0x0x7fb80230bc60) 0 + primary-for QAbstractAnimation (0x0x7fb80231f6e8) + +Class QSettings::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSettings::QPrivateSignal (0x0x7fb80230bf00) 0 empty + +Vtable for QSettings +QSettings::_ZTV9QSettings: 14 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 (0x0x7fb80231f750) 0 + vptr=((& QSettings::_ZTV9QSettings) + 16) + QObject (0x0x7fb80230bea0) 0 + primary-for QSettings (0x0x7fb80231f750) + +Class QSharedMemory::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSharedMemory::QPrivateSignal (0x0x7fb8023533c0) 0 empty + +Vtable for QSharedMemory +QSharedMemory::_ZTV13QSharedMemory: 14 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 (0x0x7fb80231f7b8) 0 + vptr=((& QSharedMemory::_ZTV13QSharedMemory) + 16) + QObject (0x0x7fb802353360) 0 + primary-for QSharedMemory (0x0x7fb80231f7b8) + +Class QSignalMapper::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalMapper::QPrivateSignal (0x0x7fb802353600) 0 empty + +Vtable for QSignalMapper +QSignalMapper::_ZTV13QSignalMapper: 14 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 (0x0x7fb80231f820) 0 + vptr=((& QSignalMapper::_ZTV13QSignalMapper) + 16) + QObject (0x0x7fb8023535a0) 0 + primary-for QSignalMapper (0x0x7fb80231f820) + +Class QSignalTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalTransition::QPrivateSignal (0x0x7fb802353840) 0 empty + +Vtable for QSignalTransition +QSignalTransition::_ZTV17QSignalTransition: 16 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 (0x0x7fb80231f888) 0 + vptr=((& QSignalTransition::_ZTV17QSignalTransition) + 16) + QAbstractTransition (0x0x7fb80231f8f0) 0 + primary-for QSignalTransition (0x0x7fb80231f888) + QObject (0x0x7fb8023537e0) 0 + primary-for QAbstractTransition (0x0x7fb80231f8f0) + +Class QSocketNotifier::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSocketNotifier::QPrivateSignal (0x0x7fb802353ae0) 0 empty + +Vtable for QSocketNotifier +QSocketNotifier::_ZTV15QSocketNotifier: 14 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 (0x0x7fb80231f958) 0 + vptr=((& QSocketNotifier::_ZTV15QSocketNotifier) + 16) + QObject (0x0x7fb802353a80) 0 + primary-for QSocketNotifier (0x0x7fb80231f958) + +Class QSortFilterProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSortFilterProxyModel::QPrivateSignal (0x0x7fb802353d20) 0 empty + +Vtable for QSortFilterProxyModel +QSortFilterProxyModel::_ZTV21QSortFilterProxyModel: 56 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 (0x0x7fb80231f9c0) 0 + vptr=((& QSortFilterProxyModel::_ZTV21QSortFilterProxyModel) + 16) + QAbstractProxyModel (0x0x7fb80231fa28) 0 + primary-for QSortFilterProxyModel (0x0x7fb80231f9c0) + QAbstractItemModel (0x0x7fb80231fa90) 0 + primary-for QAbstractProxyModel (0x0x7fb80231fa28) + QObject (0x0x7fb802353cc0) 0 + primary-for QAbstractItemModel (0x0x7fb80231fa90) + +Class QStandardPaths + size=1 align=1 + base size=0 base align=1 +QStandardPaths (0x0x7fb801fc0180) 0 empty + +Class QState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QState::QPrivateSignal (0x0x7fb801fc0a80) 0 empty + +Vtable for QState +QState::_ZTV6QState: 16 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 (0x0x7fb80231fc30) 0 + vptr=((& QState::_ZTV6QState) + 16) + QAbstractState (0x0x7fb80231fc98) 0 + primary-for QState (0x0x7fb80231fc30) + QObject (0x0x7fb801fc0a20) 0 + primary-for QAbstractState (0x0x7fb80231fc98) + +Class QStateMachine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStateMachine::QPrivateSignal (0x0x7fb801fc0f00) 0 empty + +Vtable for QStateMachine::SignalEvent +QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE: 4 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 (0x0x7fb80231fe38) 0 + vptr=((& QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE) + 16) + QEvent (0x0x7fb801fc0f60) 0 + primary-for QStateMachine::SignalEvent (0x0x7fb80231fe38) + +Vtable for QStateMachine::WrappedEvent +QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE: 4 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 (0x0x7fb80231fea0) 0 + vptr=((& QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE) + 16) + QEvent (0x0x7fb802018000) 0 + primary-for QStateMachine::WrappedEvent (0x0x7fb80231fea0) + +Vtable for QStateMachine +QStateMachine::_ZTV13QStateMachine: 20 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 (0x0x7fb80231fd00) 0 + vptr=((& QStateMachine::_ZTV13QStateMachine) + 16) + QState (0x0x7fb80231fd68) 0 + primary-for QStateMachine (0x0x7fb80231fd00) + QAbstractState (0x0x7fb80231fdd0) 0 + primary-for QState (0x0x7fb80231fd68) + QObject (0x0x7fb801fc0ea0) 0 + primary-for QAbstractState (0x0x7fb80231fdd0) + +Class QStorageInfo + size=8 align=8 + base size=8 base align=8 +QStorageInfo (0x0x7fb8020183c0) 0 + +Class QAbstractConcatenable + size=1 align=1 + base size=0 base align=1 +QAbstractConcatenable (0x0x7fb802124180) 0 empty + +Class QStringListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStringListModel::QPrivateSignal (0x0x7fb801dad4e0) 0 empty + +Vtable for QStringListModel +QStringListModel::_ZTV16QStringListModel: 48 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 (*)(...))QStringListModel::itemData +200 (int (*)(...))QStringListModel::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 (*)(...))QStringListModel::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 (0x0x7fb801d9d7b8) 0 + vptr=((& QStringListModel::_ZTV16QStringListModel) + 16) + QAbstractListModel (0x0x7fb801d9d820) 0 + primary-for QStringListModel (0x0x7fb801d9d7b8) + QAbstractItemModel (0x0x7fb801d9d888) 0 + primary-for QAbstractListModel (0x0x7fb801d9d820) + QObject (0x0x7fb801dad480) 0 + primary-for QAbstractItemModel (0x0x7fb801d9d888) + +Class QSystemSemaphore + size=8 align=8 + base size=8 base align=8 +QSystemSemaphore (0x0x7fb801dad600) 0 + +Class QTemporaryDir + size=8 align=8 + base size=8 base align=8 +QTemporaryDir (0x0x7fb801dad6c0) 0 + +Class QTemporaryFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTemporaryFile::QPrivateSignal (0x0x7fb801dad7e0) 0 empty + +Vtable for QTemporaryFile +QTemporaryFile::_ZTV14QTemporaryFile: 34 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 (0x0x7fb801d9d8f0) 0 + vptr=((& QTemporaryFile::_ZTV14QTemporaryFile) + 16) + QFile (0x0x7fb801d9d958) 0 + primary-for QTemporaryFile (0x0x7fb801d9d8f0) + QFileDevice (0x0x7fb801d9d9c0) 0 + primary-for QFile (0x0x7fb801d9d958) + QIODevice (0x0x7fb801d9da28) 0 + primary-for QFileDevice (0x0x7fb801d9d9c0) + QObject (0x0x7fb801dad780) 0 + primary-for QIODevice (0x0x7fb801d9da28) + +Class QTextBoundaryFinder + size=48 align=8 + base size=48 base align=8 +QTextBoundaryFinder (0x0x7fb801dadb40) 0 + +Class QTextCodec::ConverterState + size=32 align=8 + base size=32 base align=8 +QTextCodec::ConverterState (0x0x7fb801e2c3c0) 0 + +Vtable for QTextCodec +QTextCodec::_ZTV10QTextCodec: 9 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 0 +64 0 + +Class QTextCodec + size=8 align=8 + base size=8 base align=8 +QTextCodec (0x0x7fb801e2c360) 0 nearly-empty + vptr=((& QTextCodec::_ZTV10QTextCodec) + 16) + +Class QTextEncoder + size=40 align=8 + base size=40 base align=8 +QTextEncoder (0x0x7fb801e2cd80) 0 + +Class QTextDecoder + size=40 align=8 + base size=40 base align=8 +QTextDecoder (0x0x7fb801e2cf60) 0 + +Vtable for std::thread::_State +std::thread::_State::_ZTVNSt6thread6_StateE: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt6thread6_StateE) +16 0 +24 0 +32 (int (*)(...))__cxa_pure_virtual + +Class std::thread::_State + size=8 align=8 + base size=8 base align=8 +std::thread::_State (0x0x7fb801e831e0) 0 nearly-empty + vptr=((& std::thread::_State::_ZTVNSt6thread6_StateE) + 16) + +Class std::thread::id + size=8 align=8 + base size=8 base align=8 +std::thread::id (0x0x7fb801e83240) 0 + +Class std::thread + size=8 align=8 + base size=8 base align=8 +std::thread (0x0x7fb801e83180) 0 + +Class std::condition_variable + size=48 align=8 + base size=48 base align=8 +std::condition_variable (0x0x7fb801d16600) 0 + +Class std::__at_thread_exit_elt + size=16 align=8 + base size=16 base align=8 +std::__at_thread_exit_elt (0x0x7fb801d169c0) 0 + +Class std::_V2::condition_variable_any + size=64 align=8 + base size=64 base align=8 +std::_V2::condition_variable_any (0x0x7fb801d16a20) 0 + +Class std::__atomic_futex_unsigned_base + size=1 align=1 + base size=0 base align=1 +std::__atomic_futex_unsigned_base (0x0x7fb801aa6d20) 0 empty + +Vtable for std::future_error +std::future_error::_ZTVSt12future_error: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTISt12future_error) +16 (int (*)(...))std::future_error::~future_error +24 (int (*)(...))std::future_error::~future_error +32 (int (*)(...))std::future_error::what + +Class std::future_error + size=32 align=8 + base size=32 base align=8 +std::future_error (0x0x7fb801aa5dd0) 0 + vptr=((& std::future_error::_ZTVSt12future_error) + 16) + std::logic_error (0x0x7fb801aa5e38) 0 + primary-for std::future_error (0x0x7fb801aa5dd0) + std::exception (0x0x7fb801ad0480) 0 nearly-empty + primary-for std::logic_error (0x0x7fb801aa5e38) + +Class std::__future_base::_Result_base::_Deleter + size=1 align=1 + base size=0 base align=1 +std::__future_base::_Result_base::_Deleter (0x0x7fb801ad0ba0) 0 empty + +Vtable for std::__future_base::_Result_base +std::__future_base::_Result_base::_ZTVNSt13__future_base12_Result_baseE: 5 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt13__future_base12_Result_baseE) +16 (int (*)(...))__cxa_pure_virtual +24 0 +32 0 + +Class std::__future_base::_Result_base + size=16 align=8 + base size=16 base align=8 +std::__future_base::_Result_base (0x0x7fb801ad0b40) 0 + vptr=((& std::__future_base::_Result_base::_ZTVNSt13__future_base12_Result_baseE) + 16) + +Class std::__future_base::_State_baseV2::__exception_ptr_tag + size=1 align=1 + base size=0 base align=1 +std::__future_base::_State_baseV2::__exception_ptr_tag (0x0x7fb8018d5300) 0 empty + +Class std::__future_base::_State_baseV2::_Make_ready + size=32 align=8 + base size=32 base align=8 +std::__future_base::_State_baseV2::_Make_ready (0x0x7fb8018cd680) 0 + std::__at_thread_exit_elt (0x0x7fb8018d53c0) 0 + +Vtable for std::__future_base::_State_baseV2 +std::__future_base::_State_baseV2::_ZTVNSt13__future_base13_State_baseV2E: 6 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt13__future_base13_State_baseV2E) +16 (int (*)(...))std::__future_base::_State_baseV2::~_State_baseV2 +24 (int (*)(...))std::__future_base::_State_baseV2::~_State_baseV2 +32 (int (*)(...))std::__future_base::_State_baseV2::_M_complete_async +40 (int (*)(...))std::__future_base::_State_baseV2::_M_is_deferred_future + +Class std::__future_base::_State_baseV2 + size=32 align=8 + base size=28 base align=8 +std::__future_base::_State_baseV2 (0x0x7fb801ad0d20) 0 + vptr=((& std::__future_base::_State_baseV2::_ZTVNSt13__future_base13_State_baseV2E) + 16) + +Class std::__future_base + size=1 align=1 + base size=0 base align=1 +std::__future_base (0x0x7fb801ad0ae0) 0 empty + +Vtable for std::__future_base::_Async_state_commonV2 +std::__future_base::_Async_state_commonV2::_ZTVNSt13__future_base21_Async_state_commonV2E: 6 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTINSt13__future_base21_Async_state_commonV2E) +16 (int (*)(...))std::__future_base::_Async_state_commonV2::~_Async_state_commonV2 +24 (int (*)(...))std::__future_base::_Async_state_commonV2::~_Async_state_commonV2 +32 (int (*)(...))std::__future_base::_Async_state_commonV2::_M_complete_async +40 (int (*)(...))std::__future_base::_State_baseV2::_M_is_deferred_future + +Class std::__future_base::_Async_state_commonV2 + size=48 align=8 + base size=44 base align=8 +std::__future_base::_Async_state_commonV2 (0x0x7fb8010503a8) 0 + vptr=((& std::__future_base::_Async_state_commonV2::_ZTVNSt13__future_base21_Async_state_commonV2E) + 16) + std::__future_base::_State_baseV2 (0x0x7fb8010873c0) 0 + primary-for std::__future_base::_Async_state_commonV2 (0x0x7fb8010503a8) + +Class QThread::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThread::QPrivateSignal (0x0x7fb801087c60) 0 empty + +Vtable for QThread +QThread::_ZTV7QThread: 15 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 (0x0x7fb8010506e8) 0 + vptr=((& QThread::_ZTV7QThread) + 16) + QObject (0x0x7fb801087c00) 0 + primary-for QThread (0x0x7fb8010506e8) + +Class QThreadPool::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThreadPool::QPrivateSignal (0x0x7fb8010c4060) 0 empty + +Vtable for QThreadPool +QThreadPool::_ZTV11QThreadPool: 14 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 (0x0x7fb801050750) 0 + vptr=((& QThreadPool::_ZTV11QThreadPool) + 16) + QObject (0x0x7fb8010c4000) 0 + primary-for QThreadPool (0x0x7fb801050750) + +Class QThreadStorageData + size=4 align=4 + base size=4 base align=4 +QThreadStorageData (0x0x7fb8010c4240) 0 + +Class QTimeLine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimeLine::QPrivateSignal (0x0x7fb8010c4900) 0 empty + +Vtable for QTimeLine +QTimeLine::_ZTV9QTimeLine: 15 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 (0x0x7fb8010507b8) 0 + vptr=((& QTimeLine::_ZTV9QTimeLine) + 16) + QObject (0x0x7fb8010c48a0) 0 + primary-for QTimeLine (0x0x7fb8010507b8) + +Class QTimer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimer::QPrivateSignal (0x0x7fb8010c4b40) 0 empty + +Vtable for QTimer +QTimer::_ZTV6QTimer: 14 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 (0x0x7fb801050820) 0 + vptr=((& QTimer::_ZTV6QTimer) + 16) + QObject (0x0x7fb8010c4ae0) 0 + primary-for QTimer (0x0x7fb801050820) + +Class QTimeZone::OffsetData + size=32 align=8 + base size=28 base align=8 +QTimeZone::OffsetData (0x0x7fb80113e4e0) 0 + +Class QTimeZone + size=8 align=8 + base size=8 base align=8 +QTimeZone (0x0x7fb80113e480) 0 + +Class QTranslator::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTranslator::QPrivateSignal (0x0x7fb800ddd5a0) 0 empty + +Vtable for QTranslator +QTranslator::_ZTV11QTranslator: 16 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 (0x0x7fb800dcdf08) 0 + vptr=((& QTranslator::_ZTV11QTranslator) + 16) + QObject (0x0x7fb800ddd540) 0 + primary-for QTranslator (0x0x7fb800dcdf08) + +Class QTransposeProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTransposeProxyModel::QPrivateSignal (0x0x7fb800ddd7e0) 0 empty + +Vtable for QTransposeProxyModel +QTransposeProxyModel::_ZTV20QTransposeProxyModel: 53 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI20QTransposeProxyModel) +16 (int (*)(...))QTransposeProxyModel::metaObject +24 (int (*)(...))QTransposeProxyModel::qt_metacast +32 (int (*)(...))QTransposeProxyModel::qt_metacall +40 (int (*)(...))QTransposeProxyModel::~QTransposeProxyModel +48 (int (*)(...))QTransposeProxyModel::~QTransposeProxyModel +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 (*)(...))QTransposeProxyModel::index +120 (int (*)(...))QTransposeProxyModel::parent +128 (int (*)(...))QAbstractProxyModel::sibling +136 (int (*)(...))QTransposeProxyModel::rowCount +144 (int (*)(...))QTransposeProxyModel::columnCount +152 (int (*)(...))QAbstractProxyModel::hasChildren +160 (int (*)(...))QAbstractProxyModel::data +168 (int (*)(...))QAbstractProxyModel::setData +176 (int (*)(...))QTransposeProxyModel::headerData +184 (int (*)(...))QTransposeProxyModel::setHeaderData +192 (int (*)(...))QTransposeProxyModel::itemData +200 (int (*)(...))QTransposeProxyModel::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 (*)(...))QTransposeProxyModel::insertRows +264 (int (*)(...))QTransposeProxyModel::insertColumns +272 (int (*)(...))QTransposeProxyModel::removeRows +280 (int (*)(...))QTransposeProxyModel::removeColumns +288 (int (*)(...))QTransposeProxyModel::moveRows +296 (int (*)(...))QTransposeProxyModel::moveColumns +304 (int (*)(...))QAbstractProxyModel::fetchMore +312 (int (*)(...))QAbstractProxyModel::canFetchMore +320 (int (*)(...))QAbstractProxyModel::flags +328 (int (*)(...))QTransposeProxyModel::sort +336 (int (*)(...))QAbstractProxyModel::buddy +344 (int (*)(...))QAbstractItemModel::match +352 (int (*)(...))QTransposeProxyModel::span +360 (int (*)(...))QAbstractItemModel::roleNames +368 (int (*)(...))QAbstractProxyModel::submit +376 (int (*)(...))QAbstractProxyModel::revert +384 (int (*)(...))QTransposeProxyModel::setSourceModel +392 (int (*)(...))QTransposeProxyModel::mapToSource +400 (int (*)(...))QTransposeProxyModel::mapFromSource +408 (int (*)(...))QAbstractProxyModel::mapSelectionToSource +416 (int (*)(...))QAbstractProxyModel::mapSelectionFromSource + +Class QTransposeProxyModel + size=16 align=8 + base size=16 base align=8 +QTransposeProxyModel (0x0x7fb800dcdf70) 0 + vptr=((& QTransposeProxyModel::_ZTV20QTransposeProxyModel) + 16) + QAbstractProxyModel (0x0x7fb800df6000) 0 + primary-for QTransposeProxyModel (0x0x7fb800dcdf70) + QAbstractItemModel (0x0x7fb800df6068) 0 + primary-for QAbstractProxyModel (0x0x7fb800df6000) + QObject (0x0x7fb800ddd780) 0 + primary-for QAbstractItemModel (0x0x7fb800df6068) + +Class QUrlQuery + size=8 align=8 + base size=8 base align=8 +QUrlQuery (0x0x7fb800ddd9c0) 0 + +Class QWaitCondition + size=8 align=8 + base size=8 base align=8 +QWaitCondition (0x0x7fb800edaea0) 0 + +Class QXmlStreamStringRef + size=16 align=8 + base size=16 base align=8 +QXmlStreamStringRef (0x0x7fb800ef9000) 0 + +Class QXmlStreamAttribute + size=80 align=8 + base size=73 base align=8 +QXmlStreamAttribute (0x0x7fb800f863c0) 0 + +Class QXmlStreamAttributes + size=8 align=8 + base size=8 base align=8 +QXmlStreamAttributes (0x0x7fb800af2340) 0 + QVector (0x0x7fb800ae7ae0) 0 + +Class QXmlStreamNamespaceDeclaration + size=40 align=8 + base size=40 base align=8 +QXmlStreamNamespaceDeclaration (0x0x7fb800ae7de0) 0 + +Class QXmlStreamNotationDeclaration + size=56 align=8 + base size=56 base align=8 +QXmlStreamNotationDeclaration (0x0x7fb800b6cd80) 0 + +Class QXmlStreamEntityDeclaration + size=88 align=8 + base size=88 base align=8 +QXmlStreamEntityDeclaration (0x0x7fb800bc7d80) 0 + +Vtable for QXmlStreamEntityResolver +QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver: 6 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 (0x0x7fb800c34e40) 0 nearly-empty + vptr=((& QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver) + 16) + +Class QXmlStreamReader + size=8 align=8 + base size=8 base align=8 +QXmlStreamReader (0x0x7fb800c34ea0) 0 + +Class QXmlStreamWriter + size=8 align=8 + base size=8 base align=8 +QXmlStreamWriter (0x0x7fb800c72d80) 0 + +Class QNdefRecord + size=8 align=8 + base size=8 base align=8 +QNdefRecord (0x0x7fb800c72f60) 0 + +Class QNdefFilter::Record + size=24 align=8 + base size=24 base align=8 +QNdefFilter::Record (0x0x7fb8008cd180) 0 + +Class QNdefFilter + size=8 align=8 + base size=8 base align=8 +QNdefFilter (0x0x7fb8008cd120) 0 + +Class QNdefMessage + size=8 align=8 + base size=8 base align=8 +QNdefMessage (0x0x7fb8008ec068) 0 + QList (0x0x7fb8008ec0d0) 0 + QListSpecialMethods (0x0x7fb8008cd3c0) 0 empty + +Class QNdefNfcTextRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcTextRecord (0x0x7fb8008ec138) 0 + QNdefRecord (0x0x7fb8008cdc60) 0 + +Class QNdefNfcUriRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcUriRecord (0x0x7fb8008ec680) 0 + QNdefRecord (0x0x7fb80093c4e0) 0 + +Class QNdefNfcIconRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcIconRecord (0x0x7fb8008ec6e8) 0 + QNdefRecord (0x0x7fb80093c8a0) 0 + +Class QNdefNfcSmartPosterRecord + size=16 align=8 + base size=16 base align=8 +QNdefNfcSmartPosterRecord (0x0x7fb8008ec750) 0 + QNdefRecord (0x0x7fb80093cc00) 0 + +Class QNearFieldTarget::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldTarget::QPrivateSignal (0x0x7fb80093cde0) 0 empty + +Class QNearFieldTarget::RequestId + size=8 align=8 + base size=8 base align=8 +QNearFieldTarget::RequestId (0x0x7fb80093ce40) 0 + +Vtable for QNearFieldTarget +QNearFieldTarget::_ZTV16QNearFieldTarget: 25 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QNearFieldTarget) +16 (int (*)(...))QNearFieldTarget::metaObject +24 (int (*)(...))QNearFieldTarget::qt_metacast +32 (int (*)(...))QNearFieldTarget::qt_metacall +40 0 +48 0 +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 (*)(...))QNearFieldTarget::url +128 (int (*)(...))__cxa_pure_virtual +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))QNearFieldTarget::hasNdefMessage +152 (int (*)(...))QNearFieldTarget::readNdefMessages +160 (int (*)(...))QNearFieldTarget::writeNdefMessages +168 (int (*)(...))QNearFieldTarget::sendCommand +176 (int (*)(...))QNearFieldTarget::sendCommands +184 (int (*)(...))QNearFieldTarget::waitForRequestCompleted +192 (int (*)(...))QNearFieldTarget::handleResponse + +Class QNearFieldTarget + size=24 align=8 + base size=24 base align=8 +QNearFieldTarget (0x0x7fb8008ec7b8) 0 + vptr=((& QNearFieldTarget::_ZTV16QNearFieldTarget) + 16) + QObject (0x0x7fb80093cd80) 0 + primary-for QNearFieldTarget (0x0x7fb8008ec7b8) + +Class QNearFieldManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldManager::QPrivateSignal (0x0x7fb8009c6c00) 0 empty + +Vtable for QNearFieldManager +QNearFieldManager::_ZTV17QNearFieldManager: 14 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QNearFieldManager) +16 (int (*)(...))QNearFieldManager::metaObject +24 (int (*)(...))QNearFieldManager::qt_metacast +32 (int (*)(...))QNearFieldManager::qt_metacall +40 (int (*)(...))QNearFieldManager::~QNearFieldManager +48 (int (*)(...))QNearFieldManager::~QNearFieldManager +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 QNearFieldManager + size=24 align=8 + base size=24 base align=8 +QNearFieldManager (0x0x7fb8008ec8f0) 0 + vptr=((& QNearFieldManager::_ZTV17QNearFieldManager) + 16) + QObject (0x0x7fb8009c6ba0) 0 + primary-for QNearFieldManager (0x0x7fb8008ec8f0) + +Class QNearFieldShareManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldShareManager::QPrivateSignal (0x0x7fb800a0f6c0) 0 empty + +Vtable for QNearFieldShareManager +QNearFieldShareManager::_ZTV22QNearFieldShareManager: 14 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI22QNearFieldShareManager) +16 (int (*)(...))QNearFieldShareManager::metaObject +24 (int (*)(...))QNearFieldShareManager::qt_metacast +32 (int (*)(...))QNearFieldShareManager::qt_metacall +40 (int (*)(...))QNearFieldShareManager::~QNearFieldShareManager +48 (int (*)(...))QNearFieldShareManager::~QNearFieldShareManager +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 QNearFieldShareManager + size=24 align=8 + base size=24 base align=8 +QNearFieldShareManager (0x0x7fb8008eca28) 0 + vptr=((& QNearFieldShareManager::_ZTV22QNearFieldShareManager) + 16) + QObject (0x0x7fb800a0f660) 0 + primary-for QNearFieldShareManager (0x0x7fb8008eca28) + +Class QNearFieldShareTarget::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldShareTarget::QPrivateSignal (0x0x7fb800a75240) 0 empty + +Vtable for QNearFieldShareTarget +QNearFieldShareTarget::_ZTV21QNearFieldShareTarget: 14 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QNearFieldShareTarget) +16 (int (*)(...))QNearFieldShareTarget::metaObject +24 (int (*)(...))QNearFieldShareTarget::qt_metacast +32 (int (*)(...))QNearFieldShareTarget::qt_metacall +40 (int (*)(...))QNearFieldShareTarget::~QNearFieldShareTarget +48 (int (*)(...))QNearFieldShareTarget::~QNearFieldShareTarget +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 QNearFieldShareTarget + size=24 align=8 + base size=24 base align=8 +QNearFieldShareTarget (0x0x7fb8008ecb60) 0 + vptr=((& QNearFieldShareTarget::_ZTV21QNearFieldShareTarget) + 16) + QObject (0x0x7fb800a751e0) 0 + primary-for QNearFieldShareTarget (0x0x7fb8008ecb60) + +Class QQmlNdefRecord::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QQmlNdefRecord::QPrivateSignal (0x0x7fb800a75480) 0 empty + +Vtable for QQmlNdefRecord +QQmlNdefRecord::_ZTV14QQmlNdefRecord: 14 entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI14QQmlNdefRecord) +16 (int (*)(...))QQmlNdefRecord::metaObject +24 (int (*)(...))QQmlNdefRecord::qt_metacast +32 (int (*)(...))QQmlNdefRecord::qt_metacall +40 (int (*)(...))QQmlNdefRecord::~QQmlNdefRecord +48 (int (*)(...))QQmlNdefRecord::~QQmlNdefRecord +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 QQmlNdefRecord + size=24 align=8 + base size=24 base align=8 +QQmlNdefRecord (0x0x7fb8008ecbc8) 0 + vptr=((& QQmlNdefRecord::_ZTV14QQmlNdefRecord) + 16) + QObject (0x0x7fb800a75420) 0 + primary-for QQmlNdefRecord (0x0x7fb8008ecbc8) + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7fb8006c3a20) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7fb8006c3d80) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7fb8006c3f60) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7fb8006ee300) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7fb8006ee4e0) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7fb8006ee840) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7fb8006eea20) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7fb8006eed80) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7fb8006eef60) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = char; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7fb800729300) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7fb8007294e0) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7fb800729840) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7fb800729a20) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7fb800729d80) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7fb800729f60) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = char; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7fb800760300) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7fb80078a7e0) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7fb80078ab40) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7fb80078acc0) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7fb8007b8060) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7fb8007b81e0) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long unsigned int; _Ret = long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7fb8007b8540) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7fb8007b86c0) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long int; _Ret = long long int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7fb8007b8a20) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Save_errno (0x0x7fb8007b8ba0) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long long unsigned int; _Ret = long long unsigned int; _CharT = wchar_t; _Base = {int}; std::size_t = long unsigned int]::_Range_chk (0x0x7fb8007b8f00) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7fb8007ec0c0) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = float; _Ret = float; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7fb8007ec420) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7fb8007ec5a0) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = double; _Ret = double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7fb8007ec900) 0 empty + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno + size=4 align=4 + base size=4 base align=4 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Save_errno (0x0x7fb8007eca80) 0 + +Class __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk + size=1 align=1 + base size=0 base align=1 +__gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long double; _Ret = long double; _CharT = wchar_t; _Base = {}; std::size_t = long unsigned int]::_Range_chk (0x0x7fb8007ecde0) 0 empty + diff --git a/tests/auto/bic/data/QtNfc.5.2.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtNfc.5.2.0.linux-gcc-amd64.txt new file mode 100644 index 0000000..6c1101a --- /dev/null +++ b/tests/auto/bic/data/QtNfc.5.2.0.linux-gcc-amd64.txt @@ -0,0 +1,3743 @@ +Class std::__true_type + size=1 align=1 + base size=0 base align=1 +std::__true_type (0x0x7f66e4f61060) 0 empty + +Class std::__false_type + size=1 align=1 + base size=0 base align=1 +std::__false_type (0x0x7f66e4f610c0) 0 empty + +Class std::input_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::input_iterator_tag (0x0x7f66e4fa3c60) 0 empty + +Class std::output_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::output_iterator_tag (0x0x7f66e4fa3cc0) 0 empty + +Class std::forward_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::forward_iterator_tag (0x0x7f66e4f3b548) 0 empty + std::input_iterator_tag (0x0x7f66e4fa3d20) 0 empty + +Class std::bidirectional_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::bidirectional_iterator_tag (0x0x7f66e4f3b5b0) 0 empty + std::forward_iterator_tag (0x0x7f66e4f3b618) 0 empty + std::input_iterator_tag (0x0x7f66e4fa3d80) 0 empty + +Class std::random_access_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::random_access_iterator_tag (0x0x7f66e4f3b680) 0 empty + std::bidirectional_iterator_tag (0x0x7f66e4f3b6e8) 0 empty + std::forward_iterator_tag (0x0x7f66e4f3b750) 0 empty + std::input_iterator_tag (0x0x7f66e4fa3de0) 0 empty + +Class wait + size=4 align=4 + base size=4 base align=4 +wait (0x0x7f66e4fd6960) 0 + +Class __locale_struct + size=232 align=8 + base size=232 base align=8 +__locale_struct (0x0x7f66e4fd6ba0) 0 + +Class timespec + size=16 align=8 + base size=16 base align=8 +timespec (0x0x7f66e4fd6c60) 0 + +Class timeval + size=16 align=8 + base size=16 base align=8 +timeval (0x0x7f66e4fd6cc0) 0 + +Class pthread_attr_t + size=56 align=8 + base size=56 base align=8 +pthread_attr_t (0x0x7f66e4fd6d80) 0 + +Class __pthread_internal_list + size=16 align=8 + base size=16 base align=8 +__pthread_internal_list (0x0x7f66e4fd6de0) 0 + +Class random_data + size=48 align=8 + base size=48 base align=8 +random_data (0x0x7f66e50bc2a0) 0 + +Class drand48_data + size=24 align=8 + base size=24 base align=8 +drand48_data (0x0x7f66e50bc300) 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 (0x0x7f66e50bc360) 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 (0x0x7f66e4f3ba90) 0 nearly-empty + vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16u) + std::exception (0x0x7f66e50bc3c0) 0 nearly-empty + primary-for std::bad_exception (0x0x7f66e4f3ba90) + +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 (0x0x7f66e4f3baf8) 0 nearly-empty + vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16u) + std::exception (0x0x7f66e50bc420) 0 nearly-empty + primary-for std::bad_alloc (0x0x7f66e4f3baf8) + +Class std::nothrow_t + size=1 align=1 + base size=0 base align=1 +std::nothrow_t (0x0x7f66e50bc480) 0 empty + +Class qIsNull(double)::U + size=8 align=8 + base size=8 base align=8 +qIsNull(double)::U (0x0x7f66e3eb27e0) 0 + +Class qIsNull(float)::U + size=4 align=4 + base size=4 base align=4 +qIsNull(float)::U (0x0x7f66e3eb2840) 0 + +Class QAtomicInt + size=4 align=4 + base size=4 base align=4 +QAtomicInt (0x0x7f66e3b52548) 0 + QBasicAtomicInteger (0x0x7f66e3bb64e0) 0 + +Class QMessageLogContext + size=32 align=8 + base size=32 base align=8 +QMessageLogContext (0x0x7f66e3bb66c0) 0 + +Class QMessageLogger + size=32 align=8 + base size=32 base align=8 +QMessageLogger (0x0x7f66e3bb6720) 0 + +Class QtPrivate::big_ + size=2 align=1 + base size=2 base align=1 +QtPrivate::big_ (0x0x7f66e38fd180) 0 + +Class QFlag + size=4 align=4 + base size=4 base align=4 +QFlag (0x0x7f66e3948d80) 0 + +Class QIncompatibleFlag + size=4 align=4 + base size=4 base align=4 +QIncompatibleFlag (0x0x7f66e3948e40) 0 + +Class QSysInfo + size=1 align=1 + base size=0 base align=1 +QSysInfo (0x0x7f66e3948f60) 0 empty + +Class QInternal + size=1 align=1 + base size=0 base align=1 +QInternal (0x0x7f66e3a11e40) 0 empty + +Class QGenericArgument + size=16 align=8 + base size=16 base align=8 +QGenericArgument (0x0x7f66e37a8d80) 0 + +Class QGenericReturnArgument + size=16 align=8 + base size=16 base align=8 +QGenericReturnArgument (0x0x7f66e3a25d68) 0 + QGenericArgument (0x0x7f66e37a8de0) 0 + +Class QMetaObject + size=48 align=8 + base size=48 base align=8 +QMetaObject (0x0x7f66e37a8f60) 0 + +Class QMetaObject::Connection + size=8 align=8 + base size=8 base align=8 +QMetaObject::Connection (0x0x7f66e381c0c0) 0 + +Class QLatin1Char + size=1 align=1 + base size=1 base align=1 +QLatin1Char (0x0x7f66e381c300) 0 + +Class QChar + size=2 align=2 + base size=2 base align=2 +QChar (0x0x7f66e381c360) 0 + +Class QtPrivate::RefCount + size=4 align=4 + base size=4 base align=4 +QtPrivate::RefCount (0x0x7f66e381c420) 0 + +Class QArrayData + size=24 align=8 + base size=24 base align=8 +QArrayData (0x0x7f66e381c480) 0 + +Class QByteArrayDataPtr + size=8 align=8 + base size=8 base align=8 +QByteArrayDataPtr (0x0x7f66e381c7e0) 0 + +Class QByteArray + size=8 align=8 + base size=8 base align=8 +QByteArray (0x0x7f66e381c840) 0 + +Class QByteRef + size=16 align=8 + base size=12 base align=8 +QByteRef (0x0x7f66e381c9c0) 0 + +Class lconv + size=96 align=8 + base size=96 base align=8 +lconv (0x0x7f66e381cd80) 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 (0x0x7f66e381cde0) 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 (0x0x7f66e33018a0) 0 + +Class __sched_param + size=4 align=4 + base size=4 base align=4 +__sched_param (0x0x7f66e3301900) 0 + +Class timex + size=208 align=8 + base size=208 base align=8 +timex (0x0x7f66e33019c0) 0 + +Class tm + size=56 align=8 + base size=56 base align=8 +tm (0x0x7f66e3301a20) 0 + +Class itimerspec + size=32 align=8 + base size=32 base align=8 +itimerspec (0x0x7f66e3301a80) 0 + +Class _pthread_cleanup_buffer + size=32 align=8 + base size=32 base align=8 +_pthread_cleanup_buffer (0x0x7f66e3301ae0) 0 + +Class __pthread_cleanup_frame + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_frame (0x0x7f66e3301c00) 0 + +Class __pthread_cleanup_class + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_class (0x0x7f66e3301c60) 0 + +Class QLatin1String + size=16 align=8 + base size=16 base align=8 +QLatin1String (0x0x7f66e34d73c0) 0 + +Class QStringDataPtr + size=8 align=8 + base size=8 base align=8 +QStringDataPtr (0x0x7f66e34d74e0) 0 + +Class QString::Null + size=1 align=1 + base size=0 base align=1 +QString::Null (0x0x7f66e34d75a0) 0 empty + +Class QString + size=8 align=8 + base size=8 base align=8 +QString (0x0x7f66e34d7540) 0 + +Class QCharRef + size=16 align=8 + base size=12 base align=8 +QCharRef (0x0x7f66e34d7720) 0 + +Class QStringRef + size=16 align=8 + base size=16 base align=8 +QStringRef (0x0x7f66e34d7900) 0 + +Class std::locale + size=8 align=8 + base size=8 base align=8 +std::locale (0x0x7f66e34d7a80) 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 (0x0x7f66e34d7ae0) 0 + vptr=((& std::locale::facet::_ZTVNSt6locale5facetE) + 16u) + +Class std::locale::id + size=8 align=8 + base size=8 base align=8 +std::locale::id (0x0x7f66e34d7b40) 0 + +Class std::locale::_Impl + size=40 align=8 + base size=40 base align=8 +std::locale::_Impl (0x0x7f66e34d7ba0) 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 (0x0x7f66e30ad3a8) 0 + vptr=((& std::ios_base::failure::_ZTVNSt8ios_base7failureE) + 16u) + std::exception (0x0x7f66e2cf3000) 0 nearly-empty + primary-for std::ios_base::failure (0x0x7f66e30ad3a8) + +Class std::ios_base::_Callback_list + size=24 align=8 + base size=24 base align=8 +std::ios_base::_Callback_list (0x0x7f66e2cf3060) 0 + +Class std::ios_base::_Words + size=16 align=8 + base size=16 base align=8 +std::ios_base::_Words (0x0x7f66e2cf30c0) 0 + +Class std::ios_base::Init + size=1 align=1 + base size=0 base align=1 +std::ios_base::Init (0x0x7f66e2cf3120) 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 (0x0x7f66e34d7f60) 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 (0x0x7f66e2cf32a0) 0 empty + +Class std::__num_base + size=1 align=1 + base size=0 base align=1 +std::__num_base (0x0x7f66e2cf3960) 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 (0x0x7f66e2c54820 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 (0x0x7f66e2c54e38 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 (0x0x7f66e2968270 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 (0x0x7f66e2968340 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 (0x0x7f66e2b2ed20) 0 + +Class QListData::Data + size=24 align=8 + base size=24 base align=8 +QListData::Data (0x0x7f66e2a2c060) 0 + +Class QListData + size=8 align=8 + base size=8 base align=8 +QListData (0x0x7f66e2a2c000) 0 + +Class QScopedPointerPodDeleter + size=1 align=1 + base size=0 base align=1 +QScopedPointerPodDeleter (0x0x7f66e2a2c420) 0 empty + +Class std::_Bit_reference + size=16 align=8 + base size=16 base align=8 +std::_Bit_reference (0x0x7f66e2799240) 0 + +Class std::_Bit_iterator_base + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator_base (0x0x7f66e2968a28) 0 + std::iterator (0x0x7f66e2799300) 0 empty + +Class std::_Bit_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator (0x0x7f66e2968a90) 0 + std::_Bit_iterator_base (0x0x7f66e2968af8) 0 + std::iterator (0x0x7f66e2799360) 0 empty + +Class std::_Bit_const_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_const_iterator (0x0x7f66e2968b60) 0 + std::_Bit_iterator_base (0x0x7f66e2968bc8) 0 + std::iterator (0x0x7f66e27993c0) 0 empty + +Class std::_Rb_tree_node_base + size=32 align=8 + base size=32 base align=8 +std::_Rb_tree_node_base (0x0x7f66e2799780) 0 + +Class QtPrivate::AbstractDebugStreamFunction + size=16 align=8 + base size=16 base align=8 +QtPrivate::AbstractDebugStreamFunction (0x0x7f66e2799ba0) 0 + +Class QtPrivate::AbstractComparatorFunction + size=24 align=8 + base size=24 base align=8 +QtPrivate::AbstractComparatorFunction (0x0x7f66e2799c60) 0 + +Class QtPrivate::AbstractConverterFunction + size=8 align=8 + base size=8 base align=8 +QtPrivate::AbstractConverterFunction (0x0x7f66e2799d20) 0 + +Class QMetaType + size=80 align=8 + base size=80 base align=8 +QMetaType (0x0x7f66e266a180) 0 + +Class QtMetaTypePrivate::VariantData + size=24 align=8 + base size=20 base align=8 +QtMetaTypePrivate::VariantData (0x0x7f66e266a4e0) 0 + +Class QtMetaTypePrivate::QSequentialIterableImpl + size=104 align=8 + base size=104 base align=8 +QtMetaTypePrivate::QSequentialIterableImpl (0x0x7f66e266a900) 0 + +Class QtMetaTypePrivate::QAssociativeIterableImpl + size=112 align=8 + base size=112 base align=8 +QtMetaTypePrivate::QAssociativeIterableImpl (0x0x7f66e266aae0) 0 + +Class QtMetaTypePrivate::QPairVariantInterfaceImpl + size=40 align=8 + base size=40 base align=8 +QtMetaTypePrivate::QPairVariantInterfaceImpl (0x0x7f66e266aba0) 0 + +Class QtPrivate::QSlotObjectBase + size=16 align=8 + base size=16 base align=8 +QtPrivate::QSlotObjectBase (0x0x7f66e2484e40) 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 (0x0x7f66e20f3000) 0 + vptr=((& QObjectData::_ZTV11QObjectData) + 16u) + +Class QObject::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObject::QPrivateSignal (0x0x7f66e20f3180) 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 (0x0x7f66e20f3120) 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 (0x0x7f66e20f3480) 0 nearly-empty + vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16u) + +Class QAbstractAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractAnimation::QPrivateSignal (0x0x7f66e20f3540) 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 (0x0x7f66e20e93a8) 0 + vptr=((& QAbstractAnimation::_ZTV18QAbstractAnimation) + 16u) + QObject (0x0x7f66e20f34e0) 0 + primary-for QAbstractAnimation (0x0x7f66e20e93a8) + +Class QAnimationDriver::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationDriver::QPrivateSignal (0x0x7f66e20f3600) 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 (0x0x7f66e20e9410) 0 + vptr=((& QAnimationDriver::_ZTV16QAnimationDriver) + 16u) + QObject (0x0x7f66e20f35a0) 0 + primary-for QAnimationDriver (0x0x7f66e20e9410) + +Class QAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationGroup::QPrivateSignal (0x0x7f66e20f36c0) 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 (0x0x7f66e20e9478) 0 + vptr=((& QAnimationGroup::_ZTV15QAnimationGroup) + 16u) + QAbstractAnimation (0x0x7f66e20e94e0) 0 + primary-for QAnimationGroup (0x0x7f66e20e9478) + QObject (0x0x7f66e20f3660) 0 + primary-for QAbstractAnimation (0x0x7f66e20e94e0) + +Class QParallelAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QParallelAnimationGroup::QPrivateSignal (0x0x7f66e20f3780) 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 (0x0x7f66e20e9548) 0 + vptr=((& QParallelAnimationGroup::_ZTV23QParallelAnimationGroup) + 16u) + QAnimationGroup (0x0x7f66e20e95b0) 0 + primary-for QParallelAnimationGroup (0x0x7f66e20e9548) + QAbstractAnimation (0x0x7f66e20e9618) 0 + primary-for QAnimationGroup (0x0x7f66e20e95b0) + QObject (0x0x7f66e20f3720) 0 + primary-for QAbstractAnimation (0x0x7f66e20e9618) + +Class QPauseAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPauseAnimation::QPrivateSignal (0x0x7f66e20f3840) 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 (0x0x7f66e20e9680) 0 + vptr=((& QPauseAnimation::_ZTV15QPauseAnimation) + 16u) + QAbstractAnimation (0x0x7f66e20e96e8) 0 + primary-for QPauseAnimation (0x0x7f66e20e9680) + QObject (0x0x7f66e20f37e0) 0 + primary-for QAbstractAnimation (0x0x7f66e20e96e8) + +Class QEasingCurve + size=8 align=8 + base size=8 base align=8 +QEasingCurve (0x0x7f66e20f3a20) 0 + +Class QMapNodeBase + size=24 align=8 + base size=24 base align=8 +QMapNodeBase (0x0x7f66e20f3ba0) 0 + +Class QMapDataBase + size=40 align=8 + base size=40 base align=8 +QMapDataBase (0x0x7f66e20f3c60) 0 + +Class QHashData::Node + size=16 align=8 + base size=16 base align=8 +QHashData::Node (0x0x7f66e1fd3000) 0 + +Class QHashData + size=48 align=8 + base size=48 base align=8 +QHashData (0x0x7f66e20f3f60) 0 + +Class QHashDummyValue + size=1 align=1 + base size=0 base align=1 +QHashDummyValue (0x0x7f66e1fd3060) 0 empty + +Class QIODevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIODevice::QPrivateSignal (0x0x7f66e1fd34e0) 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 (0x0x7f66e20e9f08) 0 + vptr=((& QIODevice::_ZTV9QIODevice) + 16u) + QObject (0x0x7f66e1fd3480) 0 + primary-for QIODevice (0x0x7f66e20e9f08) + +Class QDataStream + size=32 align=8 + base size=32 base align=8 +QDataStream (0x0x7f66e1fd3600) 0 + +Class QRegExp + size=8 align=8 + base size=8 base align=8 +QRegExp (0x0x7f66e1fd36c0) 0 + +Class QStringMatcher::Data + size=272 align=8 + base size=272 base align=8 +QStringMatcher::Data (0x0x7f66e1fd37e0) 0 + +Class QStringMatcher + size=1048 align=8 + base size=1048 base align=8 +QStringMatcher (0x0x7f66e1fd3780) 0 + +Class QStringList + size=8 align=8 + base size=8 base align=8 +QStringList (0x0x7f66e1d60000) 0 + QList (0x0x7f66e1fd3960) 0 + +Class QVariant::PrivateShared + size=16 align=8 + base size=12 base align=8 +QVariant::PrivateShared (0x0x7f66e1fd3c00) 0 + +Class QVariant::Private::Data + size=8 align=8 + base size=8 base align=8 +QVariant::Private::Data (0x0x7f66e1fd3cc0) 0 + +Class QVariant::Private + size=16 align=8 + base size=12 base align=8 +QVariant::Private (0x0x7f66e1fd3c60) 0 + +Class QVariant::Handler + size=72 align=8 + base size=72 base align=8 +QVariant::Handler (0x0x7f66e1fd3d20) 0 + +Class QVariant + size=16 align=8 + base size=16 base align=8 +QVariant (0x0x7f66e1fd3ba0) 0 + +Class QVariantComparisonHelper + size=8 align=8 + base size=8 base align=8 +QVariantComparisonHelper (0x0x7f66e1e62000) 0 + +Class QSequentialIterable::const_iterator + size=112 align=8 + base size=112 base align=8 +QSequentialIterable::const_iterator (0x0x7f66e1e620c0) 0 + +Class QSequentialIterable + size=104 align=8 + base size=104 base align=8 +QSequentialIterable (0x0x7f66e1e62060) 0 + +Class QAssociativeIterable::const_iterator + size=120 align=8 + base size=120 base align=8 +QAssociativeIterable::const_iterator (0x0x7f66e1e62180) 0 + +Class QAssociativeIterable + size=112 align=8 + base size=112 base align=8 +QAssociativeIterable (0x0x7f66e1e62120) 0 + +Class QVariantAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QVariantAnimation::QPrivateSignal (0x0x7f66e1e62cc0) 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 (0x0x7f66e1d60958) 0 + vptr=((& QVariantAnimation::_ZTV17QVariantAnimation) + 16u) + QAbstractAnimation (0x0x7f66e1d609c0) 0 + primary-for QVariantAnimation (0x0x7f66e1d60958) + QObject (0x0x7f66e1e62c60) 0 + primary-for QAbstractAnimation (0x0x7f66e1d609c0) + +Class QPropertyAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPropertyAnimation::QPrivateSignal (0x0x7f66e1e62d80) 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 (0x0x7f66e1d60a90) 0 + vptr=((& QPropertyAnimation::_ZTV18QPropertyAnimation) + 16u) + QVariantAnimation (0x0x7f66e1d60af8) 0 + primary-for QPropertyAnimation (0x0x7f66e1d60a90) + QAbstractAnimation (0x0x7f66e1d60b60) 0 + primary-for QVariantAnimation (0x0x7f66e1d60af8) + QObject (0x0x7f66e1e62d20) 0 + primary-for QAbstractAnimation (0x0x7f66e1d60b60) + +Class QSequentialAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSequentialAnimationGroup::QPrivateSignal (0x0x7f66e1e62e40) 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 (0x0x7f66e1d60bc8) 0 + vptr=((& QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup) + 16u) + QAnimationGroup (0x0x7f66e1d60c30) 0 + primary-for QSequentialAnimationGroup (0x0x7f66e1d60bc8) + QAbstractAnimation (0x0x7f66e1d60c98) 0 + primary-for QAnimationGroup (0x0x7f66e1d60c30) + QObject (0x0x7f66e1e62de0) 0 + primary-for QAbstractAnimation (0x0x7f66e1d60c98) + +Class QTextCodec::ConverterState + size=32 align=8 + base size=32 base align=8 +QTextCodec::ConverterState (0x0x7f66e1e62f00) 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 (0x0x7f66e1e62ea0) 0 nearly-empty + vptr=((& QTextCodec::_ZTV10QTextCodec) + 16u) + +Class QTextEncoder + size=40 align=8 + base size=40 base align=8 +QTextEncoder (0x0x7f66e1b32060) 0 + +Class QTextDecoder + size=40 align=8 + base size=40 base align=8 +QTextDecoder (0x0x7f66e1b320c0) 0 + +Class QSharedData + size=4 align=4 + base size=4 base align=4 +QSharedData (0x0x7f66e1b32120) 0 + +Class QtSharedPointer::NormalDeleter + size=1 align=1 + base size=0 base align=1 +QtSharedPointer::NormalDeleter (0x0x7f66e1b323c0) 0 empty + +Class QtSharedPointer::ExternalRefCountData + size=16 align=8 + base size=16 base align=8 +QtSharedPointer::ExternalRefCountData (0x0x7f66e1b32540) 0 + +Class std::__numeric_limits_base + size=1 align=1 + base size=0 base align=1 +std::__numeric_limits_base (0x0x7f66e1b329c0) 0 empty + +Class QDate + size=8 align=8 + base size=8 base align=8 +QDate (0x0x7f66e1ce0180) 0 + +Class QTime + size=4 align=4 + base size=4 base align=4 +QTime (0x0x7f66e1ce0240) 0 + +Class QDateTime + size=8 align=8 + base size=8 base align=8 +QDateTime (0x0x7f66e1ce0300) 0 + +Class QLibraryInfo + size=1 align=1 + base size=0 base align=1 +QLibraryInfo (0x0x7f66e1ce0420) 0 empty + +Class QBuffer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBuffer::QPrivateSignal (0x0x7f66e1ce04e0) 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 (0x0x7f66e1975000) 0 + vptr=((& QBuffer::_ZTV7QBuffer) + 16u) + QIODevice (0x0x7f66e1975068) 0 + primary-for QBuffer (0x0x7f66e1975000) + QObject (0x0x7f66e1ce0480) 0 + primary-for QIODevice (0x0x7f66e1975068) + +Class QLocale + size=8 align=8 + base size=8 base align=8 +QLocale (0x0x7f66e1ce0540) 0 + +Class _IO_marker + size=24 align=8 + base size=24 base align=8 +_IO_marker (0x0x7f66e1ce07e0) 0 + +Class _IO_FILE + size=216 align=8 + base size=216 base align=8 +_IO_FILE (0x0x7f66e1ce0840) 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 (0x0x7f66e1ce0900) 0 + vptr=((& QTextStream::_ZTV11QTextStream) + 16u) + +Class QTextStreamManipulator + size=40 align=8 + base size=38 base align=8 +QTextStreamManipulator (0x0x7f66e1ce0ba0) 0 + +Class QContiguousCacheData + size=24 align=4 + base size=24 base align=4 +QContiguousCacheData (0x0x7f66e1ce0de0) 0 + +Class QDebug::Stream + size=72 align=8 + base size=72 base align=8 +QDebug::Stream (0x0x7f66e1723480) 0 + +Class QDebug + size=8 align=8 + base size=8 base align=8 +QDebug (0x0x7f66e1723420) 0 + +Class QDebugStateSaver + size=8 align=8 + base size=8 base align=8 +QDebugStateSaver (0x0x7f66e1723540) 0 + +Class QNoDebug + size=1 align=1 + base size=0 base align=1 +QNoDebug (0x0x7f66e1723600) 0 empty + +Class QFileDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileDevice::QPrivateSignal (0x0x7f66e17236c0) 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 (0x0x7f66e19753a8) 0 + vptr=((& QFileDevice::_ZTV11QFileDevice) + 16u) + QIODevice (0x0x7f66e1975410) 0 + primary-for QFileDevice (0x0x7f66e19753a8) + QObject (0x0x7f66e1723660) 0 + primary-for QIODevice (0x0x7f66e1975410) + +Class QFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFile::QPrivateSignal (0x0x7f66e1723840) 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 (0x0x7f66e1975548) 0 + vptr=((& QFile::_ZTV5QFile) + 16u) + QFileDevice (0x0x7f66e19755b0) 0 + primary-for QFile (0x0x7f66e1975548) + QIODevice (0x0x7f66e1975618) 0 + primary-for QFileDevice (0x0x7f66e19755b0) + QObject (0x0x7f66e17237e0) 0 + primary-for QIODevice (0x0x7f66e1975618) + +Class QFileInfo + size=8 align=8 + base size=8 base align=8 +QFileInfo (0x0x7f66e1723960) 0 + +Class QDir + size=8 align=8 + base size=8 base align=8 +QDir (0x0x7f66e1723ba0) 0 + +Class QDirIterator + size=8 align=8 + base size=8 base align=8 +QDirIterator (0x0x7f66e1723e40) 0 + +Class QFileSelector::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSelector::QPrivateSignal (0x0x7f66e18e0060) 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 (0x0x7f66e1975a28) 0 + vptr=((& QFileSelector::_ZTV13QFileSelector) + 16u) + QObject (0x0x7f66e18e0000) 0 + primary-for QFileSelector (0x0x7f66e1975a28) + +Class QFileSystemWatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSystemWatcher::QPrivateSignal (0x0x7f66e18e0120) 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 (0x0x7f66e1975a90) 0 + vptr=((& QFileSystemWatcher::_ZTV18QFileSystemWatcher) + 16u) + QObject (0x0x7f66e18e00c0) 0 + primary-for QFileSystemWatcher (0x0x7f66e1975a90) + +Class QLockFile + size=8 align=8 + base size=8 base align=8 +QLockFile (0x0x7f66e18e0180) 0 + +Class QLoggingCategory + size=24 align=8 + base size=24 base align=8 +QLoggingCategory (0x0x7f66e18e02a0) 0 + +Class QProcessEnvironment + size=8 align=8 + base size=8 base align=8 +QProcessEnvironment (0x0x7f66e18e0300) 0 + +Class QProcess::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QProcess::QPrivateSignal (0x0x7f66e18e0480) 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 (0x0x7f66e1975af8) 0 + vptr=((& QProcess::_ZTV8QProcess) + 16u) + QIODevice (0x0x7f66e1975b60) 0 + primary-for QProcess (0x0x7f66e1975af8) + QObject (0x0x7f66e18e0420) 0 + primary-for QIODevice (0x0x7f66e1975b60) + +Class QResource + size=8 align=8 + base size=8 base align=8 +QResource (0x0x7f66e18e04e0) 0 + +Class QSaveFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSaveFile::QPrivateSignal (0x0x7f66e18e0660) 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 (0x0x7f66e1975bc8) 0 + vptr=((& QSaveFile::_ZTV9QSaveFile) + 16u) + QFileDevice (0x0x7f66e1975c30) 0 + primary-for QSaveFile (0x0x7f66e1975bc8) + QIODevice (0x0x7f66e1975c98) 0 + primary-for QFileDevice (0x0x7f66e1975c30) + QObject (0x0x7f66e18e0600) 0 + primary-for QIODevice (0x0x7f66e1975c98) + +Class QSettings::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSettings::QPrivateSignal (0x0x7f66e18e0720) 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 (0x0x7f66e1975d00) 0 + vptr=((& QSettings::_ZTV9QSettings) + 16u) + QObject (0x0x7f66e18e06c0) 0 + primary-for QSettings (0x0x7f66e1975d00) + +Class QStandardPaths + size=1 align=1 + base size=0 base align=1 +QStandardPaths (0x0x7f66e18e0780) 0 empty + +Class QTemporaryDir + size=8 align=8 + base size=8 base align=8 +QTemporaryDir (0x0x7f66e18e08a0) 0 + +Class QTemporaryFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTemporaryFile::QPrivateSignal (0x0x7f66e18e09c0) 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 (0x0x7f66e1975e38) 0 + vptr=((& QTemporaryFile::_ZTV14QTemporaryFile) + 16u) + QFile (0x0x7f66e1975ea0) 0 + primary-for QTemporaryFile (0x0x7f66e1975e38) + QFileDevice (0x0x7f66e1975f08) 0 + primary-for QFile (0x0x7f66e1975ea0) + QIODevice (0x0x7f66e1975f70) 0 + primary-for QFileDevice (0x0x7f66e1975f08) + QObject (0x0x7f66e18e0960) 0 + primary-for QIODevice (0x0x7f66e1975f70) + +Class QUrl + size=8 align=8 + base size=8 base align=8 +QUrl (0x0x7f66e18e0ae0) 0 + +Class QUrlQuery + size=8 align=8 + base size=8 base align=8 +QUrlQuery (0x0x7f66e18e0ea0) 0 + +Class QModelIndex + size=24 align=8 + base size=24 base align=8 +QModelIndex (0x0x7f66e169d000) 0 + +Class QPersistentModelIndex + size=8 align=8 + base size=8 base align=8 +QPersistentModelIndex (0x0x7f66e169d0c0) 0 + +Class QAbstractItemModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractItemModel::QPrivateSignal (0x0x7f66e169d1e0) 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 (0x0x7f66e161e1a0) 0 + vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16u) + QObject (0x0x7f66e169d180) 0 + primary-for QAbstractItemModel (0x0x7f66e161e1a0) + +Class QAbstractTableModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTableModel::QPrivateSignal (0x0x7f66e169d4e0) 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 (0x0x7f66e161e2d8) 0 + vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16u) + QAbstractItemModel (0x0x7f66e161e340) 0 + primary-for QAbstractTableModel (0x0x7f66e161e2d8) + QObject (0x0x7f66e169d480) 0 + primary-for QAbstractItemModel (0x0x7f66e161e340) + +Class QAbstractListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractListModel::QPrivateSignal (0x0x7f66e169d5a0) 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 (0x0x7f66e161e3a8) 0 + vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16u) + QAbstractItemModel (0x0x7f66e161e410) 0 + primary-for QAbstractListModel (0x0x7f66e161e3a8) + QObject (0x0x7f66e169d540) 0 + primary-for QAbstractItemModel (0x0x7f66e161e410) + +Class QAbstractProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractProxyModel::QPrivateSignal (0x0x7f66e169d660) 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 (0x0x7f66e161e478) 0 + vptr=((& QAbstractProxyModel::_ZTV19QAbstractProxyModel) + 16u) + QAbstractItemModel (0x0x7f66e161e4e0) 0 + primary-for QAbstractProxyModel (0x0x7f66e161e478) + QObject (0x0x7f66e169d600) 0 + primary-for QAbstractItemModel (0x0x7f66e161e4e0) + +Class QIdentityProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIdentityProxyModel::QPrivateSignal (0x0x7f66e169d720) 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 (0x0x7f66e161e548) 0 + vptr=((& QIdentityProxyModel::_ZTV19QIdentityProxyModel) + 16u) + QAbstractProxyModel (0x0x7f66e161e5b0) 0 + primary-for QIdentityProxyModel (0x0x7f66e161e548) + QAbstractItemModel (0x0x7f66e161e618) 0 + primary-for QAbstractProxyModel (0x0x7f66e161e5b0) + QObject (0x0x7f66e169d6c0) 0 + primary-for QAbstractItemModel (0x0x7f66e161e618) + +Class QItemSelectionRange + size=16 align=8 + base size=16 base align=8 +QItemSelectionRange (0x0x7f66e169d780) 0 + +Class QItemSelectionModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QItemSelectionModel::QPrivateSignal (0x0x7f66e169d8a0) 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 (0x0x7f66e161e680) 0 + vptr=((& QItemSelectionModel::_ZTV19QItemSelectionModel) + 16u) + QObject (0x0x7f66e169d840) 0 + primary-for QItemSelectionModel (0x0x7f66e161e680) + +Class QItemSelection + size=8 align=8 + base size=8 base align=8 +QItemSelection (0x0x7f66e161e7b8) 0 + QList (0x0x7f66e169da80) 0 + +Class QSortFilterProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSortFilterProxyModel::QPrivateSignal (0x0x7f66e169db40) 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 (0x0x7f66e161e820) 0 + vptr=((& QSortFilterProxyModel::_ZTV21QSortFilterProxyModel) + 16u) + QAbstractProxyModel (0x0x7f66e161e888) 0 + primary-for QSortFilterProxyModel (0x0x7f66e161e820) + QAbstractItemModel (0x0x7f66e161e8f0) 0 + primary-for QAbstractProxyModel (0x0x7f66e161e888) + QObject (0x0x7f66e169dae0) 0 + primary-for QAbstractItemModel (0x0x7f66e161e8f0) + +Class QStringListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStringListModel::QPrivateSignal (0x0x7f66e169dc00) 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 (0x0x7f66e161e958) 0 + vptr=((& QStringListModel::_ZTV16QStringListModel) + 16u) + QAbstractListModel (0x0x7f66e161e9c0) 0 + primary-for QStringListModel (0x0x7f66e161e958) + QAbstractItemModel (0x0x7f66e161ea28) 0 + primary-for QAbstractListModel (0x0x7f66e161e9c0) + QObject (0x0x7f66e169dba0) 0 + primary-for QAbstractItemModel (0x0x7f66e161ea28) + +Class QJsonValue + size=24 align=8 + base size=20 base align=8 +QJsonValue (0x0x7f66e169dc60) 0 + +Class QJsonValueRef + size=16 align=8 + base size=12 base align=8 +QJsonValueRef (0x0x7f66e169dd20) 0 + +Class QJsonArray::iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::iterator (0x0x7f66e169de40) 0 + +Class QJsonArray::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::const_iterator (0x0x7f66e169dea0) 0 + +Class QJsonArray + size=16 align=8 + base size=16 base align=8 +QJsonArray (0x0x7f66e169dde0) 0 + +Class QJsonParseError + size=8 align=4 + base size=8 base align=4 +QJsonParseError (0x0x7f66e169df00) 0 + +Class QJsonDocument + size=8 align=8 + base size=8 base align=8 +QJsonDocument (0x0x7f66e169df60) 0 + +Class QJsonObject::iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::iterator (0x0x7f66e1119060) 0 + +Class QJsonObject::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::const_iterator (0x0x7f66e11190c0) 0 + +Class QJsonObject + size=16 align=8 + base size=16 base align=8 +QJsonObject (0x0x7f66e1119000) 0 + +Class QEventLoop::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventLoop::QPrivateSignal (0x0x7f66e11191e0) 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 (0x0x7f66e161ea90) 0 + vptr=((& QEventLoop::_ZTV10QEventLoop) + 16u) + QObject (0x0x7f66e1119180) 0 + primary-for QEventLoop (0x0x7f66e161ea90) + +Class QEventLoopLocker + size=8 align=8 + base size=8 base align=8 +QEventLoopLocker (0x0x7f66e1119300) 0 + +Class QAbstractEventDispatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractEventDispatcher::QPrivateSignal (0x0x7f66e11193c0) 0 empty + +Class QAbstractEventDispatcher::TimerInfo + size=12 align=4 + base size=12 base align=4 +QAbstractEventDispatcher::TimerInfo (0x0x7f66e1119420) 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 (0x0x7f66e161ebc8) 0 + vptr=((& QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher) + 16u) + QObject (0x0x7f66e1119360) 0 + primary-for QAbstractEventDispatcher (0x0x7f66e161ebc8) + +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 (0x0x7f66e1119480) 0 + vptr=((& QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter) + 16u) + +Class QBasicTimer + size=4 align=4 + base size=4 base align=4 +QBasicTimer (0x0x7f66e11194e0) 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 (0x0x7f66e11195a0) 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 (0x0x7f66e161ec30) 0 + vptr=((& QTimerEvent::_ZTV11QTimerEvent) + 16u) + QEvent (0x0x7f66e1119600) 0 + primary-for QTimerEvent (0x0x7f66e161ec30) + +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 (0x0x7f66e161ec98) 0 + vptr=((& QChildEvent::_ZTV11QChildEvent) + 16u) + QEvent (0x0x7f66e1119660) 0 + primary-for QChildEvent (0x0x7f66e161ec98) + +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 (0x0x7f66e161ed00) 0 + vptr=((& QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent) + 16u) + QEvent (0x0x7f66e11196c0) 0 + primary-for QDynamicPropertyChangeEvent (0x0x7f66e161ed00) + +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 (0x0x7f66e161ed68) 0 + vptr=((& QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent) + 16u) + QEvent (0x0x7f66e1119720) 0 + primary-for QDeferredDeleteEvent (0x0x7f66e161ed68) + +Class QCoreApplication::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QCoreApplication::QPrivateSignal (0x0x7f66e11197e0) 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 (0x0x7f66e161edd0) 0 + vptr=((& QCoreApplication::_ZTV16QCoreApplication) + 16u) + QObject (0x0x7f66e1119780) 0 + primary-for QCoreApplication (0x0x7f66e161edd0) + +Class __exception + size=40 align=8 + base size=40 base align=8 +__exception (0x0x7f66e1119840) 0 + +Class QMetaMethod + size=16 align=8 + base size=12 base align=8 +QMetaMethod (0x0x7f66e11198a0) 0 + +Class QMetaEnum + size=16 align=8 + base size=12 base align=8 +QMetaEnum (0x0x7f66e1119960) 0 + +Class QMetaProperty + size=32 align=8 + base size=32 base align=8 +QMetaProperty (0x0x7f66e1119a20) 0 + +Class QMetaClassInfo + size=16 align=8 + base size=12 base align=8 +QMetaClassInfo (0x0x7f66e1119a80) 0 + +Class QMimeData::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QMimeData::QPrivateSignal (0x0x7f66e1119ba0) 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 (0x0x7f66e161ef08) 0 + vptr=((& QMimeData::_ZTV9QMimeData) + 16u) + QObject (0x0x7f66e1119b40) 0 + primary-for QMimeData (0x0x7f66e161ef08) + +Class QObjectCleanupHandler::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObjectCleanupHandler::QPrivateSignal (0x0x7f66e1119c60) 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 (0x0x7f66e161ef70) 0 + vptr=((& QObjectCleanupHandler::_ZTV21QObjectCleanupHandler) + 16u) + QObject (0x0x7f66e1119c00) 0 + primary-for QObjectCleanupHandler (0x0x7f66e161ef70) + +Class QSharedMemory::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSharedMemory::QPrivateSignal (0x0x7f66e1119ea0) 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 (0x0x7f66e12cc000) 0 + vptr=((& QSharedMemory::_ZTV13QSharedMemory) + 16u) + QObject (0x0x7f66e1119e40) 0 + primary-for QSharedMemory (0x0x7f66e12cc000) + +Class QSignalMapper::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalMapper::QPrivateSignal (0x0x7f66e1119f60) 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 (0x0x7f66e12cc068) 0 + vptr=((& QSignalMapper::_ZTV13QSignalMapper) + 16u) + QObject (0x0x7f66e1119f00) 0 + primary-for QSignalMapper (0x0x7f66e12cc068) + +Class QSocketNotifier::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSocketNotifier::QPrivateSignal (0x0x7f66e0ef4060) 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 (0x0x7f66e12cc0d0) 0 + vptr=((& QSocketNotifier::_ZTV15QSocketNotifier) + 16u) + QObject (0x0x7f66e0ef4000) 0 + primary-for QSocketNotifier (0x0x7f66e12cc0d0) + +Class QSystemSemaphore + size=8 align=8 + base size=8 base align=8 +QSystemSemaphore (0x0x7f66e0ef40c0) 0 + +Class QTimer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimer::QPrivateSignal (0x0x7f66e0ef41e0) 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 (0x0x7f66e12cc138) 0 + vptr=((& QTimer::_ZTV6QTimer) + 16u) + QObject (0x0x7f66e0ef4180) 0 + primary-for QTimer (0x0x7f66e12cc138) + +Class QTranslator::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTranslator::QPrivateSignal (0x0x7f66e0ef4300) 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 (0x0x7f66e12cc1a0) 0 + vptr=((& QTranslator::_ZTV11QTranslator) + 16u) + QObject (0x0x7f66e0ef42a0) 0 + primary-for QTranslator (0x0x7f66e12cc1a0) + +Class QMimeType + size=8 align=8 + base size=8 base align=8 +QMimeType (0x0x7f66e0ef4360) 0 + +Class QMimeDatabase + size=8 align=8 + base size=8 base align=8 +QMimeDatabase (0x0x7f66e0ef4480) 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 (0x0x7f66e0ef44e0) 0 nearly-empty + vptr=((& QFactoryInterface::_ZTV17QFactoryInterface) + 16u) + +Class QLibrary::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLibrary::QPrivateSignal (0x0x7f66e0ef4600) 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 (0x0x7f66e12cc208) 0 + vptr=((& QLibrary::_ZTV8QLibrary) + 16u) + QObject (0x0x7f66e0ef45a0) 0 + primary-for QLibrary (0x0x7f66e12cc208) + +Class QStaticPlugin + size=16 align=8 + base size=16 base align=8 +QStaticPlugin (0x0x7f66e0ef4720) 0 + +Class QPluginLoader::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPluginLoader::QPrivateSignal (0x0x7f66e0ef4840) 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 (0x0x7f66e12cc340) 0 + vptr=((& QPluginLoader::_ZTV13QPluginLoader) + 16u) + QObject (0x0x7f66e0ef47e0) 0 + primary-for QPluginLoader (0x0x7f66e12cc340) + +Class QUuid + size=16 align=4 + base size=16 base align=4 +QUuid (0x0x7f66e0ef48a0) 0 + +Class QAbstractState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractState::QPrivateSignal (0x0x7f66e0ef49c0) 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 (0x0x7f66e12cc3a8) 0 + vptr=((& QAbstractState::_ZTV14QAbstractState) + 16u) + QObject (0x0x7f66e0ef4960) 0 + primary-for QAbstractState (0x0x7f66e12cc3a8) + +Class QAbstractTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTransition::QPrivateSignal (0x0x7f66e0ef4a80) 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 (0x0x7f66e12cc410) 0 + vptr=((& QAbstractTransition::_ZTV19QAbstractTransition) + 16u) + QObject (0x0x7f66e0ef4a20) 0 + primary-for QAbstractTransition (0x0x7f66e12cc410) + +Class QEventTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventTransition::QPrivateSignal (0x0x7f66e0ef4b40) 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 (0x0x7f66e12cc478) 0 + vptr=((& QEventTransition::_ZTV16QEventTransition) + 16u) + QAbstractTransition (0x0x7f66e12cc4e0) 0 + primary-for QEventTransition (0x0x7f66e12cc478) + QObject (0x0x7f66e0ef4ae0) 0 + primary-for QAbstractTransition (0x0x7f66e12cc4e0) + +Class QFinalState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFinalState::QPrivateSignal (0x0x7f66e0ef4c00) 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 (0x0x7f66e12cc548) 0 + vptr=((& QFinalState::_ZTV11QFinalState) + 16u) + QAbstractState (0x0x7f66e12cc5b0) 0 + primary-for QFinalState (0x0x7f66e12cc548) + QObject (0x0x7f66e0ef4ba0) 0 + primary-for QAbstractState (0x0x7f66e12cc5b0) + +Class QHistoryState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QHistoryState::QPrivateSignal (0x0x7f66e0ef4cc0) 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 (0x0x7f66e12cc618) 0 + vptr=((& QHistoryState::_ZTV13QHistoryState) + 16u) + QAbstractState (0x0x7f66e12cc680) 0 + primary-for QHistoryState (0x0x7f66e12cc618) + QObject (0x0x7f66e0ef4c60) 0 + primary-for QAbstractState (0x0x7f66e12cc680) + +Class QSignalTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalTransition::QPrivateSignal (0x0x7f66e0ef4d80) 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 (0x0x7f66e12cc6e8) 0 + vptr=((& QSignalTransition::_ZTV17QSignalTransition) + 16u) + QAbstractTransition (0x0x7f66e12cc750) 0 + primary-for QSignalTransition (0x0x7f66e12cc6e8) + QObject (0x0x7f66e0ef4d20) 0 + primary-for QAbstractTransition (0x0x7f66e12cc750) + +Class QState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QState::QPrivateSignal (0x0x7f66e0ef4e40) 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 (0x0x7f66e12cc7b8) 0 + vptr=((& QState::_ZTV6QState) + 16u) + QAbstractState (0x0x7f66e12cc820) 0 + primary-for QState (0x0x7f66e12cc7b8) + QObject (0x0x7f66e0ef4de0) 0 + primary-for QAbstractState (0x0x7f66e12cc820) + +Class QStateMachine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStateMachine::QPrivateSignal (0x0x7f66e0ef4f60) 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 (0x0x7f66e12cc9c0) 0 + vptr=((& QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE) + 16u) + QEvent (0x0x7f66e1041000) 0 + primary-for QStateMachine::SignalEvent (0x0x7f66e12cc9c0) + +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 (0x0x7f66e12cca28) 0 + vptr=((& QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE) + 16u) + QEvent (0x0x7f66e1041060) 0 + primary-for QStateMachine::WrappedEvent (0x0x7f66e12cca28) + +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 (0x0x7f66e12cc888) 0 + vptr=((& QStateMachine::_ZTV13QStateMachine) + 16u) + QState (0x0x7f66e12cc8f0) 0 + primary-for QStateMachine (0x0x7f66e12cc888) + QAbstractState (0x0x7f66e12cc958) 0 + primary-for QState (0x0x7f66e12cc8f0) + QObject (0x0x7f66e0ef4f00) 0 + primary-for QAbstractState (0x0x7f66e12cc958) + +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 (0x0x7f66e12cca90) 0 nearly-empty + vptr=((& QException::_ZTV10QException) + 16u) + std::exception (0x0x7f66e10410c0) 0 nearly-empty + primary-for QException (0x0x7f66e12cca90) + +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 (0x0x7f66e12ccaf8) 0 nearly-empty + vptr=((& QUnhandledException::_ZTV19QUnhandledException) + 16u) + QException (0x0x7f66e12ccb60) 0 nearly-empty + primary-for QUnhandledException (0x0x7f66e12ccaf8) + std::exception (0x0x7f66e1041120) 0 nearly-empty + primary-for QException (0x0x7f66e12ccb60) + +Class QtPrivate::ExceptionHolder + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionHolder (0x0x7f66e1041180) 0 + +Class QtPrivate::ExceptionStore + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionStore (0x0x7f66e1041240) 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 (0x0x7f66e10412a0) 0 + vptr=((& QRunnable::_ZTV9QRunnable) + 16u) + +Class QBasicMutex + size=8 align=8 + base size=8 base align=8 +QBasicMutex (0x0x7f66e1041300) 0 + +Class QMutex + size=8 align=8 + base size=8 base align=8 +QMutex (0x0x7f66e12ccd00) 0 + QBasicMutex (0x0x7f66e1041420) 0 + +Class QMutexLocker + size=8 align=8 + base size=8 base align=8 +QMutexLocker (0x0x7f66e1041480) 0 + +Class QtPrivate::ResultItem + size=16 align=8 + base size=16 base align=8 +QtPrivate::ResultItem (0x0x7f66e10414e0) 0 + +Class QtPrivate::ResultIteratorBase + size=16 align=8 + base size=12 base align=8 +QtPrivate::ResultIteratorBase (0x0x7f66e1041540) 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 (0x0x7f66e10416c0) 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 (0x0x7f66e1041780) 0 + vptr=((& QFutureInterfaceBase::_ZTV20QFutureInterfaceBase) + 16u) + +Class QFutureWatcherBase::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFutureWatcherBase::QPrivateSignal (0x0x7f66e1041ae0) 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 (0x0x7f66e0cea618) 0 + vptr=((& QFutureWatcherBase::_ZTV18QFutureWatcherBase) + 16u) + QObject (0x0x7f66e1041a80) 0 + primary-for QFutureWatcherBase (0x0x7f66e0cea618) + +Class QReadWriteLock + size=8 align=8 + base size=8 base align=8 +QReadWriteLock (0x0x7f66e1041c00) 0 + +Class QReadLocker + size=8 align=8 + base size=8 base align=8 +QReadLocker (0x0x7f66e1041c60) 0 + +Class QWriteLocker + size=8 align=8 + base size=8 base align=8 +QWriteLocker (0x0x7f66e1041d20) 0 + +Class QSemaphore + size=8 align=8 + base size=8 base align=8 +QSemaphore (0x0x7f66e1041de0) 0 + +Class QThread::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThread::QPrivateSignal (0x0x7f66e1041ea0) 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 (0x0x7f66e0cea9c0) 0 + vptr=((& QThread::_ZTV7QThread) + 16u) + QObject (0x0x7f66e1041e40) 0 + primary-for QThread (0x0x7f66e0cea9c0) + +Class QThreadPool::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThreadPool::QPrivateSignal (0x0x7f66e1041f60) 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 (0x0x7f66e0ceaa28) 0 + vptr=((& QThreadPool::_ZTV11QThreadPool) + 16u) + QObject (0x0x7f66e1041f00) 0 + primary-for QThreadPool (0x0x7f66e0ceaa28) + +Class QThreadStorageData + size=4 align=4 + base size=4 base align=4 +QThreadStorageData (0x0x7f66e0dfa000) 0 + +Class QWaitCondition + size=8 align=8 + base size=8 base align=8 +QWaitCondition (0x0x7f66e0dfa0c0) 0 + +Class QBitArray + size=8 align=8 + base size=8 base align=8 +QBitArray (0x0x7f66e0e377e0) 0 + +Class QBitRef + size=16 align=8 + base size=12 base align=8 +QBitRef (0x0x7f66e0e37840) 0 + +Class QByteArrayMatcher::Data + size=272 align=8 + base size=272 base align=8 +QByteArrayMatcher::Data (0x0x7f66e0e37960) 0 + +Class QByteArrayMatcher + size=1040 align=8 + base size=1040 base align=8 +QByteArrayMatcher (0x0x7f66e0e37900) 0 + +Class QCollatorSortKey + size=8 align=8 + base size=8 base align=8 +QCollatorSortKey (0x0x7f66e0e37ae0) 0 + +Class QCollator + size=8 align=8 + base size=8 base align=8 +QCollator (0x0x7f66e0e37ba0) 0 + +Class QCommandLineOption + size=8 align=8 + base size=8 base align=8 +QCommandLineOption (0x0x7f66e0e37cc0) 0 + +Class QCommandLineParser + size=8 align=8 + base size=8 base align=8 +QCommandLineParser (0x0x7f66e0e37de0) 0 + +Class QCryptographicHash + size=8 align=8 + base size=8 base align=8 +QCryptographicHash (0x0x7f66e0e37e40) 0 + +Class QElapsedTimer + size=16 align=8 + base size=16 base align=8 +QElapsedTimer (0x0x7f66e0e37ea0) 0 + +Class QPoint + size=8 align=4 + base size=8 base align=4 +QPoint (0x0x7f66e0e37f00) 0 + +Class QPointF + size=16 align=8 + base size=16 base align=8 +QPointF (0x0x7f66e0b68000) 0 + +Class QLine + size=16 align=4 + base size=16 base align=4 +QLine (0x0x7f66e0b680c0) 0 + +Class QLineF + size=32 align=8 + base size=32 base align=8 +QLineF (0x0x7f66e0b68180) 0 + +Class QLinkedListData + size=32 align=8 + base size=32 base align=8 +QLinkedListData (0x0x7f66e0b68240) 0 + +Class QSize + size=8 align=4 + base size=8 base align=4 +QSize (0x0x7f66e0b685a0) 0 + +Class QSizeF + size=16 align=8 + base size=16 base align=8 +QSizeF (0x0x7f66e0b68660) 0 + +Class QRect + size=16 align=4 + base size=16 base align=4 +QRect (0x0x7f66e0b68720) 0 + +Class QRectF + size=32 align=8 + base size=32 base align=8 +QRectF (0x0x7f66e0b687e0) 0 + +Class QMargins + size=16 align=4 + base size=16 base align=4 +QMargins (0x0x7f66e0b688a0) 0 + +Class QMessageAuthenticationCode + size=8 align=8 + base size=8 base align=8 +QMessageAuthenticationCode (0x0x7f66e0b68960) 0 + +Class QRegularExpression + size=8 align=8 + base size=8 base align=8 +QRegularExpression (0x0x7f66e0b68a20) 0 + +Class QRegularExpressionMatch + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatch (0x0x7f66e0b68cc0) 0 + +Class QRegularExpressionMatchIterator + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatchIterator (0x0x7f66e0b68de0) 0 + +Class QAbstractConcatenable + size=1 align=1 + base size=0 base align=1 +QAbstractConcatenable (0x0x7f66e0a99000) 0 empty + +Class QTextBoundaryFinder + size=48 align=8 + base size=48 base align=8 +QTextBoundaryFinder (0x0x7f66e0a99a20) 0 + +Class QTimeLine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimeLine::QPrivateSignal (0x0x7f66e0a99ba0) 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 (0x0x7f66e09ffbc8) 0 + vptr=((& QTimeLine::_ZTV9QTimeLine) + 16u) + QObject (0x0x7f66e0a99b40) 0 + primary-for QTimeLine (0x0x7f66e09ffbc8) + +Class QTimeZone::OffsetData + size=32 align=8 + base size=28 base align=8 +QTimeZone::OffsetData (0x0x7f66e0a99c60) 0 + +Class QTimeZone + size=8 align=8 + base size=8 base align=8 +QTimeZone (0x0x7f66e0a99c00) 0 + +Class QXmlStreamStringRef + size=16 align=8 + base size=16 base align=8 +QXmlStreamStringRef (0x0x7f66e0a99de0) 0 + +Class QXmlStreamAttribute + size=80 align=8 + base size=73 base align=8 +QXmlStreamAttribute (0x0x7f66e0a99e40) 0 + +Class QXmlStreamAttributes + size=8 align=8 + base size=8 base align=8 +QXmlStreamAttributes (0x0x7f66e09ffd00) 0 + QVector (0x0x7f66e07b9000) 0 + +Class QXmlStreamNamespaceDeclaration + size=40 align=8 + base size=40 base align=8 +QXmlStreamNamespaceDeclaration (0x0x7f66e07b9060) 0 + +Class QXmlStreamNotationDeclaration + size=56 align=8 + base size=56 base align=8 +QXmlStreamNotationDeclaration (0x0x7f66e07b9120) 0 + +Class QXmlStreamEntityDeclaration + size=88 align=8 + base size=88 base align=8 +QXmlStreamEntityDeclaration (0x0x7f66e07b91e0) 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 (0x0x7f66e07b92a0) 0 nearly-empty + vptr=((& QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver) + 16u) + +Class QXmlStreamReader + size=8 align=8 + base size=8 base align=8 +QXmlStreamReader (0x0x7f66e07b9300) 0 + +Class QXmlStreamWriter + size=8 align=8 + base size=8 base align=8 +QXmlStreamWriter (0x0x7f66e07b9420) 0 + +Class QNdefRecord + size=8 align=8 + base size=8 base align=8 +QNdefRecord (0x0x7f66e07b9540) 0 + +Class QNdefFilter::Record + size=24 align=8 + base size=24 base align=8 +QNdefFilter::Record (0x0x7f66e07b9660) 0 + +Class QNdefFilter + size=8 align=8 + base size=8 base align=8 +QNdefFilter (0x0x7f66e07b9600) 0 + +Class QNdefMessage + size=8 align=8 + base size=8 base align=8 +QNdefMessage (0x0x7f66e09ffd68) 0 + QList (0x0x7f66e07b97e0) 0 + +Class QNdefNfcTextRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcTextRecord (0x0x7f66e09ffdd0) 0 + QNdefRecord (0x0x7f66e07b9960) 0 + +Class QNdefNfcUriRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcUriRecord (0x0x7f66e09ffe38) 0 + QNdefRecord (0x0x7f66e07b99c0) 0 + +Class QNdefNfcIconRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcIconRecord (0x0x7f66e09ffea0) 0 + QNdefRecord (0x0x7f66e07b9a20) 0 + +Class QNdefNfcSmartPosterRecord + size=16 align=8 + base size=16 base align=8 +QNdefNfcSmartPosterRecord (0x0x7f66e09fff08) 0 + QNdefRecord (0x0x7f66e07b9a80) 0 + +Class QNearFieldTarget::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldTarget::QPrivateSignal (0x0x7f66e07b9ba0) 0 empty + +Class QNearFieldTarget::RequestId + size=8 align=8 + base size=8 base align=8 +QNearFieldTarget::RequestId (0x0x7f66e07b9c00) 0 + +Vtable for QNearFieldTarget +QNearFieldTarget::_ZTV16QNearFieldTarget: 25u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QNearFieldTarget) +16 (int (*)(...))QNearFieldTarget::metaObject +24 (int (*)(...))QNearFieldTarget::qt_metacast +32 (int (*)(...))QNearFieldTarget::qt_metacall +40 (int (*)(...))QNearFieldTarget::~QNearFieldTarget +48 (int (*)(...))QNearFieldTarget::~QNearFieldTarget +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 (*)(...))QNearFieldTarget::url +128 (int (*)(...))__cxa_pure_virtual +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))QNearFieldTarget::hasNdefMessage +152 (int (*)(...))QNearFieldTarget::readNdefMessages +160 (int (*)(...))QNearFieldTarget::writeNdefMessages +168 (int (*)(...))QNearFieldTarget::sendCommand +176 (int (*)(...))QNearFieldTarget::sendCommands +184 (int (*)(...))QNearFieldTarget::waitForRequestCompleted +192 (int (*)(...))QNearFieldTarget::handleResponse + +Class QNearFieldTarget + size=24 align=8 + base size=24 base align=8 +QNearFieldTarget (0x0x7f66e09fff70) 0 + vptr=((& QNearFieldTarget::_ZTV16QNearFieldTarget) + 16u) + QObject (0x0x7f66e07b9b40) 0 + primary-for QNearFieldTarget (0x0x7f66e09fff70) + +Class QNearFieldManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldManager::QPrivateSignal (0x0x7f66e051e060) 0 empty + +Vtable for QNearFieldManager +QNearFieldManager::_ZTV17QNearFieldManager: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QNearFieldManager) +16 (int (*)(...))QNearFieldManager::metaObject +24 (int (*)(...))QNearFieldManager::qt_metacast +32 (int (*)(...))QNearFieldManager::qt_metacall +40 (int (*)(...))QNearFieldManager::~QNearFieldManager +48 (int (*)(...))QNearFieldManager::~QNearFieldManager +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 QNearFieldManager + size=24 align=8 + base size=24 base align=8 +QNearFieldManager (0x0x7f66e04fb0d0) 0 + vptr=((& QNearFieldManager::_ZTV17QNearFieldManager) + 16u) + QObject (0x0x7f66e051e000) 0 + primary-for QNearFieldManager (0x0x7f66e04fb0d0) + +Class QQmlNdefRecord::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QQmlNdefRecord::QPrivateSignal (0x0x7f66e051e1e0) 0 empty + +Vtable for QQmlNdefRecord +QQmlNdefRecord::_ZTV14QQmlNdefRecord: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI14QQmlNdefRecord) +16 (int (*)(...))QQmlNdefRecord::metaObject +24 (int (*)(...))QQmlNdefRecord::qt_metacast +32 (int (*)(...))QQmlNdefRecord::qt_metacall +40 (int (*)(...))QQmlNdefRecord::~QQmlNdefRecord +48 (int (*)(...))QQmlNdefRecord::~QQmlNdefRecord +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 QQmlNdefRecord + size=24 align=8 + base size=24 base align=8 +QQmlNdefRecord (0x0x7f66e04fb270) 0 + vptr=((& QQmlNdefRecord::_ZTV14QQmlNdefRecord) + 16u) + QObject (0x0x7f66e051e180) 0 + primary-for QQmlNdefRecord (0x0x7f66e04fb270) + diff --git a/tests/auto/bic/data/QtNfc.5.3.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtNfc.5.3.0.linux-gcc-amd64.txt new file mode 100644 index 0000000..54223b9 --- /dev/null +++ b/tests/auto/bic/data/QtNfc.5.3.0.linux-gcc-amd64.txt @@ -0,0 +1,3814 @@ +Class std::__true_type + size=1 align=1 + base size=0 base align=1 +std::__true_type (0x0x7f0268081f00) 0 empty + +Class std::__false_type + size=1 align=1 + base size=0 base align=1 +std::__false_type (0x0x7f0268081f60) 0 empty + +Class std::input_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::input_iterator_tag (0x0x7f026701ab40) 0 empty + +Class std::output_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::output_iterator_tag (0x0x7f026701aba0) 0 empty + +Class std::forward_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::forward_iterator_tag (0x0x7f0266faf5b0) 0 empty + std::input_iterator_tag (0x0x7f026701ac00) 0 empty + +Class std::bidirectional_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::bidirectional_iterator_tag (0x0x7f0266faf618) 0 empty + std::forward_iterator_tag (0x0x7f0266faf680) 0 empty + std::input_iterator_tag (0x0x7f026701ac60) 0 empty + +Class std::random_access_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::random_access_iterator_tag (0x0x7f0266faf6e8) 0 empty + std::bidirectional_iterator_tag (0x0x7f0266faf750) 0 empty + std::forward_iterator_tag (0x0x7f0266faf7b8) 0 empty + std::input_iterator_tag (0x0x7f026701acc0) 0 empty + +Class wait + size=4 align=4 + base size=4 base align=4 +wait (0x0x7f0267072840) 0 + +Class __locale_struct + size=232 align=8 + base size=232 base align=8 +__locale_struct (0x0x7f0267072a80) 0 + +Class timespec + size=16 align=8 + base size=16 base align=8 +timespec (0x0x7f0267072b40) 0 + +Class timeval + size=16 align=8 + base size=16 base align=8 +timeval (0x0x7f0267072ba0) 0 + +Class pthread_attr_t + size=56 align=8 + base size=56 base align=8 +pthread_attr_t (0x0x7f0267072c60) 0 + +Class __pthread_internal_list + size=16 align=8 + base size=16 base align=8 +__pthread_internal_list (0x0x7f0267072cc0) 0 + +Class random_data + size=48 align=8 + base size=48 base align=8 +random_data (0x0x7f0267134180) 0 + +Class drand48_data + size=24 align=8 + base size=24 base align=8 +drand48_data (0x0x7f02671341e0) 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 (0x0x7f0267134240) 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 (0x0x7f0266fafaf8) 0 nearly-empty + vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16u) + std::exception (0x0x7f02671342a0) 0 nearly-empty + primary-for std::bad_exception (0x0x7f0266fafaf8) + +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 (0x0x7f0266fafb60) 0 nearly-empty + vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16u) + std::exception (0x0x7f0267134300) 0 nearly-empty + primary-for std::bad_alloc (0x0x7f0266fafb60) + +Class std::nothrow_t + size=1 align=1 + base size=0 base align=1 +std::nothrow_t (0x0x7f0267134360) 0 empty + +Class qIsNull(double)::U + size=8 align=8 + base size=8 base align=8 +qIsNull(double)::U (0x0x7f0265f3c6c0) 0 + +Class qIsNull(float)::U + size=4 align=4 + base size=4 base align=4 +qIsNull(float)::U (0x0x7f0265f3c720) 0 + +Class QtPrivate::big_ + size=2 align=1 + base size=2 base align=1 +QtPrivate::big_ (0x0x7f0265f3c900) 0 + +Class QSysInfo + size=1 align=1 + base size=0 base align=1 +QSysInfo (0x0x7f0265ca2060) 0 empty + +Class QMessageLogContext + size=32 align=8 + base size=32 base align=8 +QMessageLogContext (0x0x7f0265ca20c0) 0 + +Class QMessageLogger + size=32 align=8 + base size=32 base align=8 +QMessageLogger (0x0x7f0265ca2120) 0 + +Class QFlag + size=4 align=4 + base size=4 base align=4 +QFlag (0x0x7f0265ca2180) 0 + +Class QIncompatibleFlag + size=4 align=4 + base size=4 base align=4 +QIncompatibleFlag (0x0x7f0265ca22a0) 0 + +Class QAtomicInt + size=4 align=4 + base size=4 base align=4 +QAtomicInt (0x0x7f0265ac9138) 0 + QAtomicInteger (0x0x7f0265ac91a0) 0 + QBasicAtomicInteger (0x0x7f0265ca2d80) 0 + +Class QInternal + size=1 align=1 + base size=0 base align=1 +QInternal (0x0x7f026577eea0) 0 empty + +Class QGenericArgument + size=16 align=8 + base size=16 base align=8 +QGenericArgument (0x0x7f0265929de0) 0 + +Class QGenericReturnArgument + size=16 align=8 + base size=16 base align=8 +QGenericReturnArgument (0x0x7f026588a2d8) 0 + QGenericArgument (0x0x7f0265929e40) 0 + +Class QMetaObject + size=48 align=8 + base size=48 base align=8 +QMetaObject (0x0x7f026558e000) 0 + +Class QMetaObject::Connection + size=8 align=8 + base size=8 base align=8 +QMetaObject::Connection (0x0x7f026558e120) 0 + +Class QLatin1Char + size=1 align=1 + base size=1 base align=1 +QLatin1Char (0x0x7f026558e360) 0 + +Class QChar + size=2 align=2 + base size=2 base align=2 +QChar (0x0x7f026558e3c0) 0 + +Class QtPrivate::RefCount + size=4 align=4 + base size=4 base align=4 +QtPrivate::RefCount (0x0x7f026558e4e0) 0 + +Class QArrayData + size=24 align=8 + base size=24 base align=8 +QArrayData (0x0x7f026558e540) 0 + +Class QByteArrayDataPtr + size=8 align=8 + base size=8 base align=8 +QByteArrayDataPtr (0x0x7f026558e8a0) 0 + +Class QByteArray + size=8 align=8 + base size=8 base align=8 +QByteArray (0x0x7f026558e900) 0 + +Class QByteRef + size=16 align=8 + base size=12 base align=8 +QByteRef (0x0x7f026558ea80) 0 + +Class lconv + size=96 align=8 + base size=96 base align=8 +lconv (0x0x7f026558eea0) 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 (0x0x7f026558ef00) 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 (0x0x7f026548b9c0) 0 + +Class __sched_param + size=4 align=4 + base size=4 base align=4 +__sched_param (0x0x7f026548ba20) 0 + +Class timex + size=208 align=8 + base size=208 base align=8 +timex (0x0x7f026548bae0) 0 + +Class tm + size=56 align=8 + base size=56 base align=8 +tm (0x0x7f026548bb40) 0 + +Class itimerspec + size=32 align=8 + base size=32 base align=8 +itimerspec (0x0x7f026548bba0) 0 + +Class _pthread_cleanup_buffer + size=32 align=8 + base size=32 base align=8 +_pthread_cleanup_buffer (0x0x7f026548bc00) 0 + +Class __pthread_cleanup_frame + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_frame (0x0x7f026548bd20) 0 + +Class __pthread_cleanup_class + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_class (0x0x7f026548bd80) 0 + +Class QLatin1String + size=16 align=8 + base size=16 base align=8 +QLatin1String (0x0x7f02651934e0) 0 + +Class QStringDataPtr + size=8 align=8 + base size=8 base align=8 +QStringDataPtr (0x0x7f0265193660) 0 + +Class QString::Null + size=1 align=1 + base size=0 base align=1 +QString::Null (0x0x7f0265193720) 0 empty + +Class QString + size=8 align=8 + base size=8 base align=8 +QString (0x0x7f02651936c0) 0 + +Class QCharRef + size=16 align=8 + base size=12 base align=8 +QCharRef (0x0x7f02651938a0) 0 + +Class QStringRef + size=16 align=8 + base size=16 base align=8 +QStringRef (0x0x7f0265193b40) 0 + +Class std::locale + size=8 align=8 + base size=8 base align=8 +std::locale (0x0x7f0265193d20) 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 (0x0x7f0265193d80) 0 + vptr=((& std::locale::facet::_ZTVNSt6locale5facetE) + 16u) + +Class std::locale::id + size=8 align=8 + base size=8 base align=8 +std::locale::id (0x0x7f0265193de0) 0 + +Class std::locale::_Impl + size=40 align=8 + base size=40 base align=8 +std::locale::_Impl (0x0x7f0265193e40) 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 (0x0x7f026531ebc8) 0 + vptr=((& std::ios_base::failure::_ZTVNSt8ios_base7failureE) + 16u) + std::exception (0x0x7f0264e542a0) 0 nearly-empty + primary-for std::ios_base::failure (0x0x7f026531ebc8) + +Class std::ios_base::_Callback_list + size=24 align=8 + base size=24 base align=8 +std::ios_base::_Callback_list (0x0x7f0264e54300) 0 + +Class std::ios_base::_Words + size=16 align=8 + base size=16 base align=8 +std::ios_base::_Words (0x0x7f0264e54360) 0 + +Class std::ios_base::Init + size=1 align=1 + base size=0 base align=1 +std::ios_base::Init (0x0x7f0264e543c0) 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 (0x0x7f0264e54240) 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 (0x0x7f0264e54540) 0 empty + +Class std::__num_base + size=1 align=1 + base size=0 base align=1 +std::__num_base (0x0x7f0264e54c00) 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 (0x0x7f0264ab26e8 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 (0x0x7f0264ab27b8 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 (0x0x7f0264ab2a90 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 (0x0x7f0264ab2b60 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 (0x0x7f0264b3c000) 0 + +Class QListData::Data + size=24 align=8 + base size=24 base align=8 +QListData::Data (0x0x7f0264b3c300) 0 + +Class QListData + size=8 align=8 + base size=8 base align=8 +QListData (0x0x7f0264b3c2a0) 0 + +Class QScopedPointerPodDeleter + size=1 align=1 + base size=0 base align=1 +QScopedPointerPodDeleter (0x0x7f0264b3c6c0) 0 empty + +Class std::_Bit_reference + size=16 align=8 + base size=16 base align=8 +std::_Bit_reference (0x0x7f026492e420) 0 + +Class std::_Bit_iterator_base + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator_base (0x0x7f0264ab29c0) 0 + std::iterator (0x0x7f026492e4e0) 0 empty + +Class std::_Bit_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator (0x0x7f0264ab2c98) 0 + std::_Bit_iterator_base (0x0x7f0264ab2d00) 0 + std::iterator (0x0x7f026492e540) 0 empty + +Class std::_Bit_const_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_const_iterator (0x0x7f0264ab2d68) 0 + std::_Bit_iterator_base (0x0x7f02645f2000) 0 + std::iterator (0x0x7f026492e5a0) 0 empty + +Class std::_Rb_tree_node_base + size=32 align=8 + base size=32 base align=8 +std::_Rb_tree_node_base (0x0x7f026492e960) 0 + +Class QtPrivate::AbstractDebugStreamFunction + size=16 align=8 + base size=16 base align=8 +QtPrivate::AbstractDebugStreamFunction (0x0x7f026492ed80) 0 + +Class QtPrivate::AbstractComparatorFunction + size=24 align=8 + base size=24 base align=8 +QtPrivate::AbstractComparatorFunction (0x0x7f026492ee40) 0 + +Class QtPrivate::AbstractConverterFunction + size=8 align=8 + base size=8 base align=8 +QtPrivate::AbstractConverterFunction (0x0x7f026492ef00) 0 + +Class QMetaType + size=80 align=8 + base size=80 base align=8 +QMetaType (0x0x7f026440c360) 0 + +Class QtMetaTypePrivate::VariantData + size=24 align=8 + base size=20 base align=8 +QtMetaTypePrivate::VariantData (0x0x7f026440c6c0) 0 + +Class QtMetaTypePrivate::QSequentialIterableImpl + size=104 align=8 + base size=104 base align=8 +QtMetaTypePrivate::QSequentialIterableImpl (0x0x7f026440cae0) 0 + +Class QtMetaTypePrivate::QAssociativeIterableImpl + size=112 align=8 + base size=112 base align=8 +QtMetaTypePrivate::QAssociativeIterableImpl (0x0x7f026440ccc0) 0 + +Class QtMetaTypePrivate::QPairVariantInterfaceImpl + size=40 align=8 + base size=40 base align=8 +QtMetaTypePrivate::QPairVariantInterfaceImpl (0x0x7f026440cd80) 0 + +Class QtPrivate::QSlotObjectBase + size=16 align=8 + base size=16 base align=8 +QtPrivate::QSlotObjectBase (0x0x7f026427d060) 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 (0x0x7f026427d1e0) 0 + vptr=((& QObjectData::_ZTV11QObjectData) + 16u) + +Class QObject::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObject::QPrivateSignal (0x0x7f026427d360) 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 (0x0x7f026427d300) 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 (0x0x7f026427d660) 0 nearly-empty + vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16u) + +Class QSignalBlocker + size=16 align=8 + base size=10 base align=8 +QSignalBlocker (0x0x7f026427d6c0) 0 + +Class QAbstractAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractAnimation::QPrivateSignal (0x0x7f026427d780) 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 (0x0x7f0264501b60) 0 + vptr=((& QAbstractAnimation::_ZTV18QAbstractAnimation) + 16u) + QObject (0x0x7f026427d720) 0 + primary-for QAbstractAnimation (0x0x7f0264501b60) + +Class QAnimationDriver::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationDriver::QPrivateSignal (0x0x7f026427d840) 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 (0x0x7f0264501bc8) 0 + vptr=((& QAnimationDriver::_ZTV16QAnimationDriver) + 16u) + QObject (0x0x7f026427d7e0) 0 + primary-for QAnimationDriver (0x0x7f0264501bc8) + +Class QAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationGroup::QPrivateSignal (0x0x7f026427d900) 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 (0x0x7f0264501c30) 0 + vptr=((& QAnimationGroup::_ZTV15QAnimationGroup) + 16u) + QAbstractAnimation (0x0x7f0264501c98) 0 + primary-for QAnimationGroup (0x0x7f0264501c30) + QObject (0x0x7f026427d8a0) 0 + primary-for QAbstractAnimation (0x0x7f0264501c98) + +Class QParallelAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QParallelAnimationGroup::QPrivateSignal (0x0x7f026427d9c0) 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 (0x0x7f0264501d00) 0 + vptr=((& QParallelAnimationGroup::_ZTV23QParallelAnimationGroup) + 16u) + QAnimationGroup (0x0x7f0264501d68) 0 + primary-for QParallelAnimationGroup (0x0x7f0264501d00) + QAbstractAnimation (0x0x7f0264501dd0) 0 + primary-for QAnimationGroup (0x0x7f0264501d68) + QObject (0x0x7f026427d960) 0 + primary-for QAbstractAnimation (0x0x7f0264501dd0) + +Class QPauseAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPauseAnimation::QPrivateSignal (0x0x7f026427da80) 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 (0x0x7f0264501e38) 0 + vptr=((& QPauseAnimation::_ZTV15QPauseAnimation) + 16u) + QAbstractAnimation (0x0x7f0264501ea0) 0 + primary-for QPauseAnimation (0x0x7f0264501e38) + QObject (0x0x7f026427da20) 0 + primary-for QAbstractAnimation (0x0x7f0264501ea0) + +Class QEasingCurve + size=8 align=8 + base size=8 base align=8 +QEasingCurve (0x0x7f026427dc60) 0 + +Class QMapNodeBase + size=24 align=8 + base size=24 base align=8 +QMapNodeBase (0x0x7f026427de40) 0 + +Class QMapDataBase + size=40 align=8 + base size=40 base align=8 +QMapDataBase (0x0x7f026427df00) 0 + +Class QHashData::Node + size=16 align=8 + base size=16 base align=8 +QHashData::Node (0x0x7f02640ad2a0) 0 + +Class QHashData + size=48 align=8 + base size=48 base align=8 +QHashData (0x0x7f02640ad240) 0 + +Class QHashDummyValue + size=1 align=1 + base size=0 base align=1 +QHashDummyValue (0x0x7f02640ad300) 0 empty + +Class QIODevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIODevice::QPrivateSignal (0x0x7f02640ad7e0) 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 (0x0x7f026400a7b8) 0 + vptr=((& QIODevice::_ZTV9QIODevice) + 16u) + QObject (0x0x7f02640ad780) 0 + primary-for QIODevice (0x0x7f026400a7b8) + +Class QDataStream + size=32 align=8 + base size=32 base align=8 +QDataStream (0x0x7f02640ad900) 0 + +Class QRegExp + size=8 align=8 + base size=8 base align=8 +QRegExp (0x0x7f02640ad9c0) 0 + +Class QStringMatcher::Data + size=272 align=8 + base size=272 base align=8 +QStringMatcher::Data (0x0x7f02640adb40) 0 + +Class QStringMatcher + size=1048 align=8 + base size=1048 base align=8 +QStringMatcher (0x0x7f02640adae0) 0 + +Class QStringList + size=8 align=8 + base size=8 base align=8 +QStringList (0x0x7f026400a958) 0 + QList (0x0x7f02640adcc0) 0 + +Class QVariant::PrivateShared + size=16 align=8 + base size=12 base align=8 +QVariant::PrivateShared (0x0x7f0263b88000) 0 + +Class QVariant::Private::Data + size=8 align=8 + base size=8 base align=8 +QVariant::Private::Data (0x0x7f0263b880c0) 0 + +Class QVariant::Private + size=16 align=8 + base size=12 base align=8 +QVariant::Private (0x0x7f0263b88060) 0 + +Class QVariant::Handler + size=72 align=8 + base size=72 base align=8 +QVariant::Handler (0x0x7f0263b88120) 0 + +Class QVariant + size=16 align=8 + base size=16 base align=8 +QVariant (0x0x7f02640adf60) 0 + +Class QVariantComparisonHelper + size=8 align=8 + base size=8 base align=8 +QVariantComparisonHelper (0x0x7f0263b883c0) 0 + +Class QSequentialIterable::const_iterator + size=112 align=8 + base size=112 base align=8 +QSequentialIterable::const_iterator (0x0x7f0263b88480) 0 + +Class QSequentialIterable + size=104 align=8 + base size=104 base align=8 +QSequentialIterable (0x0x7f0263b88420) 0 + +Class QAssociativeIterable::const_iterator + size=120 align=8 + base size=120 base align=8 +QAssociativeIterable::const_iterator (0x0x7f0263b88540) 0 + +Class QAssociativeIterable + size=112 align=8 + base size=112 base align=8 +QAssociativeIterable (0x0x7f0263b884e0) 0 + +Class QVariantAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QVariantAnimation::QPrivateSignal (0x0x7f0263c9c120) 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 (0x0x7f0263c7c340) 0 + vptr=((& QVariantAnimation::_ZTV17QVariantAnimation) + 16u) + QAbstractAnimation (0x0x7f0263c7c3a8) 0 + primary-for QVariantAnimation (0x0x7f0263c7c340) + QObject (0x0x7f0263c9c0c0) 0 + primary-for QAbstractAnimation (0x0x7f0263c7c3a8) + +Class QPropertyAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPropertyAnimation::QPrivateSignal (0x0x7f0263c9c1e0) 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 (0x0x7f0263c7c478) 0 + vptr=((& QPropertyAnimation::_ZTV18QPropertyAnimation) + 16u) + QVariantAnimation (0x0x7f0263c7c4e0) 0 + primary-for QPropertyAnimation (0x0x7f0263c7c478) + QAbstractAnimation (0x0x7f0263c7c548) 0 + primary-for QVariantAnimation (0x0x7f0263c7c4e0) + QObject (0x0x7f0263c9c180) 0 + primary-for QAbstractAnimation (0x0x7f0263c7c548) + +Class QSequentialAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSequentialAnimationGroup::QPrivateSignal (0x0x7f0263c9c2a0) 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 (0x0x7f0263c7c5b0) 0 + vptr=((& QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup) + 16u) + QAnimationGroup (0x0x7f0263c7c618) 0 + primary-for QSequentialAnimationGroup (0x0x7f0263c7c5b0) + QAbstractAnimation (0x0x7f0263c7c680) 0 + primary-for QAnimationGroup (0x0x7f0263c7c618) + QObject (0x0x7f0263c9c240) 0 + primary-for QAbstractAnimation (0x0x7f0263c7c680) + +Class QTextCodec::ConverterState + size=32 align=8 + base size=32 base align=8 +QTextCodec::ConverterState (0x0x7f0263c9c360) 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 (0x0x7f0263c9c300) 0 nearly-empty + vptr=((& QTextCodec::_ZTV10QTextCodec) + 16u) + +Class QTextEncoder + size=40 align=8 + base size=40 base align=8 +QTextEncoder (0x0x7f0263c9c480) 0 + +Class QTextDecoder + size=40 align=8 + base size=40 base align=8 +QTextDecoder (0x0x7f0263c9c4e0) 0 + +Class QSharedData + size=4 align=4 + base size=4 base align=4 +QSharedData (0x0x7f0263c9c540) 0 + +Class QtSharedPointer::NormalDeleter + size=1 align=1 + base size=0 base align=1 +QtSharedPointer::NormalDeleter (0x0x7f0263c9c7e0) 0 empty + +Class QtSharedPointer::ExternalRefCountData + size=16 align=8 + base size=16 base align=8 +QtSharedPointer::ExternalRefCountData (0x0x7f0263c9c960) 0 + +Class std::__numeric_limits_base + size=1 align=1 + base size=0 base align=1 +std::__numeric_limits_base (0x0x7f0263c9cde0) 0 empty + +Class QDate + size=8 align=8 + base size=8 base align=8 +QDate (0x0x7f0263a575a0) 0 + +Class QTime + size=4 align=4 + base size=4 base align=4 +QTime (0x0x7f0263a576c0) 0 + +Class QDateTime + size=8 align=8 + base size=8 base align=8 +QDateTime (0x0x7f0263a577e0) 0 + +Class QLibraryInfo + size=1 align=1 + base size=0 base align=1 +QLibraryInfo (0x0x7f0263a57960) 0 empty + +Class QBuffer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBuffer::QPrivateSignal (0x0x7f0263a57a20) 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 (0x0x7f0263c7cc98) 0 + vptr=((& QBuffer::_ZTV7QBuffer) + 16u) + QIODevice (0x0x7f0263c7cd00) 0 + primary-for QBuffer (0x0x7f0263c7cc98) + QObject (0x0x7f0263a579c0) 0 + primary-for QIODevice (0x0x7f0263c7cd00) + +Class QLocale + size=8 align=8 + base size=8 base align=8 +QLocale (0x0x7f0263a57a80) 0 + +Class _IO_marker + size=24 align=8 + base size=24 base align=8 +_IO_marker (0x0x7f0263a57d80) 0 + +Class _IO_FILE + size=216 align=8 + base size=216 base align=8 +_IO_FILE (0x0x7f0263a57de0) 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 (0x0x7f0263a57ea0) 0 + vptr=((& QTextStream::_ZTV11QTextStream) + 16u) + +Class QTextStreamManipulator + size=40 align=8 + base size=38 base align=8 +QTextStreamManipulator (0x0x7f026382a180) 0 + +Class QContiguousCacheData + size=24 align=4 + base size=24 base align=4 +QContiguousCacheData (0x0x7f026382a3c0) 0 + +Class QDebug::Stream + size=72 align=8 + base size=72 base align=8 +QDebug::Stream (0x0x7f026382aa20) 0 + +Class QDebug + size=8 align=8 + base size=8 base align=8 +QDebug (0x0x7f026382a9c0) 0 + +Class QDebugStateSaver + size=8 align=8 + base size=8 base align=8 +QDebugStateSaver (0x0x7f026382ab40) 0 + +Class QNoDebug + size=1 align=1 + base size=0 base align=1 +QNoDebug (0x0x7f026382ac00) 0 empty + +Class QFileDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileDevice::QPrivateSignal (0x0x7f026382acc0) 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 (0x0x7f0263c7ca90) 0 + vptr=((& QFileDevice::_ZTV11QFileDevice) + 16u) + QIODevice (0x0x7f0263c7c9c0) 0 + primary-for QFileDevice (0x0x7f0263c7ca90) + QObject (0x0x7f026382ac60) 0 + primary-for QIODevice (0x0x7f0263c7c9c0) + +Class QFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFile::QPrivateSignal (0x0x7f026382ae40) 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 (0x0x7f02635ae0d0) 0 + vptr=((& QFile::_ZTV5QFile) + 16u) + QFileDevice (0x0x7f02635ae138) 0 + primary-for QFile (0x0x7f02635ae0d0) + QIODevice (0x0x7f02635ae1a0) 0 + primary-for QFileDevice (0x0x7f02635ae138) + QObject (0x0x7f026382ade0) 0 + primary-for QIODevice (0x0x7f02635ae1a0) + +Class QFileInfo + size=8 align=8 + base size=8 base align=8 +QFileInfo (0x0x7f026382af60) 0 + +Class QDir + size=8 align=8 + base size=8 base align=8 +QDir (0x0x7f02635fb240) 0 + +Class QDirIterator + size=8 align=8 + base size=8 base align=8 +QDirIterator (0x0x7f02635fb540) 0 + +Class QFileSelector::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSelector::QPrivateSignal (0x0x7f02635fb720) 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 (0x0x7f02635ae680) 0 + vptr=((& QFileSelector::_ZTV13QFileSelector) + 16u) + QObject (0x0x7f02635fb6c0) 0 + primary-for QFileSelector (0x0x7f02635ae680) + +Class QFileSystemWatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSystemWatcher::QPrivateSignal (0x0x7f02635fb7e0) 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 (0x0x7f02635ae6e8) 0 + vptr=((& QFileSystemWatcher::_ZTV18QFileSystemWatcher) + 16u) + QObject (0x0x7f02635fb780) 0 + primary-for QFileSystemWatcher (0x0x7f02635ae6e8) + +Class QLockFile + size=8 align=8 + base size=8 base align=8 +QLockFile (0x0x7f02635fb840) 0 + +Class QLoggingCategory + size=24 align=8 + base size=24 base align=8 +QLoggingCategory (0x0x7f02635fb960) 0 + +Class QProcessEnvironment + size=8 align=8 + base size=8 base align=8 +QProcessEnvironment (0x0x7f02635fb9c0) 0 + +Class QProcess::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QProcess::QPrivateSignal (0x0x7f02635fbba0) 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 (0x0x7f02635ae7b8) 0 + vptr=((& QProcess::_ZTV8QProcess) + 16u) + QIODevice (0x0x7f02635ae820) 0 + primary-for QProcess (0x0x7f02635ae7b8) + QObject (0x0x7f02635fbb40) 0 + primary-for QIODevice (0x0x7f02635ae820) + +Class QResource + size=8 align=8 + base size=8 base align=8 +QResource (0x0x7f02635fbc00) 0 + +Class QSaveFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSaveFile::QPrivateSignal (0x0x7f02635fbd80) 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 (0x0x7f02635ae888) 0 + vptr=((& QSaveFile::_ZTV9QSaveFile) + 16u) + QFileDevice (0x0x7f02635ae8f0) 0 + primary-for QSaveFile (0x0x7f02635ae888) + QIODevice (0x0x7f02635ae958) 0 + primary-for QFileDevice (0x0x7f02635ae8f0) + QObject (0x0x7f02635fbd20) 0 + primary-for QIODevice (0x0x7f02635ae958) + +Class QSettings::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSettings::QPrivateSignal (0x0x7f02635fbe40) 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 (0x0x7f02635ae9c0) 0 + vptr=((& QSettings::_ZTV9QSettings) + 16u) + QObject (0x0x7f02635fbde0) 0 + primary-for QSettings (0x0x7f02635ae9c0) + +Class QStandardPaths + size=1 align=1 + base size=0 base align=1 +QStandardPaths (0x0x7f02635fbea0) 0 empty + +Class QTemporaryDir + size=8 align=8 + base size=8 base align=8 +QTemporaryDir (0x0x7f026337e000) 0 + +Class QTemporaryFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTemporaryFile::QPrivateSignal (0x0x7f026337e120) 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 (0x0x7f02635aeaf8) 0 + vptr=((& QTemporaryFile::_ZTV14QTemporaryFile) + 16u) + QFile (0x0x7f02635aeb60) 0 + primary-for QTemporaryFile (0x0x7f02635aeaf8) + QFileDevice (0x0x7f02635aebc8) 0 + primary-for QFile (0x0x7f02635aeb60) + QIODevice (0x0x7f02635aec30) 0 + primary-for QFileDevice (0x0x7f02635aebc8) + QObject (0x0x7f026337e0c0) 0 + primary-for QIODevice (0x0x7f02635aec30) + +Class QUrl + size=8 align=8 + base size=8 base align=8 +QUrl (0x0x7f026337e240) 0 + +Class QUrlQuery + size=8 align=8 + base size=8 base align=8 +QUrlQuery (0x0x7f026337e660) 0 + +Class QModelIndex + size=24 align=8 + base size=24 base align=8 +QModelIndex (0x0x7f026337e7e0) 0 + +Class QPersistentModelIndex + size=8 align=8 + base size=8 base align=8 +QPersistentModelIndex (0x0x7f026337e900) 0 + +Class QAbstractItemModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractItemModel::QPrivateSignal (0x0x7f026337ea80) 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 (0x0x7f026348f068) 0 + vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16u) + QObject (0x0x7f026337ea20) 0 + primary-for QAbstractItemModel (0x0x7f026348f068) + +Class QAbstractTableModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTableModel::QPrivateSignal (0x0x7f026337ed80) 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 (0x0x7f026348f1a0) 0 + vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16u) + QAbstractItemModel (0x0x7f026348f208) 0 + primary-for QAbstractTableModel (0x0x7f026348f1a0) + QObject (0x0x7f026337ed20) 0 + primary-for QAbstractItemModel (0x0x7f026348f208) + +Class QAbstractListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractListModel::QPrivateSignal (0x0x7f026337ee40) 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 (0x0x7f026348f270) 0 + vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16u) + QAbstractItemModel (0x0x7f026348f2d8) 0 + primary-for QAbstractListModel (0x0x7f026348f270) + QObject (0x0x7f026337ede0) 0 + primary-for QAbstractItemModel (0x0x7f026348f2d8) + +Class QAbstractProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractProxyModel::QPrivateSignal (0x0x7f026337ef00) 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 (0x0x7f026348f340) 0 + vptr=((& QAbstractProxyModel::_ZTV19QAbstractProxyModel) + 16u) + QAbstractItemModel (0x0x7f026348f3a8) 0 + primary-for QAbstractProxyModel (0x0x7f026348f340) + QObject (0x0x7f026337eea0) 0 + primary-for QAbstractItemModel (0x0x7f026348f3a8) + +Class QIdentityProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIdentityProxyModel::QPrivateSignal (0x0x7f0263173000) 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 (0x0x7f026348f410) 0 + vptr=((& QIdentityProxyModel::_ZTV19QIdentityProxyModel) + 16u) + QAbstractProxyModel (0x0x7f026348f478) 0 + primary-for QIdentityProxyModel (0x0x7f026348f410) + QAbstractItemModel (0x0x7f026348f4e0) 0 + primary-for QAbstractProxyModel (0x0x7f026348f478) + QObject (0x0x7f026337ef60) 0 + primary-for QAbstractItemModel (0x0x7f026348f4e0) + +Class QItemSelectionRange + size=16 align=8 + base size=16 base align=8 +QItemSelectionRange (0x0x7f0263173060) 0 + +Class QItemSelectionModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QItemSelectionModel::QPrivateSignal (0x0x7f02631731e0) 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 (0x0x7f026348f5b0) 0 + vptr=((& QItemSelectionModel::_ZTV19QItemSelectionModel) + 16u) + QObject (0x0x7f0263173180) 0 + primary-for QItemSelectionModel (0x0x7f026348f5b0) + +Class QItemSelection + size=8 align=8 + base size=8 base align=8 +QItemSelection (0x0x7f026348f6e8) 0 + QList (0x0x7f02631733c0) 0 + +Class QSortFilterProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSortFilterProxyModel::QPrivateSignal (0x0x7f0263173480) 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 (0x0x7f026348f750) 0 + vptr=((& QSortFilterProxyModel::_ZTV21QSortFilterProxyModel) + 16u) + QAbstractProxyModel (0x0x7f026348f7b8) 0 + primary-for QSortFilterProxyModel (0x0x7f026348f750) + QAbstractItemModel (0x0x7f026348f820) 0 + primary-for QAbstractProxyModel (0x0x7f026348f7b8) + QObject (0x0x7f0263173420) 0 + primary-for QAbstractItemModel (0x0x7f026348f820) + +Class QStringListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStringListModel::QPrivateSignal (0x0x7f0263173540) 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 (0x0x7f026348f888) 0 + vptr=((& QStringListModel::_ZTV16QStringListModel) + 16u) + QAbstractListModel (0x0x7f026348f8f0) 0 + primary-for QStringListModel (0x0x7f026348f888) + QAbstractItemModel (0x0x7f026348f958) 0 + primary-for QAbstractListModel (0x0x7f026348f8f0) + QObject (0x0x7f02631734e0) 0 + primary-for QAbstractItemModel (0x0x7f026348f958) + +Class QJsonValue + size=24 align=8 + base size=20 base align=8 +QJsonValue (0x0x7f02631735a0) 0 + +Class QJsonValueRef + size=16 align=8 + base size=12 base align=8 +QJsonValueRef (0x0x7f0263173660) 0 + +Class QJsonArray::iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::iterator (0x0x7f0263173780) 0 + +Class QJsonArray::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::const_iterator (0x0x7f02631737e0) 0 + +Class QJsonArray + size=16 align=8 + base size=16 base align=8 +QJsonArray (0x0x7f0263173720) 0 + +Class QJsonParseError + size=8 align=4 + base size=8 base align=4 +QJsonParseError (0x0x7f0263173840) 0 + +Class QJsonDocument + size=8 align=8 + base size=8 base align=8 +QJsonDocument (0x0x7f02631738a0) 0 + +Class QJsonObject::iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::iterator (0x0x7f0263173960) 0 + +Class QJsonObject::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::const_iterator (0x0x7f02631739c0) 0 + +Class QJsonObject + size=16 align=8 + base size=16 base align=8 +QJsonObject (0x0x7f0263173900) 0 + +Class QEventLoop::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventLoop::QPrivateSignal (0x0x7f0263173ae0) 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 (0x0x7f026348f9c0) 0 + vptr=((& QEventLoop::_ZTV10QEventLoop) + 16u) + QObject (0x0x7f0263173a80) 0 + primary-for QEventLoop (0x0x7f026348f9c0) + +Class QEventLoopLocker + size=8 align=8 + base size=8 base align=8 +QEventLoopLocker (0x0x7f0263173c00) 0 + +Class QAbstractEventDispatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractEventDispatcher::QPrivateSignal (0x0x7f0263173cc0) 0 empty + +Class QAbstractEventDispatcher::TimerInfo + size=12 align=4 + base size=12 base align=4 +QAbstractEventDispatcher::TimerInfo (0x0x7f0263173d20) 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 (0x0x7f026348faf8) 0 + vptr=((& QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher) + 16u) + QObject (0x0x7f0263173c60) 0 + primary-for QAbstractEventDispatcher (0x0x7f026348faf8) + +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 (0x0x7f0263173d80) 0 + vptr=((& QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter) + 16u) + +Class QBasicTimer + size=4 align=4 + base size=4 base align=4 +QBasicTimer (0x0x7f0263173de0) 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 (0x0x7f0263173f00) 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 (0x0x7f026348fbc8) 0 + vptr=((& QTimerEvent::_ZTV11QTimerEvent) + 16u) + QEvent (0x0x7f0263173f60) 0 + primary-for QTimerEvent (0x0x7f026348fbc8) + +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 (0x0x7f026348fc30) 0 + vptr=((& QChildEvent::_ZTV11QChildEvent) + 16u) + QEvent (0x0x7f0262fa2000) 0 + primary-for QChildEvent (0x0x7f026348fc30) + +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 (0x0x7f026348fc98) 0 + vptr=((& QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent) + 16u) + QEvent (0x0x7f0262fa2060) 0 + primary-for QDynamicPropertyChangeEvent (0x0x7f026348fc98) + +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 (0x0x7f026348fd00) 0 + vptr=((& QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent) + 16u) + QEvent (0x0x7f0262fa20c0) 0 + primary-for QDeferredDeleteEvent (0x0x7f026348fd00) + +Class QCoreApplication::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QCoreApplication::QPrivateSignal (0x0x7f0262fa2180) 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 (0x0x7f026348fd68) 0 + vptr=((& QCoreApplication::_ZTV16QCoreApplication) + 16u) + QObject (0x0x7f0262fa2120) 0 + primary-for QCoreApplication (0x0x7f026348fd68) + +Class __exception + size=40 align=8 + base size=40 base align=8 +__exception (0x0x7f0262fa21e0) 0 + +Class QMetaMethod + size=16 align=8 + base size=12 base align=8 +QMetaMethod (0x0x7f0262fa2240) 0 + +Class QMetaEnum + size=16 align=8 + base size=12 base align=8 +QMetaEnum (0x0x7f0262fa2360) 0 + +Class QMetaProperty + size=32 align=8 + base size=32 base align=8 +QMetaProperty (0x0x7f0262fa2480) 0 + +Class QMetaClassInfo + size=16 align=8 + base size=12 base align=8 +QMetaClassInfo (0x0x7f0262fa24e0) 0 + +Class QMimeData::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QMimeData::QPrivateSignal (0x0x7f0262fa2660) 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 (0x0x7f0263073000) 0 + vptr=((& QMimeData::_ZTV9QMimeData) + 16u) + QObject (0x0x7f0262fa2600) 0 + primary-for QMimeData (0x0x7f0263073000) + +Class QObjectCleanupHandler::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObjectCleanupHandler::QPrivateSignal (0x0x7f0262fa2720) 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 (0x0x7f0263073068) 0 + vptr=((& QObjectCleanupHandler::_ZTV21QObjectCleanupHandler) + 16u) + QObject (0x0x7f0262fa26c0) 0 + primary-for QObjectCleanupHandler (0x0x7f0263073068) + +Class QSharedMemory::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSharedMemory::QPrivateSignal (0x0x7f0262fa2960) 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 (0x0x7f02630730d0) 0 + vptr=((& QSharedMemory::_ZTV13QSharedMemory) + 16u) + QObject (0x0x7f0262fa2900) 0 + primary-for QSharedMemory (0x0x7f02630730d0) + +Class QSignalMapper::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalMapper::QPrivateSignal (0x0x7f0262fa2a20) 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 (0x0x7f0263073138) 0 + vptr=((& QSignalMapper::_ZTV13QSignalMapper) + 16u) + QObject (0x0x7f0262fa29c0) 0 + primary-for QSignalMapper (0x0x7f0263073138) + +Class QSocketNotifier::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSocketNotifier::QPrivateSignal (0x0x7f0262fa2ae0) 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 (0x0x7f02630731a0) 0 + vptr=((& QSocketNotifier::_ZTV15QSocketNotifier) + 16u) + QObject (0x0x7f0262fa2a80) 0 + primary-for QSocketNotifier (0x0x7f02630731a0) + +Class QSystemSemaphore + size=8 align=8 + base size=8 base align=8 +QSystemSemaphore (0x0x7f0262fa2b40) 0 + +Class QTimer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimer::QPrivateSignal (0x0x7f0262fa2c60) 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 (0x0x7f0263073208) 0 + vptr=((& QTimer::_ZTV6QTimer) + 16u) + QObject (0x0x7f0262fa2c00) 0 + primary-for QTimer (0x0x7f0263073208) + +Class QTranslator::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTranslator::QPrivateSignal (0x0x7f0262fa2d80) 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 (0x0x7f0263073270) 0 + vptr=((& QTranslator::_ZTV11QTranslator) + 16u) + QObject (0x0x7f0262fa2d20) 0 + primary-for QTranslator (0x0x7f0263073270) + +Class QMimeType + size=8 align=8 + base size=8 base align=8 +QMimeType (0x0x7f0262fa2de0) 0 + +Class QMimeDatabase + size=8 align=8 + base size=8 base align=8 +QMimeDatabase (0x0x7f0262fa2f60) 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 (0x0x7f0263137000) 0 nearly-empty + vptr=((& QFactoryInterface::_ZTV17QFactoryInterface) + 16u) + +Class QLibrary::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLibrary::QPrivateSignal (0x0x7f0263137120) 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 (0x0x7f0263073340) 0 + vptr=((& QLibrary::_ZTV8QLibrary) + 16u) + QObject (0x0x7f02631370c0) 0 + primary-for QLibrary (0x0x7f0263073340) + +Class QStaticPlugin + size=16 align=8 + base size=16 base align=8 +QStaticPlugin (0x0x7f0263137240) 0 + +Class QPluginLoader::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPluginLoader::QPrivateSignal (0x0x7f02631373c0) 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 (0x0x7f02630734e0) 0 + vptr=((& QPluginLoader::_ZTV13QPluginLoader) + 16u) + QObject (0x0x7f0263137360) 0 + primary-for QPluginLoader (0x0x7f02630734e0) + +Class QUuid + size=16 align=4 + base size=16 base align=4 +QUuid (0x0x7f0263137420) 0 + +Class QAbstractState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractState::QPrivateSignal (0x0x7f02631375a0) 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 (0x0x7f02630735b0) 0 + vptr=((& QAbstractState::_ZTV14QAbstractState) + 16u) + QObject (0x0x7f0263137540) 0 + primary-for QAbstractState (0x0x7f02630735b0) + +Class QAbstractTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTransition::QPrivateSignal (0x0x7f0263137660) 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 (0x0x7f0263073618) 0 + vptr=((& QAbstractTransition::_ZTV19QAbstractTransition) + 16u) + QObject (0x0x7f0263137600) 0 + primary-for QAbstractTransition (0x0x7f0263073618) + +Class QEventTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventTransition::QPrivateSignal (0x0x7f0263137720) 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 (0x0x7f0263073680) 0 + vptr=((& QEventTransition::_ZTV16QEventTransition) + 16u) + QAbstractTransition (0x0x7f02630736e8) 0 + primary-for QEventTransition (0x0x7f0263073680) + QObject (0x0x7f02631376c0) 0 + primary-for QAbstractTransition (0x0x7f02630736e8) + +Class QFinalState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFinalState::QPrivateSignal (0x0x7f02631377e0) 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 (0x0x7f0263073750) 0 + vptr=((& QFinalState::_ZTV11QFinalState) + 16u) + QAbstractState (0x0x7f02630737b8) 0 + primary-for QFinalState (0x0x7f0263073750) + QObject (0x0x7f0263137780) 0 + primary-for QAbstractState (0x0x7f02630737b8) + +Class QHistoryState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QHistoryState::QPrivateSignal (0x0x7f02631378a0) 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 (0x0x7f0263073820) 0 + vptr=((& QHistoryState::_ZTV13QHistoryState) + 16u) + QAbstractState (0x0x7f0263073888) 0 + primary-for QHistoryState (0x0x7f0263073820) + QObject (0x0x7f0263137840) 0 + primary-for QAbstractState (0x0x7f0263073888) + +Class QSignalTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalTransition::QPrivateSignal (0x0x7f0263137960) 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 (0x0x7f02630738f0) 0 + vptr=((& QSignalTransition::_ZTV17QSignalTransition) + 16u) + QAbstractTransition (0x0x7f0263073958) 0 + primary-for QSignalTransition (0x0x7f02630738f0) + QObject (0x0x7f0263137900) 0 + primary-for QAbstractTransition (0x0x7f0263073958) + +Class QState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QState::QPrivateSignal (0x0x7f0263137a20) 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 (0x0x7f02630739c0) 0 + vptr=((& QState::_ZTV6QState) + 16u) + QAbstractState (0x0x7f0263073a28) 0 + primary-for QState (0x0x7f02630739c0) + QObject (0x0x7f02631379c0) 0 + primary-for QAbstractState (0x0x7f0263073a28) + +Class QStateMachine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStateMachine::QPrivateSignal (0x0x7f0263137b40) 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 (0x0x7f0263073bc8) 0 + vptr=((& QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE) + 16u) + QEvent (0x0x7f0263137ba0) 0 + primary-for QStateMachine::SignalEvent (0x0x7f0263073bc8) + +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 (0x0x7f0263073c30) 0 + vptr=((& QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE) + 16u) + QEvent (0x0x7f0263137c00) 0 + primary-for QStateMachine::WrappedEvent (0x0x7f0263073c30) + +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 (0x0x7f0263073a90) 0 + vptr=((& QStateMachine::_ZTV13QStateMachine) + 16u) + QState (0x0x7f0263073af8) 0 + primary-for QStateMachine (0x0x7f0263073a90) + QAbstractState (0x0x7f0263073b60) 0 + primary-for QState (0x0x7f0263073af8) + QObject (0x0x7f0263137ae0) 0 + primary-for QAbstractState (0x0x7f0263073b60) + +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 (0x0x7f0263073c98) 0 nearly-empty + vptr=((& QException::_ZTV10QException) + 16u) + std::exception (0x0x7f0263137c60) 0 nearly-empty + primary-for QException (0x0x7f0263073c98) + +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 (0x0x7f0263073d00) 0 nearly-empty + vptr=((& QUnhandledException::_ZTV19QUnhandledException) + 16u) + QException (0x0x7f0263073d68) 0 nearly-empty + primary-for QUnhandledException (0x0x7f0263073d00) + std::exception (0x0x7f0263137cc0) 0 nearly-empty + primary-for QException (0x0x7f0263073d68) + +Class QtPrivate::ExceptionHolder + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionHolder (0x0x7f0263137d20) 0 + +Class QtPrivate::ExceptionStore + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionStore (0x0x7f0263137de0) 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 (0x0x7f0263137e40) 0 + vptr=((& QRunnable::_ZTV9QRunnable) + 16u) + +Class QBasicMutex + size=8 align=8 + base size=8 base align=8 +QBasicMutex (0x0x7f0263137ea0) 0 + +Class QMutex + size=8 align=8 + base size=8 base align=8 +QMutex (0x0x7f0263073f08) 0 + QBasicMutex (0x0x7f0262e75000) 0 + +Class QMutexLocker + size=8 align=8 + base size=8 base align=8 +QMutexLocker (0x0x7f0262e75060) 0 + +Class QtPrivate::ResultItem + size=16 align=8 + base size=16 base align=8 +QtPrivate::ResultItem (0x0x7f0262e750c0) 0 + +Class QtPrivate::ResultIteratorBase + size=16 align=8 + base size=12 base align=8 +QtPrivate::ResultIteratorBase (0x0x7f0262e75120) 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 (0x0x7f0262e752a0) 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 (0x0x7f0262e75360) 0 + vptr=((& QFutureInterfaceBase::_ZTV20QFutureInterfaceBase) + 16u) + +Class QFutureWatcherBase::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFutureWatcherBase::QPrivateSignal (0x0x7f0262e756c0) 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 (0x0x7f0262eb9820) 0 + vptr=((& QFutureWatcherBase::_ZTV18QFutureWatcherBase) + 16u) + QObject (0x0x7f0262e75660) 0 + primary-for QFutureWatcherBase (0x0x7f0262eb9820) + +Class QReadWriteLock + size=8 align=8 + base size=8 base align=8 +QReadWriteLock (0x0x7f0262e757e0) 0 + +Class QReadLocker + size=8 align=8 + base size=8 base align=8 +QReadLocker (0x0x7f0262e75840) 0 + +Class QWriteLocker + size=8 align=8 + base size=8 base align=8 +QWriteLocker (0x0x7f0262e758a0) 0 + +Class QSemaphore + size=8 align=8 + base size=8 base align=8 +QSemaphore (0x0x7f0262e75900) 0 + +Class QThread::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThread::QPrivateSignal (0x0x7f0262e759c0) 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 (0x0x7f0262eb9bc8) 0 + vptr=((& QThread::_ZTV7QThread) + 16u) + QObject (0x0x7f0262e75960) 0 + primary-for QThread (0x0x7f0262eb9bc8) + +Class QThreadPool::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThreadPool::QPrivateSignal (0x0x7f0262e75a80) 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 (0x0x7f0262eb9c30) 0 + vptr=((& QThreadPool::_ZTV11QThreadPool) + 16u) + QObject (0x0x7f0262e75a20) 0 + primary-for QThreadPool (0x0x7f0262eb9c30) + +Class QThreadStorageData + size=4 align=4 + base size=4 base align=4 +QThreadStorageData (0x0x7f0262e75ae0) 0 + +Class QWaitCondition + size=8 align=8 + base size=8 base align=8 +QWaitCondition (0x0x7f0262e75ba0) 0 + +Class QBitArray + size=8 align=8 + base size=8 base align=8 +QBitArray (0x0x7f0262c31180) 0 + +Class QBitRef + size=16 align=8 + base size=12 base align=8 +QBitRef (0x0x7f0262c311e0) 0 + +Class QByteArrayMatcher::Data + size=272 align=8 + base size=272 base align=8 +QByteArrayMatcher::Data (0x0x7f0262c31360) 0 + +Class QByteArrayMatcher + size=1040 align=8 + base size=1040 base align=8 +QByteArrayMatcher (0x0x7f0262c31300) 0 + +Class QCollatorSortKey + size=8 align=8 + base size=8 base align=8 +QCollatorSortKey (0x0x7f0262c314e0) 0 + +Class QCollator + size=8 align=8 + base size=8 base align=8 +QCollator (0x0x7f0262c315a0) 0 + +Class QCommandLineOption + size=8 align=8 + base size=8 base align=8 +QCommandLineOption (0x0x7f0262c31780) 0 + +Class QCommandLineParser + size=8 align=8 + base size=8 base align=8 +QCommandLineParser (0x0x7f0262c31900) 0 + +Class QCryptographicHash + size=8 align=8 + base size=8 base align=8 +QCryptographicHash (0x0x7f0262c31960) 0 + +Class QElapsedTimer + size=16 align=8 + base size=16 base align=8 +QElapsedTimer (0x0x7f0262c319c0) 0 + +Class QPoint + size=8 align=4 + base size=8 base align=4 +QPoint (0x0x7f0262c31a20) 0 + +Class QPointF + size=16 align=8 + base size=16 base align=8 +QPointF (0x0x7f0262c31b40) 0 + +Class QLine + size=16 align=4 + base size=16 base align=4 +QLine (0x0x7f0262c31c60) 0 + +Class QLineF + size=32 align=8 + base size=32 base align=8 +QLineF (0x0x7f0262c31d80) 0 + +Class QLinkedListData + size=32 align=8 + base size=32 base align=8 +QLinkedListData (0x0x7f0262c31ea0) 0 + +Class QMargins + size=16 align=4 + base size=16 base align=4 +QMargins (0x0x7f02629e4240) 0 + +Class QMarginsF + size=32 align=8 + base size=32 base align=8 +QMarginsF (0x0x7f02629e4360) 0 + +Class QMessageAuthenticationCode + size=8 align=8 + base size=8 base align=8 +QMessageAuthenticationCode (0x0x7f02629e4480) 0 + +Class QSize + size=8 align=4 + base size=8 base align=4 +QSize (0x0x7f02629e4540) 0 + +Class QSizeF + size=16 align=8 + base size=16 base align=8 +QSizeF (0x0x7f02629e4660) 0 + +Class QRect + size=16 align=4 + base size=16 base align=4 +QRect (0x0x7f02629e4780) 0 + +Class QRectF + size=32 align=8 + base size=32 base align=8 +QRectF (0x0x7f02629e48a0) 0 + +Class QRegularExpression + size=8 align=8 + base size=8 base align=8 +QRegularExpression (0x0x7f02629e49c0) 0 + +Class QRegularExpressionMatch + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatch (0x0x7f02629e4cc0) 0 + +Class QRegularExpressionMatchIterator + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatchIterator (0x0x7f02629e4e40) 0 + +Class QAbstractConcatenable + size=1 align=1 + base size=0 base align=1 +QAbstractConcatenable (0x0x7f02628ca0c0) 0 empty + +Class QTextBoundaryFinder + size=48 align=8 + base size=48 base align=8 +QTextBoundaryFinder (0x0x7f02628caae0) 0 + +Class QTimeLine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimeLine::QPrivateSignal (0x0x7f02628cac60) 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 (0x0x7f026291c548) 0 + vptr=((& QTimeLine::_ZTV9QTimeLine) + 16u) + QObject (0x0x7f02628cac00) 0 + primary-for QTimeLine (0x0x7f026291c548) + +Class QTimeZone::OffsetData + size=32 align=8 + base size=28 base align=8 +QTimeZone::OffsetData (0x0x7f02628cad20) 0 + +Class QTimeZone + size=8 align=8 + base size=8 base align=8 +QTimeZone (0x0x7f02628cacc0) 0 + +Class QXmlStreamStringRef + size=16 align=8 + base size=16 base align=8 +QXmlStreamStringRef (0x0x7f02628caf60) 0 + +Class QXmlStreamAttribute + size=80 align=8 + base size=73 base align=8 +QXmlStreamAttribute (0x0x7f02625c3000) 0 + +Class QXmlStreamAttributes + size=8 align=8 + base size=8 base align=8 +QXmlStreamAttributes (0x0x7f026291c7b8) 0 + QVector (0x0x7f02625c31e0) 0 + +Class QXmlStreamNamespaceDeclaration + size=40 align=8 + base size=40 base align=8 +QXmlStreamNamespaceDeclaration (0x0x7f02625c3240) 0 + +Class QXmlStreamNotationDeclaration + size=56 align=8 + base size=56 base align=8 +QXmlStreamNotationDeclaration (0x0x7f02625c3360) 0 + +Class QXmlStreamEntityDeclaration + size=88 align=8 + base size=88 base align=8 +QXmlStreamEntityDeclaration (0x0x7f02625c3480) 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 (0x0x7f02625c35a0) 0 nearly-empty + vptr=((& QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver) + 16u) + +Class QXmlStreamReader + size=8 align=8 + base size=8 base align=8 +QXmlStreamReader (0x0x7f02625c3600) 0 + +Class QXmlStreamWriter + size=8 align=8 + base size=8 base align=8 +QXmlStreamWriter (0x0x7f02625c3720) 0 + +Class QNdefRecord + size=8 align=8 + base size=8 base align=8 +QNdefRecord (0x0x7f02625c3840) 0 + +Class QNdefFilter::Record + size=24 align=8 + base size=24 base align=8 +QNdefFilter::Record (0x0x7f02625c3960) 0 + +Class QNdefFilter + size=8 align=8 + base size=8 base align=8 +QNdefFilter (0x0x7f02625c3900) 0 + +Class QNdefMessage + size=8 align=8 + base size=8 base align=8 +QNdefMessage (0x0x7f026291c958) 0 + QList (0x0x7f02625c3ae0) 0 + +Class QNdefNfcTextRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcTextRecord (0x0x7f026291c9c0) 0 + QNdefRecord (0x0x7f02625c3c60) 0 + +Class QNdefNfcUriRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcUriRecord (0x0x7f026291ca28) 0 + QNdefRecord (0x0x7f02625c3cc0) 0 + +Class QNdefNfcIconRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcIconRecord (0x0x7f026291ca90) 0 + QNdefRecord (0x0x7f02625c3d20) 0 + +Class QNdefNfcSmartPosterRecord + size=16 align=8 + base size=16 base align=8 +QNdefNfcSmartPosterRecord (0x0x7f026291caf8) 0 + QNdefRecord (0x0x7f02625c3d80) 0 + +Class QNearFieldTarget::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldTarget::QPrivateSignal (0x0x7f02625c3ea0) 0 empty + +Class QNearFieldTarget::RequestId + size=8 align=8 + base size=8 base align=8 +QNearFieldTarget::RequestId (0x0x7f02625c3f00) 0 + +Vtable for QNearFieldTarget +QNearFieldTarget::_ZTV16QNearFieldTarget: 25u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QNearFieldTarget) +16 (int (*)(...))QNearFieldTarget::metaObject +24 (int (*)(...))QNearFieldTarget::qt_metacast +32 (int (*)(...))QNearFieldTarget::qt_metacall +40 (int (*)(...))QNearFieldTarget::~QNearFieldTarget +48 (int (*)(...))QNearFieldTarget::~QNearFieldTarget +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 (*)(...))QNearFieldTarget::url +128 (int (*)(...))__cxa_pure_virtual +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))QNearFieldTarget::hasNdefMessage +152 (int (*)(...))QNearFieldTarget::readNdefMessages +160 (int (*)(...))QNearFieldTarget::writeNdefMessages +168 (int (*)(...))QNearFieldTarget::sendCommand +176 (int (*)(...))QNearFieldTarget::sendCommands +184 (int (*)(...))QNearFieldTarget::waitForRequestCompleted +192 (int (*)(...))QNearFieldTarget::handleResponse + +Class QNearFieldTarget + size=24 align=8 + base size=24 base align=8 +QNearFieldTarget (0x0x7f026291cb60) 0 + vptr=((& QNearFieldTarget::_ZTV16QNearFieldTarget) + 16u) + QObject (0x0x7f02625c3e40) 0 + primary-for QNearFieldTarget (0x0x7f026291cb60) + +Class QNearFieldManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldManager::QPrivateSignal (0x0x7f0262742360) 0 empty + +Vtable for QNearFieldManager +QNearFieldManager::_ZTV17QNearFieldManager: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QNearFieldManager) +16 (int (*)(...))QNearFieldManager::metaObject +24 (int (*)(...))QNearFieldManager::qt_metacast +32 (int (*)(...))QNearFieldManager::qt_metacall +40 (int (*)(...))QNearFieldManager::~QNearFieldManager +48 (int (*)(...))QNearFieldManager::~QNearFieldManager +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 QNearFieldManager + size=24 align=8 + base size=24 base align=8 +QNearFieldManager (0x0x7f026291cc98) 0 + vptr=((& QNearFieldManager::_ZTV17QNearFieldManager) + 16u) + QObject (0x0x7f0262742300) 0 + primary-for QNearFieldManager (0x0x7f026291cc98) + +Class QNearFieldShareManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldShareManager::QPrivateSignal (0x0x7f02627424e0) 0 empty + +Vtable for QNearFieldShareManager +QNearFieldShareManager::_ZTV22QNearFieldShareManager: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI22QNearFieldShareManager) +16 (int (*)(...))QNearFieldShareManager::metaObject +24 (int (*)(...))QNearFieldShareManager::qt_metacast +32 (int (*)(...))QNearFieldShareManager::qt_metacall +40 (int (*)(...))QNearFieldShareManager::~QNearFieldShareManager +48 (int (*)(...))QNearFieldShareManager::~QNearFieldShareManager +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 QNearFieldShareManager + size=24 align=8 + base size=24 base align=8 +QNearFieldShareManager (0x0x7f026291ce38) 0 + vptr=((& QNearFieldShareManager::_ZTV22QNearFieldShareManager) + 16u) + QObject (0x0x7f0262742480) 0 + primary-for QNearFieldShareManager (0x0x7f026291ce38) + +Class QNearFieldShareTarget::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldShareTarget::QPrivateSignal (0x0x7f0262742720) 0 empty + +Vtable for QNearFieldShareTarget +QNearFieldShareTarget::_ZTV21QNearFieldShareTarget: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QNearFieldShareTarget) +16 (int (*)(...))QNearFieldShareTarget::metaObject +24 (int (*)(...))QNearFieldShareTarget::qt_metacast +32 (int (*)(...))QNearFieldShareTarget::qt_metacall +40 (int (*)(...))QNearFieldShareTarget::~QNearFieldShareTarget +48 (int (*)(...))QNearFieldShareTarget::~QNearFieldShareTarget +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 QNearFieldShareTarget + size=24 align=8 + base size=24 base align=8 +QNearFieldShareTarget (0x0x7f026291cf70) 0 + vptr=((& QNearFieldShareTarget::_ZTV21QNearFieldShareTarget) + 16u) + QObject (0x0x7f02627426c0) 0 + primary-for QNearFieldShareTarget (0x0x7f026291cf70) + +Class QQmlNdefRecord::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QQmlNdefRecord::QPrivateSignal (0x0x7f02627427e0) 0 empty + +Vtable for QQmlNdefRecord +QQmlNdefRecord::_ZTV14QQmlNdefRecord: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI14QQmlNdefRecord) +16 (int (*)(...))QQmlNdefRecord::metaObject +24 (int (*)(...))QQmlNdefRecord::qt_metacast +32 (int (*)(...))QQmlNdefRecord::qt_metacall +40 (int (*)(...))QQmlNdefRecord::~QQmlNdefRecord +48 (int (*)(...))QQmlNdefRecord::~QQmlNdefRecord +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 QQmlNdefRecord + size=24 align=8 + base size=24 base align=8 +QQmlNdefRecord (0x0x7f0262355000) 0 + vptr=((& QQmlNdefRecord::_ZTV14QQmlNdefRecord) + 16u) + QObject (0x0x7f0262742780) 0 + primary-for QQmlNdefRecord (0x0x7f0262355000) + diff --git a/tests/auto/bic/data/QtNfc.5.4.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtNfc.5.4.0.linux-gcc-amd64.txt new file mode 100644 index 0000000..a99e9ba --- /dev/null +++ b/tests/auto/bic/data/QtNfc.5.4.0.linux-gcc-amd64.txt @@ -0,0 +1,3847 @@ +Class std::__true_type + size=1 align=1 + base size=0 base align=1 +std::__true_type (0x0x7f8137288060) 0 empty + +Class std::__false_type + size=1 align=1 + base size=0 base align=1 +std::__false_type (0x0x7f81372880c0) 0 empty + +Class std::input_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::input_iterator_tag (0x0x7f81372c6c60) 0 empty + +Class std::output_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::output_iterator_tag (0x0x7f81372c6cc0) 0 empty + +Class std::forward_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::forward_iterator_tag (0x0x7f813725b6e8) 0 empty + std::input_iterator_tag (0x0x7f81372c6d20) 0 empty + +Class std::bidirectional_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::bidirectional_iterator_tag (0x0x7f813725b750) 0 empty + std::forward_iterator_tag (0x0x7f813725b7b8) 0 empty + std::input_iterator_tag (0x0x7f81372c6d80) 0 empty + +Class std::random_access_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::random_access_iterator_tag (0x0x7f813725b820) 0 empty + std::bidirectional_iterator_tag (0x0x7f813725b888) 0 empty + std::forward_iterator_tag (0x0x7f813725b8f0) 0 empty + std::input_iterator_tag (0x0x7f81372c6de0) 0 empty + +Class wait + size=4 align=4 + base size=4 base align=4 +wait (0x0x7f81372f8960) 0 + +Class __locale_struct + size=232 align=8 + base size=232 base align=8 +__locale_struct (0x0x7f81372f8ba0) 0 + +Class timespec + size=16 align=8 + base size=16 base align=8 +timespec (0x0x7f81372f8c60) 0 + +Class timeval + size=16 align=8 + base size=16 base align=8 +timeval (0x0x7f81372f8cc0) 0 + +Class pthread_attr_t + size=56 align=8 + base size=56 base align=8 +pthread_attr_t (0x0x7f81372f8d80) 0 + +Class __pthread_internal_list + size=16 align=8 + base size=16 base align=8 +__pthread_internal_list (0x0x7f81372f8de0) 0 + +Class random_data + size=48 align=8 + base size=48 base align=8 +random_data (0x0x7f81373e22a0) 0 + +Class drand48_data + size=24 align=8 + base size=24 base align=8 +drand48_data (0x0x7f81373e2300) 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 (0x0x7f81373e2360) 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 (0x0x7f813725bc30) 0 nearly-empty + vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16u) + std::exception (0x0x7f81373e23c0) 0 nearly-empty + primary-for std::bad_exception (0x0x7f813725bc30) + +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 (0x0x7f813725bc98) 0 nearly-empty + vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16u) + std::exception (0x0x7f81373e2420) 0 nearly-empty + primary-for std::bad_alloc (0x0x7f813725bc98) + +Class std::nothrow_t + size=1 align=1 + base size=0 base align=1 +std::nothrow_t (0x0x7f81373e2480) 0 empty + +Class qIsNull(double)::U + size=8 align=8 + base size=8 base align=8 +qIsNull(double)::U (0x0x7f81361d67e0) 0 + +Class qIsNull(float)::U + size=4 align=4 + base size=4 base align=4 +qIsNull(float)::U (0x0x7f81361d6840) 0 + +Class QtPrivate::big_ + size=2 align=1 + base size=2 base align=1 +QtPrivate::big_ (0x0x7f81361d6a20) 0 + +Class QSysInfo + size=1 align=1 + base size=0 base align=1 +QSysInfo (0x0x7f8135f48300) 0 empty + +Class QMessageLogContext + size=32 align=8 + base size=32 base align=8 +QMessageLogContext (0x0x7f8135f48360) 0 + +Class QMessageLogger + size=32 align=8 + base size=32 base align=8 +QMessageLogger (0x0x7f8135f483c0) 0 + +Class QFlag + size=4 align=4 + base size=4 base align=4 +QFlag (0x0x7f8135f48420) 0 + +Class QIncompatibleFlag + size=4 align=4 + base size=4 base align=4 +QIncompatibleFlag (0x0x7f8135f48540) 0 + +Class QAtomicInt + size=4 align=4 + base size=4 base align=4 +QAtomicInt (0x0x7f8135fe9410) 0 + QAtomicInteger (0x0x7f8135fe9478) 0 + QBasicAtomicInteger (0x0x7f8135d8d060) 0 + +Class QInternal + size=1 align=1 + base size=0 base align=1 +QInternal (0x0x7f8135b64180) 0 empty + +Class QGenericArgument + size=16 align=8 + base size=16 base align=8 +QGenericArgument (0x0x7f813582e0c0) 0 + +Class QGenericReturnArgument + size=16 align=8 + base size=16 base align=8 +QGenericReturnArgument (0x0x7f8135b075b0) 0 + QGenericArgument (0x0x7f813582e120) 0 + +Class QMetaObject + size=48 align=8 + base size=48 base align=8 +QMetaObject (0x0x7f813582e2a0) 0 + +Class QMetaObject::Connection + size=8 align=8 + base size=8 base align=8 +QMetaObject::Connection (0x0x7f813582e3c0) 0 + +Class QLatin1Char + size=1 align=1 + base size=1 base align=1 +QLatin1Char (0x0x7f813582e600) 0 + +Class QChar + size=2 align=2 + base size=2 base align=2 +QChar (0x0x7f813582e660) 0 + +Class QtPrivate::RefCount + size=4 align=4 + base size=4 base align=4 +QtPrivate::RefCount (0x0x7f813582e780) 0 + +Class QArrayData + size=24 align=8 + base size=24 base align=8 +QArrayData (0x0x7f813582e7e0) 0 + +Class QtPrivate::QContainerImplHelper + size=1 align=1 + base size=0 base align=1 +QtPrivate::QContainerImplHelper (0x0x7f813582eae0) 0 empty + +Class lconv + size=96 align=8 + base size=96 base align=8 +lconv (0x0x7f813582ee40) 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 (0x0x7f813582eea0) 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 (0x0x7f8135663960) 0 + +Class __sched_param + size=4 align=4 + base size=4 base align=4 +__sched_param (0x0x7f81356639c0) 0 + +Class timex + size=208 align=8 + base size=208 base align=8 +timex (0x0x7f8135663a80) 0 + +Class tm + size=56 align=8 + base size=56 base align=8 +tm (0x0x7f8135663ae0) 0 + +Class itimerspec + size=32 align=8 + base size=32 base align=8 +itimerspec (0x0x7f8135663b40) 0 + +Class _pthread_cleanup_buffer + size=32 align=8 + base size=32 base align=8 +_pthread_cleanup_buffer (0x0x7f8135663ba0) 0 + +Class __pthread_cleanup_frame + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_frame (0x0x7f8135663cc0) 0 + +Class __pthread_cleanup_class + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_class (0x0x7f8135663d20) 0 + +Class QByteArrayDataPtr + size=8 align=8 + base size=8 base align=8 +QByteArrayDataPtr (0x0x7f813576d4e0) 0 + +Class QByteArray + size=8 align=8 + base size=8 base align=8 +QByteArray (0x0x7f813576d540) 0 + +Class QByteRef + size=16 align=8 + base size=12 base align=8 +QByteRef (0x0x7f813576d6c0) 0 + +Class QLatin1String + size=16 align=8 + base size=16 base align=8 +QLatin1String (0x0x7f813576d7e0) 0 + +Class QStringDataPtr + size=8 align=8 + base size=8 base align=8 +QStringDataPtr (0x0x7f813576d960) 0 + +Class QString::Null + size=1 align=1 + base size=0 base align=1 +QString::Null (0x0x7f813576da20) 0 empty + +Class QString + size=8 align=8 + base size=8 base align=8 +QString (0x0x7f813576d9c0) 0 + +Class QCharRef + size=16 align=8 + base size=12 base align=8 +QCharRef (0x0x7f813576dba0) 0 + +Class QStringRef + size=16 align=8 + base size=16 base align=8 +QStringRef (0x0x7f813576de40) 0 + +Class std::locale + size=8 align=8 + base size=8 base align=8 +std::locale (0x0x7f8135098060) 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 (0x0x7f81350980c0) 0 + vptr=((& std::locale::facet::_ZTVNSt6locale5facetE) + 16u) + +Class std::locale::id + size=8 align=8 + base size=8 base align=8 +std::locale::id (0x0x7f8135098120) 0 + +Class std::locale::_Impl + size=40 align=8 + base size=40 base align=8 +std::locale::_Impl (0x0x7f8135098180) 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 (0x0x7f8135494f08) 0 + vptr=((& std::ios_base::failure::_ZTVNSt8ios_base7failureE) + 16u) + std::exception (0x0x7f81350985a0) 0 nearly-empty + primary-for std::ios_base::failure (0x0x7f8135494f08) + +Class std::ios_base::_Callback_list + size=24 align=8 + base size=24 base align=8 +std::ios_base::_Callback_list (0x0x7f8135098600) 0 + +Class std::ios_base::_Words + size=16 align=8 + base size=16 base align=8 +std::ios_base::_Words (0x0x7f8135098660) 0 + +Class std::ios_base::Init + size=1 align=1 + base size=0 base align=1 +std::ios_base::Init (0x0x7f81350986c0) 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 (0x0x7f8135098540) 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 (0x0x7f8135098840) 0 empty + +Class std::__num_base + size=1 align=1 + base size=0 base align=1 +std::__num_base (0x0x7f8135098f00) 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 (0x0x7f8134d5faf8 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 (0x0x7f8134d5fbc8 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 (0x0x7f8134d5fea0 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 (0x0x7f8134d5ff70 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 (0x0x7f8134d62300) 0 + +Class QListData::Data + size=24 align=8 + base size=24 base align=8 +QListData::Data (0x0x7f8134d62660) 0 + +Class QListData + size=8 align=8 + base size=8 base align=8 +QListData (0x0x7f8134d62600) 0 + +Class QScopedPointerPodDeleter + size=1 align=1 + base size=0 base align=1 +QScopedPointerPodDeleter (0x0x7f8134d62b40) 0 empty + +Class std::_Bit_reference + size=16 align=8 + base size=16 base align=8 +std::_Bit_reference (0x0x7f8134be68a0) 0 + +Class std::_Bit_iterator_base + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator_base (0x0x7f8134a9c3a8) 0 + std::iterator (0x0x7f8134be6960) 0 empty + +Class std::_Bit_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator (0x0x7f8134a9c410) 0 + std::_Bit_iterator_base (0x0x7f8134a9c478) 0 + std::iterator (0x0x7f8134be69c0) 0 empty + +Class std::_Bit_const_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_const_iterator (0x0x7f8134a9c4e0) 0 + std::_Bit_iterator_base (0x0x7f8134a9c548) 0 + std::iterator (0x0x7f8134be6a20) 0 empty + +Class std::_Rb_tree_node_base + size=32 align=8 + base size=32 base align=8 +std::_Rb_tree_node_base (0x0x7f8134be6de0) 0 + +Class QtPrivate::AbstractDebugStreamFunction + size=16 align=8 + base size=16 base align=8 +QtPrivate::AbstractDebugStreamFunction (0x0x7f81349cd240) 0 + +Class QtPrivate::AbstractComparatorFunction + size=24 align=8 + base size=24 base align=8 +QtPrivate::AbstractComparatorFunction (0x0x7f81349cd300) 0 + +Class QtPrivate::AbstractConverterFunction + size=8 align=8 + base size=8 base align=8 +QtPrivate::AbstractConverterFunction (0x0x7f81349cd3c0) 0 + +Class QMetaType + size=80 align=8 + base size=80 base align=8 +QMetaType (0x0x7f81349cd7e0) 0 + +Class QtMetaTypePrivate::VariantData + size=24 align=8 + base size=20 base align=8 +QtMetaTypePrivate::VariantData (0x0x7f81349cdb40) 0 + +Class QtMetaTypePrivate::VectorBoolElements + size=1 align=1 + base size=0 base align=1 +QtMetaTypePrivate::VectorBoolElements (0x0x7f81349cdc60) 0 empty + +Class QtMetaTypePrivate::QSequentialIterableImpl + size=104 align=8 + base size=104 base align=8 +QtMetaTypePrivate::QSequentialIterableImpl (0x0x7f81347c5480) 0 + +Class QtMetaTypePrivate::QAssociativeIterableImpl + size=112 align=8 + base size=112 base align=8 +QtMetaTypePrivate::QAssociativeIterableImpl (0x0x7f81347c5660) 0 + +Class QtMetaTypePrivate::QPairVariantInterfaceImpl + size=40 align=8 + base size=40 base align=8 +QtMetaTypePrivate::QPairVariantInterfaceImpl (0x0x7f81347c5720) 0 + +Class QtPrivate::QSlotObjectBase + size=16 align=8 + base size=16 base align=8 +QtPrivate::QSlotObjectBase (0x0x7f813458ca80) 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 (0x0x7f813458cc00) 0 + vptr=((& QObjectData::_ZTV11QObjectData) + 16u) + +Class QObject::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObject::QPrivateSignal (0x0x7f813458cde0) 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 (0x0x7f813458cd80) 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 (0x0x7f8134269120) 0 nearly-empty + vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16u) + +Class QSignalBlocker + size=16 align=8 + base size=10 base align=8 +QSignalBlocker (0x0x7f8134269180) 0 + +Class QAbstractAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractAnimation::QPrivateSignal (0x0x7f8134269240) 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 (0x0x7f81345e6340) 0 + vptr=((& QAbstractAnimation::_ZTV18QAbstractAnimation) + 16u) + QObject (0x0x7f81342691e0) 0 + primary-for QAbstractAnimation (0x0x7f81345e6340) + +Class QAnimationDriver::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationDriver::QPrivateSignal (0x0x7f8134269300) 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 (0x0x7f81345e63a8) 0 + vptr=((& QAnimationDriver::_ZTV16QAnimationDriver) + 16u) + QObject (0x0x7f81342692a0) 0 + primary-for QAnimationDriver (0x0x7f81345e63a8) + +Class QAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationGroup::QPrivateSignal (0x0x7f81342693c0) 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 (0x0x7f81345e6410) 0 + vptr=((& QAnimationGroup::_ZTV15QAnimationGroup) + 16u) + QAbstractAnimation (0x0x7f81345e6478) 0 + primary-for QAnimationGroup (0x0x7f81345e6410) + QObject (0x0x7f8134269360) 0 + primary-for QAbstractAnimation (0x0x7f81345e6478) + +Class QParallelAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QParallelAnimationGroup::QPrivateSignal (0x0x7f8134269480) 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 (0x0x7f81345e64e0) 0 + vptr=((& QParallelAnimationGroup::_ZTV23QParallelAnimationGroup) + 16u) + QAnimationGroup (0x0x7f81345e6548) 0 + primary-for QParallelAnimationGroup (0x0x7f81345e64e0) + QAbstractAnimation (0x0x7f81345e65b0) 0 + primary-for QAnimationGroup (0x0x7f81345e6548) + QObject (0x0x7f8134269420) 0 + primary-for QAbstractAnimation (0x0x7f81345e65b0) + +Class QPauseAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPauseAnimation::QPrivateSignal (0x0x7f8134269540) 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 (0x0x7f81345e6618) 0 + vptr=((& QPauseAnimation::_ZTV15QPauseAnimation) + 16u) + QAbstractAnimation (0x0x7f81345e6680) 0 + primary-for QPauseAnimation (0x0x7f81345e6618) + QObject (0x0x7f81342694e0) 0 + primary-for QAbstractAnimation (0x0x7f81345e6680) + +Class QEasingCurve + size=8 align=8 + base size=8 base align=8 +QEasingCurve (0x0x7f8134269720) 0 + +Class QMapNodeBase + size=24 align=8 + base size=24 base align=8 +QMapNodeBase (0x0x7f8134269900) 0 + +Class QMapDataBase + size=40 align=8 + base size=40 base align=8 +QMapDataBase (0x0x7f81342699c0) 0 + +Class QHashData::Node + size=16 align=8 + base size=16 base align=8 +QHashData::Node (0x0x7f8134269d20) 0 + +Class QHashData + size=48 align=8 + base size=48 base align=8 +QHashData (0x0x7f8134269cc0) 0 + +Class QHashDummyValue + size=1 align=1 + base size=0 base align=1 +QHashDummyValue (0x0x7f8134269d80) 0 empty + +Class QIODevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIODevice::QPrivateSignal (0x0x7f81340f1300) 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 (0x0x7f81345e6ea0) 0 + vptr=((& QIODevice::_ZTV9QIODevice) + 16u) + QObject (0x0x7f81340f12a0) 0 + primary-for QIODevice (0x0x7f81345e6ea0) + +Class QDataStream + size=32 align=8 + base size=32 base align=8 +QDataStream (0x0x7f81340f1420) 0 + +Class QRegExp + size=8 align=8 + base size=8 base align=8 +QRegExp (0x0x7f81340f14e0) 0 + +Class QStringMatcher::Data + size=272 align=8 + base size=272 base align=8 +QStringMatcher::Data (0x0x7f81340f1660) 0 + +Class QStringMatcher + size=1048 align=8 + base size=1048 base align=8 +QStringMatcher (0x0x7f81340f1600) 0 + +Class QStringList + size=8 align=8 + base size=8 base align=8 +QStringList (0x0x7f8133e4f068) 0 + QList (0x0x7f8133e4f0d0) 0 + QListSpecialMethods (0x0x7f81340f1840) 0 empty + +Class QVariant::PrivateShared + size=16 align=8 + base size=12 base align=8 +QVariant::PrivateShared (0x0x7f81340f1b40) 0 + +Class QVariant::Private::Data + size=8 align=8 + base size=8 base align=8 +QVariant::Private::Data (0x0x7f81340f1c00) 0 + +Class QVariant::Private + size=16 align=8 + base size=12 base align=8 +QVariant::Private (0x0x7f81340f1ba0) 0 + +Class QVariant::Handler + size=72 align=8 + base size=72 base align=8 +QVariant::Handler (0x0x7f81340f1c60) 0 + +Class QVariant + size=16 align=8 + base size=16 base align=8 +QVariant (0x0x7f81340f1ae0) 0 + +Class QVariantComparisonHelper + size=8 align=8 + base size=8 base align=8 +QVariantComparisonHelper (0x0x7f81340f1f60) 0 + +Class QSequentialIterable::const_iterator + size=112 align=8 + base size=112 base align=8 +QSequentialIterable::const_iterator (0x0x7f8133f74060) 0 + +Class QSequentialIterable + size=104 align=8 + base size=104 base align=8 +QSequentialIterable (0x0x7f8133f74000) 0 + +Class QAssociativeIterable::const_iterator + size=120 align=8 + base size=120 base align=8 +QAssociativeIterable::const_iterator (0x0x7f8133f74120) 0 + +Class QAssociativeIterable + size=112 align=8 + base size=112 base align=8 +QAssociativeIterable (0x0x7f8133f740c0) 0 + +Class QVariantAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QVariantAnimation::QPrivateSignal (0x0x7f8133f74cc0) 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 (0x0x7f8133e4fb60) 0 + vptr=((& QVariantAnimation::_ZTV17QVariantAnimation) + 16u) + QAbstractAnimation (0x0x7f8133e4fbc8) 0 + primary-for QVariantAnimation (0x0x7f8133e4fb60) + QObject (0x0x7f8133f74c60) 0 + primary-for QAbstractAnimation (0x0x7f8133e4fbc8) + +Class QPropertyAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPropertyAnimation::QPrivateSignal (0x0x7f8133f74d80) 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 (0x0x7f8133e4fc98) 0 + vptr=((& QPropertyAnimation::_ZTV18QPropertyAnimation) + 16u) + QVariantAnimation (0x0x7f8133e4fd00) 0 + primary-for QPropertyAnimation (0x0x7f8133e4fc98) + QAbstractAnimation (0x0x7f8133e4fd68) 0 + primary-for QVariantAnimation (0x0x7f8133e4fd00) + QObject (0x0x7f8133f74d20) 0 + primary-for QAbstractAnimation (0x0x7f8133e4fd68) + +Class QSequentialAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSequentialAnimationGroup::QPrivateSignal (0x0x7f8133f74e40) 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 (0x0x7f8133e4fdd0) 0 + vptr=((& QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup) + 16u) + QAnimationGroup (0x0x7f8133e4fe38) 0 + primary-for QSequentialAnimationGroup (0x0x7f8133e4fdd0) + QAbstractAnimation (0x0x7f8133e4fea0) 0 + primary-for QAnimationGroup (0x0x7f8133e4fe38) + QObject (0x0x7f8133f74de0) 0 + primary-for QAbstractAnimation (0x0x7f8133e4fea0) + +Class QTextCodec::ConverterState + size=32 align=8 + base size=32 base align=8 +QTextCodec::ConverterState (0x0x7f8133f74f00) 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 (0x0x7f8133f74ea0) 0 nearly-empty + vptr=((& QTextCodec::_ZTV10QTextCodec) + 16u) + +Class QTextEncoder + size=40 align=8 + base size=40 base align=8 +QTextEncoder (0x0x7f8133c42060) 0 + +Class QTextDecoder + size=40 align=8 + base size=40 base align=8 +QTextDecoder (0x0x7f8133c420c0) 0 + +Class QSharedData + size=4 align=4 + base size=4 base align=4 +QSharedData (0x0x7f8133c42120) 0 + +Class std::__numeric_limits_base + size=1 align=1 + base size=0 base align=1 +std::__numeric_limits_base (0x0x7f8133c42300) 0 empty + +Class QDate + size=8 align=8 + base size=8 base align=8 +QDate (0x0x7f8133c42a80) 0 + +Class QTime + size=4 align=4 + base size=4 base align=4 +QTime (0x0x7f8133c42ba0) 0 + +Class QDateTime + size=8 align=8 + base size=8 base align=8 +QDateTime (0x0x7f8133c42cc0) 0 + +Class QLibraryInfo + size=1 align=1 + base size=0 base align=1 +QLibraryInfo (0x0x7f8133c42e40) 0 empty + +Class QBuffer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBuffer::QPrivateSignal (0x0x7f8133c42f00) 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 (0x0x7f8133dc8068) 0 + vptr=((& QBuffer::_ZTV7QBuffer) + 16u) + QIODevice (0x0x7f8133dc80d0) 0 + primary-for QBuffer (0x0x7f8133dc8068) + QObject (0x0x7f8133c42ea0) 0 + primary-for QIODevice (0x0x7f8133dc80d0) + +Class QLocale + size=8 align=8 + base size=8 base align=8 +QLocale (0x0x7f8133c42f60) 0 + +Class _IO_marker + size=24 align=8 + base size=24 base align=8 +_IO_marker (0x0x7f8133a472a0) 0 + +Class _IO_FILE + size=216 align=8 + base size=216 base align=8 +_IO_FILE (0x0x7f8133a47300) 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 (0x0x7f8133a473c0) 0 + vptr=((& QTextStream::_ZTV11QTextStream) + 16u) + +Class QTextStreamManipulator + size=40 align=8 + base size=38 base align=8 +QTextStreamManipulator (0x0x7f8133a47660) 0 + +Class QContiguousCacheData + size=24 align=4 + base size=24 base align=4 +QContiguousCacheData (0x0x7f8133a478a0) 0 + +Class QDebug::Stream + size=80 align=8 + base size=76 base align=8 +QDebug::Stream (0x0x7f8133a47f00) 0 + +Class QDebug + size=8 align=8 + base size=8 base align=8 +QDebug (0x0x7f8133a47ea0) 0 + +Class QDebugStateSaver + size=8 align=8 + base size=8 base align=8 +QDebugStateSaver (0x0x7f8133809060) 0 + +Class QNoDebug + size=1 align=1 + base size=0 base align=1 +QNoDebug (0x0x7f8133809120) 0 empty + +Class QFileDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileDevice::QPrivateSignal (0x0x7f81338091e0) 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 (0x0x7f8133dc8548) 0 + vptr=((& QFileDevice::_ZTV11QFileDevice) + 16u) + QIODevice (0x0x7f8133dc85b0) 0 + primary-for QFileDevice (0x0x7f8133dc8548) + QObject (0x0x7f8133809180) 0 + primary-for QIODevice (0x0x7f8133dc85b0) + +Class QFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFile::QPrivateSignal (0x0x7f8133809360) 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 (0x0x7f8133dc86e8) 0 + vptr=((& QFile::_ZTV5QFile) + 16u) + QFileDevice (0x0x7f8133dc8750) 0 + primary-for QFile (0x0x7f8133dc86e8) + QIODevice (0x0x7f8133dc87b8) 0 + primary-for QFileDevice (0x0x7f8133dc8750) + QObject (0x0x7f8133809300) 0 + primary-for QIODevice (0x0x7f8133dc87b8) + +Class QFileInfo + size=8 align=8 + base size=8 base align=8 +QFileInfo (0x0x7f8133809480) 0 + +Class QDir + size=8 align=8 + base size=8 base align=8 +QDir (0x0x7f8133809720) 0 + +Class QDirIterator + size=8 align=8 + base size=8 base align=8 +QDirIterator (0x0x7f8133809a20) 0 + +Class QFileSelector::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSelector::QPrivateSignal (0x0x7f8133809c00) 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 (0x0x7f8133dc8c98) 0 + vptr=((& QFileSelector::_ZTV13QFileSelector) + 16u) + QObject (0x0x7f8133809ba0) 0 + primary-for QFileSelector (0x0x7f8133dc8c98) + +Class QFileSystemWatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSystemWatcher::QPrivateSignal (0x0x7f8133809cc0) 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 (0x0x7f8133dc8d00) 0 + vptr=((& QFileSystemWatcher::_ZTV18QFileSystemWatcher) + 16u) + QObject (0x0x7f8133809c60) 0 + primary-for QFileSystemWatcher (0x0x7f8133dc8d00) + +Class QLockFile + size=8 align=8 + base size=8 base align=8 +QLockFile (0x0x7f8133809d20) 0 + +Class QLoggingCategory::AtomicBools + size=3 align=1 + base size=3 base align=1 +QLoggingCategory::AtomicBools (0x0x7f8133809ea0) 0 + +Class QLoggingCategory + size=24 align=8 + base size=24 base align=8 +QLoggingCategory (0x0x7f8133809e40) 0 + +Class QProcessEnvironment + size=8 align=8 + base size=8 base align=8 +QProcessEnvironment (0x0x7f8133996060) 0 + +Class QProcess::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QProcess::QPrivateSignal (0x0x7f8133996240) 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 (0x0x7f8133dc8f08) 0 + vptr=((& QProcess::_ZTV8QProcess) + 16u) + QIODevice (0x0x7f8133dc8f70) 0 + primary-for QProcess (0x0x7f8133dc8f08) + QObject (0x0x7f81339961e0) 0 + primary-for QIODevice (0x0x7f8133dc8f70) + +Class QResource + size=8 align=8 + base size=8 base align=8 +QResource (0x0x7f81339962a0) 0 + +Class QSaveFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSaveFile::QPrivateSignal (0x0x7f8133996420) 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 (0x0x7f8133dc8410) 0 + vptr=((& QSaveFile::_ZTV9QSaveFile) + 16u) + QFileDevice (0x0x7f81335f6000) 0 + primary-for QSaveFile (0x0x7f8133dc8410) + QIODevice (0x0x7f81335f6068) 0 + primary-for QFileDevice (0x0x7f81335f6000) + QObject (0x0x7f81339963c0) 0 + primary-for QIODevice (0x0x7f81335f6068) + +Class QSettings::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSettings::QPrivateSignal (0x0x7f81339964e0) 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 (0x0x7f81335f60d0) 0 + vptr=((& QSettings::_ZTV9QSettings) + 16u) + QObject (0x0x7f8133996480) 0 + primary-for QSettings (0x0x7f81335f60d0) + +Class QStandardPaths + size=1 align=1 + base size=0 base align=1 +QStandardPaths (0x0x7f8133996540) 0 empty + +Class QStorageInfo + size=8 align=8 + base size=8 base align=8 +QStorageInfo (0x0x7f8133996660) 0 + +Class QTemporaryDir + size=8 align=8 + base size=8 base align=8 +QTemporaryDir (0x0x7f8133996900) 0 + +Class QTemporaryFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTemporaryFile::QPrivateSignal (0x0x7f8133996a20) 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 (0x0x7f81335f6270) 0 + vptr=((& QTemporaryFile::_ZTV14QTemporaryFile) + 16u) + QFile (0x0x7f81335f62d8) 0 + primary-for QTemporaryFile (0x0x7f81335f6270) + QFileDevice (0x0x7f81335f6340) 0 + primary-for QFile (0x0x7f81335f62d8) + QIODevice (0x0x7f81335f63a8) 0 + primary-for QFileDevice (0x0x7f81335f6340) + QObject (0x0x7f81339969c0) 0 + primary-for QIODevice (0x0x7f81335f63a8) + +Class QUrl + size=8 align=8 + base size=8 base align=8 +QUrl (0x0x7f8133996b40) 0 + +Class QUrlQuery + size=8 align=8 + base size=8 base align=8 +QUrlQuery (0x0x7f813373d060) 0 + +Class QModelIndex + size=24 align=8 + base size=24 base align=8 +QModelIndex (0x0x7f813373d1e0) 0 + +Class QPersistentModelIndex + size=8 align=8 + base size=8 base align=8 +QPersistentModelIndex (0x0x7f813373d300) 0 + +Class QAbstractItemModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractItemModel::QPrivateSignal (0x0x7f813373d480) 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 (0x0x7f81335f6888) 0 + vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16u) + QObject (0x0x7f813373d420) 0 + primary-for QAbstractItemModel (0x0x7f81335f6888) + +Class QAbstractTableModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTableModel::QPrivateSignal (0x0x7f813373d7e0) 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 (0x0x7f81335f6a28) 0 + vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16u) + QAbstractItemModel (0x0x7f81335f6a90) 0 + primary-for QAbstractTableModel (0x0x7f81335f6a28) + QObject (0x0x7f813373d780) 0 + primary-for QAbstractItemModel (0x0x7f81335f6a90) + +Class QAbstractListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractListModel::QPrivateSignal (0x0x7f813373d8a0) 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 (0x0x7f81335f6af8) 0 + vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16u) + QAbstractItemModel (0x0x7f81335f6b60) 0 + primary-for QAbstractListModel (0x0x7f81335f6af8) + QObject (0x0x7f813373d840) 0 + primary-for QAbstractItemModel (0x0x7f81335f6b60) + +Class QAbstractProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractProxyModel::QPrivateSignal (0x0x7f813373d960) 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 (0x0x7f81335f6bc8) 0 + vptr=((& QAbstractProxyModel::_ZTV19QAbstractProxyModel) + 16u) + QAbstractItemModel (0x0x7f81335f6c30) 0 + primary-for QAbstractProxyModel (0x0x7f81335f6bc8) + QObject (0x0x7f813373d900) 0 + primary-for QAbstractItemModel (0x0x7f81335f6c30) + +Class QIdentityProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIdentityProxyModel::QPrivateSignal (0x0x7f813373da20) 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 (0x0x7f81335f6c98) 0 + vptr=((& QIdentityProxyModel::_ZTV19QIdentityProxyModel) + 16u) + QAbstractProxyModel (0x0x7f81335f6d00) 0 + primary-for QIdentityProxyModel (0x0x7f81335f6c98) + QAbstractItemModel (0x0x7f81335f6d68) 0 + primary-for QAbstractProxyModel (0x0x7f81335f6d00) + QObject (0x0x7f813373d9c0) 0 + primary-for QAbstractItemModel (0x0x7f81335f6d68) + +Class QItemSelectionRange + size=16 align=8 + base size=16 base align=8 +QItemSelectionRange (0x0x7f813373da80) 0 + +Class QItemSelectionModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QItemSelectionModel::QPrivateSignal (0x0x7f813373dc00) 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 (0x0x7f81335f6e38) 0 + vptr=((& QItemSelectionModel::_ZTV19QItemSelectionModel) + 16u) + QObject (0x0x7f813373dba0) 0 + primary-for QItemSelectionModel (0x0x7f81335f6e38) + +Class QItemSelection + size=8 align=8 + base size=8 base align=8 +QItemSelection (0x0x7f8133507000) 0 + QList (0x0x7f8133507068) 0 + QListSpecialMethods (0x0x7f813373de40) 0 empty + +Class QSortFilterProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSortFilterProxyModel::QPrivateSignal (0x0x7f813373df00) 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 (0x0x7f81335070d0) 0 + vptr=((& QSortFilterProxyModel::_ZTV21QSortFilterProxyModel) + 16u) + QAbstractProxyModel (0x0x7f8133507138) 0 + primary-for QSortFilterProxyModel (0x0x7f81335070d0) + QAbstractItemModel (0x0x7f81335071a0) 0 + primary-for QAbstractProxyModel (0x0x7f8133507138) + QObject (0x0x7f813373dea0) 0 + primary-for QAbstractItemModel (0x0x7f81335071a0) + +Class QStringListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStringListModel::QPrivateSignal (0x0x7f8133536000) 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 (0x0x7f8133507208) 0 + vptr=((& QStringListModel::_ZTV16QStringListModel) + 16u) + QAbstractListModel (0x0x7f8133507270) 0 + primary-for QStringListModel (0x0x7f8133507208) + QAbstractItemModel (0x0x7f81335072d8) 0 + primary-for QAbstractListModel (0x0x7f8133507270) + QObject (0x0x7f813373df60) 0 + primary-for QAbstractItemModel (0x0x7f81335072d8) + +Class QJsonValue + size=24 align=8 + base size=20 base align=8 +QJsonValue (0x0x7f8133536060) 0 + +Class QJsonValueRef + size=16 align=8 + base size=12 base align=8 +QJsonValueRef (0x0x7f8133536120) 0 + +Class QJsonValuePtr + size=24 align=8 + base size=24 base align=8 +QJsonValuePtr (0x0x7f81335361e0) 0 + +Class QJsonValueRefPtr + size=16 align=8 + base size=16 base align=8 +QJsonValueRefPtr (0x0x7f8133536240) 0 + +Class QJsonArray::iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::iterator (0x0x7f8133536300) 0 + +Class QJsonArray::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::const_iterator (0x0x7f8133536360) 0 + +Class QJsonArray + size=16 align=8 + base size=16 base align=8 +QJsonArray (0x0x7f81335362a0) 0 + +Class QJsonParseError + size=8 align=4 + base size=8 base align=4 +QJsonParseError (0x0x7f81335363c0) 0 + +Class QJsonDocument + size=8 align=8 + base size=8 base align=8 +QJsonDocument (0x0x7f8133536420) 0 + +Class QJsonObject::iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::iterator (0x0x7f81335364e0) 0 + +Class QJsonObject::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::const_iterator (0x0x7f8133536540) 0 + +Class QJsonObject + size=16 align=8 + base size=16 base align=8 +QJsonObject (0x0x7f8133536480) 0 + +Class QEventLoop::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventLoop::QPrivateSignal (0x0x7f8133536660) 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 (0x0x7f8133507340) 0 + vptr=((& QEventLoop::_ZTV10QEventLoop) + 16u) + QObject (0x0x7f8133536600) 0 + primary-for QEventLoop (0x0x7f8133507340) + +Class QEventLoopLocker + size=8 align=8 + base size=8 base align=8 +QEventLoopLocker (0x0x7f8133536780) 0 + +Class QAbstractEventDispatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractEventDispatcher::QPrivateSignal (0x0x7f8133536840) 0 empty + +Class QAbstractEventDispatcher::TimerInfo + size=12 align=4 + base size=12 base align=4 +QAbstractEventDispatcher::TimerInfo (0x0x7f81335368a0) 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 (0x0x7f8133507478) 0 + vptr=((& QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher) + 16u) + QObject (0x0x7f81335367e0) 0 + primary-for QAbstractEventDispatcher (0x0x7f8133507478) + +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 (0x0x7f8133536900) 0 + vptr=((& QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter) + 16u) + +Class QBasicTimer + size=4 align=4 + base size=4 base align=4 +QBasicTimer (0x0x7f8133536960) 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 (0x0x7f8133536a80) 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 (0x0x7f8133507548) 0 + vptr=((& QTimerEvent::_ZTV11QTimerEvent) + 16u) + QEvent (0x0x7f8133536ae0) 0 + primary-for QTimerEvent (0x0x7f8133507548) + +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 (0x0x7f81335075b0) 0 + vptr=((& QChildEvent::_ZTV11QChildEvent) + 16u) + QEvent (0x0x7f8133536b40) 0 + primary-for QChildEvent (0x0x7f81335075b0) + +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 (0x0x7f8133507618) 0 + vptr=((& QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent) + 16u) + QEvent (0x0x7f8133536ba0) 0 + primary-for QDynamicPropertyChangeEvent (0x0x7f8133507618) + +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 (0x0x7f8133507680) 0 + vptr=((& QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent) + 16u) + QEvent (0x0x7f8133536c00) 0 + primary-for QDeferredDeleteEvent (0x0x7f8133507680) + +Class QCoreApplication::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QCoreApplication::QPrivateSignal (0x0x7f8133536cc0) 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 (0x0x7f81335076e8) 0 + vptr=((& QCoreApplication::_ZTV16QCoreApplication) + 16u) + QObject (0x0x7f8133536c60) 0 + primary-for QCoreApplication (0x0x7f81335076e8) + +Class __exception + size=40 align=8 + base size=40 base align=8 +__exception (0x0x7f8133536d20) 0 + +Class QMetaMethod + size=16 align=8 + base size=12 base align=8 +QMetaMethod (0x0x7f8133536d80) 0 + +Class QMetaEnum + size=16 align=8 + base size=12 base align=8 +QMetaEnum (0x0x7f8133536ea0) 0 + +Class QMetaProperty + size=32 align=8 + base size=32 base align=8 +QMetaProperty (0x0x7f813337e000) 0 + +Class QMetaClassInfo + size=16 align=8 + base size=12 base align=8 +QMetaClassInfo (0x0x7f813337e060) 0 + +Class QMimeData::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QMimeData::QPrivateSignal (0x0x7f813337e1e0) 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 (0x0x7f8133507958) 0 + vptr=((& QMimeData::_ZTV9QMimeData) + 16u) + QObject (0x0x7f813337e180) 0 + primary-for QMimeData (0x0x7f8133507958) + +Class QObjectCleanupHandler::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObjectCleanupHandler::QPrivateSignal (0x0x7f813337e2a0) 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 (0x0x7f81335079c0) 0 + vptr=((& QObjectCleanupHandler::_ZTV21QObjectCleanupHandler) + 16u) + QObject (0x0x7f813337e240) 0 + primary-for QObjectCleanupHandler (0x0x7f81335079c0) + +Class QtSharedPointer::NormalDeleter + size=1 align=1 + base size=0 base align=1 +QtSharedPointer::NormalDeleter (0x0x7f813337e3c0) 0 empty + +Class QtSharedPointer::ExternalRefCountData + size=16 align=8 + base size=16 base align=8 +QtSharedPointer::ExternalRefCountData (0x0x7f813337e540) 0 + +Class QSharedMemory::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSharedMemory::QPrivateSignal (0x0x7f813337ec00) 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 (0x0x7f8133507d68) 0 + vptr=((& QSharedMemory::_ZTV13QSharedMemory) + 16u) + QObject (0x0x7f813337eba0) 0 + primary-for QSharedMemory (0x0x7f8133507d68) + +Class QSignalMapper::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalMapper::QPrivateSignal (0x0x7f813337ecc0) 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 (0x0x7f8133507dd0) 0 + vptr=((& QSignalMapper::_ZTV13QSignalMapper) + 16u) + QObject (0x0x7f813337ec60) 0 + primary-for QSignalMapper (0x0x7f8133507dd0) + +Class QSocketNotifier::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSocketNotifier::QPrivateSignal (0x0x7f813337ed80) 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 (0x0x7f8133507e38) 0 + vptr=((& QSocketNotifier::_ZTV15QSocketNotifier) + 16u) + QObject (0x0x7f813337ed20) 0 + primary-for QSocketNotifier (0x0x7f8133507e38) + +Class QSystemSemaphore + size=8 align=8 + base size=8 base align=8 +QSystemSemaphore (0x0x7f813337ede0) 0 + +Class QTimer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimer::QPrivateSignal (0x0x7f813337ef00) 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 (0x0x7f8133507ea0) 0 + vptr=((& QTimer::_ZTV6QTimer) + 16u) + QObject (0x0x7f813337eea0) 0 + primary-for QTimer (0x0x7f8133507ea0) + +Class QTranslator::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTranslator::QPrivateSignal (0x0x7f81330e00c0) 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 (0x0x7f8133507f70) 0 + vptr=((& QTranslator::_ZTV11QTranslator) + 16u) + QObject (0x0x7f81330e0060) 0 + primary-for QTranslator (0x0x7f8133507f70) + +Class QMimeType + size=8 align=8 + base size=8 base align=8 +QMimeType (0x0x7f81330e0120) 0 + +Class QMimeDatabase + size=8 align=8 + base size=8 base align=8 +QMimeDatabase (0x0x7f81330e02a0) 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 (0x0x7f81330e0300) 0 nearly-empty + vptr=((& QFactoryInterface::_ZTV17QFactoryInterface) + 16u) + +Class QLibrary::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLibrary::QPrivateSignal (0x0x7f81330e0420) 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 (0x0x7f8133507c30) 0 + vptr=((& QLibrary::_ZTV8QLibrary) + 16u) + QObject (0x0x7f81330e03c0) 0 + primary-for QLibrary (0x0x7f8133507c30) + +Class QStaticPlugin + size=16 align=8 + base size=16 base align=8 +QStaticPlugin (0x0x7f81330e0540) 0 + +Class QPluginLoader::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPluginLoader::QPrivateSignal (0x0x7f81330e06c0) 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 (0x0x7f8133153068) 0 + vptr=((& QPluginLoader::_ZTV13QPluginLoader) + 16u) + QObject (0x0x7f81330e0660) 0 + primary-for QPluginLoader (0x0x7f8133153068) + +Class QUuid + size=16 align=4 + base size=16 base align=4 +QUuid (0x0x7f81330e0720) 0 + +Class QAbstractState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractState::QPrivateSignal (0x0x7f81330e08a0) 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 (0x0x7f8133153138) 0 + vptr=((& QAbstractState::_ZTV14QAbstractState) + 16u) + QObject (0x0x7f81330e0840) 0 + primary-for QAbstractState (0x0x7f8133153138) + +Class QAbstractTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTransition::QPrivateSignal (0x0x7f81330e0960) 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 (0x0x7f81331531a0) 0 + vptr=((& QAbstractTransition::_ZTV19QAbstractTransition) + 16u) + QObject (0x0x7f81330e0900) 0 + primary-for QAbstractTransition (0x0x7f81331531a0) + +Class QEventTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventTransition::QPrivateSignal (0x0x7f81330e0a20) 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 (0x0x7f8133153208) 0 + vptr=((& QEventTransition::_ZTV16QEventTransition) + 16u) + QAbstractTransition (0x0x7f8133153270) 0 + primary-for QEventTransition (0x0x7f8133153208) + QObject (0x0x7f81330e09c0) 0 + primary-for QAbstractTransition (0x0x7f8133153270) + +Class QFinalState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFinalState::QPrivateSignal (0x0x7f81330e0ae0) 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 (0x0x7f81331532d8) 0 + vptr=((& QFinalState::_ZTV11QFinalState) + 16u) + QAbstractState (0x0x7f8133153340) 0 + primary-for QFinalState (0x0x7f81331532d8) + QObject (0x0x7f81330e0a80) 0 + primary-for QAbstractState (0x0x7f8133153340) + +Class QHistoryState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QHistoryState::QPrivateSignal (0x0x7f81330e0ba0) 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 (0x0x7f81331533a8) 0 + vptr=((& QHistoryState::_ZTV13QHistoryState) + 16u) + QAbstractState (0x0x7f8133153410) 0 + primary-for QHistoryState (0x0x7f81331533a8) + QObject (0x0x7f81330e0b40) 0 + primary-for QAbstractState (0x0x7f8133153410) + +Class QSignalTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalTransition::QPrivateSignal (0x0x7f81330e0c60) 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 (0x0x7f8133153478) 0 + vptr=((& QSignalTransition::_ZTV17QSignalTransition) + 16u) + QAbstractTransition (0x0x7f81331534e0) 0 + primary-for QSignalTransition (0x0x7f8133153478) + QObject (0x0x7f81330e0c00) 0 + primary-for QAbstractTransition (0x0x7f81331534e0) + +Class QState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QState::QPrivateSignal (0x0x7f81330e0d20) 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 (0x0x7f8133153548) 0 + vptr=((& QState::_ZTV6QState) + 16u) + QAbstractState (0x0x7f81331535b0) 0 + primary-for QState (0x0x7f8133153548) + QObject (0x0x7f81330e0cc0) 0 + primary-for QAbstractState (0x0x7f81331535b0) + +Class QStateMachine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStateMachine::QPrivateSignal (0x0x7f81330e0e40) 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 (0x0x7f8133153750) 0 + vptr=((& QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE) + 16u) + QEvent (0x0x7f81330e0ea0) 0 + primary-for QStateMachine::SignalEvent (0x0x7f8133153750) + +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 (0x0x7f81331537b8) 0 + vptr=((& QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE) + 16u) + QEvent (0x0x7f81330e0f00) 0 + primary-for QStateMachine::WrappedEvent (0x0x7f81331537b8) + +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 (0x0x7f8133153618) 0 + vptr=((& QStateMachine::_ZTV13QStateMachine) + 16u) + QState (0x0x7f8133153680) 0 + primary-for QStateMachine (0x0x7f8133153618) + QAbstractState (0x0x7f81331536e8) 0 + primary-for QState (0x0x7f8133153680) + QObject (0x0x7f81330e0de0) 0 + primary-for QAbstractState (0x0x7f81331536e8) + +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 (0x0x7f8133153820) 0 nearly-empty + vptr=((& QException::_ZTV10QException) + 16u) + std::exception (0x0x7f81330e0f60) 0 nearly-empty + primary-for QException (0x0x7f8133153820) + +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 (0x0x7f8133153888) 0 nearly-empty + vptr=((& QUnhandledException::_ZTV19QUnhandledException) + 16u) + QException (0x0x7f81331538f0) 0 nearly-empty + primary-for QUnhandledException (0x0x7f8133153888) + std::exception (0x0x7f8132e29000) 0 nearly-empty + primary-for QException (0x0x7f81331538f0) + +Class QtPrivate::ExceptionHolder + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionHolder (0x0x7f8132e29060) 0 + +Class QtPrivate::ExceptionStore + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionStore (0x0x7f8132e29120) 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 (0x0x7f8132e29180) 0 + vptr=((& QRunnable::_ZTV9QRunnable) + 16u) + +Class QBasicMutex + size=8 align=8 + base size=8 base align=8 +QBasicMutex (0x0x7f8132e291e0) 0 + +Class QMutex + size=8 align=8 + base size=8 base align=8 +QMutex (0x0x7f8133153a90) 0 + QBasicMutex (0x0x7f8132e29300) 0 + +Class QMutexLocker + size=8 align=8 + base size=8 base align=8 +QMutexLocker (0x0x7f8132e29360) 0 + +Class QtPrivate::ResultItem + size=16 align=8 + base size=16 base align=8 +QtPrivate::ResultItem (0x0x7f8132e293c0) 0 + +Class QtPrivate::ResultIteratorBase + size=16 align=8 + base size=12 base align=8 +QtPrivate::ResultIteratorBase (0x0x7f8132e29420) 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 (0x0x7f8132e295a0) 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 (0x0x7f8132e29660) 0 + vptr=((& QFutureInterfaceBase::_ZTV20QFutureInterfaceBase) + 16u) + +Class QFutureWatcherBase::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFutureWatcherBase::QPrivateSignal (0x0x7f8132e299c0) 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 (0x0x7f8132eb83a8) 0 + vptr=((& QFutureWatcherBase::_ZTV18QFutureWatcherBase) + 16u) + QObject (0x0x7f8132e29960) 0 + primary-for QFutureWatcherBase (0x0x7f8132eb83a8) + +Class QReadWriteLock + size=8 align=8 + base size=8 base align=8 +QReadWriteLock (0x0x7f8132e29ae0) 0 + +Class QReadLocker + size=8 align=8 + base size=8 base align=8 +QReadLocker (0x0x7f8132e29b40) 0 + +Class QWriteLocker + size=8 align=8 + base size=8 base align=8 +QWriteLocker (0x0x7f8132e29ba0) 0 + +Class QSemaphore + size=8 align=8 + base size=8 base align=8 +QSemaphore (0x0x7f8132e29c00) 0 + +Class QThread::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThread::QPrivateSignal (0x0x7f8132e29cc0) 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 (0x0x7f8132eb8750) 0 + vptr=((& QThread::_ZTV7QThread) + 16u) + QObject (0x0x7f8132e29c60) 0 + primary-for QThread (0x0x7f8132eb8750) + +Class QThreadPool::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThreadPool::QPrivateSignal (0x0x7f8132e29d80) 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 (0x0x7f8132eb87b8) 0 + vptr=((& QThreadPool::_ZTV11QThreadPool) + 16u) + QObject (0x0x7f8132e29d20) 0 + primary-for QThreadPool (0x0x7f8132eb87b8) + +Class QThreadStorageData + size=4 align=4 + base size=4 base align=4 +QThreadStorageData (0x0x7f8132e29de0) 0 + +Class QWaitCondition + size=8 align=8 + base size=8 base align=8 +QWaitCondition (0x0x7f8132e29ea0) 0 + +Class QBitArray + size=8 align=8 + base size=8 base align=8 +QBitArray (0x0x7f8132c01480) 0 + +Class QBitRef + size=16 align=8 + base size=12 base align=8 +QBitRef (0x0x7f8132c014e0) 0 + +Class QByteArrayMatcher::Data + size=272 align=8 + base size=272 base align=8 +QByteArrayMatcher::Data (0x0x7f8132c01660) 0 + +Class QByteArrayMatcher + size=1040 align=8 + base size=1040 base align=8 +QByteArrayMatcher (0x0x7f8132c01600) 0 + +Class QCollatorSortKey + size=8 align=8 + base size=8 base align=8 +QCollatorSortKey (0x0x7f8132c017e0) 0 + +Class QCollator + size=8 align=8 + base size=8 base align=8 +QCollator (0x0x7f8132c018a0) 0 + +Class QCommandLineOption + size=8 align=8 + base size=8 base align=8 +QCommandLineOption (0x0x7f8132c01a80) 0 + +Class QCommandLineParser + size=8 align=8 + base size=8 base align=8 +QCommandLineParser (0x0x7f8132c01c00) 0 + +Class QCryptographicHash + size=8 align=8 + base size=8 base align=8 +QCryptographicHash (0x0x7f8132c01c60) 0 + +Class QElapsedTimer + size=16 align=8 + base size=16 base align=8 +QElapsedTimer (0x0x7f8132c01cc0) 0 + +Class QPoint + size=8 align=4 + base size=8 base align=4 +QPoint (0x0x7f8132c01d20) 0 + +Class QPointF + size=16 align=8 + base size=16 base align=8 +QPointF (0x0x7f8132c01e40) 0 + +Class QLine + size=16 align=4 + base size=16 base align=4 +QLine (0x0x7f8132c01f60) 0 + +Class QLineF + size=32 align=8 + base size=32 base align=8 +QLineF (0x0x7f8132d790c0) 0 + +Class QLinkedListData + size=32 align=8 + base size=32 base align=8 +QLinkedListData (0x0x7f8132d791e0) 0 + +Class QMargins + size=16 align=4 + base size=16 base align=4 +QMargins (0x0x7f8132d79540) 0 + +Class QMarginsF + size=32 align=8 + base size=32 base align=8 +QMarginsF (0x0x7f8132d79660) 0 + +Class QMessageAuthenticationCode + size=8 align=8 + base size=8 base align=8 +QMessageAuthenticationCode (0x0x7f8132d79780) 0 + +Class QSize + size=8 align=4 + base size=8 base align=4 +QSize (0x0x7f8132d79840) 0 + +Class QSizeF + size=16 align=8 + base size=16 base align=8 +QSizeF (0x0x7f8132d79960) 0 + +Class QRect + size=16 align=4 + base size=16 base align=4 +QRect (0x0x7f8132d79a80) 0 + +Class QRectF + size=32 align=8 + base size=32 base align=8 +QRectF (0x0x7f8132d79ba0) 0 + +Class QRegularExpression + size=8 align=8 + base size=8 base align=8 +QRegularExpression (0x0x7f8132d79cc0) 0 + +Class QRegularExpressionMatch + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatch (0x0x7f813288b000) 0 + +Class QRegularExpressionMatchIterator + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatchIterator (0x0x7f813288b180) 0 + +Class QAbstractConcatenable + size=1 align=1 + base size=0 base align=1 +QAbstractConcatenable (0x0x7f813288b3c0) 0 empty + +Class QTextBoundaryFinder + size=48 align=8 + base size=48 base align=8 +QTextBoundaryFinder (0x0x7f813288bde0) 0 + +Class QTimeLine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimeLine::QPrivateSignal (0x0x7f813288bf60) 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 (0x0x7f813294c0d0) 0 + vptr=((& QTimeLine::_ZTV9QTimeLine) + 16u) + QObject (0x0x7f813288bf00) 0 + primary-for QTimeLine (0x0x7f813294c0d0) + +Class QTimeZone::OffsetData + size=32 align=8 + base size=28 base align=8 +QTimeZone::OffsetData (0x0x7f813297c060) 0 + +Class QTimeZone + size=8 align=8 + base size=8 base align=8 +QTimeZone (0x0x7f813297c000) 0 + +Class QXmlStreamStringRef + size=16 align=8 + base size=16 base align=8 +QXmlStreamStringRef (0x0x7f813297c2a0) 0 + +Class QXmlStreamAttribute + size=80 align=8 + base size=73 base align=8 +QXmlStreamAttribute (0x0x7f813297c300) 0 + +Class QXmlStreamAttributes + size=8 align=8 + base size=8 base align=8 +QXmlStreamAttributes (0x0x7f813294c340) 0 + QVector (0x0x7f813297c4e0) 0 + +Class QXmlStreamNamespaceDeclaration + size=40 align=8 + base size=40 base align=8 +QXmlStreamNamespaceDeclaration (0x0x7f813297c540) 0 + +Class QXmlStreamNotationDeclaration + size=56 align=8 + base size=56 base align=8 +QXmlStreamNotationDeclaration (0x0x7f813297c660) 0 + +Class QXmlStreamEntityDeclaration + size=88 align=8 + base size=88 base align=8 +QXmlStreamEntityDeclaration (0x0x7f813297c780) 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 (0x0x7f813297c8a0) 0 nearly-empty + vptr=((& QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver) + 16u) + +Class QXmlStreamReader + size=8 align=8 + base size=8 base align=8 +QXmlStreamReader (0x0x7f813297c900) 0 + +Class QXmlStreamWriter + size=8 align=8 + base size=8 base align=8 +QXmlStreamWriter (0x0x7f813297ca20) 0 + +Class QNdefRecord + size=8 align=8 + base size=8 base align=8 +QNdefRecord (0x0x7f813297cb40) 0 + +Class QNdefFilter::Record + size=24 align=8 + base size=24 base align=8 +QNdefFilter::Record (0x0x7f813297cc60) 0 + +Class QNdefFilter + size=8 align=8 + base size=8 base align=8 +QNdefFilter (0x0x7f813297cc00) 0 + +Class QNdefMessage + size=8 align=8 + base size=8 base align=8 +QNdefMessage (0x0x7f813294c548) 0 + QList (0x0x7f813294c5b0) 0 + QListSpecialMethods (0x0x7f813297ce40) 0 empty + +Class QNdefNfcTextRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcTextRecord (0x0x7f813294c618) 0 + QNdefRecord (0x0x7f81326d1000) 0 + +Class QNdefNfcUriRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcUriRecord (0x0x7f813294c680) 0 + QNdefRecord (0x0x7f81326d1060) 0 + +Class QNdefNfcIconRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcIconRecord (0x0x7f813294c6e8) 0 + QNdefRecord (0x0x7f81326d10c0) 0 + +Class QNdefNfcSmartPosterRecord + size=16 align=8 + base size=16 base align=8 +QNdefNfcSmartPosterRecord (0x0x7f813294c750) 0 + QNdefRecord (0x0x7f81326d1120) 0 + +Class QNearFieldTarget::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldTarget::QPrivateSignal (0x0x7f81326d1240) 0 empty + +Class QNearFieldTarget::RequestId + size=8 align=8 + base size=8 base align=8 +QNearFieldTarget::RequestId (0x0x7f81326d12a0) 0 + +Vtable for QNearFieldTarget +QNearFieldTarget::_ZTV16QNearFieldTarget: 25u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QNearFieldTarget) +16 (int (*)(...))QNearFieldTarget::metaObject +24 (int (*)(...))QNearFieldTarget::qt_metacast +32 (int (*)(...))QNearFieldTarget::qt_metacall +40 (int (*)(...))QNearFieldTarget::~QNearFieldTarget +48 (int (*)(...))QNearFieldTarget::~QNearFieldTarget +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 (*)(...))QNearFieldTarget::url +128 (int (*)(...))__cxa_pure_virtual +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))QNearFieldTarget::hasNdefMessage +152 (int (*)(...))QNearFieldTarget::readNdefMessages +160 (int (*)(...))QNearFieldTarget::writeNdefMessages +168 (int (*)(...))QNearFieldTarget::sendCommand +176 (int (*)(...))QNearFieldTarget::sendCommands +184 (int (*)(...))QNearFieldTarget::waitForRequestCompleted +192 (int (*)(...))QNearFieldTarget::handleResponse + +Class QNearFieldTarget + size=24 align=8 + base size=24 base align=8 +QNearFieldTarget (0x0x7f813294c7b8) 0 + vptr=((& QNearFieldTarget::_ZTV16QNearFieldTarget) + 16u) + QObject (0x0x7f81326d11e0) 0 + primary-for QNearFieldTarget (0x0x7f813294c7b8) + +Class QNearFieldManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldManager::QPrivateSignal (0x0x7f81326d16c0) 0 empty + +Vtable for QNearFieldManager +QNearFieldManager::_ZTV17QNearFieldManager: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QNearFieldManager) +16 (int (*)(...))QNearFieldManager::metaObject +24 (int (*)(...))QNearFieldManager::qt_metacast +32 (int (*)(...))QNearFieldManager::qt_metacall +40 (int (*)(...))QNearFieldManager::~QNearFieldManager +48 (int (*)(...))QNearFieldManager::~QNearFieldManager +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 QNearFieldManager + size=24 align=8 + base size=24 base align=8 +QNearFieldManager (0x0x7f813294c8f0) 0 + vptr=((& QNearFieldManager::_ZTV17QNearFieldManager) + 16u) + QObject (0x0x7f81326d1660) 0 + primary-for QNearFieldManager (0x0x7f813294c8f0) + +Class QNearFieldShareManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldShareManager::QPrivateSignal (0x0x7f81326d1840) 0 empty + +Vtable for QNearFieldShareManager +QNearFieldShareManager::_ZTV22QNearFieldShareManager: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI22QNearFieldShareManager) +16 (int (*)(...))QNearFieldShareManager::metaObject +24 (int (*)(...))QNearFieldShareManager::qt_metacast +32 (int (*)(...))QNearFieldShareManager::qt_metacall +40 (int (*)(...))QNearFieldShareManager::~QNearFieldShareManager +48 (int (*)(...))QNearFieldShareManager::~QNearFieldShareManager +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 QNearFieldShareManager + size=24 align=8 + base size=24 base align=8 +QNearFieldShareManager (0x0x7f813294ca90) 0 + vptr=((& QNearFieldShareManager::_ZTV22QNearFieldShareManager) + 16u) + QObject (0x0x7f81326d17e0) 0 + primary-for QNearFieldShareManager (0x0x7f813294ca90) + +Class QNearFieldShareTarget::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldShareTarget::QPrivateSignal (0x0x7f81326d1a80) 0 empty + +Vtable for QNearFieldShareTarget +QNearFieldShareTarget::_ZTV21QNearFieldShareTarget: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QNearFieldShareTarget) +16 (int (*)(...))QNearFieldShareTarget::metaObject +24 (int (*)(...))QNearFieldShareTarget::qt_metacast +32 (int (*)(...))QNearFieldShareTarget::qt_metacall +40 (int (*)(...))QNearFieldShareTarget::~QNearFieldShareTarget +48 (int (*)(...))QNearFieldShareTarget::~QNearFieldShareTarget +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 QNearFieldShareTarget + size=24 align=8 + base size=24 base align=8 +QNearFieldShareTarget (0x0x7f813294cbc8) 0 + vptr=((& QNearFieldShareTarget::_ZTV21QNearFieldShareTarget) + 16u) + QObject (0x0x7f81326d1a20) 0 + primary-for QNearFieldShareTarget (0x0x7f813294cbc8) + +Class QQmlNdefRecord::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QQmlNdefRecord::QPrivateSignal (0x0x7f81326d1b40) 0 empty + +Vtable for QQmlNdefRecord +QQmlNdefRecord::_ZTV14QQmlNdefRecord: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI14QQmlNdefRecord) +16 (int (*)(...))QQmlNdefRecord::metaObject +24 (int (*)(...))QQmlNdefRecord::qt_metacast +32 (int (*)(...))QQmlNdefRecord::qt_metacall +40 (int (*)(...))QQmlNdefRecord::~QQmlNdefRecord +48 (int (*)(...))QQmlNdefRecord::~QQmlNdefRecord +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 QQmlNdefRecord + size=24 align=8 + base size=24 base align=8 +QQmlNdefRecord (0x0x7f813294cc30) 0 + vptr=((& QQmlNdefRecord::_ZTV14QQmlNdefRecord) + 16u) + QObject (0x0x7f81326d1ae0) 0 + primary-for QQmlNdefRecord (0x0x7f813294cc30) + diff --git a/tests/auto/bic/data/QtNfc.5.6.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtNfc.5.6.0.linux-gcc-amd64.txt new file mode 100644 index 0000000..f80e58e --- /dev/null +++ b/tests/auto/bic/data/QtNfc.5.6.0.linux-gcc-amd64.txt @@ -0,0 +1,4111 @@ +Class std::__true_type + size=1 align=1 + base size=0 base align=1 +std::__true_type (0x0x7fee649b4ae0) 0 empty + +Class std::__false_type + size=1 align=1 + base size=0 base align=1 +std::__false_type (0x0x7fee649b4b40) 0 empty + +Class std::input_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::input_iterator_tag (0x0x7fee64a72780) 0 empty + +Class std::output_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::output_iterator_tag (0x0x7fee64a727e0) 0 empty + +Class std::forward_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::forward_iterator_tag (0x0x7fee649ef6e8) 0 empty + std::input_iterator_tag (0x0x7fee64a72840) 0 empty + +Class std::bidirectional_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::bidirectional_iterator_tag (0x0x7fee649ef750) 0 empty + std::forward_iterator_tag (0x0x7fee649ef7b8) 0 empty + std::input_iterator_tag (0x0x7fee64a728a0) 0 empty + +Class std::random_access_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::random_access_iterator_tag (0x0x7fee649ef820) 0 empty + std::bidirectional_iterator_tag (0x0x7fee649ef888) 0 empty + std::forward_iterator_tag (0x0x7fee649ef8f0) 0 empty + std::input_iterator_tag (0x0x7fee64a72900) 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 (0x0x7fee64a72de0) 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 (0x0x7fee64a72e40) 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 (0x0x7fee64a72ea0) 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 (0x0x7fee64a72f00) 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 (0x0x7fee64a72f60) 0 empty + +Class wait + size=4 align=4 + base size=4 base align=4 +wait (0x0x7fee64b059c0) 0 + +Class __locale_struct + size=232 align=8 + base size=232 base align=8 +__locale_struct (0x0x7fee64b05c00) 0 + +Class timespec + size=16 align=8 + base size=16 base align=8 +timespec (0x0x7fee64b05cc0) 0 + +Class timeval + size=16 align=8 + base size=16 base align=8 +timeval (0x0x7fee64b05d20) 0 + +Class pthread_attr_t + size=56 align=8 + base size=56 base align=8 +pthread_attr_t (0x0x7fee64b05de0) 0 + +Class __pthread_internal_list + size=16 align=8 + base size=16 base align=8 +__pthread_internal_list (0x0x7fee64b05e40) 0 + +Class random_data + size=48 align=8 + base size=48 base align=8 +random_data (0x0x7fee637b0300) 0 + +Class drand48_data + size=24 align=8 + base size=24 base align=8 +drand48_data (0x0x7fee637b0360) 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 (0x0x7fee637b03c0) 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 (0x0x7fee649efbc8) 0 nearly-empty + vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16u) + std::exception (0x0x7fee637b0420) 0 nearly-empty + primary-for std::bad_exception (0x0x7fee649efbc8) + +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 (0x0x7fee649efc30) 0 nearly-empty + vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16u) + std::exception (0x0x7fee637b0480) 0 nearly-empty + primary-for std::bad_alloc (0x0x7fee649efc30) + +Class std::nothrow_t + size=1 align=1 + base size=0 base align=1 +std::nothrow_t (0x0x7fee637b04e0) 0 empty + +Class qIsNull(double)::U + size=8 align=8 + base size=8 base align=8 +qIsNull(double)::U (0x0x7fee6354ac00) 0 + +Class qIsNull(float)::U + size=4 align=4 + base size=4 base align=4 +qIsNull(float)::U (0x0x7fee6354ac60) 0 + +Class QtPrivate::big_ + size=2 align=1 + base size=2 base align=1 +QtPrivate::big_ (0x0x7fee6354ae40) 0 + +Class QSysInfo + size=1 align=1 + base size=0 base align=1 +QSysInfo (0x0x7fee6366dea0) 0 empty + +Class QMessageLogContext + size=32 align=8 + base size=32 base align=8 +QMessageLogContext (0x0x7fee6366df00) 0 + +Class QMessageLogger + size=32 align=8 + base size=32 base align=8 +QMessageLogger (0x0x7fee6366df60) 0 + +Class QFlag + size=4 align=4 + base size=4 base align=4 +QFlag (0x0x7fee636d4000) 0 + +Class QIncompatibleFlag + size=4 align=4 + base size=4 base align=4 +QIncompatibleFlag (0x0x7fee636d4180) 0 + +Class QAtomicInt + size=4 align=4 + base size=4 base align=4 +QAtomicInt (0x0x7fee6337f3a8) 0 + QAtomicInteger (0x0x7fee6337f410) 0 + QBasicAtomicInteger (0x0x7fee636d4cc0) 0 + +Class QInternal + size=1 align=1 + base size=0 base align=1 +QInternal (0x0x7fee6319ede0) 0 empty + +Class QGenericArgument + size=16 align=8 + base size=16 base align=8 +QGenericArgument (0x0x7fee62fdb2a0) 0 + +Class QGenericReturnArgument + size=16 align=8 + base size=16 base align=8 +QGenericReturnArgument (0x0x7fee63239618) 0 + QGenericArgument (0x0x7fee62fdb300) 0 + +Class QMetaObject + size=48 align=8 + base size=48 base align=8 +QMetaObject (0x0x7fee62fdb480) 0 + +Class QMetaObject::Connection + size=8 align=8 + base size=8 base align=8 +QMetaObject::Connection (0x0x7fee62fdb540) 0 + +Class QLatin1Char + size=1 align=1 + base size=1 base align=1 +QLatin1Char (0x0x7fee62fdb600) 0 + +Class QChar + size=2 align=2 + base size=2 base align=2 +QChar (0x0x7fee62fdb660) 0 + +Class QtPrivate::RefCount + size=4 align=4 + base size=4 base align=4 +QtPrivate::RefCount (0x0x7fee62fdb7e0) 0 + +Class QArrayData + size=24 align=8 + base size=24 base align=8 +QArrayData (0x0x7fee62fdb8a0) 0 + +Class QtPrivate::QContainerImplHelper + size=1 align=1 + base size=0 base align=1 +QtPrivate::QContainerImplHelper (0x0x7fee62fdbcc0) 0 empty + +Class lconv + size=96 align=8 + base size=96 base align=8 +lconv (0x0x7fee62d67060) 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 (0x0x7fee62d670c0) 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 (0x0x7fee62d67f60) 0 + +Class __sched_param + size=4 align=4 + base size=4 base align=4 +__sched_param (0x0x7fee62e2e000) 0 + +Class timex + size=208 align=8 + base size=208 base align=8 +timex (0x0x7fee62e2e0c0) 0 + +Class tm + size=56 align=8 + base size=56 base align=8 +tm (0x0x7fee62e2e120) 0 + +Class itimerspec + size=32 align=8 + base size=32 base align=8 +itimerspec (0x0x7fee62e2e180) 0 + +Class _pthread_cleanup_buffer + size=32 align=8 + base size=32 base align=8 +_pthread_cleanup_buffer (0x0x7fee62e2e1e0) 0 + +Class __pthread_cleanup_frame + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_frame (0x0x7fee62e2e300) 0 + +Class __pthread_cleanup_class + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_class (0x0x7fee62e2e360) 0 + +Class std::locale + size=8 align=8 + base size=8 base align=8 +std::locale (0x0x7fee62e2ec00) 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 (0x0x7fee62e2ec60) 0 + vptr=((& std::locale::facet::_ZTVNSt6locale5facetE) + 16u) + +Class std::locale::id + size=8 align=8 + base size=8 base align=8 +std::locale::id (0x0x7fee62e2ecc0) 0 + +Class std::locale::_Impl + size=40 align=8 + base size=40 base align=8 +std::locale::_Impl (0x0x7fee62e2ed20) 0 + +Class std::__cow_string + size=8 align=8 + base size=8 base align=8 +std::__cow_string (0x0x7fee62cec120) 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 (0x0x7fee62bbe7b8) 0 + vptr=((& std::logic_error::_ZTVSt11logic_error) + 16u) + std::exception (0x0x7fee62cec1e0) 0 nearly-empty + primary-for std::logic_error (0x0x7fee62bbe7b8) + +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 (0x0x7fee62bbe820) 0 + vptr=((& std::domain_error::_ZTVSt12domain_error) + 16u) + std::logic_error (0x0x7fee62bbe888) 0 + primary-for std::domain_error (0x0x7fee62bbe820) + std::exception (0x0x7fee62cec240) 0 nearly-empty + primary-for std::logic_error (0x0x7fee62bbe888) + +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 (0x0x7fee62bbe8f0) 0 + vptr=((& std::invalid_argument::_ZTVSt16invalid_argument) + 16u) + std::logic_error (0x0x7fee62bbe958) 0 + primary-for std::invalid_argument (0x0x7fee62bbe8f0) + std::exception (0x0x7fee62cec2a0) 0 nearly-empty + primary-for std::logic_error (0x0x7fee62bbe958) + +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 (0x0x7fee62bbe9c0) 0 + vptr=((& std::length_error::_ZTVSt12length_error) + 16u) + std::logic_error (0x0x7fee62bbea28) 0 + primary-for std::length_error (0x0x7fee62bbe9c0) + std::exception (0x0x7fee62cec300) 0 nearly-empty + primary-for std::logic_error (0x0x7fee62bbea28) + +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 (0x0x7fee62bbea90) 0 + vptr=((& std::out_of_range::_ZTVSt12out_of_range) + 16u) + std::logic_error (0x0x7fee62bbeaf8) 0 + primary-for std::out_of_range (0x0x7fee62bbea90) + std::exception (0x0x7fee62cec360) 0 nearly-empty + primary-for std::logic_error (0x0x7fee62bbeaf8) + +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 (0x0x7fee62bbeb60) 0 + vptr=((& std::runtime_error::_ZTVSt13runtime_error) + 16u) + std::exception (0x0x7fee62cec3c0) 0 nearly-empty + primary-for std::runtime_error (0x0x7fee62bbeb60) + +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 (0x0x7fee62bbebc8) 0 + vptr=((& std::range_error::_ZTVSt11range_error) + 16u) + std::runtime_error (0x0x7fee62bbec30) 0 + primary-for std::range_error (0x0x7fee62bbebc8) + std::exception (0x0x7fee62cec420) 0 nearly-empty + primary-for std::runtime_error (0x0x7fee62bbec30) + +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 (0x0x7fee62bbec98) 0 + vptr=((& std::overflow_error::_ZTVSt14overflow_error) + 16u) + std::runtime_error (0x0x7fee62bbed00) 0 + primary-for std::overflow_error (0x0x7fee62bbec98) + std::exception (0x0x7fee62cec480) 0 nearly-empty + primary-for std::runtime_error (0x0x7fee62bbed00) + +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 (0x0x7fee62bbed68) 0 + vptr=((& std::underflow_error::_ZTVSt15underflow_error) + 16u) + std::runtime_error (0x0x7fee62bbedd0) 0 + primary-for std::underflow_error (0x0x7fee62bbed68) + std::exception (0x0x7fee62cec4e0) 0 nearly-empty + primary-for std::runtime_error (0x0x7fee62bbedd0) + +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 (0x0x7fee62cec600) 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 (0x0x7fee62bbee38) 0 + vptr=((& std::ios_base::system_error::_ZTVNSt8ios_base12system_errorE) + 16u) + std::runtime_error (0x0x7fee62bbeea0) 0 + primary-for std::ios_base::system_error (0x0x7fee62bbee38) + std::exception (0x0x7fee62cec5a0) 0 nearly-empty + primary-for std::runtime_error (0x0x7fee62bbeea0) + +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 (0x0x7fee62bbef08) 0 + vptr=((& std::ios_base::failure::_ZTVNSt8ios_base7failureB5cxx11E) + 16u) + std::ios_base::system_error (0x0x7fee62bbef70) 0 + primary-for std::ios_base::failure (0x0x7fee62bbef08) + std::runtime_error (0x0x7fee62bbe068) 0 + primary-for std::ios_base::system_error (0x0x7fee62bbef70) + std::exception (0x0x7fee62cec660) 0 nearly-empty + primary-for std::runtime_error (0x0x7fee62bbe068) + +Class std::ios_base::_Callback_list + size=24 align=8 + base size=24 base align=8 +std::ios_base::_Callback_list (0x0x7fee62cec6c0) 0 + +Class std::ios_base::_Words + size=16 align=8 + base size=16 base align=8 +std::ios_base::_Words (0x0x7fee62cec720) 0 + +Class std::ios_base::Init + size=1 align=1 + base size=0 base align=1 +std::ios_base::Init (0x0x7fee62cec780) 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 (0x0x7fee62cec540) 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 (0x0x7fee62cecea0) 0 empty + +Class std::__num_base + size=1 align=1 + base size=0 base align=1 +std::__num_base (0x0x7fee62a3c5a0) 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 (0x0x7fee625644e0 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 (0x0x7fee625645b0 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 (0x0x7fee62564958 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 (0x0x7fee62564a28 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 (0x0x7fee627c2cc0) 0 + +Class QByteArray + size=8 align=8 + base size=8 base align=8 +QByteArray (0x0x7fee627c2d20) 0 + +Class QByteRef + size=16 align=8 + base size=12 base align=8 +QByteRef (0x0x7fee6264a360) 0 + +Class QLatin1String + size=16 align=8 + base size=16 base align=8 +QLatin1String (0x0x7fee6264a540) 0 + +Class QStringDataPtr + size=8 align=8 + base size=8 base align=8 +QStringDataPtr (0x0x7fee6264a780) 0 + +Class QString::Null + size=1 align=1 + base size=0 base align=1 +QString::Null (0x0x7fee6264a840) 0 empty + +Class QString + size=8 align=8 + base size=8 base align=8 +QString (0x0x7fee6264a7e0) 0 + +Class QCharRef + size=16 align=8 + base size=12 base align=8 +QCharRef (0x0x7fee6264aea0) 0 + +Class QStringRef + size=16 align=8 + base size=16 base align=8 +QStringRef (0x0x7fee624a42a0) 0 + +Class QtPrivate::QHashCombine + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombine (0x0x7fee624a4660) 0 empty + +Class QtPrivate::QHashCombineCommutative + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombineCommutative (0x0x7fee624a46c0) 0 empty + +Class std::__detail::_List_node_base + size=16 align=8 + base size=16 base align=8 +std::__detail::_List_node_base (0x0x7fee624a4720) 0 + +Class QListData::NotArrayCompatibleLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotArrayCompatibleLayout (0x0x7fee624a4ae0) 0 empty + +Class QListData::NotIndirectLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotIndirectLayout (0x0x7fee624a4b40) 0 empty + +Class QListData::ArrayCompatibleLayout + size=1 align=1 + base size=1 base align=1 +QListData::ArrayCompatibleLayout (0x0x7fee626e0a28) 0 empty + QListData::NotIndirectLayout (0x0x7fee624a4ba0) 0 empty + +Class QListData::InlineWithPaddingLayout + size=1 align=1 + base size=1 base align=1 +QListData::InlineWithPaddingLayout (0x0x7fee622c6310) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7fee624a4c00) 0 empty + QListData::NotIndirectLayout (0x0x7fee624a4c60) 0 empty + +Class QListData::IndirectLayout + size=1 align=1 + base size=1 base align=1 +QListData::IndirectLayout (0x0x7fee626e0a90) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7fee624a4cc0) 0 empty + +Class QListData::Data + size=24 align=8 + base size=24 base align=8 +QListData::Data (0x0x7fee624a4d20) 0 + +Class QListData + size=8 align=8 + base size=8 base align=8 +QListData (0x0x7fee624a4a80) 0 + +Class QRegExp + size=8 align=8 + base size=8 base align=8 +QRegExp (0x0x7fee62336900) 0 + +Class QStringMatcher::Data + size=272 align=8 + base size=272 base align=8 +QStringMatcher::Data (0x0x7fee62336ae0) 0 + +Class QStringMatcher + size=1048 align=8 + base size=1048 base align=8 +QStringMatcher (0x0x7fee62336a80) 0 + +Class QStringList + size=8 align=8 + base size=8 base align=8 +QStringList (0x0x7fee626e0ea0) 0 + QList (0x0x7fee626e0f08) 0 + QListSpecialMethods (0x0x7fee62336cc0) 0 empty + +Class QScopedPointerPodDeleter + size=1 align=1 + base size=0 base align=1 +QScopedPointerPodDeleter (0x0x7fee62336f00) 0 empty + +Class std::_Bit_reference + size=16 align=8 + base size=16 base align=8 +std::_Bit_reference (0x0x7fee6207a600) 0 + +Class std::_Bit_iterator_base + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator_base (0x0x7fee62082a90) 0 + std::iterator (0x0x7fee6207a6c0) 0 empty + +Class std::_Bit_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator (0x0x7fee62082af8) 0 + std::_Bit_iterator_base (0x0x7fee62082b60) 0 + std::iterator (0x0x7fee6207a720) 0 empty + +Class std::_Bit_const_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_const_iterator (0x0x7fee62082bc8) 0 + std::_Bit_iterator_base (0x0x7fee62082c30) 0 + std::iterator (0x0x7fee6207a780) 0 empty + +Class std::_Rb_tree_node_base + size=32 align=8 + base size=32 base align=8 +std::_Rb_tree_node_base (0x0x7fee6207ab40) 0 + +Class QtPrivate::AbstractDebugStreamFunction + size=16 align=8 + base size=16 base align=8 +QtPrivate::AbstractDebugStreamFunction (0x0x7fee61b8c060) 0 + +Class QtPrivate::AbstractComparatorFunction + size=24 align=8 + base size=24 base align=8 +QtPrivate::AbstractComparatorFunction (0x0x7fee61b8c120) 0 + +Class QtPrivate::AbstractConverterFunction + size=8 align=8 + base size=8 base align=8 +QtPrivate::AbstractConverterFunction (0x0x7fee61b8c240) 0 + +Class QMetaType + size=80 align=8 + base size=80 base align=8 +QMetaType (0x0x7fee61b8c3c0) 0 + +Class QtMetaTypePrivate::VariantData + size=24 align=8 + base size=20 base align=8 +QtMetaTypePrivate::VariantData (0x0x7fee61b8c660) 0 + +Class QtMetaTypePrivate::VectorBoolElements + size=1 align=1 + base size=0 base align=1 +QtMetaTypePrivate::VectorBoolElements (0x0x7fee61b8c780) 0 empty + +Class QtMetaTypePrivate::QSequentialIterableImpl + size=104 align=8 + base size=104 base align=8 +QtMetaTypePrivate::QSequentialIterableImpl (0x0x7fee61cbc180) 0 + +Class QtMetaTypePrivate::QAssociativeIterableImpl + size=112 align=8 + base size=112 base align=8 +QtMetaTypePrivate::QAssociativeIterableImpl (0x0x7fee61cbc540) 0 + +Class QtMetaTypePrivate::QPairVariantInterfaceImpl + size=40 align=8 + base size=40 base align=8 +QtMetaTypePrivate::QPairVariantInterfaceImpl (0x0x7fee61cbc780) 0 + +Class QtPrivate::QSlotObjectBase + size=16 align=8 + base size=16 base align=8 +QtPrivate::QSlotObjectBase (0x0x7fee61a987e0) 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 (0x0x7fee61a98960) 0 + vptr=((& QObjectData::_ZTV11QObjectData) + 16u) + +Class QObject::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObject::QPrivateSignal (0x0x7fee61a98b40) 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 (0x0x7fee61a98ae0) 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 (0x0x7fee61a98ea0) 0 nearly-empty + vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16u) + +Class QSignalBlocker + size=16 align=8 + base size=10 base align=8 +QSignalBlocker (0x0x7fee61a98f00) 0 + +Class QAbstractAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractAnimation::QPrivateSignal (0x0x7fee61794000) 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 (0x0x7fee61ce4d68) 0 + vptr=((& QAbstractAnimation::_ZTV18QAbstractAnimation) + 16u) + QObject (0x0x7fee61a98f60) 0 + primary-for QAbstractAnimation (0x0x7fee61ce4d68) + +Class QAnimationDriver::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationDriver::QPrivateSignal (0x0x7fee617940c0) 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 (0x0x7fee61ce4dd0) 0 + vptr=((& QAnimationDriver::_ZTV16QAnimationDriver) + 16u) + QObject (0x0x7fee61794060) 0 + primary-for QAnimationDriver (0x0x7fee61ce4dd0) + +Class QAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationGroup::QPrivateSignal (0x0x7fee61794180) 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 (0x0x7fee61ce4e38) 0 + vptr=((& QAnimationGroup::_ZTV15QAnimationGroup) + 16u) + QAbstractAnimation (0x0x7fee61ce4ea0) 0 + primary-for QAnimationGroup (0x0x7fee61ce4e38) + QObject (0x0x7fee61794120) 0 + primary-for QAbstractAnimation (0x0x7fee61ce4ea0) + +Class QParallelAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QParallelAnimationGroup::QPrivateSignal (0x0x7fee61794240) 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 (0x0x7fee61ce4f08) 0 + vptr=((& QParallelAnimationGroup::_ZTV23QParallelAnimationGroup) + 16u) + QAnimationGroup (0x0x7fee61ce4f70) 0 + primary-for QParallelAnimationGroup (0x0x7fee61ce4f08) + QAbstractAnimation (0x0x7fee617ce000) 0 + primary-for QAnimationGroup (0x0x7fee61ce4f70) + QObject (0x0x7fee617941e0) 0 + primary-for QAbstractAnimation (0x0x7fee617ce000) + +Class QPauseAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPauseAnimation::QPrivateSignal (0x0x7fee61794300) 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 (0x0x7fee617ce068) 0 + vptr=((& QPauseAnimation::_ZTV15QPauseAnimation) + 16u) + QAbstractAnimation (0x0x7fee617ce0d0) 0 + primary-for QPauseAnimation (0x0x7fee617ce068) + QObject (0x0x7fee617942a0) 0 + primary-for QAbstractAnimation (0x0x7fee617ce0d0) + +Class QEasingCurve + size=8 align=8 + base size=8 base align=8 +QEasingCurve (0x0x7fee61863660) 0 + +Class QMapNodeBase + size=24 align=8 + base size=24 base align=8 +QMapNodeBase (0x0x7fee618637e0) 0 + +Class QMapDataBase + size=40 align=8 + base size=40 base align=8 +QMapDataBase (0x0x7fee618638a0) 0 + +Class QHashData::Node + size=16 align=8 + base size=16 base align=8 +QHashData::Node (0x0x7fee61863c60) 0 + +Class QHashData + size=48 align=8 + base size=48 base align=8 +QHashData (0x0x7fee61863c00) 0 + +Class QHashDummyValue + size=1 align=1 + base size=0 base align=1 +QHashDummyValue (0x0x7fee61863cc0) 0 empty + +Class QVariant::PrivateShared + size=16 align=8 + base size=12 base align=8 +QVariant::PrivateShared (0x0x7fee615e9720) 0 + +Class QVariant::Private::Data + size=8 align=8 + base size=8 base align=8 +QVariant::Private::Data (0x0x7fee615e97e0) 0 + +Class QVariant::Private + size=16 align=8 + base size=12 base align=8 +QVariant::Private (0x0x7fee615e9780) 0 + +Class QVariant::Handler + size=72 align=8 + base size=72 base align=8 +QVariant::Handler (0x0x7fee615e9840) 0 + +Class QVariant + size=16 align=8 + base size=16 base align=8 +QVariant (0x0x7fee615e96c0) 0 + +Class QVariantComparisonHelper + size=8 align=8 + base size=8 base align=8 +QVariantComparisonHelper (0x0x7fee615e9b40) 0 + +Class QSequentialIterable::const_iterator + size=112 align=8 + base size=112 base align=8 +QSequentialIterable::const_iterator (0x0x7fee615e9c00) 0 + +Class QSequentialIterable + size=104 align=8 + base size=104 base align=8 +QSequentialIterable (0x0x7fee615e9ba0) 0 + +Class QAssociativeIterable::const_iterator + size=120 align=8 + base size=120 base align=8 +QAssociativeIterable::const_iterator (0x0x7fee615e9cc0) 0 + +Class QAssociativeIterable + size=112 align=8 + base size=112 base align=8 +QAssociativeIterable (0x0x7fee615e9c60) 0 + +Class QVariantAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QVariantAnimation::QPrivateSignal (0x0x7fee613b6900) 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 (0x0x7fee61405000) 0 + vptr=((& QVariantAnimation::_ZTV17QVariantAnimation) + 16u) + QAbstractAnimation (0x0x7fee61405068) 0 + primary-for QVariantAnimation (0x0x7fee61405000) + QObject (0x0x7fee613b68a0) 0 + primary-for QAbstractAnimation (0x0x7fee61405068) + +Class QPropertyAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPropertyAnimation::QPrivateSignal (0x0x7fee613b69c0) 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 (0x0x7fee61405138) 0 + vptr=((& QPropertyAnimation::_ZTV18QPropertyAnimation) + 16u) + QVariantAnimation (0x0x7fee614051a0) 0 + primary-for QPropertyAnimation (0x0x7fee61405138) + QAbstractAnimation (0x0x7fee61405208) 0 + primary-for QVariantAnimation (0x0x7fee614051a0) + QObject (0x0x7fee613b6960) 0 + primary-for QAbstractAnimation (0x0x7fee61405208) + +Class QSequentialAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSequentialAnimationGroup::QPrivateSignal (0x0x7fee613b6a80) 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 (0x0x7fee61405270) 0 + vptr=((& QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup) + 16u) + QAnimationGroup (0x0x7fee614052d8) 0 + primary-for QSequentialAnimationGroup (0x0x7fee61405270) + QAbstractAnimation (0x0x7fee61405340) 0 + primary-for QAnimationGroup (0x0x7fee614052d8) + QObject (0x0x7fee613b6a20) 0 + primary-for QAbstractAnimation (0x0x7fee61405340) + +Class QTextCodec::ConverterState + size=32 align=8 + base size=32 base align=8 +QTextCodec::ConverterState (0x0x7fee613b6b40) 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 (0x0x7fee613b6ae0) 0 nearly-empty + vptr=((& QTextCodec::_ZTV10QTextCodec) + 16u) + +Class QTextEncoder + size=40 align=8 + base size=40 base align=8 +QTextEncoder (0x0x7fee613b6c60) 0 + +Class QTextDecoder + size=40 align=8 + base size=40 base align=8 +QTextDecoder (0x0x7fee613b6cc0) 0 + +Class QSharedData + size=4 align=4 + base size=4 base align=4 +QSharedData (0x0x7fee613b6d20) 0 + +Class std::__numeric_limits_base + size=1 align=1 + base size=0 base align=1 +std::__numeric_limits_base (0x0x7fee613b6f00) 0 empty + +Class QDate + size=8 align=8 + base size=8 base align=8 +QDate (0x0x7fee614f26c0) 0 + +Class QTime + size=4 align=4 + base size=4 base align=4 +QTime (0x0x7fee614f2840) 0 + +Class QDateTime + size=8 align=8 + base size=8 base align=8 +QDateTime (0x0x7fee614f29c0) 0 + +Class QLibraryInfo + size=1 align=1 + base size=0 base align=1 +QLibraryInfo (0x0x7fee614f2ba0) 0 empty + +Class QIODevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIODevice::QPrivateSignal (0x0x7fee614f2c60) 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 (0x0x7fee61405618) 0 + vptr=((& QIODevice::_ZTV9QIODevice) + 16u) + QObject (0x0x7fee614f2c00) 0 + primary-for QIODevice (0x0x7fee61405618) + +Class QBuffer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBuffer::QPrivateSignal (0x0x7fee614f2de0) 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 (0x0x7fee61405750) 0 + vptr=((& QBuffer::_ZTV7QBuffer) + 16u) + QIODevice (0x0x7fee614057b8) 0 + primary-for QBuffer (0x0x7fee61405750) + QObject (0x0x7fee614f2d80) 0 + primary-for QIODevice (0x0x7fee614057b8) + +Class QDataStream + size=32 align=8 + base size=32 base align=8 +QDataStream (0x0x7fee614f2e40) 0 + +Class QLocale + size=8 align=8 + base size=8 base align=8 +QLocale (0x0x7fee614f2f00) 0 + +Class _IO_marker + size=24 align=8 + base size=24 base align=8 +_IO_marker (0x0x7fee612e62a0) 0 + +Class _IO_FILE + size=216 align=8 + base size=216 base align=8 +_IO_FILE (0x0x7fee612e6300) 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 (0x0x7fee612e63c0) 0 + vptr=((& QTextStream::_ZTV11QTextStream) + 16u) + +Class QTextStreamManipulator + size=40 align=8 + base size=38 base align=8 +QTextStreamManipulator (0x0x7fee612e65a0) 0 + +Class QContiguousCacheData + size=24 align=4 + base size=24 base align=4 +QContiguousCacheData (0x0x7fee612e67e0) 0 + +Class QDebug::Stream + size=80 align=8 + base size=76 base align=8 +QDebug::Stream (0x0x7fee612e6ae0) 0 + +Class QDebug + size=8 align=8 + base size=8 base align=8 +QDebug (0x0x7fee612e6a80) 0 + +Class QDebugStateSaver + size=8 align=8 + base size=8 base align=8 +QDebugStateSaver (0x0x7fee612e6c60) 0 + +Class QNoDebug + size=1 align=1 + base size=0 base align=1 +QNoDebug (0x0x7fee612e6d20) 0 empty + +Class QFileDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileDevice::QPrivateSignal (0x0x7fee612e6f00) 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 (0x0x7fee610f60d0) 0 + vptr=((& QFileDevice::_ZTV11QFileDevice) + 16u) + QIODevice (0x0x7fee610f6138) 0 + primary-for QFileDevice (0x0x7fee610f60d0) + QObject (0x0x7fee612e6ea0) 0 + primary-for QIODevice (0x0x7fee610f6138) + +Class QFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFile::QPrivateSignal (0x0x7fee611200c0) 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 (0x0x7fee610f6270) 0 + vptr=((& QFile::_ZTV5QFile) + 16u) + QFileDevice (0x0x7fee610f62d8) 0 + primary-for QFile (0x0x7fee610f6270) + QIODevice (0x0x7fee610f6340) 0 + primary-for QFileDevice (0x0x7fee610f62d8) + QObject (0x0x7fee61120060) 0 + primary-for QIODevice (0x0x7fee610f6340) + +Class QFileInfo + size=8 align=8 + base size=8 base align=8 +QFileInfo (0x0x7fee611201e0) 0 + +Class QDir + size=8 align=8 + base size=8 base align=8 +QDir (0x0x7fee611204e0) 0 + +Class QDirIterator + size=8 align=8 + base size=8 base align=8 +QDirIterator (0x0x7fee61120840) 0 + +Class QFileSelector::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSelector::QPrivateSignal (0x0x7fee61120a20) 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 (0x0x7fee610f6820) 0 + vptr=((& QFileSelector::_ZTV13QFileSelector) + 16u) + QObject (0x0x7fee611209c0) 0 + primary-for QFileSelector (0x0x7fee610f6820) + +Class QFileSystemWatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSystemWatcher::QPrivateSignal (0x0x7fee61120ae0) 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 (0x0x7fee610f6888) 0 + vptr=((& QFileSystemWatcher::_ZTV18QFileSystemWatcher) + 16u) + QObject (0x0x7fee61120a80) 0 + primary-for QFileSystemWatcher (0x0x7fee610f6888) + +Class QLockFile + size=8 align=8 + base size=8 base align=8 +QLockFile (0x0x7fee61120b40) 0 + +Class QLoggingCategory::AtomicBools + size=4 align=1 + base size=4 base align=1 +QLoggingCategory::AtomicBools (0x0x7fee61120cc0) 0 + +Class QLoggingCategory + size=24 align=8 + base size=24 base align=8 +QLoggingCategory (0x0x7fee61120c60) 0 + +Class QProcessEnvironment + size=8 align=8 + base size=8 base align=8 +QProcessEnvironment (0x0x7fee61120e40) 0 + +Class QProcess::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QProcess::QPrivateSignal (0x0x7fee60e740c0) 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 (0x0x7fee610f6a90) 0 + vptr=((& QProcess::_ZTV8QProcess) + 16u) + QIODevice (0x0x7fee610f6af8) 0 + primary-for QProcess (0x0x7fee610f6a90) + QObject (0x0x7fee60e74060) 0 + primary-for QIODevice (0x0x7fee610f6af8) + +Class QResource + size=8 align=8 + base size=8 base align=8 +QResource (0x0x7fee60e74120) 0 + +Class QSaveFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSaveFile::QPrivateSignal (0x0x7fee60e742a0) 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 (0x0x7fee610f6b60) 0 + vptr=((& QSaveFile::_ZTV9QSaveFile) + 16u) + QFileDevice (0x0x7fee610f6bc8) 0 + primary-for QSaveFile (0x0x7fee610f6b60) + QIODevice (0x0x7fee610f6c30) 0 + primary-for QFileDevice (0x0x7fee610f6bc8) + QObject (0x0x7fee60e74240) 0 + primary-for QIODevice (0x0x7fee610f6c30) + +Class QSettings::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSettings::QPrivateSignal (0x0x7fee60e74360) 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 (0x0x7fee610f6c98) 0 + vptr=((& QSettings::_ZTV9QSettings) + 16u) + QObject (0x0x7fee60e74300) 0 + primary-for QSettings (0x0x7fee610f6c98) + +Class QStandardPaths + size=1 align=1 + base size=0 base align=1 +QStandardPaths (0x0x7fee60e743c0) 0 empty + +Class QStorageInfo + size=8 align=8 + base size=8 base align=8 +QStorageInfo (0x0x7fee60e744e0) 0 + +Class QTemporaryDir + size=8 align=8 + base size=8 base align=8 +QTemporaryDir (0x0x7fee60e747e0) 0 + +Class QTemporaryFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTemporaryFile::QPrivateSignal (0x0x7fee60e74900) 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 (0x0x7fee610f6e38) 0 + vptr=((& QTemporaryFile::_ZTV14QTemporaryFile) + 16u) + QFile (0x0x7fee610f6ea0) 0 + primary-for QTemporaryFile (0x0x7fee610f6e38) + QFileDevice (0x0x7fee610f6f08) 0 + primary-for QFile (0x0x7fee610f6ea0) + QIODevice (0x0x7fee610f6f70) 0 + primary-for QFileDevice (0x0x7fee610f6f08) + QObject (0x0x7fee60e748a0) 0 + primary-for QIODevice (0x0x7fee610f6f70) + +Class QUrl + size=8 align=8 + base size=8 base align=8 +QUrl (0x0x7fee60e74a20) 0 + +Class QUrlQuery + size=8 align=8 + base size=8 base align=8 +QUrlQuery (0x0x7fee60e74e40) 0 + +Class QModelIndex + size=24 align=8 + base size=24 base align=8 +QModelIndex (0x0x7fee60c2f060) 0 + +Class QPersistentModelIndex + size=8 align=8 + base size=8 base align=8 +QPersistentModelIndex (0x0x7fee60c2f1e0) 0 + +Class QAbstractItemModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractItemModel::QPrivateSignal (0x0x7fee60c2f3c0) 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 (0x0x7fee60b9f410) 0 + vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16u) + QObject (0x0x7fee60c2f360) 0 + primary-for QAbstractItemModel (0x0x7fee60b9f410) + +Class QAbstractTableModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTableModel::QPrivateSignal (0x0x7fee60c2f720) 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 (0x0x7fee60b9f618) 0 + vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16u) + QAbstractItemModel (0x0x7fee60b9f680) 0 + primary-for QAbstractTableModel (0x0x7fee60b9f618) + QObject (0x0x7fee60c2f6c0) 0 + primary-for QAbstractItemModel (0x0x7fee60b9f680) + +Class QAbstractListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractListModel::QPrivateSignal (0x0x7fee60c2f7e0) 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 (0x0x7fee60b9f6e8) 0 + vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16u) + QAbstractItemModel (0x0x7fee60b9f750) 0 + primary-for QAbstractListModel (0x0x7fee60b9f6e8) + QObject (0x0x7fee60c2f780) 0 + primary-for QAbstractItemModel (0x0x7fee60b9f750) + +Class QAbstractProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractProxyModel::QPrivateSignal (0x0x7fee60c2fae0) 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 (0x0x7fee60b9f888) 0 + vptr=((& QAbstractProxyModel::_ZTV19QAbstractProxyModel) + 16u) + QAbstractItemModel (0x0x7fee60b9f8f0) 0 + primary-for QAbstractProxyModel (0x0x7fee60b9f888) + QObject (0x0x7fee60c2fa80) 0 + primary-for QAbstractItemModel (0x0x7fee60b9f8f0) + +Class QIdentityProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIdentityProxyModel::QPrivateSignal (0x0x7fee60c2fba0) 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 (0x0x7fee60b9f958) 0 + vptr=((& QIdentityProxyModel::_ZTV19QIdentityProxyModel) + 16u) + QAbstractProxyModel (0x0x7fee60b9f9c0) 0 + primary-for QIdentityProxyModel (0x0x7fee60b9f958) + QAbstractItemModel (0x0x7fee60b9fa28) 0 + primary-for QAbstractProxyModel (0x0x7fee60b9f9c0) + QObject (0x0x7fee60c2fb40) 0 + primary-for QAbstractItemModel (0x0x7fee60b9fa28) + +Class QItemSelectionRange + size=16 align=8 + base size=16 base align=8 +QItemSelectionRange (0x0x7fee60c2fc00) 0 + +Class QItemSelectionModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QItemSelectionModel::QPrivateSignal (0x0x7fee60c2fde0) 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 (0x0x7fee60b9fb60) 0 + vptr=((& QItemSelectionModel::_ZTV19QItemSelectionModel) + 16u) + QObject (0x0x7fee60c2fd80) 0 + primary-for QItemSelectionModel (0x0x7fee60b9fb60) + +Class QItemSelection + size=8 align=8 + base size=8 base align=8 +QItemSelection (0x0x7fee60b9fd68) 0 + QList (0x0x7fee60b9fdd0) 0 + QListSpecialMethods (0x0x7fee609de060) 0 empty + +Class QSortFilterProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSortFilterProxyModel::QPrivateSignal (0x0x7fee609de480) 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 (0x0x7fee60b9fea0) 0 + vptr=((& QSortFilterProxyModel::_ZTV21QSortFilterProxyModel) + 16u) + QAbstractProxyModel (0x0x7fee60b9ff08) 0 + primary-for QSortFilterProxyModel (0x0x7fee60b9fea0) + QAbstractItemModel (0x0x7fee60b9ff70) 0 + primary-for QAbstractProxyModel (0x0x7fee60b9ff08) + QObject (0x0x7fee609de420) 0 + primary-for QAbstractItemModel (0x0x7fee60b9ff70) + +Class QStringListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStringListModel::QPrivateSignal (0x0x7fee609de540) 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 (0x0x7fee60a45000) 0 + vptr=((& QStringListModel::_ZTV16QStringListModel) + 16u) + QAbstractListModel (0x0x7fee60a45068) 0 + primary-for QStringListModel (0x0x7fee60a45000) + QAbstractItemModel (0x0x7fee60a450d0) 0 + primary-for QAbstractListModel (0x0x7fee60a45068) + QObject (0x0x7fee609de4e0) 0 + primary-for QAbstractItemModel (0x0x7fee60a450d0) + +Class QJsonValue + size=24 align=8 + base size=20 base align=8 +QJsonValue (0x0x7fee609de5a0) 0 + +Class QJsonValueRef + size=16 align=8 + base size=12 base align=8 +QJsonValueRef (0x0x7fee609de660) 0 + +Class QJsonValuePtr + size=24 align=8 + base size=24 base align=8 +QJsonValuePtr (0x0x7fee609de720) 0 + +Class QJsonValueRefPtr + size=16 align=8 + base size=16 base align=8 +QJsonValueRefPtr (0x0x7fee609de780) 0 + +Class QJsonArray::iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::iterator (0x0x7fee609de840) 0 + +Class QJsonArray::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::const_iterator (0x0x7fee609de8a0) 0 + +Class QJsonArray + size=16 align=8 + base size=16 base align=8 +QJsonArray (0x0x7fee609de7e0) 0 + +Class QJsonParseError + size=8 align=4 + base size=8 base align=4 +QJsonParseError (0x0x7fee609de900) 0 + +Class QJsonDocument + size=8 align=8 + base size=8 base align=8 +QJsonDocument (0x0x7fee609de960) 0 + +Class QJsonObject::iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::iterator (0x0x7fee609dea20) 0 + +Class QJsonObject::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::const_iterator (0x0x7fee609dea80) 0 + +Class QJsonObject + size=16 align=8 + base size=16 base align=8 +QJsonObject (0x0x7fee609de9c0) 0 + +Class QEventLoop::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventLoop::QPrivateSignal (0x0x7fee609deba0) 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 (0x0x7fee60a45138) 0 + vptr=((& QEventLoop::_ZTV10QEventLoop) + 16u) + QObject (0x0x7fee609deb40) 0 + primary-for QEventLoop (0x0x7fee60a45138) + +Class QEventLoopLocker + size=8 align=8 + base size=8 base align=8 +QEventLoopLocker (0x0x7fee609decc0) 0 + +Class QAbstractEventDispatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractEventDispatcher::QPrivateSignal (0x0x7fee609ded80) 0 empty + +Class QAbstractEventDispatcher::TimerInfo + size=12 align=4 + base size=12 base align=4 +QAbstractEventDispatcher::TimerInfo (0x0x7fee609dede0) 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 (0x0x7fee60a45270) 0 + vptr=((& QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher) + 16u) + QObject (0x0x7fee609ded20) 0 + primary-for QAbstractEventDispatcher (0x0x7fee60a45270) + +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 (0x0x7fee609dee40) 0 + vptr=((& QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter) + 16u) + +Class QBasicTimer + size=4 align=4 + base size=4 base align=4 +QBasicTimer (0x0x7fee609deea0) 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 (0x0x7fee607b3060) 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 (0x0x7fee60a45340) 0 + vptr=((& QTimerEvent::_ZTV11QTimerEvent) + 16u) + QEvent (0x0x7fee607b30c0) 0 + primary-for QTimerEvent (0x0x7fee60a45340) + +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 (0x0x7fee60a453a8) 0 + vptr=((& QChildEvent::_ZTV11QChildEvent) + 16u) + QEvent (0x0x7fee607b3120) 0 + primary-for QChildEvent (0x0x7fee60a453a8) + +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 (0x0x7fee60a45410) 0 + vptr=((& QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent) + 16u) + QEvent (0x0x7fee607b3180) 0 + primary-for QDynamicPropertyChangeEvent (0x0x7fee60a45410) + +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 (0x0x7fee60a45478) 0 + vptr=((& QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent) + 16u) + QEvent (0x0x7fee607b31e0) 0 + primary-for QDeferredDeleteEvent (0x0x7fee60a45478) + +Class QCoreApplication::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QCoreApplication::QPrivateSignal (0x0x7fee607b32a0) 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 (0x0x7fee60a454e0) 0 + vptr=((& QCoreApplication::_ZTV16QCoreApplication) + 16u) + QObject (0x0x7fee607b3240) 0 + primary-for QCoreApplication (0x0x7fee60a454e0) + +Class __exception + size=40 align=8 + base size=40 base align=8 +__exception (0x0x7fee607b3300) 0 + +Class QMetaMethod + size=16 align=8 + base size=12 base align=8 +QMetaMethod (0x0x7fee607b3480) 0 + +Class QMetaEnum + size=16 align=8 + base size=12 base align=8 +QMetaEnum (0x0x7fee607b3600) 0 + +Class QMetaProperty + size=32 align=8 + base size=32 base align=8 +QMetaProperty (0x0x7fee607b3780) 0 + +Class QMetaClassInfo + size=16 align=8 + base size=12 base align=8 +QMetaClassInfo (0x0x7fee607b37e0) 0 + +Class QMimeData::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QMimeData::QPrivateSignal (0x0x7fee607b39c0) 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 (0x0x7fee60a45680) 0 + vptr=((& QMimeData::_ZTV9QMimeData) + 16u) + QObject (0x0x7fee607b3960) 0 + primary-for QMimeData (0x0x7fee60a45680) + +Class QObjectCleanupHandler::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObjectCleanupHandler::QPrivateSignal (0x0x7fee607b3a80) 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 (0x0x7fee60a456e8) 0 + vptr=((& QObjectCleanupHandler::_ZTV21QObjectCleanupHandler) + 16u) + QObject (0x0x7fee607b3a20) 0 + primary-for QObjectCleanupHandler (0x0x7fee60a456e8) + +Class QtSharedPointer::NormalDeleter + size=1 align=1 + base size=0 base align=1 +QtSharedPointer::NormalDeleter (0x0x7fee607b3ae0) 0 empty + +Class QtSharedPointer::ExternalRefCountData + size=16 align=8 + base size=16 base align=8 +QtSharedPointer::ExternalRefCountData (0x0x7fee607b3c60) 0 + +Class QSharedMemory::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSharedMemory::QPrivateSignal (0x0x7fee605bd2a0) 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 (0x0x7fee60a45af8) 0 + vptr=((& QSharedMemory::_ZTV13QSharedMemory) + 16u) + QObject (0x0x7fee605bd240) 0 + primary-for QSharedMemory (0x0x7fee60a45af8) + +Class QSignalMapper::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalMapper::QPrivateSignal (0x0x7fee605bd360) 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 (0x0x7fee60a45b60) 0 + vptr=((& QSignalMapper::_ZTV13QSignalMapper) + 16u) + QObject (0x0x7fee605bd300) 0 + primary-for QSignalMapper (0x0x7fee60a45b60) + +Class QSocketNotifier::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSocketNotifier::QPrivateSignal (0x0x7fee605bd420) 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 (0x0x7fee60a45bc8) 0 + vptr=((& QSocketNotifier::_ZTV15QSocketNotifier) + 16u) + QObject (0x0x7fee605bd3c0) 0 + primary-for QSocketNotifier (0x0x7fee60a45bc8) + +Class QSystemSemaphore + size=8 align=8 + base size=8 base align=8 +QSystemSemaphore (0x0x7fee605bd480) 0 + +Class QTimer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimer::QPrivateSignal (0x0x7fee605bd5a0) 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 (0x0x7fee60a45c30) 0 + vptr=((& QTimer::_ZTV6QTimer) + 16u) + QObject (0x0x7fee605bd540) 0 + primary-for QTimer (0x0x7fee60a45c30) + +Class QTranslator::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTranslator::QPrivateSignal (0x0x7fee605bd720) 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 (0x0x7fee60a45d00) 0 + vptr=((& QTranslator::_ZTV11QTranslator) + 16u) + QObject (0x0x7fee605bd6c0) 0 + primary-for QTranslator (0x0x7fee60a45d00) + +Class QMimeType + size=8 align=8 + base size=8 base align=8 +QMimeType (0x0x7fee605bd780) 0 + +Class QMimeDatabase + size=8 align=8 + base size=8 base align=8 +QMimeDatabase (0x0x7fee605bd960) 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 (0x0x7fee605bd9c0) 0 nearly-empty + vptr=((& QFactoryInterface::_ZTV17QFactoryInterface) + 16u) + +Class QLibrary::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLibrary::QPrivateSignal (0x0x7fee605bdae0) 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 (0x0x7fee60a45dd0) 0 + vptr=((& QLibrary::_ZTV8QLibrary) + 16u) + QObject (0x0x7fee605bda80) 0 + primary-for QLibrary (0x0x7fee60a45dd0) + +Class QStaticPlugin + size=16 align=8 + base size=16 base align=8 +QStaticPlugin (0x0x7fee605bdc00) 0 + +Class QPluginLoader::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPluginLoader::QPrivateSignal (0x0x7fee605bdde0) 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 (0x0x7fee60a45f70) 0 + vptr=((& QPluginLoader::_ZTV13QPluginLoader) + 16u) + QObject (0x0x7fee605bdd80) 0 + primary-for QPluginLoader (0x0x7fee60a45f70) + +Class QUuid + size=16 align=4 + base size=16 base align=4 +QUuid (0x0x7fee605bde40) 0 + +Class QAbstractState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractState::QPrivateSignal (0x0x7fee606e2060) 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 (0x0x7fee60a45a28) 0 + vptr=((& QAbstractState::_ZTV14QAbstractState) + 16u) + QObject (0x0x7fee606e2000) 0 + primary-for QAbstractState (0x0x7fee60a45a28) + +Class QAbstractTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTransition::QPrivateSignal (0x0x7fee606e2120) 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 (0x0x7fee60a45a90) 0 + vptr=((& QAbstractTransition::_ZTV19QAbstractTransition) + 16u) + QObject (0x0x7fee606e20c0) 0 + primary-for QAbstractTransition (0x0x7fee60a45a90) + +Class QEventTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventTransition::QPrivateSignal (0x0x7fee606e21e0) 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 (0x0x7fee6070e000) 0 + vptr=((& QEventTransition::_ZTV16QEventTransition) + 16u) + QAbstractTransition (0x0x7fee6070e068) 0 + primary-for QEventTransition (0x0x7fee6070e000) + QObject (0x0x7fee606e2180) 0 + primary-for QAbstractTransition (0x0x7fee6070e068) + +Class QFinalState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFinalState::QPrivateSignal (0x0x7fee606e22a0) 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 (0x0x7fee6070e0d0) 0 + vptr=((& QFinalState::_ZTV11QFinalState) + 16u) + QAbstractState (0x0x7fee6070e138) 0 + primary-for QFinalState (0x0x7fee6070e0d0) + QObject (0x0x7fee606e2240) 0 + primary-for QAbstractState (0x0x7fee6070e138) + +Class QHistoryState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QHistoryState::QPrivateSignal (0x0x7fee606e2360) 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 (0x0x7fee6070e1a0) 0 + vptr=((& QHistoryState::_ZTV13QHistoryState) + 16u) + QAbstractState (0x0x7fee6070e208) 0 + primary-for QHistoryState (0x0x7fee6070e1a0) + QObject (0x0x7fee606e2300) 0 + primary-for QAbstractState (0x0x7fee6070e208) + +Class QSignalTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalTransition::QPrivateSignal (0x0x7fee606e2420) 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 (0x0x7fee6070e270) 0 + vptr=((& QSignalTransition::_ZTV17QSignalTransition) + 16u) + QAbstractTransition (0x0x7fee6070e2d8) 0 + primary-for QSignalTransition (0x0x7fee6070e270) + QObject (0x0x7fee606e23c0) 0 + primary-for QAbstractTransition (0x0x7fee6070e2d8) + +Class QState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QState::QPrivateSignal (0x0x7fee606e24e0) 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 (0x0x7fee6070e340) 0 + vptr=((& QState::_ZTV6QState) + 16u) + QAbstractState (0x0x7fee6070e3a8) 0 + primary-for QState (0x0x7fee6070e340) + QObject (0x0x7fee606e2480) 0 + primary-for QAbstractState (0x0x7fee6070e3a8) + +Class QStateMachine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStateMachine::QPrivateSignal (0x0x7fee606e2600) 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 (0x0x7fee6070e548) 0 + vptr=((& QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE) + 16u) + QEvent (0x0x7fee606e2660) 0 + primary-for QStateMachine::SignalEvent (0x0x7fee6070e548) + +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 (0x0x7fee6070e5b0) 0 + vptr=((& QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE) + 16u) + QEvent (0x0x7fee606e26c0) 0 + primary-for QStateMachine::WrappedEvent (0x0x7fee6070e5b0) + +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 (0x0x7fee6070e410) 0 + vptr=((& QStateMachine::_ZTV13QStateMachine) + 16u) + QState (0x0x7fee6070e478) 0 + primary-for QStateMachine (0x0x7fee6070e410) + QAbstractState (0x0x7fee6070e4e0) 0 + primary-for QState (0x0x7fee6070e478) + QObject (0x0x7fee606e25a0) 0 + primary-for QAbstractState (0x0x7fee6070e4e0) + +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 (0x0x7fee6070e618) 0 nearly-empty + vptr=((& QException::_ZTV10QException) + 16u) + std::exception (0x0x7fee606e2720) 0 nearly-empty + primary-for QException (0x0x7fee6070e618) + +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 (0x0x7fee6070e680) 0 nearly-empty + vptr=((& QUnhandledException::_ZTV19QUnhandledException) + 16u) + QException (0x0x7fee6070e6e8) 0 nearly-empty + primary-for QUnhandledException (0x0x7fee6070e680) + std::exception (0x0x7fee606e2780) 0 nearly-empty + primary-for QException (0x0x7fee6070e6e8) + +Class QtPrivate::ExceptionHolder + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionHolder (0x0x7fee606e27e0) 0 + +Class QtPrivate::ExceptionStore + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionStore (0x0x7fee606e28a0) 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 (0x0x7fee606e2900) 0 + vptr=((& QRunnable::_ZTV9QRunnable) + 16u) + +Class QBasicMutex + size=8 align=8 + base size=8 base align=8 +QBasicMutex (0x0x7fee606e2960) 0 + +Class QMutex + size=8 align=8 + base size=8 base align=8 +QMutex (0x0x7fee6070e888) 0 + QBasicMutex (0x0x7fee606e2ae0) 0 + +Class QMutexLocker + size=8 align=8 + base size=8 base align=8 +QMutexLocker (0x0x7fee606e2b40) 0 + +Class QtPrivate::ResultItem + size=16 align=8 + base size=16 base align=8 +QtPrivate::ResultItem (0x0x7fee606e2c00) 0 + +Class QtPrivate::ResultIteratorBase + size=16 align=8 + base size=12 base align=8 +QtPrivate::ResultIteratorBase (0x0x7fee606e2c60) 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 (0x0x7fee606e2de0) 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 (0x0x7fee606e2ea0) 0 + vptr=((& QFutureInterfaceBase::_ZTV20QFutureInterfaceBase) + 16u) + +Class QFutureWatcherBase::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFutureWatcherBase::QPrivateSignal (0x0x7fee60463240) 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 (0x0x7fee6044f138) 0 + vptr=((& QFutureWatcherBase::_ZTV18QFutureWatcherBase) + 16u) + QObject (0x0x7fee604631e0) 0 + primary-for QFutureWatcherBase (0x0x7fee6044f138) + +Class QReadWriteLock + size=8 align=8 + base size=8 base align=8 +QReadWriteLock (0x0x7fee60463360) 0 + +Class QReadLocker + size=8 align=8 + base size=8 base align=8 +QReadLocker (0x0x7fee604633c0) 0 + +Class QWriteLocker + size=8 align=8 + base size=8 base align=8 +QWriteLocker (0x0x7fee60463420) 0 + +Class QSemaphore + size=8 align=8 + base size=8 base align=8 +QSemaphore (0x0x7fee60463480) 0 + +Class QThread::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThread::QPrivateSignal (0x0x7fee60463540) 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 (0x0x7fee6044f5b0) 0 + vptr=((& QThread::_ZTV7QThread) + 16u) + QObject (0x0x7fee604634e0) 0 + primary-for QThread (0x0x7fee6044f5b0) + +Class QThreadPool::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThreadPool::QPrivateSignal (0x0x7fee60463600) 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 (0x0x7fee6044f618) 0 + vptr=((& QThreadPool::_ZTV11QThreadPool) + 16u) + QObject (0x0x7fee604635a0) 0 + primary-for QThreadPool (0x0x7fee6044f618) + +Class QThreadStorageData + size=4 align=4 + base size=4 base align=4 +QThreadStorageData (0x0x7fee60463660) 0 + +Class QWaitCondition + size=8 align=8 + base size=8 base align=8 +QWaitCondition (0x0x7fee60463720) 0 + +Class QBitArray + size=8 align=8 + base size=8 base align=8 +QBitArray (0x0x7fee60463c00) 0 + +Class QBitRef + size=16 align=8 + base size=12 base align=8 +QBitRef (0x0x7fee60463de0) 0 + +Class QByteArrayMatcher::Data + size=272 align=8 + base size=272 base align=8 +QByteArrayMatcher::Data (0x0x7fee601e7060) 0 + +Class QByteArrayMatcher + size=1040 align=8 + base size=1040 base align=8 +QByteArrayMatcher (0x0x7fee601e7000) 0 + +Class QCollatorSortKey + size=8 align=8 + base size=8 base align=8 +QCollatorSortKey (0x0x7fee601e71e0) 0 + +Class QCollator + size=8 align=8 + base size=8 base align=8 +QCollator (0x0x7fee601e72a0) 0 + +Class QCommandLineOption + size=8 align=8 + base size=8 base align=8 +QCommandLineOption (0x0x7fee601e7540) 0 + +Class QCommandLineParser + size=8 align=8 + base size=8 base align=8 +QCommandLineParser (0x0x7fee601e7720) 0 + +Class QCryptographicHash + size=8 align=8 + base size=8 base align=8 +QCryptographicHash (0x0x7fee601e7780) 0 + +Class QElapsedTimer + size=16 align=8 + base size=16 base align=8 +QElapsedTimer (0x0x7fee601e77e0) 0 + +Class QPoint + size=8 align=4 + base size=8 base align=4 +QPoint (0x0x7fee601e7840) 0 + +Class QPointF + size=16 align=8 + base size=16 base align=8 +QPointF (0x0x7fee601e79c0) 0 + +Class QLine + size=16 align=4 + base size=16 base align=4 +QLine (0x0x7fee601e7b40) 0 + +Class QLineF + size=32 align=8 + base size=32 base align=8 +QLineF (0x0x7fee601e7cc0) 0 + +Class QLinkedListData + size=32 align=8 + base size=32 base align=8 +QLinkedListData (0x0x7fee601e7e40) 0 + +Class QMargins + size=16 align=4 + base size=16 base align=4 +QMargins (0x0x7fee5ff39600) 0 + +Class QMarginsF + size=32 align=8 + base size=32 base align=8 +QMarginsF (0x0x7fee5ff39780) 0 + +Class QMessageAuthenticationCode + size=8 align=8 + base size=8 base align=8 +QMessageAuthenticationCode (0x0x7fee5ff39900) 0 + +Class QSize + size=8 align=4 + base size=8 base align=4 +QSize (0x0x7fee5ff399c0) 0 + +Class QSizeF + size=16 align=8 + base size=16 base align=8 +QSizeF (0x0x7fee5ff39c00) 0 + +Class QRect + size=16 align=4 + base size=16 base align=4 +QRect (0x0x7fee5ff39e40) 0 + +Class QRectF + size=32 align=8 + base size=32 base align=8 +QRectF (0x0x7fee6011d000) 0 + +Class QRegularExpression + size=8 align=8 + base size=8 base align=8 +QRegularExpression (0x0x7fee6011d180) 0 + +Class QRegularExpressionMatch + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatch (0x0x7fee6011d4e0) 0 + +Class QRegularExpressionMatchIterator + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatchIterator (0x0x7fee6011d6c0) 0 + +Class QAbstractConcatenable + size=1 align=1 + base size=0 base align=1 +QAbstractConcatenable (0x0x7fee6011da80) 0 empty + +Class QTextBoundaryFinder + size=48 align=8 + base size=48 base align=8 +QTextBoundaryFinder (0x0x7fee5fddd4e0) 0 + +Class QTimeLine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimeLine::QPrivateSignal (0x0x7fee5fddd660) 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 (0x0x7fee5fdae958) 0 + vptr=((& QTimeLine::_ZTV9QTimeLine) + 16u) + QObject (0x0x7fee5fddd600) 0 + primary-for QTimeLine (0x0x7fee5fdae958) + +Class QTimeZone::OffsetData + size=32 align=8 + base size=28 base align=8 +QTimeZone::OffsetData (0x0x7fee5fddd720) 0 + +Class QTimeZone + size=8 align=8 + base size=8 base align=8 +QTimeZone (0x0x7fee5fddd6c0) 0 + +Class QVersionNumber::SegmentStorage + size=8 align=8 + base size=8 base align=8 +QVersionNumber::SegmentStorage (0x0x7fee5fddda80) 0 + +Class QVersionNumber + size=8 align=8 + base size=8 base align=8 +QVersionNumber (0x0x7fee5fddda20) 0 + +Class QXmlStreamStringRef + size=16 align=8 + base size=16 base align=8 +QXmlStreamStringRef (0x0x7fee5fdddd80) 0 + +Class QXmlStreamAttribute + size=80 align=8 + base size=73 base align=8 +QXmlStreamAttribute (0x0x7fee5fdddf00) 0 + +Class QXmlStreamAttributes + size=8 align=8 + base size=8 base align=8 +QXmlStreamAttributes (0x0x7fee5fdaedd0) 0 + QVector (0x0x7fee5fafe180) 0 + +Class QXmlStreamNamespaceDeclaration + size=40 align=8 + base size=40 base align=8 +QXmlStreamNamespaceDeclaration (0x0x7fee5fafe1e0) 0 + +Class QXmlStreamNotationDeclaration + size=56 align=8 + base size=56 base align=8 +QXmlStreamNotationDeclaration (0x0x7fee5fafe360) 0 + +Class QXmlStreamEntityDeclaration + size=88 align=8 + base size=88 base align=8 +QXmlStreamEntityDeclaration (0x0x7fee5fafe4e0) 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 (0x0x7fee5fafe660) 0 nearly-empty + vptr=((& QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver) + 16u) + +Class QXmlStreamReader + size=8 align=8 + base size=8 base align=8 +QXmlStreamReader (0x0x7fee5fafe6c0) 0 + +Class QXmlStreamWriter + size=8 align=8 + base size=8 base align=8 +QXmlStreamWriter (0x0x7fee5fafe7e0) 0 + +Class QNdefRecord + size=8 align=8 + base size=8 base align=8 +QNdefRecord (0x0x7fee5fafe900) 0 + +Class QNdefFilter::Record + size=24 align=8 + base size=24 base align=8 +QNdefFilter::Record (0x0x7fee5fafea20) 0 + +Class QNdefFilter + size=8 align=8 + base size=8 base align=8 +QNdefFilter (0x0x7fee5fafe9c0) 0 + +Class QNdefMessage + size=8 align=8 + base size=8 base align=8 +QNdefMessage (0x0x7fee5fbdb068) 0 + QList (0x0x7fee5fbdb0d0) 0 + QListSpecialMethods (0x0x7fee5fafec00) 0 empty + +Class QNdefNfcTextRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcTextRecord (0x0x7fee5fbdb138) 0 + QNdefRecord (0x0x7fee5fafed80) 0 + +Class QNdefNfcUriRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcUriRecord (0x0x7fee5fbdb1a0) 0 + QNdefRecord (0x0x7fee5fafede0) 0 + +Class QNdefNfcIconRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcIconRecord (0x0x7fee5fbdb208) 0 + QNdefRecord (0x0x7fee5fafee40) 0 + +Class QNdefNfcSmartPosterRecord + size=16 align=8 + base size=16 base align=8 +QNdefNfcSmartPosterRecord (0x0x7fee5fbdb270) 0 + QNdefRecord (0x0x7fee5fafeea0) 0 + +Class QNearFieldTarget::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldTarget::QPrivateSignal (0x0x7fee5fc68000) 0 empty + +Class QNearFieldTarget::RequestId + size=8 align=8 + base size=8 base align=8 +QNearFieldTarget::RequestId (0x0x7fee5fc68060) 0 + +Vtable for QNearFieldTarget +QNearFieldTarget::_ZTV16QNearFieldTarget: 25u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QNearFieldTarget) +16 (int (*)(...))QNearFieldTarget::metaObject +24 (int (*)(...))QNearFieldTarget::qt_metacast +32 (int (*)(...))QNearFieldTarget::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 (*)(...))QNearFieldTarget::url +128 (int (*)(...))__cxa_pure_virtual +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))QNearFieldTarget::hasNdefMessage +152 (int (*)(...))QNearFieldTarget::readNdefMessages +160 (int (*)(...))QNearFieldTarget::writeNdefMessages +168 (int (*)(...))QNearFieldTarget::sendCommand +176 (int (*)(...))QNearFieldTarget::sendCommands +184 (int (*)(...))QNearFieldTarget::waitForRequestCompleted +192 (int (*)(...))QNearFieldTarget::handleResponse + +Class QNearFieldTarget + size=24 align=8 + base size=24 base align=8 +QNearFieldTarget (0x0x7fee5fbdb2d8) 0 + vptr=((& QNearFieldTarget::_ZTV16QNearFieldTarget) + 16u) + QObject (0x0x7fee5fafef60) 0 + primary-for QNearFieldTarget (0x0x7fee5fbdb2d8) + +Class QNearFieldManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldManager::QPrivateSignal (0x0x7fee5fc68360) 0 empty + +Vtable for QNearFieldManager +QNearFieldManager::_ZTV17QNearFieldManager: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QNearFieldManager) +16 (int (*)(...))QNearFieldManager::metaObject +24 (int (*)(...))QNearFieldManager::qt_metacast +32 (int (*)(...))QNearFieldManager::qt_metacall +40 (int (*)(...))QNearFieldManager::~QNearFieldManager +48 (int (*)(...))QNearFieldManager::~QNearFieldManager +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 QNearFieldManager + size=24 align=8 + base size=24 base align=8 +QNearFieldManager (0x0x7fee5fbdb410) 0 + vptr=((& QNearFieldManager::_ZTV17QNearFieldManager) + 16u) + QObject (0x0x7fee5fc68300) 0 + primary-for QNearFieldManager (0x0x7fee5fbdb410) + +Class QNearFieldShareManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldShareManager::QPrivateSignal (0x0x7fee5fc684e0) 0 empty + +Vtable for QNearFieldShareManager +QNearFieldShareManager::_ZTV22QNearFieldShareManager: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI22QNearFieldShareManager) +16 (int (*)(...))QNearFieldShareManager::metaObject +24 (int (*)(...))QNearFieldShareManager::qt_metacast +32 (int (*)(...))QNearFieldShareManager::qt_metacall +40 (int (*)(...))QNearFieldShareManager::~QNearFieldShareManager +48 (int (*)(...))QNearFieldShareManager::~QNearFieldShareManager +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 QNearFieldShareManager + size=24 align=8 + base size=24 base align=8 +QNearFieldShareManager (0x0x7fee5fbdb5b0) 0 + vptr=((& QNearFieldShareManager::_ZTV22QNearFieldShareManager) + 16u) + QObject (0x0x7fee5fc68480) 0 + primary-for QNearFieldShareManager (0x0x7fee5fbdb5b0) + +Class QNearFieldShareTarget::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldShareTarget::QPrivateSignal (0x0x7fee5fc68720) 0 empty + +Vtable for QNearFieldShareTarget +QNearFieldShareTarget::_ZTV21QNearFieldShareTarget: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QNearFieldShareTarget) +16 (int (*)(...))QNearFieldShareTarget::metaObject +24 (int (*)(...))QNearFieldShareTarget::qt_metacast +32 (int (*)(...))QNearFieldShareTarget::qt_metacall +40 (int (*)(...))QNearFieldShareTarget::~QNearFieldShareTarget +48 (int (*)(...))QNearFieldShareTarget::~QNearFieldShareTarget +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 QNearFieldShareTarget + size=24 align=8 + base size=24 base align=8 +QNearFieldShareTarget (0x0x7fee5fbdb6e8) 0 + vptr=((& QNearFieldShareTarget::_ZTV21QNearFieldShareTarget) + 16u) + QObject (0x0x7fee5fc686c0) 0 + primary-for QNearFieldShareTarget (0x0x7fee5fbdb6e8) + +Class QQmlNdefRecord::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QQmlNdefRecord::QPrivateSignal (0x0x7fee5fc687e0) 0 empty + +Vtable for QQmlNdefRecord +QQmlNdefRecord::_ZTV14QQmlNdefRecord: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI14QQmlNdefRecord) +16 (int (*)(...))QQmlNdefRecord::metaObject +24 (int (*)(...))QQmlNdefRecord::qt_metacast +32 (int (*)(...))QQmlNdefRecord::qt_metacall +40 (int (*)(...))QQmlNdefRecord::~QQmlNdefRecord +48 (int (*)(...))QQmlNdefRecord::~QQmlNdefRecord +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 QQmlNdefRecord + size=24 align=8 + base size=24 base align=8 +QQmlNdefRecord (0x0x7fee5fbdb750) 0 + vptr=((& QQmlNdefRecord::_ZTV14QQmlNdefRecord) + 16u) + QObject (0x0x7fee5fc68780) 0 + primary-for QQmlNdefRecord (0x0x7fee5fbdb750) + diff --git a/tests/auto/bic/data/QtNfc.5.7.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtNfc.5.7.0.linux-gcc-amd64.txt new file mode 100644 index 0000000..aea91d2 --- /dev/null +++ b/tests/auto/bic/data/QtNfc.5.7.0.linux-gcc-amd64.txt @@ -0,0 +1,4393 @@ +Class std::__failure_type + size=1 align=1 + base size=0 base align=1 +std::__failure_type (0x0x7ff728d72060) 0 empty + +Class std::__do_is_destructible_impl + size=1 align=1 + base size=0 base align=1 +std::__do_is_destructible_impl (0x0x7ff728db97e0) 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 (0x0x7ff728db9a20) 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 (0x0x7ff728db9c60) 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 (0x0x7ff728db9ea0) 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 (0x0x7ff728de5060) 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 (0x0x7ff728de5420) 0 empty + +Class std::__do_common_type_impl + size=1 align=1 + base size=0 base align=1 +std::__do_common_type_impl (0x0x7ff726a74ba0) 0 empty + +Class std::__do_member_type_wrapper + size=1 align=1 + base size=0 base align=1 +std::__do_member_type_wrapper (0x0x7ff726a74c60) 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 (0x0x7ff726aa2000) 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 (0x0x7ff726aa20c0) 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 (0x0x7ff726aa2180) 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 (0x0x7ff726aa2240) 0 empty + +Class std::__result_of_other_impl + size=1 align=1 + base size=0 base align=1 +std::__result_of_other_impl (0x0x7ff726aa24e0) 0 empty + +Class std::piecewise_construct_t + size=1 align=1 + base size=0 base align=1 +std::piecewise_construct_t (0x0x7ff726aa2660) 0 empty + +Class std::__true_type + size=1 align=1 + base size=0 base align=1 +std::__true_type (0x0x7ff726aa2ae0) 0 empty + +Class std::__false_type + size=1 align=1 + base size=0 base align=1 +std::__false_type (0x0x7ff726aa2b40) 0 empty + +Class std::input_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::input_iterator_tag (0x0x7ff726b4e7e0) 0 empty + +Class std::output_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::output_iterator_tag (0x0x7ff726b4e840) 0 empty + +Class std::forward_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::forward_iterator_tag (0x0x7ff726a38f08) 0 empty + std::input_iterator_tag (0x0x7ff726b4e8a0) 0 empty + +Class std::bidirectional_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::bidirectional_iterator_tag (0x0x7ff726a38f70) 0 empty + std::forward_iterator_tag (0x0x7ff726b6c000) 0 empty + std::input_iterator_tag (0x0x7ff726b4e900) 0 empty + +Class std::random_access_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::random_access_iterator_tag (0x0x7ff726b6c068) 0 empty + std::bidirectional_iterator_tag (0x0x7ff726b6c0d0) 0 empty + std::forward_iterator_tag (0x0x7ff726b6c138) 0 empty + std::input_iterator_tag (0x0x7ff726b4e960) 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 (0x0x7ff726b90600) 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 (0x0x7ff726b90660) 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 (0x0x7ff726b906c0) 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 (0x0x7ff726b90720) 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 (0x0x7ff726b90780) 0 empty + +Class wait + size=4 align=4 + base size=4 base align=4 +wait (0x0x7ff7268922a0) 0 + +Class __locale_struct + size=232 align=8 + base size=232 base align=8 +__locale_struct (0x0x7ff7268924e0) 0 + +Class timespec + size=16 align=8 + base size=16 base align=8 +timespec (0x0x7ff7268925a0) 0 + +Class timeval + size=16 align=8 + base size=16 base align=8 +timeval (0x0x7ff726892600) 0 + +Class pthread_attr_t + size=56 align=8 + base size=56 base align=8 +pthread_attr_t (0x0x7ff7268926c0) 0 + +Class __pthread_internal_list + size=16 align=8 + base size=16 base align=8 +__pthread_internal_list (0x0x7ff726892720) 0 + +Class random_data + size=48 align=8 + base size=48 base align=8 +random_data (0x0x7ff726892ba0) 0 + +Class drand48_data + size=24 align=8 + base size=24 base align=8 +drand48_data (0x0x7ff726892c00) 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 (0x0x7ff726892c60) 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 (0x0x7ff726b6c680) 0 nearly-empty + vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16u) + std::exception (0x0x7ff726892cc0) 0 nearly-empty + primary-for std::bad_exception (0x0x7ff726b6c680) + +Class std::__exception_ptr::exception_ptr + size=8 align=8 + base size=8 base align=8 +std::__exception_ptr::exception_ptr (0x0x7ff726892d20) 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 (0x0x7ff726892d80) 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 (0x0x7ff726b6c888) 0 nearly-empty + vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16u) + std::exception (0x0x7ff7269c91e0) 0 nearly-empty + primary-for std::bad_alloc (0x0x7ff726b6c888) + +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 (0x0x7ff726b6c8f0) 0 nearly-empty + vptr=((& std::bad_array_new_length::_ZTVSt20bad_array_new_length) + 16u) + std::bad_alloc (0x0x7ff726b6c958) 0 nearly-empty + primary-for std::bad_array_new_length (0x0x7ff726b6c8f0) + std::exception (0x0x7ff7269c9240) 0 nearly-empty + primary-for std::bad_alloc (0x0x7ff726b6c958) + +Class std::nothrow_t + size=1 align=1 + base size=0 base align=1 +std::nothrow_t (0x0x7ff7269c92a0) 0 empty + +Class __exception + size=40 align=8 + base size=40 base align=8 +__exception (0x0x7ff7269c9ea0) 0 + +Class lconv + size=96 align=8 + base size=96 base align=8 +lconv (0x0x7ff72670eba0) 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 (0x0x7ff72670ec00) 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 (0x0x7ff7264c6ae0) 0 + +Class __sched_param + size=4 align=4 + base size=4 base align=4 +__sched_param (0x0x7ff7264c6b40) 0 + +Class timex + size=208 align=8 + base size=208 base align=8 +timex (0x0x7ff7264c6c00) 0 + +Class tm + size=56 align=8 + base size=56 base align=8 +tm (0x0x7ff7264c6c60) 0 + +Class itimerspec + size=32 align=8 + base size=32 base align=8 +itimerspec (0x0x7ff7264c6cc0) 0 + +Class _pthread_cleanup_buffer + size=32 align=8 + base size=32 base align=8 +_pthread_cleanup_buffer (0x0x7ff7264c6d20) 0 + +Class __pthread_cleanup_frame + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_frame (0x0x7ff7264c6e40) 0 + +Class __pthread_cleanup_class + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_class (0x0x7ff7264c6ea0) 0 + +Class _IO_marker + size=24 align=8 + base size=24 base align=8 +_IO_marker (0x0x7ff7265bb300) 0 + +Class _IO_FILE + size=216 align=8 + base size=216 base align=8 +_IO_FILE (0x0x7ff7265bb360) 0 + +Class std::_Hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Hash_impl (0x0x7ff72641fb40) 0 empty + +Class std::_Fnv_hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Fnv_hash_impl (0x0x7ff72641fba0) 0 empty + +Class std::__numeric_limits_base + size=1 align=1 + base size=0 base align=1 +std::__numeric_limits_base (0x0x7ff726053b40) 0 empty + +Class std::_Bit_reference + size=16 align=8 + base size=16 base align=8 +std::_Bit_reference (0x0x7ff726222960) 0 + +Class std::_Bit_iterator_base + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator_base (0x0x7ff7260ee618) 0 + std::iterator (0x0x7ff726222a20) 0 empty + +Class std::_Bit_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator (0x0x7ff7260ee680) 0 + std::_Bit_iterator_base (0x0x7ff7260ee6e8) 0 + std::iterator (0x0x7ff726222a80) 0 empty + +Class std::_Bit_const_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_const_iterator (0x0x7ff7260ee750) 0 + std::_Bit_iterator_base (0x0x7ff7260ee7b8) 0 + std::iterator (0x0x7ff726222ae0) 0 empty + +Class std::random_device + size=5000 align=8 + base size=5000 base align=8 +std::random_device (0x0x7ff726012900) 0 + +Class std::bernoulli_distribution::param_type + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution::param_type (0x0x7ff725d0c6c0) 0 + +Class std::bernoulli_distribution + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution (0x0x7ff725d0c660) 0 + +Class std::seed_seq + size=24 align=8 + base size=24 base align=8 +std::seed_seq (0x0x7ff725aed660) 0 + +Class qIsNull(double)::U + size=8 align=8 + base size=8 base align=8 +qIsNull(double)::U (0x0x7ff72466a120) 0 + +Class qIsNull(float)::U + size=4 align=4 + base size=4 base align=4 +qIsNull(float)::U (0x0x7ff72466a180) 0 + +Class QtPrivate::big_ + size=2 align=1 + base size=2 base align=1 +QtPrivate::big_ (0x0x7ff72466a540) 0 + +Class QSysInfo + size=1 align=1 + base size=0 base align=1 +QSysInfo (0x0x7ff724746a20) 0 empty + +Class QMessageLogContext + size=32 align=8 + base size=32 base align=8 +QMessageLogContext (0x0x7ff724746a80) 0 + +Class QMessageLogger + size=32 align=8 + base size=32 base align=8 +QMessageLogger (0x0x7ff724746ae0) 0 + +Class QFlag + size=4 align=4 + base size=4 base align=4 +QFlag (0x0x7ff724746b40) 0 + +Class QIncompatibleFlag + size=4 align=4 + base size=4 base align=4 +QIncompatibleFlag (0x0x7ff724746cc0) 0 + +Class std::__atomic_flag_base + size=1 align=1 + base size=1 base align=1 +std::__atomic_flag_base (0x0x7ff7247c8120) 0 + +Class std::atomic_flag + size=1 align=1 + base size=1 base align=1 +std::atomic_flag (0x0x7ff7247098f0) 0 + std::__atomic_flag_base (0x0x7ff7247c8180) 0 + +Class QAtomicInt + size=4 align=4 + base size=4 base align=4 +QAtomicInt (0x0x7ff7243bb068) 0 + QAtomicInteger (0x0x7ff7243bb0d0) 0 + QBasicAtomicInteger (0x0x7ff72424c6c0) 0 + +Class QInternal + size=1 align=1 + base size=0 base align=1 +QInternal (0x0x7ff7240f7f60) 0 empty + +Class QGenericArgument + size=16 align=8 + base size=16 base align=8 +QGenericArgument (0x0x7ff723f6be40) 0 + +Class QGenericReturnArgument + size=16 align=8 + base size=16 base align=8 +QGenericReturnArgument (0x0x7ff7241bb340) 0 + QGenericArgument (0x0x7ff723f6bea0) 0 + +Class QMetaObject + size=48 align=8 + base size=48 base align=8 +QMetaObject (0x0x7ff723fc8060) 0 + +Class QMetaObject::Connection + size=8 align=8 + base size=8 base align=8 +QMetaObject::Connection (0x0x7ff723fc8120) 0 + +Class QLatin1Char + size=1 align=1 + base size=1 base align=1 +QLatin1Char (0x0x7ff723c6f180) 0 + +Class QChar + size=2 align=2 + base size=2 base align=2 +QChar (0x0x7ff723c6f1e0) 0 + +Class QtPrivate::RefCount + size=4 align=4 + base size=4 base align=4 +QtPrivate::RefCount (0x0x7ff723c6f360) 0 + +Class QArrayData + size=24 align=8 + base size=24 base align=8 +QArrayData (0x0x7ff723c6f420) 0 + +Class QtPrivate::QContainerImplHelper + size=1 align=1 + base size=0 base align=1 +QtPrivate::QContainerImplHelper (0x0x7ff723c6f840) 0 empty + +Class std::locale + size=8 align=8 + base size=8 base align=8 +std::locale (0x0x7ff723c6f8a0) 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 (0x0x7ff723c6f900) 0 + vptr=((& std::locale::facet::_ZTVNSt6locale5facetE) + 16u) + +Class std::locale::id + size=8 align=8 + base size=8 base align=8 +std::locale::id (0x0x7ff723c6f960) 0 + +Class std::locale::_Impl + size=40 align=8 + base size=40 base align=8 +std::locale::_Impl (0x0x7ff723c6f9c0) 0 + +Class std::__cow_string + size=8 align=8 + base size=8 base align=8 +std::__cow_string (0x0x7ff723c6fd80) 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 (0x0x7ff723d6a7b8) 0 + vptr=((& std::logic_error::_ZTVSt11logic_error) + 16u) + std::exception (0x0x7ff723c6fe40) 0 nearly-empty + primary-for std::logic_error (0x0x7ff723d6a7b8) + +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 (0x0x7ff723d6a820) 0 + vptr=((& std::domain_error::_ZTVSt12domain_error) + 16u) + std::logic_error (0x0x7ff723d6a888) 0 + primary-for std::domain_error (0x0x7ff723d6a820) + std::exception (0x0x7ff723c6fea0) 0 nearly-empty + primary-for std::logic_error (0x0x7ff723d6a888) + +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 (0x0x7ff723d6a8f0) 0 + vptr=((& std::invalid_argument::_ZTVSt16invalid_argument) + 16u) + std::logic_error (0x0x7ff723d6a958) 0 + primary-for std::invalid_argument (0x0x7ff723d6a8f0) + std::exception (0x0x7ff723c6ff00) 0 nearly-empty + primary-for std::logic_error (0x0x7ff723d6a958) + +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 (0x0x7ff723d6a9c0) 0 + vptr=((& std::length_error::_ZTVSt12length_error) + 16u) + std::logic_error (0x0x7ff723d6aa28) 0 + primary-for std::length_error (0x0x7ff723d6a9c0) + std::exception (0x0x7ff723c6ff60) 0 nearly-empty + primary-for std::logic_error (0x0x7ff723d6aa28) + +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 (0x0x7ff723d6aa90) 0 + vptr=((& std::out_of_range::_ZTVSt12out_of_range) + 16u) + std::logic_error (0x0x7ff723d6aaf8) 0 + primary-for std::out_of_range (0x0x7ff723d6aa90) + std::exception (0x0x7ff723e12000) 0 nearly-empty + primary-for std::logic_error (0x0x7ff723d6aaf8) + +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 (0x0x7ff723d6ab60) 0 + vptr=((& std::runtime_error::_ZTVSt13runtime_error) + 16u) + std::exception (0x0x7ff723e12060) 0 nearly-empty + primary-for std::runtime_error (0x0x7ff723d6ab60) + +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 (0x0x7ff723d6abc8) 0 + vptr=((& std::range_error::_ZTVSt11range_error) + 16u) + std::runtime_error (0x0x7ff723d6ac30) 0 + primary-for std::range_error (0x0x7ff723d6abc8) + std::exception (0x0x7ff723e120c0) 0 nearly-empty + primary-for std::runtime_error (0x0x7ff723d6ac30) + +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 (0x0x7ff723d6ac98) 0 + vptr=((& std::overflow_error::_ZTVSt14overflow_error) + 16u) + std::runtime_error (0x0x7ff723d6ad00) 0 + primary-for std::overflow_error (0x0x7ff723d6ac98) + std::exception (0x0x7ff723e12120) 0 nearly-empty + primary-for std::runtime_error (0x0x7ff723d6ad00) + +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 (0x0x7ff723d6ad68) 0 + vptr=((& std::underflow_error::_ZTVSt15underflow_error) + 16u) + std::runtime_error (0x0x7ff723d6add0) 0 + primary-for std::underflow_error (0x0x7ff723d6ad68) + std::exception (0x0x7ff723e12180) 0 nearly-empty + primary-for std::runtime_error (0x0x7ff723d6add0) + +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 (0x0x7ff723e12300) 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 (0x0x7ff723e12540) 0 + +Class std::error_condition + size=16 align=8 + base size=16 base align=8 +std::error_condition (0x0x7ff723e126c0) 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 (0x0x7ff723a62208) 0 + vptr=((& std::system_error::_ZTVSt12system_error) + 16u) + std::runtime_error (0x0x7ff723a62270) 0 + primary-for std::system_error (0x0x7ff723a62208) + std::exception (0x0x7ff723e12900) 0 nearly-empty + primary-for std::runtime_error (0x0x7ff723a62270) + +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 (0x0x7ff723a62e38) 0 + vptr=((& std::ios_base::failure::_ZTVNSt8ios_base7failureB5cxx11E) + 16u) + std::system_error (0x0x7ff723a62ea0) 0 + primary-for std::ios_base::failure (0x0x7ff723a62e38) + std::runtime_error (0x0x7ff723a62f08) 0 + primary-for std::system_error (0x0x7ff723a62ea0) + std::exception (0x0x7ff723e12c00) 0 nearly-empty + primary-for std::runtime_error (0x0x7ff723a62f08) + +Class std::ios_base::_Callback_list + size=24 align=8 + base size=24 base align=8 +std::ios_base::_Callback_list (0x0x7ff723e12c60) 0 + +Class std::ios_base::_Words + size=16 align=8 + base size=16 base align=8 +std::ios_base::_Words (0x0x7ff723e12cc0) 0 + +Class std::ios_base::Init + size=1 align=1 + base size=0 base align=1 +std::ios_base::Init (0x0x7ff723e12d20) 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 (0x0x7ff723e12ba0) 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 (0x0x7ff723b5d4e0) 0 empty + +Class std::__num_base + size=1 align=1 + base size=0 base align=1 +std::__num_base (0x0x7ff723b5dba0) 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 (0x0x7ff723718820 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 (0x0x7ff7237188f0 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 (0x0x7ff723718c98 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 (0x0x7ff723718d68 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 (0x0x7ff723703480) 0 + +Class QByteArray + size=8 align=8 + base size=8 base align=8 +QByteArray (0x0x7ff7237034e0) 0 + +Class QByteRef + size=16 align=8 + base size=12 base align=8 +QByteRef (0x0x7ff72348b900) 0 + +Class QLatin1String + size=16 align=8 + base size=16 base align=8 +QLatin1String (0x0x7ff72348bae0) 0 + +Class QStringDataPtr + size=8 align=8 + base size=8 base align=8 +QStringDataPtr (0x0x7ff72348bd20) 0 + +Class QString::Null + size=1 align=1 + base size=0 base align=1 +QString::Null (0x0x7ff72348bde0) 0 empty + +Class QString + size=8 align=8 + base size=8 base align=8 +QString (0x0x7ff72348bd80) 0 + +Class QCharRef + size=16 align=8 + base size=12 base align=8 +QCharRef (0x0x7ff7232bdd80) 0 + +Class QStringRef + size=16 align=8 + base size=16 base align=8 +QStringRef (0x0x7ff72304f900) 0 + +Class QtPrivate::QHashCombine + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombine (0x0x7ff72304fd20) 0 empty + +Class QtPrivate::QHashCombineCommutative + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombineCommutative (0x0x7ff72304fd80) 0 empty + +Class std::__detail::_List_node_base + size=16 align=8 + base size=16 base align=8 +std::__detail::_List_node_base (0x0x7ff72304fde0) 0 + +Class QListData::NotArrayCompatibleLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotArrayCompatibleLayout (0x0x7ff7231b21e0) 0 empty + +Class QListData::NotIndirectLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotIndirectLayout (0x0x7ff7231b2240) 0 empty + +Class QListData::ArrayCompatibleLayout + size=1 align=1 + base size=1 base align=1 +QListData::ArrayCompatibleLayout (0x0x7ff7233c9dd0) 0 empty + QListData::NotIndirectLayout (0x0x7ff7231b22a0) 0 empty + +Class QListData::InlineWithPaddingLayout + size=1 align=1 + base size=1 base align=1 +QListData::InlineWithPaddingLayout (0x0x7ff722e4b850) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7ff7231b2300) 0 empty + QListData::NotIndirectLayout (0x0x7ff7231b2360) 0 empty + +Class QListData::IndirectLayout + size=1 align=1 + base size=1 base align=1 +QListData::IndirectLayout (0x0x7ff7233c9e38) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7ff7231b23c0) 0 empty + +Class QListData::Data + size=24 align=8 + base size=24 base align=8 +QListData::Data (0x0x7ff7231b2420) 0 + +Class QListData + size=8 align=8 + base size=8 base align=8 +QListData (0x0x7ff7231b2180) 0 + +Class QRegExp + size=8 align=8 + base size=8 base align=8 +QRegExp (0x0x7ff722f7f000) 0 + +Class QStringMatcher::Data + size=272 align=8 + base size=272 base align=8 +QStringMatcher::Data (0x0x7ff723005120) 0 + +Class QStringMatcher + size=1048 align=8 + base size=1048 base align=8 +QStringMatcher (0x0x7ff7230050c0) 0 + +Class QStringList + size=8 align=8 + base size=8 base align=8 +QStringList (0x0x7ff722ffc6e8) 0 + QList (0x0x7ff722ffc750) 0 + QListSpecialMethods (0x0x7ff723005300) 0 empty + +Class QScopedPointerPodDeleter + size=1 align=1 + base size=0 base align=1 +QScopedPointerPodDeleter (0x0x7ff723005600) 0 empty + +Class std::_Rb_tree_node_base + size=32 align=8 + base size=32 base align=8 +std::_Rb_tree_node_base (0x0x7ff723005a20) 0 + +Class std::allocator_arg_t + size=1 align=1 + base size=0 base align=1 +std::allocator_arg_t (0x0x7ff722a8b0c0) 0 empty + +Class std::__uses_alloc_base + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc_base (0x0x7ff722a8b240) 0 empty + +Class std::__uses_alloc0::_Sink + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc0::_Sink (0x0x7ff722a8b300) 0 empty + +Class std::__uses_alloc0 + size=1 align=1 + base size=1 base align=1 +std::__uses_alloc0 (0x0x7ff722d01618) 0 + std::__uses_alloc_base (0x0x7ff722a8b2a0) 0 empty + +Class std::_Swallow_assign + size=1 align=1 + base size=0 base align=1 +std::_Swallow_assign (0x0x7ff722b7e360) 0 empty + +Class QtPrivate::AbstractDebugStreamFunction + size=16 align=8 + base size=16 base align=8 +QtPrivate::AbstractDebugStreamFunction (0x0x7ff722b7e5a0) 0 + +Class QtPrivate::AbstractComparatorFunction + size=24 align=8 + base size=24 base align=8 +QtPrivate::AbstractComparatorFunction (0x0x7ff722b7e660) 0 + +Class QtPrivate::AbstractConverterFunction + size=8 align=8 + base size=8 base align=8 +QtPrivate::AbstractConverterFunction (0x0x7ff722b7e780) 0 + +Class QMetaType + size=80 align=8 + base size=80 base align=8 +QMetaType (0x0x7ff722b7e900) 0 + +Class QtMetaTypePrivate::VariantData + size=24 align=8 + base size=20 base align=8 +QtMetaTypePrivate::VariantData (0x0x7ff722b7ecc0) 0 + +Class QtMetaTypePrivate::VectorBoolElements + size=1 align=1 + base size=0 base align=1 +QtMetaTypePrivate::VectorBoolElements (0x0x7ff722b7ede0) 0 empty + +Class QtMetaTypePrivate::QSequentialIterableImpl + size=104 align=8 + base size=104 base align=8 +QtMetaTypePrivate::QSequentialIterableImpl (0x0x7ff7228df780) 0 + +Class QtMetaTypePrivate::QAssociativeIterableImpl + size=112 align=8 + base size=112 base align=8 +QtMetaTypePrivate::QAssociativeIterableImpl (0x0x7ff7228dfb40) 0 + +Class QtMetaTypePrivate::QPairVariantInterfaceImpl + size=40 align=8 + base size=40 base align=8 +QtMetaTypePrivate::QPairVariantInterfaceImpl (0x0x7ff7228dfd80) 0 + +Class QtPrivate::QSlotObjectBase + size=16 align=8 + base size=16 base align=8 +QtPrivate::QSlotObjectBase (0x0x7ff72271eae0) 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 (0x0x7ff72271ec60) 0 + vptr=((& QObjectData::_ZTV11QObjectData) + 16u) + +Class QObject::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObject::QPrivateSignal (0x0x7ff72271ee40) 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 (0x0x7ff72271ede0) 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 (0x0x7ff7227e91e0) 0 nearly-empty + vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16u) + +Class QSignalBlocker + size=16 align=8 + base size=10 base align=8 +QSignalBlocker (0x0x7ff7227e9240) 0 + +Class QAbstractAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractAnimation::QPrivateSignal (0x0x7ff7227e9300) 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 (0x0x7ff72280b0d0) 0 + vptr=((& QAbstractAnimation::_ZTV18QAbstractAnimation) + 16u) + QObject (0x0x7ff7227e92a0) 0 + primary-for QAbstractAnimation (0x0x7ff72280b0d0) + +Class QAnimationDriver::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationDriver::QPrivateSignal (0x0x7ff7227e93c0) 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 (0x0x7ff72280b138) 0 + vptr=((& QAnimationDriver::_ZTV16QAnimationDriver) + 16u) + QObject (0x0x7ff7227e9360) 0 + primary-for QAnimationDriver (0x0x7ff72280b138) + +Class QAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationGroup::QPrivateSignal (0x0x7ff7227e9480) 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 (0x0x7ff72280b1a0) 0 + vptr=((& QAnimationGroup::_ZTV15QAnimationGroup) + 16u) + QAbstractAnimation (0x0x7ff72280b208) 0 + primary-for QAnimationGroup (0x0x7ff72280b1a0) + QObject (0x0x7ff7227e9420) 0 + primary-for QAbstractAnimation (0x0x7ff72280b208) + +Class QParallelAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QParallelAnimationGroup::QPrivateSignal (0x0x7ff7227e9540) 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 (0x0x7ff72280b270) 0 + vptr=((& QParallelAnimationGroup::_ZTV23QParallelAnimationGroup) + 16u) + QAnimationGroup (0x0x7ff72280b2d8) 0 + primary-for QParallelAnimationGroup (0x0x7ff72280b270) + QAbstractAnimation (0x0x7ff72280b340) 0 + primary-for QAnimationGroup (0x0x7ff72280b2d8) + QObject (0x0x7ff7227e94e0) 0 + primary-for QAbstractAnimation (0x0x7ff72280b340) + +Class QPauseAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPauseAnimation::QPrivateSignal (0x0x7ff7227e9600) 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 (0x0x7ff72280b3a8) 0 + vptr=((& QPauseAnimation::_ZTV15QPauseAnimation) + 16u) + QAbstractAnimation (0x0x7ff72280b410) 0 + primary-for QPauseAnimation (0x0x7ff72280b3a8) + QObject (0x0x7ff7227e95a0) 0 + primary-for QAbstractAnimation (0x0x7ff72280b410) + +Class QEasingCurve + size=8 align=8 + base size=8 base align=8 +QEasingCurve (0x0x7ff722501960) 0 + +Class QMapNodeBase + size=24 align=8 + base size=24 base align=8 +QMapNodeBase (0x0x7ff7225dba20) 0 + +Class QMapDataBase + size=40 align=8 + base size=40 base align=8 +QMapDataBase (0x0x7ff7225dbae0) 0 + +Class QHashData::Node + size=16 align=8 + base size=16 base align=8 +QHashData::Node (0x0x7ff7225dbea0) 0 + +Class QHashData + size=48 align=8 + base size=44 base align=8 +QHashData (0x0x7ff7225dbe40) 0 + +Class QHashDummyValue + size=1 align=1 + base size=0 base align=1 +QHashDummyValue (0x0x7ff7225dbf00) 0 empty + +Class QVariant::PrivateShared + size=16 align=8 + base size=12 base align=8 +QVariant::PrivateShared (0x0x7ff7222fb960) 0 + +Class QVariant::Private::Data + size=8 align=8 + base size=8 base align=8 +QVariant::Private::Data (0x0x7ff7222fba20) 0 + +Class QVariant::Private + size=16 align=8 + base size=12 base align=8 +QVariant::Private (0x0x7ff7222fb9c0) 0 + +Class QVariant::Handler + size=72 align=8 + base size=72 base align=8 +QVariant::Handler (0x0x7ff7222fba80) 0 + +Class QVariant + size=16 align=8 + base size=16 base align=8 +QVariant (0x0x7ff7222fb900) 0 + +Class QVariantComparisonHelper + size=8 align=8 + base size=8 base align=8 +QVariantComparisonHelper (0x0x7ff722097d80) 0 + +Class QSequentialIterable::const_iterator + size=112 align=8 + base size=112 base align=8 +QSequentialIterable::const_iterator (0x0x7ff722097f60) 0 + +Class QSequentialIterable + size=104 align=8 + base size=104 base align=8 +QSequentialIterable (0x0x7ff722097f00) 0 + +Class QAssociativeIterable::const_iterator + size=120 align=8 + base size=120 base align=8 +QAssociativeIterable::const_iterator (0x0x7ff72214a060) 0 + +Class QAssociativeIterable + size=112 align=8 + base size=112 base align=8 +QAssociativeIterable (0x0x7ff72214a000) 0 + +Class QVariantAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QVariantAnimation::QPrivateSignal (0x0x7ff721e269c0) 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 (0x0x7ff721e299c0) 0 + vptr=((& QVariantAnimation::_ZTV17QVariantAnimation) + 16u) + QAbstractAnimation (0x0x7ff721e29a28) 0 + primary-for QVariantAnimation (0x0x7ff721e299c0) + QObject (0x0x7ff721e26960) 0 + primary-for QAbstractAnimation (0x0x7ff721e29a28) + +Class QPropertyAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPropertyAnimation::QPrivateSignal (0x0x7ff721e26a80) 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 (0x0x7ff721e29af8) 0 + vptr=((& QPropertyAnimation::_ZTV18QPropertyAnimation) + 16u) + QVariantAnimation (0x0x7ff721e29b60) 0 + primary-for QPropertyAnimation (0x0x7ff721e29af8) + QAbstractAnimation (0x0x7ff721e29bc8) 0 + primary-for QVariantAnimation (0x0x7ff721e29b60) + QObject (0x0x7ff721e26a20) 0 + primary-for QAbstractAnimation (0x0x7ff721e29bc8) + +Class QSequentialAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSequentialAnimationGroup::QPrivateSignal (0x0x7ff721e26b40) 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 (0x0x7ff721e29c30) 0 + vptr=((& QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup) + 16u) + QAnimationGroup (0x0x7ff721e29c98) 0 + primary-for QSequentialAnimationGroup (0x0x7ff721e29c30) + QAbstractAnimation (0x0x7ff721e29d00) 0 + primary-for QAnimationGroup (0x0x7ff721e29c98) + QObject (0x0x7ff721e26ae0) 0 + primary-for QAbstractAnimation (0x0x7ff721e29d00) + +Class QTextCodec::ConverterState + size=32 align=8 + base size=32 base align=8 +QTextCodec::ConverterState (0x0x7ff721e26c00) 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 (0x0x7ff721e26ba0) 0 nearly-empty + vptr=((& QTextCodec::_ZTV10QTextCodec) + 16u) + +Class QTextEncoder + size=40 align=8 + base size=40 base align=8 +QTextEncoder (0x0x7ff721e26d80) 0 + +Class QTextDecoder + size=40 align=8 + base size=40 base align=8 +QTextDecoder (0x0x7ff721e26de0) 0 + +Class QSharedData + size=4 align=4 + base size=4 base align=4 +QSharedData (0x0x7ff721e26e40) 0 + +Class QDate + size=8 align=8 + base size=8 base align=8 +QDate (0x0x7ff721f31060) 0 + +Class QTime + size=4 align=4 + base size=4 base align=4 +QTime (0x0x7ff721f311e0) 0 + +Class QDateTime + size=8 align=8 + base size=8 base align=8 +QDateTime (0x0x7ff721f31360) 0 + +Class QLibraryInfo + size=1 align=1 + base size=0 base align=1 +QLibraryInfo (0x0x7ff721f31540) 0 empty + +Class QIODevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIODevice::QPrivateSignal (0x0x7ff721f31600) 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 (0x0x7ff721e29f70) 0 + vptr=((& QIODevice::_ZTV9QIODevice) + 16u) + QObject (0x0x7ff721f315a0) 0 + primary-for QIODevice (0x0x7ff721e29f70) + +Class QBuffer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBuffer::QPrivateSignal (0x0x7ff721f317e0) 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 (0x0x7ff721fd40d0) 0 + vptr=((& QBuffer::_ZTV7QBuffer) + 16u) + QIODevice (0x0x7ff721fd4138) 0 + primary-for QBuffer (0x0x7ff721fd40d0) + QObject (0x0x7ff721f31780) 0 + primary-for QIODevice (0x0x7ff721fd4138) + +Class QDataStream + size=32 align=8 + base size=32 base align=8 +QDataStream (0x0x7ff721f31840) 0 + +Class QLocale + size=8 align=8 + base size=8 base align=8 +QLocale (0x0x7ff721f31900) 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 (0x0x7ff721f31c00) 0 + vptr=((& QTextStream::_ZTV11QTextStream) + 16u) + +Class QTextStreamManipulator + size=40 align=8 + base size=38 base align=8 +QTextStreamManipulator (0x0x7ff721f31e40) 0 + +Class QContiguousCacheData + size=24 align=4 + base size=24 base align=4 +QContiguousCacheData (0x0x7ff721ddb0c0) 0 + +Class QtSharedPointer::NormalDeleter + size=1 align=1 + base size=0 base align=1 +QtSharedPointer::NormalDeleter (0x0x7ff721ddb360) 0 empty + +Class QtSharedPointer::ExternalRefCountData + size=16 align=8 + base size=16 base align=8 +QtSharedPointer::ExternalRefCountData (0x0x7ff721ddb4e0) 0 + +Class QDebug::Stream + size=80 align=8 + base size=76 base align=8 +QDebug::Stream (0x0x7ff721ddb960) 0 + +Class QDebug + size=8 align=8 + base size=8 base align=8 +QDebug (0x0x7ff721ddb900) 0 + +Class QDebugStateSaver + size=8 align=8 + base size=8 base align=8 +QDebugStateSaver (0x0x7ff721b63a20) 0 + +Class QNoDebug + size=1 align=1 + base size=0 base align=1 +QNoDebug (0x0x7ff721b63ae0) 0 empty + +Class QFileDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileDevice::QPrivateSignal (0x0x7ff721b63ba0) 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 (0x0x7ff721ba2068) 0 + vptr=((& QFileDevice::_ZTV11QFileDevice) + 16u) + QIODevice (0x0x7ff721ba20d0) 0 + primary-for QFileDevice (0x0x7ff721ba2068) + QObject (0x0x7ff721b63b40) 0 + primary-for QIODevice (0x0x7ff721ba20d0) + +Class QFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFile::QPrivateSignal (0x0x7ff721b63d80) 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 (0x0x7ff721ba2208) 0 + vptr=((& QFile::_ZTV5QFile) + 16u) + QFileDevice (0x0x7ff721ba2270) 0 + primary-for QFile (0x0x7ff721ba2208) + QIODevice (0x0x7ff721ba22d8) 0 + primary-for QFileDevice (0x0x7ff721ba2270) + QObject (0x0x7ff721b63d20) 0 + primary-for QIODevice (0x0x7ff721ba22d8) + +Class QFileInfo + size=8 align=8 + base size=8 base align=8 +QFileInfo (0x0x7ff721b63f00) 0 + +Class QDir + size=8 align=8 + base size=8 base align=8 +QDir (0x0x7ff721888240) 0 + +Class QDirIterator + size=8 align=8 + base size=8 base align=8 +QDirIterator (0x0x7ff721888660) 0 + +Class QFileSelector::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSelector::QPrivateSignal (0x0x7ff7218888a0) 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 (0x0x7ff721ba27b8) 0 + vptr=((& QFileSelector::_ZTV13QFileSelector) + 16u) + QObject (0x0x7ff721888840) 0 + primary-for QFileSelector (0x0x7ff721ba27b8) + +Class QFileSystemWatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSystemWatcher::QPrivateSignal (0x0x7ff721888960) 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 (0x0x7ff721ba2820) 0 + vptr=((& QFileSystemWatcher::_ZTV18QFileSystemWatcher) + 16u) + QObject (0x0x7ff721888900) 0 + primary-for QFileSystemWatcher (0x0x7ff721ba2820) + +Class QLockFile + size=8 align=8 + base size=8 base align=8 +QLockFile (0x0x7ff7218889c0) 0 + +Class QLoggingCategory::AtomicBools + size=4 align=1 + base size=4 base align=1 +QLoggingCategory::AtomicBools (0x0x7ff721888b40) 0 + +Class QLoggingCategory + size=24 align=8 + base size=24 base align=8 +QLoggingCategory (0x0x7ff721888ae0) 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 (0x0x7ff721888cc0) 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 (0x0x7ff721ba28f0) 0 nearly-empty + vptr=((& std::bad_cast::_ZTVSt8bad_cast) + 16u) + std::exception (0x0x7ff721888d20) 0 nearly-empty + primary-for std::bad_cast (0x0x7ff721ba28f0) + +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 (0x0x7ff721ba2958) 0 nearly-empty + vptr=((& std::bad_typeid::_ZTVSt10bad_typeid) + 16u) + std::exception (0x0x7ff721888d80) 0 nearly-empty + primary-for std::bad_typeid (0x0x7ff721ba2958) + +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 (0x0x7ff721675bc8) 0 nearly-empty + vptr=((& std::bad_function_call::_ZTVSt17bad_function_call) + 16u) + std::exception (0x0x7ff7216c2e40) 0 nearly-empty + primary-for std::bad_function_call (0x0x7ff721675bc8) + +Class std::_Nocopy_types + size=16 align=8 + base size=16 base align=8 +std::_Nocopy_types (0x0x7ff7216c2f00) 0 + +Class std::_Any_data + size=16 align=8 + base size=16 base align=8 +std::_Any_data (0x0x7ff7216c2f60) 0 + +Class std::_Function_base + size=24 align=8 + base size=24 base align=8 +std::_Function_base (0x0x7ff7217650c0) 0 + +Class QProcessEnvironment + size=8 align=8 + base size=8 base align=8 +QProcessEnvironment (0x0x7ff7217655a0) 0 + +Class QProcess::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QProcess::QPrivateSignal (0x0x7ff7217657e0) 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 (0x0x7ff72179c410) 0 + vptr=((& QProcess::_ZTV8QProcess) + 16u) + QIODevice (0x0x7ff72179c478) 0 + primary-for QProcess (0x0x7ff72179c410) + QObject (0x0x7ff721765780) 0 + primary-for QIODevice (0x0x7ff72179c478) + +Class QResource + size=8 align=8 + base size=8 base align=8 +QResource (0x0x7ff721765840) 0 + +Class QSaveFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSaveFile::QPrivateSignal (0x0x7ff7217659c0) 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 (0x0x7ff72179c4e0) 0 + vptr=((& QSaveFile::_ZTV9QSaveFile) + 16u) + QFileDevice (0x0x7ff72179c548) 0 + primary-for QSaveFile (0x0x7ff72179c4e0) + QIODevice (0x0x7ff72179c5b0) 0 + primary-for QFileDevice (0x0x7ff72179c548) + QObject (0x0x7ff721765960) 0 + primary-for QIODevice (0x0x7ff72179c5b0) + +Class QSettings::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSettings::QPrivateSignal (0x0x7ff721765a80) 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 (0x0x7ff72179c618) 0 + vptr=((& QSettings::_ZTV9QSettings) + 16u) + QObject (0x0x7ff721765a20) 0 + primary-for QSettings (0x0x7ff72179c618) + +Class QStandardPaths + size=1 align=1 + base size=0 base align=1 +QStandardPaths (0x0x7ff721765ae0) 0 empty + +Class QStorageInfo + size=8 align=8 + base size=8 base align=8 +QStorageInfo (0x0x7ff721765c60) 0 + +Class QTemporaryDir + size=8 align=8 + base size=8 base align=8 +QTemporaryDir (0x0x7ff721765f60) 0 + +Class QTemporaryFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTemporaryFile::QPrivateSignal (0x0x7ff7214bf0c0) 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 (0x0x7ff72179c7b8) 0 + vptr=((& QTemporaryFile::_ZTV14QTemporaryFile) + 16u) + QFile (0x0x7ff72179c820) 0 + primary-for QTemporaryFile (0x0x7ff72179c7b8) + QFileDevice (0x0x7ff72179c888) 0 + primary-for QFile (0x0x7ff72179c820) + QIODevice (0x0x7ff72179c8f0) 0 + primary-for QFileDevice (0x0x7ff72179c888) + QObject (0x0x7ff7214bf060) 0 + primary-for QIODevice (0x0x7ff72179c8f0) + +Class QUrl + size=8 align=8 + base size=8 base align=8 +QUrl (0x0x7ff7214bf1e0) 0 + +Class QUrlQuery + size=8 align=8 + base size=8 base align=8 +QUrlQuery (0x0x7ff7211d5660) 0 + +Class QModelIndex + size=24 align=8 + base size=24 base align=8 +QModelIndex (0x0x7ff7211d5840) 0 + +Class QPersistentModelIndex + size=8 align=8 + base size=8 base align=8 +QPersistentModelIndex (0x0x7ff7211d59c0) 0 + +Class QAbstractItemModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractItemModel::QPrivateSignal (0x0x7ff7212f38a0) 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 (0x0x7ff7212f9750) 0 + vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16u) + QObject (0x0x7ff7212f3840) 0 + primary-for QAbstractItemModel (0x0x7ff7212f9750) + +Class QAbstractTableModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTableModel::QPrivateSignal (0x0x7ff7212f3c00) 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 (0x0x7ff7212f9958) 0 + vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16u) + QAbstractItemModel (0x0x7ff7212f99c0) 0 + primary-for QAbstractTableModel (0x0x7ff7212f9958) + QObject (0x0x7ff7212f3ba0) 0 + primary-for QAbstractItemModel (0x0x7ff7212f99c0) + +Class QAbstractListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractListModel::QPrivateSignal (0x0x7ff7212f3cc0) 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 (0x0x7ff7212f9a28) 0 + vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16u) + QAbstractItemModel (0x0x7ff7212f9a90) 0 + primary-for QAbstractListModel (0x0x7ff7212f9a28) + QObject (0x0x7ff7212f3c60) 0 + primary-for QAbstractItemModel (0x0x7ff7212f9a90) + +Class QAbstractProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractProxyModel::QPrivateSignal (0x0x7ff72100b000) 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 (0x0x7ff7212f9bc8) 0 + vptr=((& QAbstractProxyModel::_ZTV19QAbstractProxyModel) + 16u) + QAbstractItemModel (0x0x7ff7212f9c30) 0 + primary-for QAbstractProxyModel (0x0x7ff7212f9bc8) + QObject (0x0x7ff7212f3f60) 0 + primary-for QAbstractItemModel (0x0x7ff7212f9c30) + +Class QIdentityProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIdentityProxyModel::QPrivateSignal (0x0x7ff72100b0c0) 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 (0x0x7ff7212f9c98) 0 + vptr=((& QIdentityProxyModel::_ZTV19QIdentityProxyModel) + 16u) + QAbstractProxyModel (0x0x7ff7212f9d00) 0 + primary-for QIdentityProxyModel (0x0x7ff7212f9c98) + QAbstractItemModel (0x0x7ff7212f9d68) 0 + primary-for QAbstractProxyModel (0x0x7ff7212f9d00) + QObject (0x0x7ff72100b060) 0 + primary-for QAbstractItemModel (0x0x7ff7212f9d68) + +Class QItemSelectionRange + size=16 align=8 + base size=16 base align=8 +QItemSelectionRange (0x0x7ff72100b120) 0 + +Class QItemSelectionModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QItemSelectionModel::QPrivateSignal (0x0x7ff72100b360) 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 (0x0x7ff721080000) 0 + vptr=((& QItemSelectionModel::_ZTV19QItemSelectionModel) + 16u) + QObject (0x0x7ff72100b300) 0 + primary-for QItemSelectionModel (0x0x7ff721080000) + +Class QItemSelection + size=8 align=8 + base size=8 base align=8 +QItemSelection (0x0x7ff721080208) 0 + QList (0x0x7ff721080270) 0 + QListSpecialMethods (0x0x7ff72100b600) 0 empty + +Class QSortFilterProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSortFilterProxyModel::QPrivateSignal (0x0x7ff72100ba20) 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 (0x0x7ff721080340) 0 + vptr=((& QSortFilterProxyModel::_ZTV21QSortFilterProxyModel) + 16u) + QAbstractProxyModel (0x0x7ff7210803a8) 0 + primary-for QSortFilterProxyModel (0x0x7ff721080340) + QAbstractItemModel (0x0x7ff721080410) 0 + primary-for QAbstractProxyModel (0x0x7ff7210803a8) + QObject (0x0x7ff72100b9c0) 0 + primary-for QAbstractItemModel (0x0x7ff721080410) + +Class QStringListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStringListModel::QPrivateSignal (0x0x7ff72100bae0) 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 (0x0x7ff721080478) 0 + vptr=((& QStringListModel::_ZTV16QStringListModel) + 16u) + QAbstractListModel (0x0x7ff7210804e0) 0 + primary-for QStringListModel (0x0x7ff721080478) + QAbstractItemModel (0x0x7ff721080548) 0 + primary-for QAbstractListModel (0x0x7ff7210804e0) + QObject (0x0x7ff72100ba80) 0 + primary-for QAbstractItemModel (0x0x7ff721080548) + +Class QJsonValue + size=24 align=8 + base size=20 base align=8 +QJsonValue (0x0x7ff72100bb40) 0 + +Class QJsonValueRef + size=16 align=8 + base size=12 base align=8 +QJsonValueRef (0x0x7ff72100bc00) 0 + +Class QJsonValuePtr + size=24 align=8 + base size=24 base align=8 +QJsonValuePtr (0x0x7ff72100bcc0) 0 + +Class QJsonValueRefPtr + size=16 align=8 + base size=16 base align=8 +QJsonValueRefPtr (0x0x7ff72100bd20) 0 + +Class QJsonArray::iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::iterator (0x0x7ff72100bde0) 0 + +Class QJsonArray::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::const_iterator (0x0x7ff72100be40) 0 + +Class QJsonArray + size=16 align=8 + base size=16 base align=8 +QJsonArray (0x0x7ff72100bd80) 0 + +Class QJsonParseError + size=8 align=4 + base size=8 base align=4 +QJsonParseError (0x0x7ff72100bf00) 0 + +Class QJsonDocument + size=8 align=8 + base size=8 base align=8 +QJsonDocument (0x0x7ff72100bf60) 0 + +Class QJsonObject::iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::iterator (0x0x7ff720e1c060) 0 + +Class QJsonObject::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::const_iterator (0x0x7ff720e1c0c0) 0 + +Class QJsonObject + size=16 align=8 + base size=16 base align=8 +QJsonObject (0x0x7ff720e1c000) 0 + +Class QEventLoop::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventLoop::QPrivateSignal (0x0x7ff720e1c2a0) 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 (0x0x7ff721080750) 0 + vptr=((& QEventLoop::_ZTV10QEventLoop) + 16u) + QObject (0x0x7ff720e1c240) 0 + primary-for QEventLoop (0x0x7ff721080750) + +Class QEventLoopLocker + size=8 align=8 + base size=8 base align=8 +QEventLoopLocker (0x0x7ff720e1c420) 0 + +Class QAbstractEventDispatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractEventDispatcher::QPrivateSignal (0x0x7ff720e1c4e0) 0 empty + +Class QAbstractEventDispatcher::TimerInfo + size=12 align=4 + base size=12 base align=4 +QAbstractEventDispatcher::TimerInfo (0x0x7ff720e1c540) 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 (0x0x7ff721080888) 0 + vptr=((& QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher) + 16u) + QObject (0x0x7ff720e1c480) 0 + primary-for QAbstractEventDispatcher (0x0x7ff721080888) + +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 (0x0x7ff720e1c5a0) 0 + vptr=((& QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter) + 16u) + +Class QBasicTimer + size=4 align=4 + base size=4 base align=4 +QBasicTimer (0x0x7ff720e1c600) 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 (0x0x7ff720e1c780) 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 (0x0x7ff721080958) 0 + vptr=((& QTimerEvent::_ZTV11QTimerEvent) + 16u) + QEvent (0x0x7ff720e1c7e0) 0 + primary-for QTimerEvent (0x0x7ff721080958) + +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 (0x0x7ff7210809c0) 0 + vptr=((& QChildEvent::_ZTV11QChildEvent) + 16u) + QEvent (0x0x7ff720e1c840) 0 + primary-for QChildEvent (0x0x7ff7210809c0) + +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 (0x0x7ff721080a28) 0 + vptr=((& QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent) + 16u) + QEvent (0x0x7ff720e1c8a0) 0 + primary-for QDynamicPropertyChangeEvent (0x0x7ff721080a28) + +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 (0x0x7ff721080a90) 0 + vptr=((& QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent) + 16u) + QEvent (0x0x7ff720e1c900) 0 + primary-for QDeferredDeleteEvent (0x0x7ff721080a90) + +Class QCoreApplication::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QCoreApplication::QPrivateSignal (0x0x7ff720e1c9c0) 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 (0x0x7ff721080af8) 0 + vptr=((& QCoreApplication::_ZTV16QCoreApplication) + 16u) + QObject (0x0x7ff720e1c960) 0 + primary-for QCoreApplication (0x0x7ff721080af8) + +Class QMetaMethod + size=16 align=8 + base size=12 base align=8 +QMetaMethod (0x0x7ff720e1ca80) 0 + +Class QMetaEnum + size=16 align=8 + base size=12 base align=8 +QMetaEnum (0x0x7ff720e1cc00) 0 + +Class QMetaProperty + size=32 align=8 + base size=32 base align=8 +QMetaProperty (0x0x7ff720e1cde0) 0 + +Class QMetaClassInfo + size=16 align=8 + base size=12 base align=8 +QMetaClassInfo (0x0x7ff720e1ce40) 0 + +Class QMimeData::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QMimeData::QPrivateSignal (0x0x7ff720f9f060) 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 (0x0x7ff721080c98) 0 + vptr=((& QMimeData::_ZTV9QMimeData) + 16u) + QObject (0x0x7ff720f9f000) 0 + primary-for QMimeData (0x0x7ff721080c98) + +Class QObjectCleanupHandler::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObjectCleanupHandler::QPrivateSignal (0x0x7ff720f9f120) 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 (0x0x7ff721080d00) 0 + vptr=((& QObjectCleanupHandler::_ZTV21QObjectCleanupHandler) + 16u) + QObject (0x0x7ff720f9f0c0) 0 + primary-for QObjectCleanupHandler (0x0x7ff721080d00) + +Class QSharedMemory::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSharedMemory::QPrivateSignal (0x0x7ff720f9f360) 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 (0x0x7ff721080d68) 0 + vptr=((& QSharedMemory::_ZTV13QSharedMemory) + 16u) + QObject (0x0x7ff720f9f300) 0 + primary-for QSharedMemory (0x0x7ff721080d68) + +Class QSignalMapper::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalMapper::QPrivateSignal (0x0x7ff720f9f420) 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 (0x0x7ff721080dd0) 0 + vptr=((& QSignalMapper::_ZTV13QSignalMapper) + 16u) + QObject (0x0x7ff720f9f3c0) 0 + primary-for QSignalMapper (0x0x7ff721080dd0) + +Class QSocketNotifier::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSocketNotifier::QPrivateSignal (0x0x7ff720f9f4e0) 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 (0x0x7ff721080e38) 0 + vptr=((& QSocketNotifier::_ZTV15QSocketNotifier) + 16u) + QObject (0x0x7ff720f9f480) 0 + primary-for QSocketNotifier (0x0x7ff721080e38) + +Class QSystemSemaphore + size=8 align=8 + base size=8 base align=8 +QSystemSemaphore (0x0x7ff720f9f540) 0 + +Class QTimer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimer::QPrivateSignal (0x0x7ff720f9f660) 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 (0x0x7ff721080ea0) 0 + vptr=((& QTimer::_ZTV6QTimer) + 16u) + QObject (0x0x7ff720f9f600) 0 + primary-for QTimer (0x0x7ff721080ea0) + +Class QTranslator::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTranslator::QPrivateSignal (0x0x7ff720f9f7e0) 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 (0x0x7ff721080f70) 0 + vptr=((& QTranslator::_ZTV11QTranslator) + 16u) + QObject (0x0x7ff720f9f780) 0 + primary-for QTranslator (0x0x7ff721080f70) + +Class QMimeType + size=8 align=8 + base size=8 base align=8 +QMimeType (0x0x7ff720f9f840) 0 + +Class QMimeDatabase + size=8 align=8 + base size=8 base align=8 +QMimeDatabase (0x0x7ff720f9fa20) 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 (0x0x7ff720f9fa80) 0 nearly-empty + vptr=((& QFactoryInterface::_ZTV17QFactoryInterface) + 16u) + +Class QLibrary::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLibrary::QPrivateSignal (0x0x7ff720f9fba0) 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 (0x0x7ff720c65068) 0 + vptr=((& QLibrary::_ZTV8QLibrary) + 16u) + QObject (0x0x7ff720f9fb40) 0 + primary-for QLibrary (0x0x7ff720c65068) + +Class QStaticPlugin + size=16 align=8 + base size=16 base align=8 +QStaticPlugin (0x0x7ff720f9fd20) 0 + +Class QPluginLoader::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPluginLoader::QPrivateSignal (0x0x7ff720f9ff00) 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 (0x0x7ff720c65208) 0 + vptr=((& QPluginLoader::_ZTV13QPluginLoader) + 16u) + QObject (0x0x7ff720f9fea0) 0 + primary-for QPluginLoader (0x0x7ff720c65208) + +Class QUuid + size=16 align=4 + base size=16 base align=4 +QUuid (0x0x7ff720f9ff60) 0 + +Class QAbstractState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractState::QPrivateSignal (0x0x7ff720cec180) 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 (0x0x7ff720c652d8) 0 + vptr=((& QAbstractState::_ZTV14QAbstractState) + 16u) + QObject (0x0x7ff720cec120) 0 + primary-for QAbstractState (0x0x7ff720c652d8) + +Class QAbstractTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTransition::QPrivateSignal (0x0x7ff720cec240) 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 (0x0x7ff720c65340) 0 + vptr=((& QAbstractTransition::_ZTV19QAbstractTransition) + 16u) + QObject (0x0x7ff720cec1e0) 0 + primary-for QAbstractTransition (0x0x7ff720c65340) + +Class QEventTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventTransition::QPrivateSignal (0x0x7ff720cec300) 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 (0x0x7ff720c653a8) 0 + vptr=((& QEventTransition::_ZTV16QEventTransition) + 16u) + QAbstractTransition (0x0x7ff720c65410) 0 + primary-for QEventTransition (0x0x7ff720c653a8) + QObject (0x0x7ff720cec2a0) 0 + primary-for QAbstractTransition (0x0x7ff720c65410) + +Class QFinalState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFinalState::QPrivateSignal (0x0x7ff720cec3c0) 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 (0x0x7ff720c65478) 0 + vptr=((& QFinalState::_ZTV11QFinalState) + 16u) + QAbstractState (0x0x7ff720c654e0) 0 + primary-for QFinalState (0x0x7ff720c65478) + QObject (0x0x7ff720cec360) 0 + primary-for QAbstractState (0x0x7ff720c654e0) + +Class QHistoryState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QHistoryState::QPrivateSignal (0x0x7ff720cec480) 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 (0x0x7ff720c65548) 0 + vptr=((& QHistoryState::_ZTV13QHistoryState) + 16u) + QAbstractState (0x0x7ff720c655b0) 0 + primary-for QHistoryState (0x0x7ff720c65548) + QObject (0x0x7ff720cec420) 0 + primary-for QAbstractState (0x0x7ff720c655b0) + +Class QSignalTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalTransition::QPrivateSignal (0x0x7ff720cec540) 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 (0x0x7ff720c65618) 0 + vptr=((& QSignalTransition::_ZTV17QSignalTransition) + 16u) + QAbstractTransition (0x0x7ff720c65680) 0 + primary-for QSignalTransition (0x0x7ff720c65618) + QObject (0x0x7ff720cec4e0) 0 + primary-for QAbstractTransition (0x0x7ff720c65680) + +Class QState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QState::QPrivateSignal (0x0x7ff720cec600) 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 (0x0x7ff720c656e8) 0 + vptr=((& QState::_ZTV6QState) + 16u) + QAbstractState (0x0x7ff720c65750) 0 + primary-for QState (0x0x7ff720c656e8) + QObject (0x0x7ff720cec5a0) 0 + primary-for QAbstractState (0x0x7ff720c65750) + +Class QStateMachine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStateMachine::QPrivateSignal (0x0x7ff720cec720) 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 (0x0x7ff720c658f0) 0 + vptr=((& QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE) + 16u) + QEvent (0x0x7ff720cec780) 0 + primary-for QStateMachine::SignalEvent (0x0x7ff720c658f0) + +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 (0x0x7ff720c65958) 0 + vptr=((& QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE) + 16u) + QEvent (0x0x7ff720cec7e0) 0 + primary-for QStateMachine::WrappedEvent (0x0x7ff720c65958) + +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 (0x0x7ff720c657b8) 0 + vptr=((& QStateMachine::_ZTV13QStateMachine) + 16u) + QState (0x0x7ff720c65820) 0 + primary-for QStateMachine (0x0x7ff720c657b8) + QAbstractState (0x0x7ff720c65888) 0 + primary-for QState (0x0x7ff720c65820) + QObject (0x0x7ff720cec6c0) 0 + primary-for QAbstractState (0x0x7ff720c65888) + +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 (0x0x7ff720c659c0) 0 nearly-empty + vptr=((& QException::_ZTV10QException) + 16u) + std::exception (0x0x7ff720cec840) 0 nearly-empty + primary-for QException (0x0x7ff720c659c0) + +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 (0x0x7ff720c65a28) 0 nearly-empty + vptr=((& QUnhandledException::_ZTV19QUnhandledException) + 16u) + QException (0x0x7ff720c65a90) 0 nearly-empty + primary-for QUnhandledException (0x0x7ff720c65a28) + std::exception (0x0x7ff720cec8a0) 0 nearly-empty + primary-for QException (0x0x7ff720c65a90) + +Class QtPrivate::ExceptionHolder + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionHolder (0x0x7ff720cec900) 0 + +Class QtPrivate::ExceptionStore + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionStore (0x0x7ff720cec9c0) 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 (0x0x7ff720ceca20) 0 + vptr=((& QRunnable::_ZTV9QRunnable) + 16u) + +Class QBasicMutex + size=8 align=8 + base size=8 base align=8 +QBasicMutex (0x0x7ff720ceca80) 0 + +Class QMutex + size=8 align=8 + base size=8 base align=8 +QMutex (0x0x7ff720c65bc8) 0 + QBasicMutex (0x0x7ff720ceccc0) 0 + +Class QMutexLocker + size=8 align=8 + base size=8 base align=8 +QMutexLocker (0x0x7ff720cecd20) 0 + +Class QtPrivate::ResultItem + size=16 align=8 + base size=16 base align=8 +QtPrivate::ResultItem (0x0x7ff720cecde0) 0 + +Class QtPrivate::ResultIteratorBase + size=16 align=8 + base size=12 base align=8 +QtPrivate::ResultIteratorBase (0x0x7ff720cece40) 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 (0x0x7ff720a82000) 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 (0x0x7ff720a820c0) 0 + vptr=((& QFutureInterfaceBase::_ZTV20QFutureInterfaceBase) + 16u) + +Class QFutureWatcherBase::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFutureWatcherBase::QPrivateSignal (0x0x7ff720a82420) 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 (0x0x7ff720a93478) 0 + vptr=((& QFutureWatcherBase::_ZTV18QFutureWatcherBase) + 16u) + QObject (0x0x7ff720a823c0) 0 + primary-for QFutureWatcherBase (0x0x7ff720a93478) + +Class QReadWriteLock + size=8 align=8 + base size=8 base align=8 +QReadWriteLock (0x0x7ff720a82540) 0 + +Class QReadLocker + size=8 align=8 + base size=8 base align=8 +QReadLocker (0x0x7ff720a827e0) 0 + +Class QWriteLocker + size=8 align=8 + base size=8 base align=8 +QWriteLocker (0x0x7ff720a82840) 0 + +Class QSemaphore + size=8 align=8 + base size=8 base align=8 +QSemaphore (0x0x7ff720a828a0) 0 + +Class QThread::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThread::QPrivateSignal (0x0x7ff720a82960) 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 (0x0x7ff720a93a28) 0 + vptr=((& QThread::_ZTV7QThread) + 16u) + QObject (0x0x7ff720a82900) 0 + primary-for QThread (0x0x7ff720a93a28) + +Class QThreadPool::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThreadPool::QPrivateSignal (0x0x7ff720a82a20) 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 (0x0x7ff720a93a90) 0 + vptr=((& QThreadPool::_ZTV11QThreadPool) + 16u) + QObject (0x0x7ff720a829c0) 0 + primary-for QThreadPool (0x0x7ff720a93a90) + +Class QThreadStorageData + size=4 align=4 + base size=4 base align=4 +QThreadStorageData (0x0x7ff720a82a80) 0 + +Class QWaitCondition + size=8 align=8 + base size=8 base align=8 +QWaitCondition (0x0x7ff720a82b40) 0 + +Class QBitArray + size=8 align=8 + base size=8 base align=8 +QBitArray (0x0x7ff720865060) 0 + +Class QBitRef + size=16 align=8 + base size=12 base align=8 +QBitRef (0x0x7ff7208652a0) 0 + +Class QByteArrayMatcher::Data + size=272 align=8 + base size=272 base align=8 +QByteArrayMatcher::Data (0x0x7ff7208654e0) 0 + +Class QByteArrayMatcher + size=1040 align=8 + base size=1040 base align=8 +QByteArrayMatcher (0x0x7ff720865480) 0 + +Class QCollatorSortKey + size=8 align=8 + base size=8 base align=8 +QCollatorSortKey (0x0x7ff720865660) 0 + +Class QCollator + size=8 align=8 + base size=8 base align=8 +QCollator (0x0x7ff720865720) 0 + +Class QCommandLineOption + size=8 align=8 + base size=8 base align=8 +QCommandLineOption (0x0x7ff7209874e0) 0 + +Class QCommandLineParser + size=8 align=8 + base size=8 base align=8 +QCommandLineParser (0x0x7ff7209876c0) 0 + +Class QCryptographicHash + size=8 align=8 + base size=8 base align=8 +QCryptographicHash (0x0x7ff720987720) 0 + +Class QElapsedTimer + size=16 align=8 + base size=16 base align=8 +QElapsedTimer (0x0x7ff720987780) 0 + +Class QPoint + size=8 align=4 + base size=8 base align=4 +QPoint (0x0x7ff7209877e0) 0 + +Class QPointF + size=16 align=8 + base size=16 base align=8 +QPointF (0x0x7ff720987960) 0 + +Class QLine + size=16 align=4 + base size=16 base align=4 +QLine (0x0x7ff720987ae0) 0 + +Class QLineF + size=32 align=8 + base size=32 base align=8 +QLineF (0x0x7ff720987c60) 0 + +Class QLinkedListData + size=32 align=8 + base size=25 base align=8 +QLinkedListData (0x0x7ff720987de0) 0 + +Class QMargins + size=16 align=4 + base size=16 base align=4 +QMargins (0x0x7ff7206c15a0) 0 + +Class QMarginsF + size=32 align=8 + base size=32 base align=8 +QMarginsF (0x0x7ff7206c1720) 0 + +Class QMessageAuthenticationCode + size=8 align=8 + base size=8 base align=8 +QMessageAuthenticationCode (0x0x7ff7206c18a0) 0 + +Class QSize + size=8 align=4 + base size=8 base align=4 +QSize (0x0x7ff7206c1960) 0 + +Class QSizeF + size=16 align=8 + base size=16 base align=8 +QSizeF (0x0x7ff7206c1ba0) 0 + +Class QRect + size=16 align=4 + base size=16 base align=4 +QRect (0x0x7ff7206c1de0) 0 + +Class QRectF + size=32 align=8 + base size=32 base align=8 +QRectF (0x0x7ff7206c1f60) 0 + +Class QRegularExpression + size=8 align=8 + base size=8 base align=8 +QRegularExpression (0x0x7ff7204ff120) 0 + +Class QRegularExpressionMatch + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatch (0x0x7ff7204ff540) 0 + +Class QRegularExpressionMatchIterator + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatchIterator (0x0x7ff7204ff720) 0 + +Class QAbstractConcatenable + size=1 align=1 + base size=0 base align=1 +QAbstractConcatenable (0x0x7ff7204ffae0) 0 empty + +Class QTextBoundaryFinder + size=48 align=8 + base size=48 base align=8 +QTextBoundaryFinder (0x0x7ff720242540) 0 + +Class QTimeLine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimeLine::QPrivateSignal (0x0x7ff720242720) 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 (0x0x7ff720229888) 0 + vptr=((& QTimeLine::_ZTV9QTimeLine) + 16u) + QObject (0x0x7ff7202426c0) 0 + primary-for QTimeLine (0x0x7ff720229888) + +Class QTimeZone::OffsetData + size=32 align=8 + base size=28 base align=8 +QTimeZone::OffsetData (0x0x7ff7202427e0) 0 + +Class QTimeZone + size=8 align=8 + base size=8 base align=8 +QTimeZone (0x0x7ff720242780) 0 + +Class QVersionNumber::SegmentStorage + size=8 align=8 + base size=8 base align=8 +QVersionNumber::SegmentStorage (0x0x7ff720242b40) 0 + +Class QVersionNumber + size=8 align=8 + base size=8 base align=8 +QVersionNumber (0x0x7ff720242ae0) 0 + +Class QXmlStreamStringRef + size=16 align=8 + base size=16 base align=8 +QXmlStreamStringRef (0x0x7ff720393900) 0 + +Class QXmlStreamAttribute + size=80 align=8 + base size=73 base align=8 +QXmlStreamAttribute (0x0x7ff720061600) 0 + +Class QXmlStreamAttributes + size=8 align=8 + base size=8 base align=8 +QXmlStreamAttributes (0x0x7ff7200c5000) 0 + QVector (0x0x7ff7200618a0) 0 + +Class QXmlStreamNamespaceDeclaration + size=40 align=8 + base size=40 base align=8 +QXmlStreamNamespaceDeclaration (0x0x7ff720061900) 0 + +Class QXmlStreamNotationDeclaration + size=56 align=8 + base size=56 base align=8 +QXmlStreamNotationDeclaration (0x0x7ff720061a80) 0 + +Class QXmlStreamEntityDeclaration + size=88 align=8 + base size=88 base align=8 +QXmlStreamEntityDeclaration (0x0x7ff720061c00) 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 (0x0x7ff720061d80) 0 nearly-empty + vptr=((& QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver) + 16u) + +Class QXmlStreamReader + size=8 align=8 + base size=8 base align=8 +QXmlStreamReader (0x0x7ff720061de0) 0 + +Class QXmlStreamWriter + size=8 align=8 + base size=8 base align=8 +QXmlStreamWriter (0x0x7ff720061f00) 0 + +Class QNdefRecord + size=8 align=8 + base size=8 base align=8 +QNdefRecord (0x0x7ff72016c060) 0 + +Class QNdefFilter::Record + size=24 align=8 + base size=24 base align=8 +QNdefFilter::Record (0x0x7ff72016c180) 0 + +Class QNdefFilter + size=8 align=8 + base size=8 base align=8 +QNdefFilter (0x0x7ff72016c120) 0 + +Class QNdefMessage + size=8 align=8 + base size=8 base align=8 +QNdefMessage (0x0x7ff7200c5618) 0 + QList (0x0x7ff7200c5680) 0 + QListSpecialMethods (0x0x7ff72016c360) 0 empty + +Class QNdefNfcTextRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcTextRecord (0x0x7ff7200c56e8) 0 + QNdefRecord (0x0x7ff72016c540) 0 + +Class QNdefNfcUriRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcUriRecord (0x0x7ff7200c5750) 0 + QNdefRecord (0x0x7ff72016c5a0) 0 + +Class QNdefNfcIconRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcIconRecord (0x0x7ff7200c57b8) 0 + QNdefRecord (0x0x7ff72016c600) 0 + +Class QNdefNfcSmartPosterRecord + size=16 align=8 + base size=16 base align=8 +QNdefNfcSmartPosterRecord (0x0x7ff7200c5820) 0 + QNdefRecord (0x0x7ff72016c660) 0 + +Class QNearFieldTarget::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldTarget::QPrivateSignal (0x0x7ff72016c780) 0 empty + +Class QNearFieldTarget::RequestId + size=8 align=8 + base size=8 base align=8 +QNearFieldTarget::RequestId (0x0x7ff72016c7e0) 0 + +Vtable for QNearFieldTarget +QNearFieldTarget::_ZTV16QNearFieldTarget: 25u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QNearFieldTarget) +16 (int (*)(...))QNearFieldTarget::metaObject +24 (int (*)(...))QNearFieldTarget::qt_metacast +32 (int (*)(...))QNearFieldTarget::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 (*)(...))QNearFieldTarget::url +128 (int (*)(...))__cxa_pure_virtual +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))QNearFieldTarget::hasNdefMessage +152 (int (*)(...))QNearFieldTarget::readNdefMessages +160 (int (*)(...))QNearFieldTarget::writeNdefMessages +168 (int (*)(...))QNearFieldTarget::sendCommand +176 (int (*)(...))QNearFieldTarget::sendCommands +184 (int (*)(...))QNearFieldTarget::waitForRequestCompleted +192 (int (*)(...))QNearFieldTarget::handleResponse + +Class QNearFieldTarget + size=24 align=8 + base size=24 base align=8 +QNearFieldTarget (0x0x7ff7200c5888) 0 + vptr=((& QNearFieldTarget::_ZTV16QNearFieldTarget) + 16u) + QObject (0x0x7ff72016c720) 0 + primary-for QNearFieldTarget (0x0x7ff7200c5888) + +Class QNearFieldManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldManager::QPrivateSignal (0x0x7ff72016cb40) 0 empty + +Vtable for QNearFieldManager +QNearFieldManager::_ZTV17QNearFieldManager: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QNearFieldManager) +16 (int (*)(...))QNearFieldManager::metaObject +24 (int (*)(...))QNearFieldManager::qt_metacast +32 (int (*)(...))QNearFieldManager::qt_metacall +40 (int (*)(...))QNearFieldManager::~QNearFieldManager +48 (int (*)(...))QNearFieldManager::~QNearFieldManager +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 QNearFieldManager + size=24 align=8 + base size=24 base align=8 +QNearFieldManager (0x0x7ff7200c59c0) 0 + vptr=((& QNearFieldManager::_ZTV17QNearFieldManager) + 16u) + QObject (0x0x7ff72016cae0) 0 + primary-for QNearFieldManager (0x0x7ff7200c59c0) + +Class QNearFieldShareManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldShareManager::QPrivateSignal (0x0x7ff72016cd20) 0 empty + +Vtable for QNearFieldShareManager +QNearFieldShareManager::_ZTV22QNearFieldShareManager: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI22QNearFieldShareManager) +16 (int (*)(...))QNearFieldShareManager::metaObject +24 (int (*)(...))QNearFieldShareManager::qt_metacast +32 (int (*)(...))QNearFieldShareManager::qt_metacall +40 (int (*)(...))QNearFieldShareManager::~QNearFieldShareManager +48 (int (*)(...))QNearFieldShareManager::~QNearFieldShareManager +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 QNearFieldShareManager + size=24 align=8 + base size=24 base align=8 +QNearFieldShareManager (0x0x7ff7200c5b60) 0 + vptr=((& QNearFieldShareManager::_ZTV22QNearFieldShareManager) + 16u) + QObject (0x0x7ff72016ccc0) 0 + primary-for QNearFieldShareManager (0x0x7ff7200c5b60) + +Class QNearFieldShareTarget::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldShareTarget::QPrivateSignal (0x0x7ff71ff05000) 0 empty + +Vtable for QNearFieldShareTarget +QNearFieldShareTarget::_ZTV21QNearFieldShareTarget: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QNearFieldShareTarget) +16 (int (*)(...))QNearFieldShareTarget::metaObject +24 (int (*)(...))QNearFieldShareTarget::qt_metacast +32 (int (*)(...))QNearFieldShareTarget::qt_metacall +40 (int (*)(...))QNearFieldShareTarget::~QNearFieldShareTarget +48 (int (*)(...))QNearFieldShareTarget::~QNearFieldShareTarget +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 QNearFieldShareTarget + size=24 align=8 + base size=24 base align=8 +QNearFieldShareTarget (0x0x7ff7200c5c98) 0 + vptr=((& QNearFieldShareTarget::_ZTV21QNearFieldShareTarget) + 16u) + QObject (0x0x7ff72016cf60) 0 + primary-for QNearFieldShareTarget (0x0x7ff7200c5c98) + +Class QQmlNdefRecord::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QQmlNdefRecord::QPrivateSignal (0x0x7ff71ff050c0) 0 empty + +Vtable for QQmlNdefRecord +QQmlNdefRecord::_ZTV14QQmlNdefRecord: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI14QQmlNdefRecord) +16 (int (*)(...))QQmlNdefRecord::metaObject +24 (int (*)(...))QQmlNdefRecord::qt_metacast +32 (int (*)(...))QQmlNdefRecord::qt_metacall +40 (int (*)(...))QQmlNdefRecord::~QQmlNdefRecord +48 (int (*)(...))QQmlNdefRecord::~QQmlNdefRecord +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 QQmlNdefRecord + size=24 align=8 + base size=24 base align=8 +QQmlNdefRecord (0x0x7ff7200c5d00) 0 + vptr=((& QQmlNdefRecord::_ZTV14QQmlNdefRecord) + 16u) + QObject (0x0x7ff71ff05060) 0 + primary-for QQmlNdefRecord (0x0x7ff7200c5d00) + diff --git a/tests/auto/bic/data/QtNfc.5.8.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtNfc.5.8.0.linux-gcc-amd64.txt new file mode 100644 index 0000000..ac6d5f7 --- /dev/null +++ b/tests/auto/bic/data/QtNfc.5.8.0.linux-gcc-amd64.txt @@ -0,0 +1,4418 @@ +Class std::__failure_type + size=1 align=1 + base size=0 base align=1 +std::__failure_type (0x0x7fee2763c5a0) 0 empty + +Class std::__do_is_destructible_impl + size=1 align=1 + base size=0 base align=1 +std::__do_is_destructible_impl (0x0x7fee2768dd20) 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 (0x0x7fee2768df60) 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 (0x0x7fee276b71e0) 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 (0x0x7fee276b7420) 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 (0x0x7fee276b75a0) 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 (0x0x7fee276b7960) 0 empty + +Class std::__do_common_type_impl + size=1 align=1 + base size=0 base align=1 +std::__do_common_type_impl (0x0x7fee25374120) 0 empty + +Class std::__do_member_type_wrapper + size=1 align=1 + base size=0 base align=1 +std::__do_member_type_wrapper (0x0x7fee253741e0) 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 (0x0x7fee25374540) 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 (0x0x7fee25374600) 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 (0x0x7fee253746c0) 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 (0x0x7fee25374780) 0 empty + +Class std::__result_of_other_impl + size=1 align=1 + base size=0 base align=1 +std::__result_of_other_impl (0x0x7fee25374a20) 0 empty + +Class std::piecewise_construct_t + size=1 align=1 + base size=0 base align=1 +std::piecewise_construct_t (0x0x7fee25374c00) 0 empty + +Class std::__true_type + size=1 align=1 + base size=0 base align=1 +std::__true_type (0x0x7fee253f50c0) 0 empty + +Class std::__false_type + size=1 align=1 + base size=0 base align=1 +std::__false_type (0x0x7fee253f5120) 0 empty + +Class std::input_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::input_iterator_tag (0x0x7fee25429d80) 0 empty + +Class std::output_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::output_iterator_tag (0x0x7fee25429de0) 0 empty + +Class std::forward_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::forward_iterator_tag (0x0x7fee253a6270) 0 empty + std::input_iterator_tag (0x0x7fee25429e40) 0 empty + +Class std::bidirectional_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::bidirectional_iterator_tag (0x0x7fee253a62d8) 0 empty + std::forward_iterator_tag (0x0x7fee253a6340) 0 empty + std::input_iterator_tag (0x0x7fee25429ea0) 0 empty + +Class std::random_access_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::random_access_iterator_tag (0x0x7fee253a63a8) 0 empty + std::bidirectional_iterator_tag (0x0x7fee253a6410) 0 empty + std::forward_iterator_tag (0x0x7fee253a6478) 0 empty + std::input_iterator_tag (0x0x7fee25429f00) 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 (0x0x7fee2545aba0) 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 (0x0x7fee2545ac00) 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 (0x0x7fee2545ac60) 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 (0x0x7fee2545acc0) 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 (0x0x7fee2545ad20) 0 empty + +Class wait + size=4 align=4 + base size=4 base align=4 +wait (0x0x7fee2512e840) 0 + +Class __locale_struct + size=232 align=8 + base size=232 base align=8 +__locale_struct (0x0x7fee2512ea80) 0 + +Class timespec + size=16 align=8 + base size=16 base align=8 +timespec (0x0x7fee2512eb40) 0 + +Class timeval + size=16 align=8 + base size=16 base align=8 +timeval (0x0x7fee2512eba0) 0 + +Class pthread_attr_t + size=56 align=8 + base size=56 base align=8 +pthread_attr_t (0x0x7fee2512ec60) 0 + +Class __pthread_internal_list + size=16 align=8 + base size=16 base align=8 +__pthread_internal_list (0x0x7fee2512ecc0) 0 + +Class random_data + size=48 align=8 + base size=48 base align=8 +random_data (0x0x7fee251c9180) 0 + +Class drand48_data + size=24 align=8 + base size=24 base align=8 +drand48_data (0x0x7fee251c91e0) 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 (0x0x7fee251c9240) 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 (0x0x7fee253a69c0) 0 nearly-empty + vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16u) + std::exception (0x0x7fee251c92a0) 0 nearly-empty + primary-for std::bad_exception (0x0x7fee253a69c0) + +Class std::__exception_ptr::exception_ptr + size=8 align=8 + base size=8 base align=8 +std::__exception_ptr::exception_ptr (0x0x7fee251c9300) 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 (0x0x7fee251c9360) 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 (0x0x7fee253a6bc8) 0 nearly-empty + vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16u) + std::exception (0x0x7fee251c9780) 0 nearly-empty + primary-for std::bad_alloc (0x0x7fee253a6bc8) + +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 (0x0x7fee253a6c30) 0 nearly-empty + vptr=((& std::bad_array_new_length::_ZTVSt20bad_array_new_length) + 16u) + std::bad_alloc (0x0x7fee253a6c98) 0 nearly-empty + primary-for std::bad_array_new_length (0x0x7fee253a6c30) + std::exception (0x0x7fee251c97e0) 0 nearly-empty + primary-for std::bad_alloc (0x0x7fee253a6c98) + +Class std::nothrow_t + size=1 align=1 + base size=0 base align=1 +std::nothrow_t (0x0x7fee251c9840) 0 empty + +Class __exception + size=40 align=8 + base size=40 base align=8 +__exception (0x0x7fee24f42480) 0 + +Class lconv + size=96 align=8 + base size=96 base align=8 +lconv (0x0x7fee24d59180) 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 (0x0x7fee24d591e0) 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 (0x0x7fee24e100c0) 0 + +Class __sched_param + size=4 align=4 + base size=4 base align=4 +__sched_param (0x0x7fee24e10120) 0 + +Class timex + size=208 align=8 + base size=208 base align=8 +timex (0x0x7fee24e101e0) 0 + +Class tm + size=56 align=8 + base size=56 base align=8 +tm (0x0x7fee24e10240) 0 + +Class itimerspec + size=32 align=8 + base size=32 base align=8 +itimerspec (0x0x7fee24e102a0) 0 + +Class _pthread_cleanup_buffer + size=32 align=8 + base size=32 base align=8 +_pthread_cleanup_buffer (0x0x7fee24e10300) 0 + +Class __pthread_cleanup_frame + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_frame (0x0x7fee24e10420) 0 + +Class __pthread_cleanup_class + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_class (0x0x7fee24e10480) 0 + +Class _IO_marker + size=24 align=8 + base size=24 base align=8 +_IO_marker (0x0x7fee24e108a0) 0 + +Class _IO_FILE + size=216 align=8 + base size=216 base align=8 +_IO_FILE (0x0x7fee24e10900) 0 + +Class std::_Hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Hash_impl (0x0x7fee24926120) 0 empty + +Class std::_Fnv_hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Fnv_hash_impl (0x0x7fee24926180) 0 empty + +Class std::__numeric_limits_base + size=1 align=1 + base size=0 base align=1 +std::__numeric_limits_base (0x0x7fee24a02120) 0 empty + +Class std::_Bit_reference + size=16 align=8 + base size=16 base align=8 +std::_Bit_reference (0x0x7fee24a02f00) 0 + +Class std::_Bit_iterator_base + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator_base (0x0x7fee2493ea28) 0 + std::iterator (0x0x7fee24820000) 0 empty + +Class std::_Bit_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator (0x0x7fee2493ea90) 0 + std::_Bit_iterator_base (0x0x7fee2493eaf8) 0 + std::iterator (0x0x7fee24820060) 0 empty + +Class std::_Bit_const_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_const_iterator (0x0x7fee2493eb60) 0 + std::_Bit_iterator_base (0x0x7fee2493ebc8) 0 + std::iterator (0x0x7fee248200c0) 0 empty + +Class std::random_device + size=5000 align=8 + base size=5000 base align=8 +std::random_device (0x0x7fee24820ea0) 0 + +Class std::bernoulli_distribution::param_type + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution::param_type (0x0x7fee245eec60) 0 + +Class std::bernoulli_distribution + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution (0x0x7fee245eec00) 0 + +Class std::seed_seq + size=24 align=8 + base size=24 base align=8 +std::seed_seq (0x0x7fee24336c00) 0 + +Class qIsNull(double)::U + size=8 align=8 + base size=8 base align=8 +qIsNull(double)::U (0x0x7fee22f376c0) 0 + +Class qIsNull(float)::U + size=4 align=4 + base size=4 base align=4 +qIsNull(float)::U (0x0x7fee22f37720) 0 + +Class QSysInfo + size=1 align=1 + base size=0 base align=1 +QSysInfo (0x0x7fee23002960) 0 empty + +Class QMessageLogContext + size=32 align=8 + base size=32 base align=8 +QMessageLogContext (0x0x7fee230029c0) 0 + +Class QMessageLogger + size=32 align=8 + base size=32 base align=8 +QMessageLogger (0x0x7fee23002a20) 0 + +Class QFlag + size=4 align=4 + base size=4 base align=4 +QFlag (0x0x7fee230584e0) 0 + +Class QIncompatibleFlag + size=4 align=4 + base size=4 base align=4 +QIncompatibleFlag (0x0x7fee230587e0) 0 + +Class std::__atomic_flag_base + size=1 align=1 + base size=1 base align=1 +std::__atomic_flag_base (0x0x7fee23058d80) 0 + +Class std::atomic_flag + size=1 align=1 + base size=1 base align=1 +std::atomic_flag (0x0x7fee23051e38) 0 + std::__atomic_flag_base (0x0x7fee23058de0) 0 + +Class QAtomicInt + size=4 align=4 + base size=4 base align=4 +QAtomicInt (0x0x7fee22e2d5b0) 0 + QAtomicInteger (0x0x7fee22e2d618) 0 + QBasicAtomicInteger (0x0x7fee22bc9540) 0 + +Class QInternal + size=1 align=1 + base size=0 base align=1 +QInternal (0x0x7fee229f2de0) 0 empty + +Class QGenericArgument + size=16 align=8 + base size=16 base align=8 +QGenericArgument (0x0x7fee22846e40) 0 + +Class QGenericReturnArgument + size=16 align=8 + base size=16 base align=8 +QGenericReturnArgument (0x0x7fee22a1aa28) 0 + QGenericArgument (0x0x7fee22846ea0) 0 + +Class QMetaObject + size=48 align=8 + base size=48 base align=8 +QMetaObject (0x0x7fee228a9060) 0 + +Class QMetaObject::Connection + size=8 align=8 + base size=8 base align=8 +QMetaObject::Connection (0x0x7fee228a9120) 0 + +Class QLatin1Char + size=1 align=1 + base size=1 base align=1 +QLatin1Char (0x0x7fee22550180) 0 + +Class QChar + size=2 align=2 + base size=2 base align=2 +QChar (0x0x7fee225501e0) 0 + +Class QtPrivate::RefCount + size=4 align=4 + base size=4 base align=4 +QtPrivate::RefCount (0x0x7fee22550660) 0 + +Class QArrayData + size=24 align=8 + base size=24 base align=8 +QArrayData (0x0x7fee22550720) 0 + +Class QtPrivate::QContainerImplHelper + size=1 align=1 + base size=0 base align=1 +QtPrivate::QContainerImplHelper (0x0x7fee22550b40) 0 empty + +Class std::locale + size=8 align=8 + base size=8 base align=8 +std::locale (0x0x7fee22550ba0) 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 (0x0x7fee22550c00) 0 + vptr=((& std::locale::facet::_ZTVNSt6locale5facetE) + 16u) + +Class std::locale::id + size=8 align=8 + base size=8 base align=8 +std::locale::id (0x0x7fee22550c60) 0 + +Class std::locale::_Impl + size=40 align=8 + base size=40 base align=8 +std::locale::_Impl (0x0x7fee22550cc0) 0 + +Class std::__cow_string + size=8 align=8 + base size=8 base align=8 +std::__cow_string (0x0x7fee226d20c0) 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 (0x0x7fee2254ed00) 0 + vptr=((& std::logic_error::_ZTVSt11logic_error) + 16u) + std::exception (0x0x7fee226d2180) 0 nearly-empty + primary-for std::logic_error (0x0x7fee2254ed00) + +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 (0x0x7fee2254edd0) 0 + vptr=((& std::domain_error::_ZTVSt12domain_error) + 16u) + std::logic_error (0x0x7fee226ed000) 0 + primary-for std::domain_error (0x0x7fee2254edd0) + std::exception (0x0x7fee226d21e0) 0 nearly-empty + primary-for std::logic_error (0x0x7fee226ed000) + +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 (0x0x7fee226ed068) 0 + vptr=((& std::invalid_argument::_ZTVSt16invalid_argument) + 16u) + std::logic_error (0x0x7fee226ed0d0) 0 + primary-for std::invalid_argument (0x0x7fee226ed068) + std::exception (0x0x7fee226d2240) 0 nearly-empty + primary-for std::logic_error (0x0x7fee226ed0d0) + +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 (0x0x7fee226ed138) 0 + vptr=((& std::length_error::_ZTVSt12length_error) + 16u) + std::logic_error (0x0x7fee226ed1a0) 0 + primary-for std::length_error (0x0x7fee226ed138) + std::exception (0x0x7fee226d22a0) 0 nearly-empty + primary-for std::logic_error (0x0x7fee226ed1a0) + +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 (0x0x7fee226ed208) 0 + vptr=((& std::out_of_range::_ZTVSt12out_of_range) + 16u) + std::logic_error (0x0x7fee226ed270) 0 + primary-for std::out_of_range (0x0x7fee226ed208) + std::exception (0x0x7fee226d2300) 0 nearly-empty + primary-for std::logic_error (0x0x7fee226ed270) + +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 (0x0x7fee226ed2d8) 0 + vptr=((& std::runtime_error::_ZTVSt13runtime_error) + 16u) + std::exception (0x0x7fee226d2360) 0 nearly-empty + primary-for std::runtime_error (0x0x7fee226ed2d8) + +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 (0x0x7fee226ed340) 0 + vptr=((& std::range_error::_ZTVSt11range_error) + 16u) + std::runtime_error (0x0x7fee226ed3a8) 0 + primary-for std::range_error (0x0x7fee226ed340) + std::exception (0x0x7fee226d23c0) 0 nearly-empty + primary-for std::runtime_error (0x0x7fee226ed3a8) + +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 (0x0x7fee226ed410) 0 + vptr=((& std::overflow_error::_ZTVSt14overflow_error) + 16u) + std::runtime_error (0x0x7fee226ed478) 0 + primary-for std::overflow_error (0x0x7fee226ed410) + std::exception (0x0x7fee226d2420) 0 nearly-empty + primary-for std::runtime_error (0x0x7fee226ed478) + +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 (0x0x7fee226ed4e0) 0 + vptr=((& std::underflow_error::_ZTVSt15underflow_error) + 16u) + std::runtime_error (0x0x7fee226ed548) 0 + primary-for std::underflow_error (0x0x7fee226ed4e0) + std::exception (0x0x7fee226d2480) 0 nearly-empty + primary-for std::runtime_error (0x0x7fee226ed548) + +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 (0x0x7fee226d2600) 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 (0x0x7fee226d2840) 0 + +Class std::error_condition + size=16 align=8 + base size=16 base align=8 +std::error_condition (0x0x7fee226d29c0) 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 (0x0x7fee226eda28) 0 + vptr=((& std::system_error::_ZTVSt12system_error) + 16u) + std::runtime_error (0x0x7fee226eda90) 0 + primary-for std::system_error (0x0x7fee226eda28) + std::exception (0x0x7fee226d2c00) 0 nearly-empty + primary-for std::runtime_error (0x0x7fee226eda90) + +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 (0x0x7fee2236d680) 0 + vptr=((& std::ios_base::failure::_ZTVNSt8ios_base7failureB5cxx11E) + 16u) + std::system_error (0x0x7fee2236d6e8) 0 + primary-for std::ios_base::failure (0x0x7fee2236d680) + std::runtime_error (0x0x7fee2236d750) 0 + primary-for std::system_error (0x0x7fee2236d6e8) + std::exception (0x0x7fee226d2f00) 0 nearly-empty + primary-for std::runtime_error (0x0x7fee2236d750) + +Class std::ios_base::_Callback_list + size=24 align=8 + base size=24 base align=8 +std::ios_base::_Callback_list (0x0x7fee226d2f60) 0 + +Class std::ios_base::_Words + size=16 align=8 + base size=16 base align=8 +std::ios_base::_Words (0x0x7fee223ac000) 0 + +Class std::ios_base::Init + size=1 align=1 + base size=0 base align=1 +std::ios_base::Init (0x0x7fee223ac060) 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 (0x0x7fee226d2ea0) 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 (0x0x7fee223ac7e0) 0 empty + +Class std::__num_base + size=1 align=1 + base size=0 base align=1 +std::__num_base (0x0x7fee223acea0) 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 (0x0x7fee2205e000 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 (0x0x7fee2205e0d0 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 (0x0x7fee2205e478 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 (0x0x7fee2205e548 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 (0x0x7fee21f5c780) 0 + +Class QByteArray + size=8 align=8 + base size=8 base align=8 +QByteArray (0x0x7fee21f5c7e0) 0 + +Class QByteRef + size=16 align=8 + base size=12 base align=8 +QByteRef (0x0x7fee21d6fc00) 0 + +Class QLatin1String + size=16 align=8 + base size=16 base align=8 +QLatin1String (0x0x7fee21d6ff60) 0 + +Class QStringDataPtr + size=8 align=8 + base size=8 base align=8 +QStringDataPtr (0x0x7fee21e68360) 0 + +Class QString::Null + size=1 align=1 + base size=0 base align=1 +QString::Null (0x0x7fee21e68420) 0 empty + +Class QString + size=8 align=8 + base size=8 base align=8 +QString (0x0x7fee21e683c0) 0 + +Class QCharRef + size=16 align=8 + base size=12 base align=8 +QCharRef (0x0x7fee21c253c0) 0 + +Class QStringRef + size=16 align=8 + base size=16 base align=8 +QStringRef (0x0x7fee21982240) 0 + +Class QtPrivate::QHashCombine + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombine (0x0x7fee21982900) 0 empty + +Class QtPrivate::QHashCombineCommutative + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombineCommutative (0x0x7fee21982960) 0 empty + +Class std::__detail::_List_node_base + size=16 align=8 + base size=16 base align=8 +std::__detail::_List_node_base (0x0x7fee219829c0) 0 + +Class QListData::NotArrayCompatibleLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotArrayCompatibleLayout (0x0x7fee21982d80) 0 empty + +Class QListData::NotIndirectLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotIndirectLayout (0x0x7fee21982de0) 0 empty + +Class QListData::ArrayCompatibleLayout + size=1 align=1 + base size=1 base align=1 +QListData::ArrayCompatibleLayout (0x0x7fee21959b60) 0 empty + QListData::NotIndirectLayout (0x0x7fee21982e40) 0 empty + +Class QListData::InlineWithPaddingLayout + size=1 align=1 + base size=1 base align=1 +QListData::InlineWithPaddingLayout (0x0x7fee217b5af0) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7fee21982ea0) 0 empty + QListData::NotIndirectLayout (0x0x7fee21982f00) 0 empty + +Class QListData::IndirectLayout + size=1 align=1 + base size=1 base align=1 +QListData::IndirectLayout (0x0x7fee21959bc8) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7fee21982f60) 0 empty + +Class QListData::Data + size=24 align=8 + base size=24 base align=8 +QListData::Data (0x0x7fee217bd000) 0 + +Class QListData + size=8 align=8 + base size=8 base align=8 +QListData (0x0x7fee21982d20) 0 + +Class QRegExp + size=8 align=8 + base size=8 base align=8 +QRegExp (0x0x7fee217bdba0) 0 + +Class QStringMatcher::Data + size=272 align=8 + base size=272 base align=8 +QStringMatcher::Data (0x0x7fee21555e40) 0 + +Class QStringMatcher + size=1048 align=8 + base size=1048 base align=8 +QStringMatcher (0x0x7fee21555de0) 0 + +Class QStringList + size=8 align=8 + base size=8 base align=8 +QStringList (0x0x7fee21570548) 0 + QList (0x0x7fee215705b0) 0 + QListSpecialMethods (0x0x7fee2158b060) 0 empty + +Class QScopedPointerPodDeleter + size=1 align=1 + base size=0 base align=1 +QScopedPointerPodDeleter (0x0x7fee2158b4e0) 0 empty + +Class std::_Rb_tree_node_base + size=32 align=8 + base size=32 base align=8 +std::_Rb_tree_node_base (0x0x7fee2158b900) 0 + +Class std::allocator_arg_t + size=1 align=1 + base size=0 base align=1 +std::allocator_arg_t (0x0x7fee2158bf60) 0 empty + +Class std::__uses_alloc_base + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc_base (0x0x7fee2140d120) 0 empty + +Class std::__uses_alloc0::_Sink + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc0::_Sink (0x0x7fee2140d1e0) 0 empty + +Class std::__uses_alloc0 + size=1 align=1 + base size=1 base align=1 +std::__uses_alloc0 (0x0x7fee216834e0) 0 + std::__uses_alloc_base (0x0x7fee2140d180) 0 empty + +Class std::_Swallow_assign + size=1 align=1 + base size=0 base align=1 +std::_Swallow_assign (0x0x7fee210fa240) 0 empty + +Class QtPrivate::AbstractDebugStreamFunction + size=16 align=8 + base size=16 base align=8 +QtPrivate::AbstractDebugStreamFunction (0x0x7fee210fa480) 0 + +Class QtPrivate::AbstractComparatorFunction + size=24 align=8 + base size=24 base align=8 +QtPrivate::AbstractComparatorFunction (0x0x7fee210fa540) 0 + +Class QtPrivate::AbstractConverterFunction + size=8 align=8 + base size=8 base align=8 +QtPrivate::AbstractConverterFunction (0x0x7fee210fa660) 0 + +Class QMetaType + size=80 align=8 + base size=80 base align=8 +QMetaType (0x0x7fee210fa7e0) 0 + +Class QtMetaTypePrivate::VariantData + size=24 align=8 + base size=20 base align=8 +QtMetaTypePrivate::VariantData (0x0x7fee210faba0) 0 + +Class QtMetaTypePrivate::VectorBoolElements + size=1 align=1 + base size=0 base align=1 +QtMetaTypePrivate::VectorBoolElements (0x0x7fee210facc0) 0 empty + +Class QtMetaTypePrivate::QSequentialIterableImpl + size=104 align=8 + base size=104 base align=8 +QtMetaTypePrivate::QSequentialIterableImpl (0x0x7fee2127f660) 0 + +Class QtMetaTypePrivate::QAssociativeIterableImpl + size=112 align=8 + base size=112 base align=8 +QtMetaTypePrivate::QAssociativeIterableImpl (0x0x7fee2127fba0) 0 + +Class QtMetaTypePrivate::QPairVariantInterfaceImpl + size=40 align=8 + base size=40 base align=8 +QtMetaTypePrivate::QPairVariantInterfaceImpl (0x0x7fee2127ff60) 0 + +Class QtPrivate::QSlotObjectBase + size=16 align=8 + base size=16 base align=8 +QtPrivate::QSlotObjectBase (0x0x7fee210dd060) 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 (0x0x7fee210dd1e0) 0 + vptr=((& QObjectData::_ZTV11QObjectData) + 16u) + +Class QObject::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObject::QPrivateSignal (0x0x7fee210dd3c0) 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 (0x0x7fee210dd360) 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 (0x0x7fee210dd960) 0 nearly-empty + vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16u) + +Class QSignalBlocker + size=16 align=8 + base size=10 base align=8 +QSignalBlocker (0x0x7fee210dd9c0) 0 + +Class QAbstractAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractAnimation::QPrivateSignal (0x0x7fee210dda80) 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 (0x0x7fee20d015b0) 0 + vptr=((& QAbstractAnimation::_ZTV18QAbstractAnimation) + 16u) + QObject (0x0x7fee210dda20) 0 + primary-for QAbstractAnimation (0x0x7fee20d015b0) + +Class QAnimationDriver::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationDriver::QPrivateSignal (0x0x7fee210ddb40) 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 (0x0x7fee20d01618) 0 + vptr=((& QAnimationDriver::_ZTV16QAnimationDriver) + 16u) + QObject (0x0x7fee210ddae0) 0 + primary-for QAnimationDriver (0x0x7fee20d01618) + +Class QEventLoop::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventLoop::QPrivateSignal (0x0x7fee210ddc00) 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 (0x0x7fee20d01680) 0 + vptr=((& QEventLoop::_ZTV10QEventLoop) + 16u) + QObject (0x0x7fee210ddba0) 0 + primary-for QEventLoop (0x0x7fee20d01680) + +Class QEventLoopLocker + size=8 align=8 + base size=8 base align=8 +QEventLoopLocker (0x0x7fee210ddd80) 0 + +Class QAbstractEventDispatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractEventDispatcher::QPrivateSignal (0x0x7fee210dde40) 0 empty + +Class QAbstractEventDispatcher::TimerInfo + size=12 align=4 + base size=12 base align=4 +QAbstractEventDispatcher::TimerInfo (0x0x7fee210ddea0) 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 (0x0x7fee20d017b8) 0 + vptr=((& QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher) + 16u) + QObject (0x0x7fee210ddde0) 0 + primary-for QAbstractEventDispatcher (0x0x7fee20d017b8) + +Class QMapNodeBase + size=24 align=8 + base size=24 base align=8 +QMapNodeBase (0x0x7fee210ddf00) 0 + +Class QMapDataBase + size=40 align=8 + base size=40 base align=8 +QMapDataBase (0x0x7fee20e46180) 0 + +Class QHashData::Node + size=16 align=8 + base size=16 base align=8 +QHashData::Node (0x0x7fee20e46540) 0 + +Class QHashData + size=48 align=8 + base size=44 base align=8 +QHashData (0x0x7fee20e464e0) 0 + +Class QHashDummyValue + size=1 align=1 + base size=0 base align=1 +QHashDummyValue (0x0x7fee20e465a0) 0 empty + +Class QVariant::PrivateShared + size=16 align=8 + base size=12 base align=8 +QVariant::PrivateShared (0x0x7fee20c2b180) 0 + +Class QVariant::Private::Data + size=8 align=8 + base size=8 base align=8 +QVariant::Private::Data (0x0x7fee20c2b240) 0 + +Class QVariant::Private + size=16 align=8 + base size=12 base align=8 +QVariant::Private (0x0x7fee20c2b1e0) 0 + +Class QVariant::Handler + size=72 align=8 + base size=72 base align=8 +QVariant::Handler (0x0x7fee20c2b2a0) 0 + +Class QVariant + size=16 align=8 + base size=16 base align=8 +QVariant (0x0x7fee20c2b120) 0 + +Class QVariantComparisonHelper + size=8 align=8 + base size=8 base align=8 +QVariantComparisonHelper (0x0x7fee208e9720) 0 + +Class QSequentialIterable::const_iterator + size=112 align=8 + base size=112 base align=8 +QSequentialIterable::const_iterator (0x0x7fee208e9a80) 0 + +Class QSequentialIterable + size=104 align=8 + base size=104 base align=8 +QSequentialIterable (0x0x7fee208e9a20) 0 + +Class QAssociativeIterable::const_iterator + size=120 align=8 + base size=120 base align=8 +QAssociativeIterable::const_iterator (0x0x7fee208e9b40) 0 + +Class QAssociativeIterable + size=112 align=8 + base size=112 base align=8 +QAssociativeIterable (0x0x7fee208e9ae0) 0 + +Class QModelIndex + size=24 align=8 + base size=24 base align=8 +QModelIndex (0x0x7fee207155a0) 0 + +Class QPersistentModelIndex + size=8 align=8 + base size=8 base align=8 +QPersistentModelIndex (0x0x7fee207158a0) 0 + +Class QAbstractItemModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractItemModel::QPrivateSignal (0x0x7fee207fd900) 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 (0x0x7fee2080d068) 0 + vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16u) + QObject (0x0x7fee207fd8a0) 0 + primary-for QAbstractItemModel (0x0x7fee2080d068) + +Class QAbstractTableModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTableModel::QPrivateSignal (0x0x7fee207fdc60) 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 (0x0x7fee2080d270) 0 + vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16u) + QAbstractItemModel (0x0x7fee2080d2d8) 0 + primary-for QAbstractTableModel (0x0x7fee2080d270) + QObject (0x0x7fee207fdc00) 0 + primary-for QAbstractItemModel (0x0x7fee2080d2d8) + +Class QAbstractListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractListModel::QPrivateSignal (0x0x7fee207fdd20) 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 (0x0x7fee2080d340) 0 + vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16u) + QAbstractItemModel (0x0x7fee2080d3a8) 0 + primary-for QAbstractListModel (0x0x7fee2080d340) + QObject (0x0x7fee207fdcc0) 0 + primary-for QAbstractItemModel (0x0x7fee2080d3a8) + +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 (0x0x7fee20510000) 0 + vptr=((& QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter) + 16u) + +Class QAbstractProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractProxyModel::QPrivateSignal (0x0x7fee205100c0) 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 (0x0x7fee2080d4e0) 0 + vptr=((& QAbstractProxyModel::_ZTV19QAbstractProxyModel) + 16u) + QAbstractItemModel (0x0x7fee2080d548) 0 + primary-for QAbstractProxyModel (0x0x7fee2080d4e0) + QObject (0x0x7fee20510060) 0 + primary-for QAbstractItemModel (0x0x7fee2080d548) + +Class QAbstractState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractState::QPrivateSignal (0x0x7fee20510180) 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 (0x0x7fee2080d5b0) 0 + vptr=((& QAbstractState::_ZTV14QAbstractState) + 16u) + QObject (0x0x7fee20510120) 0 + primary-for QAbstractState (0x0x7fee2080d5b0) + +Class QAbstractTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTransition::QPrivateSignal (0x0x7fee20510240) 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 (0x0x7fee2080d618) 0 + vptr=((& QAbstractTransition::_ZTV19QAbstractTransition) + 16u) + QObject (0x0x7fee205101e0) 0 + primary-for QAbstractTransition (0x0x7fee2080d618) + +Class QAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationGroup::QPrivateSignal (0x0x7fee20510300) 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 (0x0x7fee2080d680) 0 + vptr=((& QAnimationGroup::_ZTV15QAnimationGroup) + 16u) + QAbstractAnimation (0x0x7fee2080d6e8) 0 + primary-for QAnimationGroup (0x0x7fee2080d680) + QObject (0x0x7fee205102a0) 0 + primary-for QAbstractAnimation (0x0x7fee2080d6e8) + +Class QBasicTimer + size=4 align=4 + base size=4 base align=4 +QBasicTimer (0x0x7fee205107e0) 0 + +Class QBitArray + size=8 align=8 + base size=8 base align=8 +QBitArray (0x0x7fee20510ae0) 0 + +Class QBitRef + size=16 align=8 + base size=12 base align=8 +QBitRef (0x0x7fee20510d20) 0 + +Class QIODevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIODevice::QPrivateSignal (0x0x7fee2061f120) 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 (0x0x7fee205966e8) 0 + vptr=((& QIODevice::_ZTV9QIODevice) + 16u) + QObject (0x0x7fee2061f0c0) 0 + primary-for QIODevice (0x0x7fee205966e8) + +Class QBuffer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBuffer::QPrivateSignal (0x0x7fee2061f300) 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 (0x0x7fee20596820) 0 + vptr=((& QBuffer::_ZTV7QBuffer) + 16u) + QIODevice (0x0x7fee20596888) 0 + primary-for QBuffer (0x0x7fee20596820) + QObject (0x0x7fee2061f2a0) 0 + primary-for QIODevice (0x0x7fee20596888) + +Class QByteArrayMatcher::Data + size=272 align=8 + base size=272 base align=8 +QByteArrayMatcher::Data (0x0x7fee2061f3c0) 0 + +Class QByteArrayMatcher + size=1040 align=8 + base size=1040 base align=8 +QByteArrayMatcher (0x0x7fee2061f360) 0 + +Class QSharedData + size=4 align=4 + base size=4 base align=4 +QSharedData (0x0x7fee2061f540) 0 + +Class QLocale + size=8 align=8 + base size=8 base align=8 +QLocale (0x0x7fee2061f720) 0 + +Class QCollatorSortKey + size=8 align=8 + base size=8 base align=8 +QCollatorSortKey (0x0x7fee2061fba0) 0 + +Class QCollator + size=8 align=8 + base size=8 base align=8 +QCollator (0x0x7fee2061fc60) 0 + +Class QCommandLineOption + size=8 align=8 + base size=8 base align=8 +QCommandLineOption (0x0x7fee20424d20) 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 (0x0x7fee204611e0) 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 (0x0x7fee2042f9c0) 0 + vptr=((& QTimerEvent::_ZTV11QTimerEvent) + 16u) + QEvent (0x0x7fee20461240) 0 + primary-for QTimerEvent (0x0x7fee2042f9c0) + +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 (0x0x7fee2042fa28) 0 + vptr=((& QChildEvent::_ZTV11QChildEvent) + 16u) + QEvent (0x0x7fee204612a0) 0 + primary-for QChildEvent (0x0x7fee2042fa28) + +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 (0x0x7fee2042fb60) 0 + vptr=((& QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent) + 16u) + QEvent (0x0x7fee20461480) 0 + primary-for QDynamicPropertyChangeEvent (0x0x7fee2042fb60) + +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 (0x0x7fee2042fbc8) 0 + vptr=((& QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent) + 16u) + QEvent (0x0x7fee204614e0) 0 + primary-for QDeferredDeleteEvent (0x0x7fee2042fbc8) + +Class QCoreApplication::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QCoreApplication::QPrivateSignal (0x0x7fee204615a0) 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 (0x0x7fee2042fc30) 0 + vptr=((& QCoreApplication::_ZTV16QCoreApplication) + 16u) + QObject (0x0x7fee20461540) 0 + primary-for QCoreApplication (0x0x7fee2042fc30) + +Class QCommandLineParser + size=8 align=8 + base size=8 base align=8 +QCommandLineParser (0x0x7fee20461600) 0 + +Class QContiguousCacheData + size=24 align=4 + base size=24 base align=4 +QContiguousCacheData (0x0x7fee20461660) 0 + +Class QCryptographicHash + size=8 align=8 + base size=8 base align=8 +QCryptographicHash (0x0x7fee20461900) 0 + +Class QDataStream + size=32 align=8 + base size=32 base align=8 +QDataStream (0x0x7fee20461960) 0 + +Class QtPrivate::StreamStateSaver + size=16 align=8 + base size=12 base align=8 +QtPrivate::StreamStateSaver (0x0x7fee20461a20) 0 + +Class QDate + size=8 align=8 + base size=8 base align=8 +QDate (0x0x7fee20461c00) 0 + +Class QTime + size=4 align=4 + base size=4 base align=4 +QTime (0x0x7fee20461f00) 0 + +Class QDateTime::ShortData + size=8 align=8 + base size=8 base align=8 +QDateTime::ShortData (0x0x7fee201a9420) 0 + +Class QDateTime::Data + size=8 align=8 + base size=8 base align=8 +QDateTime::Data (0x0x7fee201a9480) 0 + +Class QDateTime + size=8 align=8 + base size=8 base align=8 +QDateTime (0x0x7fee201a93c0) 0 + +Class QElapsedTimer + size=16 align=8 + base size=16 base align=8 +QElapsedTimer (0x0x7fee2025d2a0) 0 + +Class std::chrono::_V2::system_clock + size=1 align=1 + base size=0 base align=1 +std::chrono::_V2::system_clock (0x0x7fee1fed1660) 0 empty + +Class std::chrono::_V2::steady_clock + size=1 align=1 + base size=0 base align=1 +std::chrono::_V2::steady_clock (0x0x7fee2001d4e0) 0 empty + +Class QDeadlineTimer + size=16 align=8 + base size=16 base align=8 +QDeadlineTimer (0x0x7fee2001d540) 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 (0x0x7fee1fd623c0) 0 + vptr=((& QTextStream::_ZTV11QTextStream) + 16u) + +Class QTextStreamManipulator + size=40 align=8 + base size=38 base align=8 +QTextStreamManipulator (0x0x7fee1fd62600) 0 + +Class QtSharedPointer::NormalDeleter + size=1 align=1 + base size=0 base align=1 +QtSharedPointer::NormalDeleter (0x0x7fee1fd62840) 0 empty + +Class QtSharedPointer::ExternalRefCountData + size=16 align=8 + base size=16 base align=8 +QtSharedPointer::ExternalRefCountData (0x0x7fee1fd629c0) 0 + +Class QDebug::Stream + size=80 align=8 + base size=76 base align=8 +QDebug::Stream (0x0x7fee1fd62e40) 0 + +Class QDebug + size=8 align=8 + base size=8 base align=8 +QDebug (0x0x7fee1fd62de0) 0 + +Class QDebugStateSaver + size=8 align=8 + base size=8 base align=8 +QDebugStateSaver (0x0x7fee1fc010c0) 0 + +Class QNoDebug + size=1 align=1 + base size=0 base align=1 +QNoDebug (0x0x7fee1fc01180) 0 empty + +Class QFileDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileDevice::QPrivateSignal (0x0x7fee1fc01240) 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 (0x0x7fee1fbcb340) 0 + vptr=((& QFileDevice::_ZTV11QFileDevice) + 16u) + QIODevice (0x0x7fee1fbcb3a8) 0 + primary-for QFileDevice (0x0x7fee1fbcb340) + QObject (0x0x7fee1fc011e0) 0 + primary-for QIODevice (0x0x7fee1fbcb3a8) + +Class QFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFile::QPrivateSignal (0x0x7fee1fc01420) 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 (0x0x7fee1fbcb4e0) 0 + vptr=((& QFile::_ZTV5QFile) + 16u) + QFileDevice (0x0x7fee1fbcb548) 0 + primary-for QFile (0x0x7fee1fbcb4e0) + QIODevice (0x0x7fee1fbcb5b0) 0 + primary-for QFileDevice (0x0x7fee1fbcb548) + QObject (0x0x7fee1fc013c0) 0 + primary-for QIODevice (0x0x7fee1fbcb5b0) + +Class QFileInfo + size=8 align=8 + base size=8 base align=8 +QFileInfo (0x0x7fee1fc015a0) 0 + +Class QDir + size=8 align=8 + base size=8 base align=8 +QDir (0x0x7fee1fc01a20) 0 + +Class QDirIterator + size=8 align=8 + base size=8 base align=8 +QDirIterator (0x0x7fee1f97e000) 0 + +Class QEasingCurve + size=8 align=8 + base size=8 base align=8 +QEasingCurve (0x0x7fee1f97e1e0) 0 + +Class QEventTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventTransition::QPrivateSignal (0x0x7fee1fa43480) 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 (0x0x7fee1fa443a8) 0 + vptr=((& QEventTransition::_ZTV16QEventTransition) + 16u) + QAbstractTransition (0x0x7fee1fa44410) 0 + primary-for QEventTransition (0x0x7fee1fa443a8) + QObject (0x0x7fee1fa43420) 0 + primary-for QAbstractTransition (0x0x7fee1fa44410) + +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 (0x0x7fee1fa44478) 0 nearly-empty + vptr=((& QException::_ZTV10QException) + 16u) + std::exception (0x0x7fee1fa434e0) 0 nearly-empty + primary-for QException (0x0x7fee1fa44478) + +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 (0x0x7fee1fa444e0) 0 nearly-empty + vptr=((& QUnhandledException::_ZTV19QUnhandledException) + 16u) + QException (0x0x7fee1fa44548) 0 nearly-empty + primary-for QUnhandledException (0x0x7fee1fa444e0) + std::exception (0x0x7fee1fa43540) 0 nearly-empty + primary-for QException (0x0x7fee1fa44548) + +Class QtPrivate::ExceptionHolder + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionHolder (0x0x7fee1fa435a0) 0 + +Class QtPrivate::ExceptionStore + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionStore (0x0x7fee1fa43660) 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 (0x0x7fee1fa436c0) 0 nearly-empty + vptr=((& QFactoryInterface::_ZTV17QFactoryInterface) + 16u) + +Class QFileSelector::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSelector::QPrivateSignal (0x0x7fee1fa437e0) 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 (0x0x7fee1fa445b0) 0 + vptr=((& QFileSelector::_ZTV13QFileSelector) + 16u) + QObject (0x0x7fee1fa43780) 0 + primary-for QFileSelector (0x0x7fee1fa445b0) + +Class QFileSystemWatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSystemWatcher::QPrivateSignal (0x0x7fee1fa438a0) 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 (0x0x7fee1fa44618) 0 + vptr=((& QFileSystemWatcher::_ZTV18QFileSystemWatcher) + 16u) + QObject (0x0x7fee1fa43840) 0 + primary-for QFileSystemWatcher (0x0x7fee1fa44618) + +Class QFinalState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFinalState::QPrivateSignal (0x0x7fee1fa43960) 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 (0x0x7fee1fa44680) 0 + vptr=((& QFinalState::_ZTV11QFinalState) + 16u) + QAbstractState (0x0x7fee1fa446e8) 0 + primary-for QFinalState (0x0x7fee1fa44680) + QObject (0x0x7fee1fa43900) 0 + primary-for QAbstractState (0x0x7fee1fa446e8) + +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 (0x0x7fee1fa439c0) 0 + vptr=((& QRunnable::_ZTV9QRunnable) + 16u) + +Class QBasicMutex + size=8 align=8 + base size=8 base align=8 +QBasicMutex (0x0x7fee1fa43a20) 0 + +Class QMutex + size=8 align=8 + base size=8 base align=8 +QMutex (0x0x7fee1fa44820) 0 + QBasicMutex (0x0x7fee1fa43c60) 0 + +Class QMutexLocker + size=8 align=8 + base size=8 base align=8 +QMutexLocker (0x0x7fee1f762060) 0 + +Class QtPrivate::ResultItem + size=16 align=8 + base size=16 base align=8 +QtPrivate::ResultItem (0x0x7fee1f762120) 0 + +Class QtPrivate::ResultIteratorBase + size=16 align=8 + base size=12 base align=8 +QtPrivate::ResultIteratorBase (0x0x7fee1f762180) 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 (0x0x7fee1f762300) 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 (0x0x7fee1f7623c0) 0 + vptr=((& QFutureInterfaceBase::_ZTV20QFutureInterfaceBase) + 16u) + +Class QFutureWatcherBase::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFutureWatcherBase::QPrivateSignal (0x0x7fee1f762720) 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 (0x0x7fee1f7cd410) 0 + vptr=((& QFutureWatcherBase::_ZTV18QFutureWatcherBase) + 16u) + QObject (0x0x7fee1f7626c0) 0 + primary-for QFutureWatcherBase (0x0x7fee1f7cd410) + +Class QHistoryState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QHistoryState::QPrivateSignal (0x0x7fee1f7628a0) 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 (0x0x7fee1f7cd820) 0 + vptr=((& QHistoryState::_ZTV13QHistoryState) + 16u) + QAbstractState (0x0x7fee1f7cd888) 0 + primary-for QHistoryState (0x0x7fee1f7cd820) + QObject (0x0x7fee1f762840) 0 + primary-for QAbstractState (0x0x7fee1f7cd888) + +Class QIdentityProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIdentityProxyModel::QPrivateSignal (0x0x7fee1f762960) 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 (0x0x7fee1f7cd8f0) 0 + vptr=((& QIdentityProxyModel::_ZTV19QIdentityProxyModel) + 16u) + QAbstractProxyModel (0x0x7fee1f7cd958) 0 + primary-for QIdentityProxyModel (0x0x7fee1f7cd8f0) + QAbstractItemModel (0x0x7fee1f7cd9c0) 0 + primary-for QAbstractProxyModel (0x0x7fee1f7cd958) + QObject (0x0x7fee1f762900) 0 + primary-for QAbstractItemModel (0x0x7fee1f7cd9c0) + +Class QItemSelectionRange + size=16 align=8 + base size=16 base align=8 +QItemSelectionRange (0x0x7fee1f7629c0) 0 + +Class QItemSelectionModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QItemSelectionModel::QPrivateSignal (0x0x7fee1f762d80) 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 (0x0x7fee1f7cdd00) 0 + vptr=((& QItemSelectionModel::_ZTV19QItemSelectionModel) + 16u) + QObject (0x0x7fee1f762d20) 0 + primary-for QItemSelectionModel (0x0x7fee1f7cdd00) + +Class QItemSelection + size=8 align=8 + base size=8 base align=8 +QItemSelection (0x0x7fee1f7cdf08) 0 + QList (0x0x7fee1f7cdf70) 0 + QListSpecialMethods (0x0x7fee1f554060) 0 empty + +Class QJsonValue + size=24 align=8 + base size=20 base align=8 +QJsonValue (0x0x7fee1f5545a0) 0 + +Class QJsonValueRef + size=16 align=8 + base size=12 base align=8 +QJsonValueRef (0x0x7fee1f5547e0) 0 + +Class QJsonValuePtr + size=24 align=8 + base size=24 base align=8 +QJsonValuePtr (0x0x7fee1f5548a0) 0 + +Class QJsonValueRefPtr + size=16 align=8 + base size=16 base align=8 +QJsonValueRefPtr (0x0x7fee1f554900) 0 + +Class QJsonArray::iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::iterator (0x0x7fee1f5549c0) 0 + +Class QJsonArray::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::const_iterator (0x0x7fee1f554a20) 0 + +Class QJsonArray + size=16 align=8 + base size=16 base align=8 +QJsonArray (0x0x7fee1f554960) 0 + +Class QJsonParseError + size=8 align=4 + base size=8 base align=4 +QJsonParseError (0x0x7fee1f554ae0) 0 + +Class QJsonDocument + size=8 align=8 + base size=8 base align=8 +QJsonDocument (0x0x7fee1f554b40) 0 + +Class QJsonObject::iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::iterator (0x0x7fee1f554c00) 0 + +Class QJsonObject::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::const_iterator (0x0x7fee1f554c60) 0 + +Class QJsonObject + size=16 align=8 + base size=16 base align=8 +QJsonObject (0x0x7fee1f554ba0) 0 + +Class QLibrary::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLibrary::QPrivateSignal (0x0x7fee1f554e40) 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 (0x0x7fee1f5833a8) 0 + vptr=((& QLibrary::_ZTV8QLibrary) + 16u) + QObject (0x0x7fee1f554de0) 0 + primary-for QLibrary (0x0x7fee1f5833a8) + +Class QVersionNumber::SegmentStorage + size=8 align=8 + base size=8 base align=8 +QVersionNumber::SegmentStorage (0x0x7fee1f32b060) 0 + +Class QVersionNumber + size=8 align=8 + base size=8 base align=8 +QVersionNumber (0x0x7fee1f32b000) 0 + +Class QLibraryInfo + size=1 align=1 + base size=0 base align=1 +QLibraryInfo (0x0x7fee1f3adde0) 0 empty + +Class QPoint + size=8 align=4 + base size=8 base align=4 +QPoint (0x0x7fee1f3ade40) 0 + +Class QPointF + size=16 align=8 + base size=16 base align=8 +QPointF (0x0x7fee1f416180) 0 + +Class QLine + size=16 align=4 + base size=16 base align=4 +QLine (0x0x7fee1f416480) 0 + +Class QLineF + size=32 align=8 + base size=32 base align=8 +QLineF (0x0x7fee1f416780) 0 + +Class QLinkedListData + size=32 align=8 + base size=25 base align=8 +QLinkedListData (0x0x7fee1f416a80) 0 + +Class QLockFile + size=8 align=8 + base size=8 base align=8 +QLockFile (0x0x7fee1f155240) 0 + +Class QLoggingCategory::AtomicBools + size=4 align=1 + base size=4 base align=1 +QLoggingCategory::AtomicBools (0x0x7fee1f1553c0) 0 + +Class QLoggingCategory + size=24 align=8 + base size=24 base align=8 +QLoggingCategory (0x0x7fee1f155360) 0 + +Class QMargins + size=16 align=4 + base size=16 base align=4 +QMargins (0x0x7fee1f155540) 0 + +Class QMarginsF + size=32 align=8 + base size=32 base align=8 +QMarginsF (0x0x7fee1f155840) 0 + +Class QMessageAuthenticationCode + size=8 align=8 + base size=8 base align=8 +QMessageAuthenticationCode (0x0x7fee1f155ba0) 0 + +Class QMetaMethod + size=16 align=8 + base size=12 base align=8 +QMetaMethod (0x0x7fee1f155c00) 0 + +Class QMetaEnum + size=16 align=8 + base size=12 base align=8 +QMetaEnum (0x0x7fee1f155f00) 0 + +Class QMetaProperty + size=32 align=8 + base size=32 base align=8 +QMetaProperty (0x0x7fee1eecf2a0) 0 + +Class QMetaClassInfo + size=16 align=8 + base size=12 base align=8 +QMetaClassInfo (0x0x7fee1eecf300) 0 + +Class QMimeData::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QMimeData::QPrivateSignal (0x0x7fee1eecf660) 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 (0x0x7fee1eee60d0) 0 + vptr=((& QMimeData::_ZTV9QMimeData) + 16u) + QObject (0x0x7fee1eecf600) 0 + primary-for QMimeData (0x0x7fee1eee60d0) + +Class QMimeType + size=8 align=8 + base size=8 base align=8 +QMimeType (0x0x7fee1eecf6c0) 0 + +Class QMimeDatabase + size=8 align=8 + base size=8 base align=8 +QMimeDatabase (0x0x7fee1eecfa20) 0 + +Class QObjectCleanupHandler::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObjectCleanupHandler::QPrivateSignal (0x0x7fee1eecfae0) 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 (0x0x7fee1eee6270) 0 + vptr=((& QObjectCleanupHandler::_ZTV21QObjectCleanupHandler) + 16u) + QObject (0x0x7fee1eecfa80) 0 + primary-for QObjectCleanupHandler (0x0x7fee1eee6270) + +Class QParallelAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QParallelAnimationGroup::QPrivateSignal (0x0x7fee1eecfba0) 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 (0x0x7fee1eee62d8) 0 + vptr=((& QParallelAnimationGroup::_ZTV23QParallelAnimationGroup) + 16u) + QAnimationGroup (0x0x7fee1eee6340) 0 + primary-for QParallelAnimationGroup (0x0x7fee1eee62d8) + QAbstractAnimation (0x0x7fee1eee63a8) 0 + primary-for QAnimationGroup (0x0x7fee1eee6340) + QObject (0x0x7fee1eecfb40) 0 + primary-for QAbstractAnimation (0x0x7fee1eee63a8) + +Class QPauseAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPauseAnimation::QPrivateSignal (0x0x7fee1eecfc60) 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 (0x0x7fee1eee6410) 0 + vptr=((& QPauseAnimation::_ZTV15QPauseAnimation) + 16u) + QAbstractAnimation (0x0x7fee1eee6478) 0 + primary-for QPauseAnimation (0x0x7fee1eee6410) + QObject (0x0x7fee1eecfc00) 0 + primary-for QAbstractAnimation (0x0x7fee1eee6478) + +Class QStaticPlugin + size=16 align=8 + base size=16 base align=8 +QStaticPlugin (0x0x7fee1eecfe40) 0 + +Class QPluginLoader::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPluginLoader::QPrivateSignal (0x0x7fee1ef6b1e0) 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 (0x0x7fee1eee6618) 0 + vptr=((& QPluginLoader::_ZTV13QPluginLoader) + 16u) + QObject (0x0x7fee1ef6b180) 0 + primary-for QPluginLoader (0x0x7fee1eee6618) + +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 (0x0x7fee1ef6b240) 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 (0x0x7fee1eee6680) 0 nearly-empty + vptr=((& std::bad_cast::_ZTVSt8bad_cast) + 16u) + std::exception (0x0x7fee1ef6b2a0) 0 nearly-empty + primary-for std::bad_cast (0x0x7fee1eee6680) + +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 (0x0x7fee1eee66e8) 0 nearly-empty + vptr=((& std::bad_typeid::_ZTVSt10bad_typeid) + 16u) + std::exception (0x0x7fee1ef6b300) 0 nearly-empty + primary-for std::bad_typeid (0x0x7fee1eee66e8) + +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 (0x0x7fee1f04a958) 0 nearly-empty + vptr=((& std::bad_function_call::_ZTVSt17bad_function_call) + 16u) + std::exception (0x0x7fee1ecfa3c0) 0 nearly-empty + primary-for std::bad_function_call (0x0x7fee1f04a958) + +Class std::_Nocopy_types + size=16 align=8 + base size=16 base align=8 +std::_Nocopy_types (0x0x7fee1ecfa480) 0 + +Class std::_Any_data + size=16 align=8 + base size=16 base align=8 +std::_Any_data (0x0x7fee1ecfa4e0) 0 + +Class std::_Function_base + size=24 align=8 + base size=24 base align=8 +std::_Function_base (0x0x7fee1ecfa600) 0 + +Class QProcessEnvironment + size=8 align=8 + base size=8 base align=8 +QProcessEnvironment (0x0x7fee1ecfaae0) 0 + +Class QProcess::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QProcess::QPrivateSignal (0x0x7fee1ecfaea0) 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 (0x0x7fee1ed80270) 0 + vptr=((& QProcess::_ZTV8QProcess) + 16u) + QIODevice (0x0x7fee1ed802d8) 0 + primary-for QProcess (0x0x7fee1ed80270) + QObject (0x0x7fee1ecfae40) 0 + primary-for QIODevice (0x0x7fee1ed802d8) + +Class QVariantAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QVariantAnimation::QPrivateSignal (0x0x7fee1ecfaf60) 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 (0x0x7fee1ed80340) 0 + vptr=((& QVariantAnimation::_ZTV17QVariantAnimation) + 16u) + QAbstractAnimation (0x0x7fee1ed803a8) 0 + primary-for QVariantAnimation (0x0x7fee1ed80340) + QObject (0x0x7fee1ecfaf00) 0 + primary-for QAbstractAnimation (0x0x7fee1ed803a8) + +Class QPropertyAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPropertyAnimation::QPrivateSignal (0x0x7fee1ee0c060) 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 (0x0x7fee1ed80478) 0 + vptr=((& QPropertyAnimation::_ZTV18QPropertyAnimation) + 16u) + QVariantAnimation (0x0x7fee1ed804e0) 0 + primary-for QPropertyAnimation (0x0x7fee1ed80478) + QAbstractAnimation (0x0x7fee1ed80548) 0 + primary-for QVariantAnimation (0x0x7fee1ed804e0) + QObject (0x0x7fee1ee0c000) 0 + primary-for QAbstractAnimation (0x0x7fee1ed80548) + +Class QReadWriteLock + size=8 align=8 + base size=8 base align=8 +QReadWriteLock (0x0x7fee1ee0c120) 0 + +Class QReadLocker + size=8 align=8 + base size=8 base align=8 +QReadLocker (0x0x7fee1ee0c3c0) 0 + +Class QWriteLocker + size=8 align=8 + base size=8 base align=8 +QWriteLocker (0x0x7fee1ee0c420) 0 + +Class QSize + size=8 align=4 + base size=8 base align=4 +QSize (0x0x7fee1ee0c480) 0 + +Class QSizeF + size=16 align=8 + base size=16 base align=8 +QSizeF (0x0x7fee1ee0c840) 0 + +Class QRect + size=16 align=4 + base size=16 base align=4 +QRect (0x0x7fee1ee0cc00) 0 + +Class QRectF + size=32 align=8 + base size=32 base align=8 +QRectF (0x0x7fee1ee0cf00) 0 + +Class QRegularExpression + size=8 align=8 + base size=8 base align=8 +QRegularExpression (0x0x7fee1ebe0240) 0 + +Class QRegularExpressionMatch + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatch (0x0x7fee1ebe07e0) 0 + +Class QRegularExpressionMatchIterator + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatchIterator (0x0x7fee1ebe0b40) 0 + +Class QResource + size=8 align=8 + base size=8 base align=8 +QResource (0x0x7fee1ebe0ea0) 0 + +Class QSaveFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSaveFile::QPrivateSignal (0x0x7fee1e90b060) 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 (0x0x7fee1ec67548) 0 + vptr=((& QSaveFile::_ZTV9QSaveFile) + 16u) + QFileDevice (0x0x7fee1ec675b0) 0 + primary-for QSaveFile (0x0x7fee1ec67548) + QIODevice (0x0x7fee1ec67618) 0 + primary-for QFileDevice (0x0x7fee1ec675b0) + QObject (0x0x7fee1e90b000) 0 + primary-for QIODevice (0x0x7fee1ec67618) + +Class QSemaphore + size=8 align=8 + base size=8 base align=8 +QSemaphore (0x0x7fee1e90b120) 0 + +Class QSequentialAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSequentialAnimationGroup::QPrivateSignal (0x0x7fee1e90b1e0) 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 (0x0x7fee1ec67680) 0 + vptr=((& QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup) + 16u) + QAnimationGroup (0x0x7fee1ec676e8) 0 + primary-for QSequentialAnimationGroup (0x0x7fee1ec67680) + QAbstractAnimation (0x0x7fee1ec67750) 0 + primary-for QAnimationGroup (0x0x7fee1ec676e8) + QObject (0x0x7fee1e90b180) 0 + primary-for QAbstractAnimation (0x0x7fee1ec67750) + +Class QSettings::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSettings::QPrivateSignal (0x0x7fee1e90b2a0) 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 (0x0x7fee1ec677b8) 0 + vptr=((& QSettings::_ZTV9QSettings) + 16u) + QObject (0x0x7fee1e90b240) 0 + primary-for QSettings (0x0x7fee1ec677b8) + +Class QSharedMemory::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSharedMemory::QPrivateSignal (0x0x7fee1e90b360) 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 (0x0x7fee1ec67820) 0 + vptr=((& QSharedMemory::_ZTV13QSharedMemory) + 16u) + QObject (0x0x7fee1e90b300) 0 + primary-for QSharedMemory (0x0x7fee1ec67820) + +Class QSignalMapper::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalMapper::QPrivateSignal (0x0x7fee1e90b420) 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 (0x0x7fee1ec67888) 0 + vptr=((& QSignalMapper::_ZTV13QSignalMapper) + 16u) + QObject (0x0x7fee1e90b3c0) 0 + primary-for QSignalMapper (0x0x7fee1ec67888) + +Class QSignalTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalTransition::QPrivateSignal (0x0x7fee1e90b4e0) 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 (0x0x7fee1ec678f0) 0 + vptr=((& QSignalTransition::_ZTV17QSignalTransition) + 16u) + QAbstractTransition (0x0x7fee1ec67958) 0 + primary-for QSignalTransition (0x0x7fee1ec678f0) + QObject (0x0x7fee1e90b480) 0 + primary-for QAbstractTransition (0x0x7fee1ec67958) + +Class QSocketNotifier::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSocketNotifier::QPrivateSignal (0x0x7fee1e90b5a0) 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 (0x0x7fee1ec679c0) 0 + vptr=((& QSocketNotifier::_ZTV15QSocketNotifier) + 16u) + QObject (0x0x7fee1e90b540) 0 + primary-for QSocketNotifier (0x0x7fee1ec679c0) + +Class QSortFilterProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSortFilterProxyModel::QPrivateSignal (0x0x7fee1e90b660) 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 (0x0x7fee1ec67a28) 0 + vptr=((& QSortFilterProxyModel::_ZTV21QSortFilterProxyModel) + 16u) + QAbstractProxyModel (0x0x7fee1ec67a90) 0 + primary-for QSortFilterProxyModel (0x0x7fee1ec67a28) + QAbstractItemModel (0x0x7fee1ec67af8) 0 + primary-for QAbstractProxyModel (0x0x7fee1ec67a90) + QObject (0x0x7fee1e90b600) 0 + primary-for QAbstractItemModel (0x0x7fee1ec67af8) + +Class QStandardPaths + size=1 align=1 + base size=0 base align=1 +QStandardPaths (0x0x7fee1e90b840) 0 empty + +Class QState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QState::QPrivateSignal (0x0x7fee1e90ba20) 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 (0x0x7fee1ec67c98) 0 + vptr=((& QState::_ZTV6QState) + 16u) + QAbstractState (0x0x7fee1ec67d00) 0 + primary-for QState (0x0x7fee1ec67c98) + QObject (0x0x7fee1e90b9c0) 0 + primary-for QAbstractState (0x0x7fee1ec67d00) + +Class QStateMachine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStateMachine::QPrivateSignal (0x0x7fee1e90bb40) 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 (0x0x7fee1ec67ea0) 0 + vptr=((& QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE) + 16u) + QEvent (0x0x7fee1e90bba0) 0 + primary-for QStateMachine::SignalEvent (0x0x7fee1ec67ea0) + +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 (0x0x7fee1ec67f08) 0 + vptr=((& QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE) + 16u) + QEvent (0x0x7fee1e90bc00) 0 + primary-for QStateMachine::WrappedEvent (0x0x7fee1ec67f08) + +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 (0x0x7fee1ec67d68) 0 + vptr=((& QStateMachine::_ZTV13QStateMachine) + 16u) + QState (0x0x7fee1ec67dd0) 0 + primary-for QStateMachine (0x0x7fee1ec67d68) + QAbstractState (0x0x7fee1ec67e38) 0 + primary-for QState (0x0x7fee1ec67dd0) + QObject (0x0x7fee1e90bae0) 0 + primary-for QAbstractState (0x0x7fee1ec67e38) + +Class QStorageInfo + size=8 align=8 + base size=8 base align=8 +QStorageInfo (0x0x7fee1e90bc60) 0 + +Class QAbstractConcatenable + size=1 align=1 + base size=0 base align=1 +QAbstractConcatenable (0x0x7fee1ea87120) 0 empty + +Class QStringListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStringListModel::QPrivateSignal (0x0x7fee1ea87ba0) 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 (0x0x7fee1ea839c0) 0 + vptr=((& QStringListModel::_ZTV16QStringListModel) + 16u) + QAbstractListModel (0x0x7fee1ea83a28) 0 + primary-for QStringListModel (0x0x7fee1ea839c0) + QAbstractItemModel (0x0x7fee1ea83a90) 0 + primary-for QAbstractListModel (0x0x7fee1ea83a28) + QObject (0x0x7fee1ea87b40) 0 + primary-for QAbstractItemModel (0x0x7fee1ea83a90) + +Class QSystemSemaphore + size=8 align=8 + base size=8 base align=8 +QSystemSemaphore (0x0x7fee1ea87c00) 0 + +Class QTemporaryDir + size=8 align=8 + base size=8 base align=8 +QTemporaryDir (0x0x7fee1ea87cc0) 0 + +Class QTemporaryFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTemporaryFile::QPrivateSignal (0x0x7fee1ea87de0) 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 (0x0x7fee1ea83af8) 0 + vptr=((& QTemporaryFile::_ZTV14QTemporaryFile) + 16u) + QFile (0x0x7fee1ea83b60) 0 + primary-for QTemporaryFile (0x0x7fee1ea83af8) + QFileDevice (0x0x7fee1ea83bc8) 0 + primary-for QFile (0x0x7fee1ea83b60) + QIODevice (0x0x7fee1ea83c30) 0 + primary-for QFileDevice (0x0x7fee1ea83bc8) + QObject (0x0x7fee1ea87d80) 0 + primary-for QIODevice (0x0x7fee1ea83c30) + +Class QTextBoundaryFinder + size=48 align=8 + base size=48 base align=8 +QTextBoundaryFinder (0x0x7fee1ea87e40) 0 + +Class QTextCodec::ConverterState + size=32 align=8 + base size=32 base align=8 +QTextCodec::ConverterState (0x0x7fee1e780060) 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 (0x0x7fee1e780000) 0 nearly-empty + vptr=((& QTextCodec::_ZTV10QTextCodec) + 16u) + +Class QTextEncoder + size=40 align=8 + base size=40 base align=8 +QTextEncoder (0x0x7fee1e7801e0) 0 + +Class QTextDecoder + size=40 align=8 + base size=40 base align=8 +QTextDecoder (0x0x7fee1e780240) 0 + +Class QThread::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThread::QPrivateSignal (0x0x7fee1e780300) 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 (0x0x7fee1ea83e38) 0 + vptr=((& QThread::_ZTV7QThread) + 16u) + QObject (0x0x7fee1e7802a0) 0 + primary-for QThread (0x0x7fee1ea83e38) + +Class QThreadPool::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThreadPool::QPrivateSignal (0x0x7fee1e7803c0) 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 (0x0x7fee1ea83ea0) 0 + vptr=((& QThreadPool::_ZTV11QThreadPool) + 16u) + QObject (0x0x7fee1e780360) 0 + primary-for QThreadPool (0x0x7fee1ea83ea0) + +Class QThreadStorageData + size=4 align=4 + base size=4 base align=4 +QThreadStorageData (0x0x7fee1e780420) 0 + +Class QTimeLine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimeLine::QPrivateSignal (0x0x7fee1e780540) 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 (0x0x7fee1ea83f08) 0 + vptr=((& QTimeLine::_ZTV9QTimeLine) + 16u) + QObject (0x0x7fee1e7804e0) 0 + primary-for QTimeLine (0x0x7fee1ea83f08) + +Class QTimer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimer::QPrivateSignal (0x0x7fee1e780600) 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 (0x0x7fee1ea83f70) 0 + vptr=((& QTimer::_ZTV6QTimer) + 16u) + QObject (0x0x7fee1e7805a0) 0 + primary-for QTimer (0x0x7fee1ea83f70) + +Class QTimeZone::OffsetData + size=32 align=8 + base size=28 base align=8 +QTimeZone::OffsetData (0x0x7fee1e861420) 0 + +Class QTimeZone + size=8 align=8 + base size=8 base align=8 +QTimeZone (0x0x7fee1e8613c0) 0 + +Class QTranslator::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTranslator::QPrivateSignal (0x0x7fee1e861a80) 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 (0x0x7fee1e4a1138) 0 + vptr=((& QTranslator::_ZTV11QTranslator) + 16u) + QObject (0x0x7fee1e861a20) 0 + primary-for QTranslator (0x0x7fee1e4a1138) + +Class QUrl + size=8 align=8 + base size=8 base align=8 +QUrl (0x0x7fee1e861ba0) 0 + +Class QUrlQuery + size=8 align=8 + base size=8 base align=8 +QUrlQuery (0x0x7fee1e5c51e0) 0 + +Class QUuid + size=16 align=4 + base size=16 base align=4 +QUuid (0x0x7fee1e5c5540) 0 + +Class QWaitCondition + size=8 align=8 + base size=8 base align=8 +QWaitCondition (0x0x7fee1e5c5840) 0 + +Class QXmlStreamStringRef + size=16 align=8 + base size=16 base align=8 +QXmlStreamStringRef (0x0x7fee1e5c58a0) 0 + +Class QXmlStreamAttribute + size=80 align=8 + base size=73 base align=8 +QXmlStreamAttribute (0x0x7fee1e2d7e40) 0 + +Class QXmlStreamAttributes + size=8 align=8 + base size=8 base align=8 +QXmlStreamAttributes (0x0x7fee1e2efa28) 0 + QVector (0x0x7fee1e3212a0) 0 + +Class QXmlStreamNamespaceDeclaration + size=40 align=8 + base size=40 base align=8 +QXmlStreamNamespaceDeclaration (0x0x7fee1e321300) 0 + +Class QXmlStreamNotationDeclaration + size=56 align=8 + base size=56 base align=8 +QXmlStreamNotationDeclaration (0x0x7fee1e321600) 0 + +Class QXmlStreamEntityDeclaration + size=88 align=8 + base size=88 base align=8 +QXmlStreamEntityDeclaration (0x0x7fee1e321900) 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 (0x0x7fee1e321c00) 0 nearly-empty + vptr=((& QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver) + 16u) + +Class QXmlStreamReader + size=8 align=8 + base size=8 base align=8 +QXmlStreamReader (0x0x7fee1e321c60) 0 + +Class QXmlStreamWriter + size=8 align=8 + base size=8 base align=8 +QXmlStreamWriter (0x0x7fee1e3f40c0) 0 + +Class QNdefRecord + size=8 align=8 + base size=8 base align=8 +QNdefRecord (0x0x7fee1e3f41e0) 0 + +Class QNdefFilter::Record + size=24 align=8 + base size=24 base align=8 +QNdefFilter::Record (0x0x7fee1e3f4300) 0 + +Class QNdefFilter + size=8 align=8 + base size=8 base align=8 +QNdefFilter (0x0x7fee1e3f42a0) 0 + +Class QNdefMessage + size=8 align=8 + base size=8 base align=8 +QNdefMessage (0x0x7fee1e3dc270) 0 + QList (0x0x7fee1e3dc2d8) 0 + QListSpecialMethods (0x0x7fee1e3f44e0) 0 empty + +Class QNdefNfcTextRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcTextRecord (0x0x7fee1e3dc340) 0 + QNdefRecord (0x0x7fee1e3f46c0) 0 + +Class QNdefNfcUriRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcUriRecord (0x0x7fee1e3dc478) 0 + QNdefRecord (0x0x7fee1e3f48a0) 0 + +Class QNdefNfcIconRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcIconRecord (0x0x7fee1e3dc4e0) 0 + QNdefRecord (0x0x7fee1e3f4900) 0 + +Class QNdefNfcSmartPosterRecord + size=16 align=8 + base size=16 base align=8 +QNdefNfcSmartPosterRecord (0x0x7fee1e3dc548) 0 + QNdefRecord (0x0x7fee1e3f4960) 0 + +Class QNearFieldTarget::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldTarget::QPrivateSignal (0x0x7fee1e3f4a80) 0 empty + +Class QNearFieldTarget::RequestId + size=8 align=8 + base size=8 base align=8 +QNearFieldTarget::RequestId (0x0x7fee1e3f4ae0) 0 + +Vtable for QNearFieldTarget +QNearFieldTarget::_ZTV16QNearFieldTarget: 25u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QNearFieldTarget) +16 (int (*)(...))QNearFieldTarget::metaObject +24 (int (*)(...))QNearFieldTarget::qt_metacast +32 (int (*)(...))QNearFieldTarget::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 (*)(...))QNearFieldTarget::url +128 (int (*)(...))__cxa_pure_virtual +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))QNearFieldTarget::hasNdefMessage +152 (int (*)(...))QNearFieldTarget::readNdefMessages +160 (int (*)(...))QNearFieldTarget::writeNdefMessages +168 (int (*)(...))QNearFieldTarget::sendCommand +176 (int (*)(...))QNearFieldTarget::sendCommands +184 (int (*)(...))QNearFieldTarget::waitForRequestCompleted +192 (int (*)(...))QNearFieldTarget::handleResponse + +Class QNearFieldTarget + size=24 align=8 + base size=24 base align=8 +QNearFieldTarget (0x0x7fee1e3dc5b0) 0 + vptr=((& QNearFieldTarget::_ZTV16QNearFieldTarget) + 16u) + QObject (0x0x7fee1e3f4a20) 0 + primary-for QNearFieldTarget (0x0x7fee1e3dc5b0) + +Class QNearFieldManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldManager::QPrivateSignal (0x0x7fee1e3f4e40) 0 empty + +Vtable for QNearFieldManager +QNearFieldManager::_ZTV17QNearFieldManager: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QNearFieldManager) +16 (int (*)(...))QNearFieldManager::metaObject +24 (int (*)(...))QNearFieldManager::qt_metacast +32 (int (*)(...))QNearFieldManager::qt_metacall +40 (int (*)(...))QNearFieldManager::~QNearFieldManager +48 (int (*)(...))QNearFieldManager::~QNearFieldManager +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 QNearFieldManager + size=24 align=8 + base size=24 base align=8 +QNearFieldManager (0x0x7fee1e3dc6e8) 0 + vptr=((& QNearFieldManager::_ZTV17QNearFieldManager) + 16u) + QObject (0x0x7fee1e3f4de0) 0 + primary-for QNearFieldManager (0x0x7fee1e3dc6e8) + +Class QNearFieldShareManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldShareManager::QPrivateSignal (0x0x7fee1e179060) 0 empty + +Vtable for QNearFieldShareManager +QNearFieldShareManager::_ZTV22QNearFieldShareManager: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI22QNearFieldShareManager) +16 (int (*)(...))QNearFieldShareManager::metaObject +24 (int (*)(...))QNearFieldShareManager::qt_metacast +32 (int (*)(...))QNearFieldShareManager::qt_metacall +40 (int (*)(...))QNearFieldShareManager::~QNearFieldShareManager +48 (int (*)(...))QNearFieldShareManager::~QNearFieldShareManager +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 QNearFieldShareManager + size=24 align=8 + base size=24 base align=8 +QNearFieldShareManager (0x0x7fee1e3dc888) 0 + vptr=((& QNearFieldShareManager::_ZTV22QNearFieldShareManager) + 16u) + QObject (0x0x7fee1e179000) 0 + primary-for QNearFieldShareManager (0x0x7fee1e3dc888) + +Class QNearFieldShareTarget::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldShareTarget::QPrivateSignal (0x0x7fee1e179300) 0 empty + +Vtable for QNearFieldShareTarget +QNearFieldShareTarget::_ZTV21QNearFieldShareTarget: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QNearFieldShareTarget) +16 (int (*)(...))QNearFieldShareTarget::metaObject +24 (int (*)(...))QNearFieldShareTarget::qt_metacast +32 (int (*)(...))QNearFieldShareTarget::qt_metacall +40 (int (*)(...))QNearFieldShareTarget::~QNearFieldShareTarget +48 (int (*)(...))QNearFieldShareTarget::~QNearFieldShareTarget +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 QNearFieldShareTarget + size=24 align=8 + base size=24 base align=8 +QNearFieldShareTarget (0x0x7fee1e3dc9c0) 0 + vptr=((& QNearFieldShareTarget::_ZTV21QNearFieldShareTarget) + 16u) + QObject (0x0x7fee1e1792a0) 0 + primary-for QNearFieldShareTarget (0x0x7fee1e3dc9c0) + +Class QQmlNdefRecord::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QQmlNdefRecord::QPrivateSignal (0x0x7fee1e1793c0) 0 empty + +Vtable for QQmlNdefRecord +QQmlNdefRecord::_ZTV14QQmlNdefRecord: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI14QQmlNdefRecord) +16 (int (*)(...))QQmlNdefRecord::metaObject +24 (int (*)(...))QQmlNdefRecord::qt_metacast +32 (int (*)(...))QQmlNdefRecord::qt_metacall +40 (int (*)(...))QQmlNdefRecord::~QQmlNdefRecord +48 (int (*)(...))QQmlNdefRecord::~QQmlNdefRecord +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 QQmlNdefRecord + size=24 align=8 + base size=24 base align=8 +QQmlNdefRecord (0x0x7fee1e3dca28) 0 + vptr=((& QQmlNdefRecord::_ZTV14QQmlNdefRecord) + 16u) + QObject (0x0x7fee1e179360) 0 + primary-for QQmlNdefRecord (0x0x7fee1e3dca28) + diff --git a/tests/auto/bic/data/QtNfc.5.9.0.linux-gcc-amd64.txt b/tests/auto/bic/data/QtNfc.5.9.0.linux-gcc-amd64.txt new file mode 100644 index 0000000..7cb0897 --- /dev/null +++ b/tests/auto/bic/data/QtNfc.5.9.0.linux-gcc-amd64.txt @@ -0,0 +1,4433 @@ +Class std::__failure_type + size=1 align=1 + base size=0 base align=1 +std::__failure_type (0x0x7f916c5aa660) 0 empty + +Class std::__do_is_destructible_impl + size=1 align=1 + base size=0 base align=1 +std::__do_is_destructible_impl (0x0x7f916c5fcde0) 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 (0x0x7f916c626060) 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 (0x0x7f916c6262a0) 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 (0x0x7f916c6264e0) 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 (0x0x7f916c626660) 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 (0x0x7f916c626a20) 0 empty + +Class std::__do_common_type_impl + size=1 align=1 + base size=0 base align=1 +std::__do_common_type_impl (0x0x7f916a2e11e0) 0 empty + +Class std::__do_member_type_wrapper + size=1 align=1 + base size=0 base align=1 +std::__do_member_type_wrapper (0x0x7f916a2e12a0) 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 (0x0x7f916a2e1600) 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 (0x0x7f916a2e16c0) 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 (0x0x7f916a2e1780) 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 (0x0x7f916a2e1840) 0 empty + +Class std::__result_of_other_impl + size=1 align=1 + base size=0 base align=1 +std::__result_of_other_impl (0x0x7f916a2e1ae0) 0 empty + +Class std::piecewise_construct_t + size=1 align=1 + base size=0 base align=1 +std::piecewise_construct_t (0x0x7f916a2e1cc0) 0 empty + +Class std::__true_type + size=1 align=1 + base size=0 base align=1 +std::__true_type (0x0x7f916a35d180) 0 empty + +Class std::__false_type + size=1 align=1 + base size=0 base align=1 +std::__false_type (0x0x7f916a35d1e0) 0 empty + +Class std::input_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::input_iterator_tag (0x0x7f916a398e40) 0 empty + +Class std::output_iterator_tag + size=1 align=1 + base size=0 base align=1 +std::output_iterator_tag (0x0x7f916a398ea0) 0 empty + +Class std::forward_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::forward_iterator_tag (0x0x7f916a3122d8) 0 empty + std::input_iterator_tag (0x0x7f916a398f00) 0 empty + +Class std::bidirectional_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::bidirectional_iterator_tag (0x0x7f916a312340) 0 empty + std::forward_iterator_tag (0x0x7f916a3123a8) 0 empty + std::input_iterator_tag (0x0x7f916a398f60) 0 empty + +Class std::random_access_iterator_tag + size=1 align=1 + base size=1 base align=1 +std::random_access_iterator_tag (0x0x7f916a312410) 0 empty + std::bidirectional_iterator_tag (0x0x7f916a312478) 0 empty + std::forward_iterator_tag (0x0x7f916a3124e0) 0 empty + std::input_iterator_tag (0x0x7f916a3c5000) 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 (0x0x7f916a3c5c60) 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 (0x0x7f916a3c5cc0) 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 (0x0x7f916a3c5d20) 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 (0x0x7f916a3c5d80) 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 (0x0x7f916a3c5de0) 0 empty + +Class wait + size=4 align=4 + base size=4 base align=4 +wait (0x0x7f916a096900) 0 + +Class __locale_struct + size=232 align=8 + base size=232 base align=8 +__locale_struct (0x0x7f916a096b40) 0 + +Class timespec + size=16 align=8 + base size=16 base align=8 +timespec (0x0x7f916a096c00) 0 + +Class timeval + size=16 align=8 + base size=16 base align=8 +timeval (0x0x7f916a096c60) 0 + +Class pthread_attr_t + size=56 align=8 + base size=56 base align=8 +pthread_attr_t (0x0x7f916a096d20) 0 + +Class __pthread_internal_list + size=16 align=8 + base size=16 base align=8 +__pthread_internal_list (0x0x7f916a096d80) 0 + +Class random_data + size=48 align=8 + base size=48 base align=8 +random_data (0x0x7f916a136240) 0 + +Class drand48_data + size=24 align=8 + base size=24 base align=8 +drand48_data (0x0x7f916a1362a0) 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 (0x0x7f916a136300) 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 (0x0x7f916a312a28) 0 nearly-empty + vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16u) + std::exception (0x0x7f916a136360) 0 nearly-empty + primary-for std::bad_exception (0x0x7f916a312a28) + +Class std::__exception_ptr::exception_ptr + size=8 align=8 + base size=8 base align=8 +std::__exception_ptr::exception_ptr (0x0x7f916a1363c0) 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 (0x0x7f916a136420) 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 (0x0x7f916a312c30) 0 nearly-empty + vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16u) + std::exception (0x0x7f916a136840) 0 nearly-empty + primary-for std::bad_alloc (0x0x7f916a312c30) + +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 (0x0x7f916a312c98) 0 nearly-empty + vptr=((& std::bad_array_new_length::_ZTVSt20bad_array_new_length) + 16u) + std::bad_alloc (0x0x7f916a312d00) 0 nearly-empty + primary-for std::bad_array_new_length (0x0x7f916a312c98) + std::exception (0x0x7f916a1368a0) 0 nearly-empty + primary-for std::bad_alloc (0x0x7f916a312d00) + +Class std::nothrow_t + size=1 align=1 + base size=0 base align=1 +std::nothrow_t (0x0x7f916a136900) 0 empty + +Class __exception + size=40 align=8 + base size=40 base align=8 +__exception (0x0x7f9169eaf540) 0 + +Class lconv + size=96 align=8 + base size=96 base align=8 +lconv (0x0x7f9169cc5240) 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 (0x0x7f9169cc52a0) 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 (0x0x7f9169d68180) 0 + +Class __sched_param + size=4 align=4 + base size=4 base align=4 +__sched_param (0x0x7f9169d681e0) 0 + +Class timex + size=208 align=8 + base size=208 base align=8 +timex (0x0x7f9169d682a0) 0 + +Class tm + size=56 align=8 + base size=56 base align=8 +tm (0x0x7f9169d68300) 0 + +Class itimerspec + size=32 align=8 + base size=32 base align=8 +itimerspec (0x0x7f9169d68360) 0 + +Class _pthread_cleanup_buffer + size=32 align=8 + base size=32 base align=8 +_pthread_cleanup_buffer (0x0x7f9169d683c0) 0 + +Class __pthread_cleanup_frame + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_frame (0x0x7f9169d684e0) 0 + +Class __pthread_cleanup_class + size=24 align=8 + base size=24 base align=8 +__pthread_cleanup_class (0x0x7f9169d68540) 0 + +Class _IO_marker + size=24 align=8 + base size=24 base align=8 +_IO_marker (0x0x7f9169d68960) 0 + +Class _IO_FILE + size=216 align=8 + base size=216 base align=8 +_IO_FILE (0x0x7f9169d689c0) 0 + +Class std::_Hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Hash_impl (0x0x7f91698941e0) 0 empty + +Class std::_Fnv_hash_impl + size=1 align=1 + base size=0 base align=1 +std::_Fnv_hash_impl (0x0x7f9169894240) 0 empty + +Class std::__numeric_limits_base + size=1 align=1 + base size=0 base align=1 +std::__numeric_limits_base (0x0x7f916996c1e0) 0 empty + +Class std::_Bit_reference + size=16 align=8 + base size=16 base align=8 +std::_Bit_reference (0x0x7f916977c000) 0 + +Class std::_Bit_iterator_base + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator_base (0x0x7f91698aba90) 0 + std::iterator (0x0x7f916977c0c0) 0 empty + +Class std::_Bit_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_iterator (0x0x7f91698abaf8) 0 + std::_Bit_iterator_base (0x0x7f91698abb60) 0 + std::iterator (0x0x7f916977c120) 0 empty + +Class std::_Bit_const_iterator + size=16 align=8 + base size=12 base align=8 +std::_Bit_const_iterator (0x0x7f91698abbc8) 0 + std::_Bit_iterator_base (0x0x7f91698abc30) 0 + std::iterator (0x0x7f916977c180) 0 empty + +Class std::random_device + size=5000 align=8 + base size=5000 base align=8 +std::random_device (0x0x7f916977cf60) 0 + +Class std::bernoulli_distribution::param_type + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution::param_type (0x0x7f9169558d20) 0 + +Class std::bernoulli_distribution + size=8 align=8 + base size=8 base align=8 +std::bernoulli_distribution (0x0x7f9169558cc0) 0 + +Class std::seed_seq + size=24 align=8 + base size=24 base align=8 +std::seed_seq (0x0x7f9169288cc0) 0 + +Class qIsNull(double)::U + size=8 align=8 + base size=8 base align=8 +qIsNull(double)::U (0x0x7f9167e9f780) 0 + +Class qIsNull(float)::U + size=4 align=4 + base size=4 base align=4 +qIsNull(float)::U (0x0x7f9167e9f7e0) 0 + +Class QSysInfo + size=1 align=1 + base size=0 base align=1 +QSysInfo (0x0x7f9167f84300) 0 empty + +Class QMessageLogContext + size=32 align=8 + base size=32 base align=8 +QMessageLogContext (0x0x7f9167f84360) 0 + +Class QMessageLogger + size=32 align=8 + base size=32 base align=8 +QMessageLogger (0x0x7f9167f843c0) 0 + +Class QFlag + size=4 align=4 + base size=4 base align=4 +QFlag (0x0x7f9167f84420) 0 + +Class QIncompatibleFlag + size=4 align=4 + base size=4 base align=4 +QIncompatibleFlag (0x0x7f9167f846c0) 0 + +Class std::__atomic_flag_base + size=1 align=1 + base size=1 base align=1 +std::__atomic_flag_base (0x0x7f9167f84c00) 0 + +Class std::atomic_flag + size=1 align=1 + base size=1 base align=1 +std::atomic_flag (0x0x7f9167f768f0) 0 + std::__atomic_flag_base (0x0x7f9167f84c60) 0 + +Class QAtomicInt + size=4 align=4 + base size=4 base align=4 +QAtomicInt (0x0x7f9167bf1068) 0 + QAtomicInteger (0x0x7f9167bf10d0) 0 + QBasicAtomicInteger (0x0x7f9167b2f3c0) 0 + +Class QInternal + size=1 align=1 + base size=0 base align=1 +QInternal (0x0x7f91679fa8a0) 0 empty + +Class QGenericArgument + size=16 align=8 + base size=16 base align=8 +QGenericArgument (0x0x7f91677fe900) 0 + +Class QGenericReturnArgument + size=16 align=8 + base size=16 base align=8 +QGenericReturnArgument (0x0x7f91679b1958) 0 + QGenericArgument (0x0x7f91677fe960) 0 + +Class QMetaObject + size=48 align=8 + base size=48 base align=8 +QMetaObject (0x0x7f91677feae0) 0 + +Class QMetaObject::Connection + size=8 align=8 + base size=8 base align=8 +QMetaObject::Connection (0x0x7f91677feba0) 0 + +Class QLatin1Char + size=1 align=1 + base size=1 base align=1 +QLatin1Char (0x0x7f91674cfc00) 0 + +Class QChar + size=2 align=2 + base size=2 base align=2 +QChar (0x0x7f91674cfc60) 0 + +Class QtPrivate::RefCount + size=4 align=4 + base size=4 base align=4 +QtPrivate::RefCount (0x0x7f91674cff00) 0 + +Class QArrayData + size=24 align=8 + base size=24 base align=8 +QArrayData (0x0x7f91675b2000) 0 + +Class QtPrivate::QContainerImplHelper + size=1 align=1 + base size=0 base align=1 +QtPrivate::QContainerImplHelper (0x0x7f91675b2480) 0 empty + +Class std::locale + size=8 align=8 + base size=8 base align=8 +std::locale (0x0x7f91675b24e0) 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 (0x0x7f91675b2540) 0 + vptr=((& std::locale::facet::_ZTVNSt6locale5facetE) + 16u) + +Class std::locale::id + size=8 align=8 + base size=8 base align=8 +std::locale::id (0x0x7f91675b25a0) 0 + +Class std::locale::_Impl + size=40 align=8 + base size=40 base align=8 +std::locale::_Impl (0x0x7f91675b2600) 0 + +Class std::__cow_string + size=8 align=8 + base size=8 base align=8 +std::__cow_string (0x0x7f91675b29c0) 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 (0x0x7f91674e9f70) 0 + vptr=((& std::logic_error::_ZTVSt11logic_error) + 16u) + std::exception (0x0x7f91675b2a80) 0 nearly-empty + primary-for std::logic_error (0x0x7f91674e9f70) + +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 (0x0x7f91674e9c98) 0 + vptr=((& std::domain_error::_ZTVSt12domain_error) + 16u) + std::logic_error (0x0x7f91674e9d68) 0 + primary-for std::domain_error (0x0x7f91674e9c98) + std::exception (0x0x7f91675b2ae0) 0 nearly-empty + primary-for std::logic_error (0x0x7f91674e9d68) + +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 (0x0x7f9167298000) 0 + vptr=((& std::invalid_argument::_ZTVSt16invalid_argument) + 16u) + std::logic_error (0x0x7f9167298068) 0 + primary-for std::invalid_argument (0x0x7f9167298000) + std::exception (0x0x7f91675b2b40) 0 nearly-empty + primary-for std::logic_error (0x0x7f9167298068) + +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 (0x0x7f91672980d0) 0 + vptr=((& std::length_error::_ZTVSt12length_error) + 16u) + std::logic_error (0x0x7f9167298138) 0 + primary-for std::length_error (0x0x7f91672980d0) + std::exception (0x0x7f91675b2ba0) 0 nearly-empty + primary-for std::logic_error (0x0x7f9167298138) + +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 (0x0x7f91672981a0) 0 + vptr=((& std::out_of_range::_ZTVSt12out_of_range) + 16u) + std::logic_error (0x0x7f9167298208) 0 + primary-for std::out_of_range (0x0x7f91672981a0) + std::exception (0x0x7f91675b2c00) 0 nearly-empty + primary-for std::logic_error (0x0x7f9167298208) + +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 (0x0x7f9167298270) 0 + vptr=((& std::runtime_error::_ZTVSt13runtime_error) + 16u) + std::exception (0x0x7f91675b2c60) 0 nearly-empty + primary-for std::runtime_error (0x0x7f9167298270) + +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 (0x0x7f91672982d8) 0 + vptr=((& std::range_error::_ZTVSt11range_error) + 16u) + std::runtime_error (0x0x7f9167298340) 0 + primary-for std::range_error (0x0x7f91672982d8) + std::exception (0x0x7f91675b2cc0) 0 nearly-empty + primary-for std::runtime_error (0x0x7f9167298340) + +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 (0x0x7f91672983a8) 0 + vptr=((& std::overflow_error::_ZTVSt14overflow_error) + 16u) + std::runtime_error (0x0x7f9167298410) 0 + primary-for std::overflow_error (0x0x7f91672983a8) + std::exception (0x0x7f91675b2d20) 0 nearly-empty + primary-for std::runtime_error (0x0x7f9167298410) + +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 (0x0x7f9167298478) 0 + vptr=((& std::underflow_error::_ZTVSt15underflow_error) + 16u) + std::runtime_error (0x0x7f91672984e0) 0 + primary-for std::underflow_error (0x0x7f9167298478) + std::exception (0x0x7f91675b2d80) 0 nearly-empty + primary-for std::runtime_error (0x0x7f91672984e0) + +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 (0x0x7f91675b2f00) 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 (0x0x7f91672c0180) 0 + +Class std::error_condition + size=16 align=8 + base size=16 base align=8 +std::error_condition (0x0x7f91672c0300) 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 (0x0x7f91672989c0) 0 + vptr=((& std::system_error::_ZTVSt12system_error) + 16u) + std::runtime_error (0x0x7f9167298a28) 0 + primary-for std::system_error (0x0x7f91672989c0) + std::exception (0x0x7f91672c0540) 0 nearly-empty + primary-for std::runtime_error (0x0x7f9167298a28) + +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 (0x0x7f9167316618) 0 + vptr=((& std::ios_base::failure::_ZTVNSt8ios_base7failureB5cxx11E) + 16u) + std::system_error (0x0x7f9167316680) 0 + primary-for std::ios_base::failure (0x0x7f9167316618) + std::runtime_error (0x0x7f91673166e8) 0 + primary-for std::system_error (0x0x7f9167316680) + std::exception (0x0x7f91672c0840) 0 nearly-empty + primary-for std::runtime_error (0x0x7f91673166e8) + +Class std::ios_base::_Callback_list + size=24 align=8 + base size=24 base align=8 +std::ios_base::_Callback_list (0x0x7f91672c08a0) 0 + +Class std::ios_base::_Words + size=16 align=8 + base size=16 base align=8 +std::ios_base::_Words (0x0x7f91672c0900) 0 + +Class std::ios_base::Init + size=1 align=1 + base size=0 base align=1 +std::ios_base::Init (0x0x7f91672c0960) 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 (0x0x7f91672c07e0) 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 (0x0x7f9167410120) 0 empty + +Class std::__num_base + size=1 align=1 + base size=0 base align=1 +std::__num_base (0x0x7f91674107e0) 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 (0x0x7f9166f3cf08 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 (0x0x7f9167005068 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 (0x0x7f9167005410 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 (0x0x7f91670054e0 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 (0x0x7f916704f0c0) 0 + +Class QByteArray + size=8 align=8 + base size=8 base align=8 +QByteArray (0x0x7f916704f120) 0 + +Class QByteRef + size=16 align=8 + base size=12 base align=8 +QByteRef (0x0x7f9166d305a0) 0 + +Class QLatin1String + size=16 align=8 + base size=16 base align=8 +QLatin1String (0x0x7f9166d308a0) 0 + +Class QStringDataPtr + size=8 align=8 + base size=8 base align=8 +QStringDataPtr (0x0x7f9166d30c00) 0 + +Class QString::Null + size=1 align=1 + base size=0 base align=1 +QString::Null (0x0x7f9166d30cc0) 0 empty + +Class QString + size=8 align=8 + base size=8 base align=8 +QString (0x0x7f9166d30c60) 0 + +Class QCharRef + size=16 align=8 + base size=12 base align=8 +QCharRef (0x0x7f9166b72cc0) 0 + +Class QStringRef + size=16 align=8 + base size=16 base align=8 +QStringRef (0x0x7f91668fca80) 0 + +Class QtPrivate::QHashCombine + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombine (0x0x7f91666a6000) 0 empty + +Class QtPrivate::QHashCombineCommutative + size=1 align=1 + base size=0 base align=1 +QtPrivate::QHashCombineCommutative (0x0x7f91666a6060) 0 empty + +Class std::__detail::_List_node_base + size=16 align=8 + base size=16 base align=8 +std::__detail::_List_node_base (0x0x7f91666a60c0) 0 + +Class QListData::NotArrayCompatibleLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotArrayCompatibleLayout (0x0x7f91666a6480) 0 empty + +Class QListData::NotIndirectLayout + size=1 align=1 + base size=0 base align=1 +QListData::NotIndirectLayout (0x0x7f91666a64e0) 0 empty + +Class QListData::ArrayCompatibleLayout + size=1 align=1 + base size=1 base align=1 +QListData::ArrayCompatibleLayout (0x0x7f9166906bc8) 0 empty + QListData::NotIndirectLayout (0x0x7f91666a6540) 0 empty + +Class QListData::InlineWithPaddingLayout + size=1 align=1 + base size=1 base align=1 +QListData::InlineWithPaddingLayout (0x0x7f9166765af0) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7f91666a65a0) 0 empty + QListData::NotIndirectLayout (0x0x7f91666a6600) 0 empty + +Class QListData::IndirectLayout + size=1 align=1 + base size=1 base align=1 +QListData::IndirectLayout (0x0x7f9166906c30) 0 empty + QListData::NotArrayCompatibleLayout (0x0x7f91666a6660) 0 empty + +Class QListData::Data + size=24 align=8 + base size=24 base align=8 +QListData::Data (0x0x7f91666a66c0) 0 + +Class QListData + size=8 align=8 + base size=8 base align=8 +QListData (0x0x7f91666a6420) 0 + +Class QRegExp + size=8 align=8 + base size=8 base align=8 +QRegExp (0x0x7f916684a2a0) 0 + +Class QStringMatcher::Data + size=272 align=8 + base size=272 base align=8 +QStringMatcher::Data (0x0x7f916650d4e0) 0 + +Class QStringMatcher + size=1048 align=8 + base size=1048 base align=8 +QStringMatcher (0x0x7f916650d480) 0 + +Class QStringList + size=8 align=8 + base size=8 base align=8 +QStringList (0x0x7f916650f618) 0 + QList (0x0x7f916650f680) 0 + QListSpecialMethods (0x0x7f916650d6c0) 0 empty + +Class QScopedPointerPodDeleter + size=1 align=1 + base size=0 base align=1 +QScopedPointerPodDeleter (0x0x7f916650dae0) 0 empty + +Class std::_Rb_tree_node_base + size=32 align=8 + base size=32 base align=8 +std::_Rb_tree_node_base (0x0x7f916650df00) 0 + +Class std::allocator_arg_t + size=1 align=1 + base size=0 base align=1 +std::allocator_arg_t (0x0x7f91666495a0) 0 empty + +Class std::__uses_alloc_base + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc_base (0x0x7f9166649720) 0 empty + +Class std::__uses_alloc0::_Sink + size=1 align=1 + base size=0 base align=1 +std::__uses_alloc0::_Sink (0x0x7f91666497e0) 0 empty + +Class std::__uses_alloc0 + size=1 align=1 + base size=1 base align=1 +std::__uses_alloc0 (0x0x7f916661b680) 0 + std::__uses_alloc_base (0x0x7f9166649780) 0 empty + +Class std::_Swallow_assign + size=1 align=1 + base size=0 base align=1 +std::_Swallow_assign (0x0x7f9166073840) 0 empty + +Class QtPrivate::AbstractDebugStreamFunction + size=16 align=8 + base size=16 base align=8 +QtPrivate::AbstractDebugStreamFunction (0x0x7f9166073a80) 0 + +Class QtPrivate::AbstractComparatorFunction + size=24 align=8 + base size=24 base align=8 +QtPrivate::AbstractComparatorFunction (0x0x7f9166073b40) 0 + +Class QtPrivate::AbstractConverterFunction + size=8 align=8 + base size=8 base align=8 +QtPrivate::AbstractConverterFunction (0x0x7f9166073c60) 0 + +Class QMetaType + size=80 align=8 + base size=80 base align=8 +QMetaType (0x0x7f9166073de0) 0 + +Class QtMetaTypePrivate::VariantData + size=24 align=8 + base size=20 base align=8 +QtMetaTypePrivate::VariantData (0x0x7f91661ab240) 0 + +Class QtMetaTypePrivate::VectorBoolElements + size=1 align=1 + base size=0 base align=1 +QtMetaTypePrivate::VectorBoolElements (0x0x7f91661ab360) 0 empty + +Class QtMetaTypePrivate::QSequentialIterableImpl + size=104 align=8 + base size=104 base align=8 +QtMetaTypePrivate::QSequentialIterableImpl (0x0x7f91661abcc0) 0 + +Class QtMetaTypePrivate::QAssociativeIterableImpl + size=112 align=8 + base size=112 base align=8 +QtMetaTypePrivate::QAssociativeIterableImpl (0x0x7f9165e961e0) 0 + +Class QtMetaTypePrivate::QPairVariantInterfaceImpl + size=40 align=8 + base size=40 base align=8 +QtMetaTypePrivate::QPairVariantInterfaceImpl (0x0x7f9165e96540) 0 + +Class QtPrivate::QSlotObjectBase + size=16 align=8 + base size=16 base align=8 +QtPrivate::QSlotObjectBase (0x0x7f9165c61420) 0 + +Class std::chrono::_V2::system_clock + size=1 align=1 + base size=0 base align=1 +std::chrono::_V2::system_clock (0x0x7f9165cdc900) 0 empty + +Class std::chrono::_V2::steady_clock + size=1 align=1 + base size=0 base align=1 +std::chrono::_V2::steady_clock (0x0x7f9165e3d780) 0 empty + +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 (0x0x7f9165e3d7e0) 0 + vptr=((& QObjectData::_ZTV11QObjectData) + 16u) + +Class QObject::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObject::QPrivateSignal (0x0x7f9165e3d9c0) 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 (0x0x7f9165e3d960) 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 (0x0x7f9165b05120) 0 nearly-empty + vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16u) + +Class QSignalBlocker + size=16 align=8 + base size=10 base align=8 +QSignalBlocker (0x0x7f9165b05180) 0 + +Class QAbstractAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractAnimation::QPrivateSignal (0x0x7f9165b05240) 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 (0x0x7f9165e3cf70) 0 + vptr=((& QAbstractAnimation::_ZTV18QAbstractAnimation) + 16u) + QObject (0x0x7f9165b051e0) 0 + primary-for QAbstractAnimation (0x0x7f9165e3cf70) + +Class QAnimationDriver::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationDriver::QPrivateSignal (0x0x7f9165b05300) 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 (0x0x7f9165e3c6e8) 0 + vptr=((& QAnimationDriver::_ZTV16QAnimationDriver) + 16u) + QObject (0x0x7f9165b052a0) 0 + primary-for QAnimationDriver (0x0x7f9165e3c6e8) + +Class QEventLoop::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventLoop::QPrivateSignal (0x0x7f9165b053c0) 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 (0x0x7f9165b58000) 0 + vptr=((& QEventLoop::_ZTV10QEventLoop) + 16u) + QObject (0x0x7f9165b05360) 0 + primary-for QEventLoop (0x0x7f9165b58000) + +Class QEventLoopLocker + size=8 align=8 + base size=8 base align=8 +QEventLoopLocker (0x0x7f9165b055a0) 0 + +Class QAbstractEventDispatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractEventDispatcher::QPrivateSignal (0x0x7f9165b05660) 0 empty + +Class QAbstractEventDispatcher::TimerInfo + size=12 align=4 + base size=12 base align=4 +QAbstractEventDispatcher::TimerInfo (0x0x7f9165b056c0) 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 (0x0x7f9165b58138) 0 + vptr=((& QAbstractEventDispatcher::_ZTV24QAbstractEventDispatcher) + 16u) + QObject (0x0x7f9165b05600) 0 + primary-for QAbstractEventDispatcher (0x0x7f9165b58138) + +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 (0x0x7f9165b05720) 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 (0x0x7f9165b581a0) 0 nearly-empty + vptr=((& std::bad_cast::_ZTVSt8bad_cast) + 16u) + std::exception (0x0x7f9165b05780) 0 nearly-empty + primary-for std::bad_cast (0x0x7f9165b581a0) + +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 (0x0x7f9165b58208) 0 nearly-empty + vptr=((& std::bad_typeid::_ZTVSt10bad_typeid) + 16u) + std::exception (0x0x7f9165b057e0) 0 nearly-empty + primary-for std::bad_typeid (0x0x7f9165b58208) + +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 (0x0x7f916591e478) 0 nearly-empty + vptr=((& std::bad_function_call::_ZTVSt17bad_function_call) + 16u) + std::exception (0x0x7f91658d38a0) 0 nearly-empty + primary-for std::bad_function_call (0x0x7f916591e478) + +Class std::_Nocopy_types + size=16 align=8 + base size=16 base align=8 +std::_Nocopy_types (0x0x7f91658d3960) 0 + +Class std::_Any_data + size=16 align=8 + base size=16 base align=8 +std::_Any_data (0x0x7f91658d39c0) 0 + +Class std::_Function_base + size=24 align=8 + base size=24 base align=8 +std::_Function_base (0x0x7f91658d3ae0) 0 + +Class QMapNodeBase + size=24 align=8 + base size=24 base align=8 +QMapNodeBase (0x0x7f91659c6000) 0 + +Class QMapDataBase + size=40 align=8 + base size=40 base align=8 +QMapDataBase (0x0x7f91659c60c0) 0 + +Class QHashData::Node + size=16 align=8 + base size=16 base align=8 +QHashData::Node (0x0x7f91659c6480) 0 + +Class QHashData + size=48 align=8 + base size=44 base align=8 +QHashData (0x0x7f91659c6420) 0 + +Class QHashDummyValue + size=1 align=1 + base size=0 base align=1 +QHashDummyValue (0x0x7f91659c64e0) 0 empty + +Class QVariant::PrivateShared + size=16 align=8 + base size=12 base align=8 +QVariant::PrivateShared (0x0x7f91657c8060) 0 + +Class QVariant::Private::Data + size=8 align=8 + base size=8 base align=8 +QVariant::Private::Data (0x0x7f91657c8120) 0 + +Class QVariant::Private + size=16 align=8 + base size=12 base align=8 +QVariant::Private (0x0x7f91657c80c0) 0 + +Class QVariant::Handler + size=72 align=8 + base size=72 base align=8 +QVariant::Handler (0x0x7f91657c8180) 0 + +Class QVariant + size=16 align=8 + base size=16 base align=8 +QVariant (0x0x7f91657c8000) 0 + +Class QVariantComparisonHelper + size=8 align=8 + base size=8 base align=8 +QVariantComparisonHelper (0x0x7f916549c480) 0 + +Class QSequentialIterable::const_iterator + size=112 align=8 + base size=112 base align=8 +QSequentialIterable::const_iterator (0x0x7f916549c780) 0 + +Class QSequentialIterable + size=104 align=8 + base size=104 base align=8 +QSequentialIterable (0x0x7f916549c720) 0 + +Class QAssociativeIterable::const_iterator + size=120 align=8 + base size=120 base align=8 +QAssociativeIterable::const_iterator (0x0x7f916549c840) 0 + +Class QAssociativeIterable + size=112 align=8 + base size=112 base align=8 +QAssociativeIterable (0x0x7f916549c7e0) 0 + +Class QModelIndex + size=24 align=8 + base size=24 base align=8 +QModelIndex (0x0x7f91652ce2a0) 0 + +Class QPersistentModelIndex + size=8 align=8 + base size=8 base align=8 +QPersistentModelIndex (0x0x7f91652ce540) 0 + +Class QAbstractItemModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractItemModel::QPrivateSignal (0x0x7f91653a9540) 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 (0x0x7f91653ac618) 0 + vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16u) + QObject (0x0x7f91653a94e0) 0 + primary-for QAbstractItemModel (0x0x7f91653ac618) + +Class QAbstractTableModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTableModel::QPrivateSignal (0x0x7f91653a98a0) 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 (0x0x7f91653ac820) 0 + vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16u) + QAbstractItemModel (0x0x7f91653ac888) 0 + primary-for QAbstractTableModel (0x0x7f91653ac820) + QObject (0x0x7f91653a9840) 0 + primary-for QAbstractItemModel (0x0x7f91653ac888) + +Class QAbstractListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractListModel::QPrivateSignal (0x0x7f91653a9960) 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 (0x0x7f91653ac8f0) 0 + vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16u) + QAbstractItemModel (0x0x7f91653ac958) 0 + primary-for QAbstractListModel (0x0x7f91653ac8f0) + QObject (0x0x7f91653a9900) 0 + primary-for QAbstractItemModel (0x0x7f91653ac958) + +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 (0x0x7f91653a9c00) 0 + vptr=((& QAbstractNativeEventFilter::_ZTV26QAbstractNativeEventFilter) + 16u) + +Class QAbstractProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractProxyModel::QPrivateSignal (0x0x7f91653a9cc0) 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 (0x0x7f91653aca90) 0 + vptr=((& QAbstractProxyModel::_ZTV19QAbstractProxyModel) + 16u) + QAbstractItemModel (0x0x7f91653acaf8) 0 + primary-for QAbstractProxyModel (0x0x7f91653aca90) + QObject (0x0x7f91653a9c60) 0 + primary-for QAbstractItemModel (0x0x7f91653acaf8) + +Class QAbstractState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractState::QPrivateSignal (0x0x7f91653a9d80) 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 (0x0x7f91653acb60) 0 + vptr=((& QAbstractState::_ZTV14QAbstractState) + 16u) + QObject (0x0x7f91653a9d20) 0 + primary-for QAbstractState (0x0x7f91653acb60) + +Class QAbstractTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAbstractTransition::QPrivateSignal (0x0x7f91653a9e40) 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 (0x0x7f91653acbc8) 0 + vptr=((& QAbstractTransition::_ZTV19QAbstractTransition) + 16u) + QObject (0x0x7f91653a9de0) 0 + primary-for QAbstractTransition (0x0x7f91653acbc8) + +Class QAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QAnimationGroup::QPrivateSignal (0x0x7f91653a9f00) 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 (0x0x7f91653acc30) 0 + vptr=((& QAnimationGroup::_ZTV15QAnimationGroup) + 16u) + QAbstractAnimation (0x0x7f91653acc98) 0 + primary-for QAnimationGroup (0x0x7f91653acc30) + QObject (0x0x7f91653a9ea0) 0 + primary-for QAbstractAnimation (0x0x7f91653acc98) + +Class QBasicTimer + size=4 align=4 + base size=4 base align=4 +QBasicTimer (0x0x7f916511b420) 0 + +Class QBitArray + size=8 align=8 + base size=8 base align=8 +QBitArray (0x0x7f916511b6c0) 0 + +Class QBitRef + size=16 align=8 + base size=12 base align=8 +QBitRef (0x0x7f916511b900) 0 + +Class QIODevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIODevice::QPrivateSignal (0x0x7f916511bc60) 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 (0x0x7f916512dd68) 0 + vptr=((& QIODevice::_ZTV9QIODevice) + 16u) + QObject (0x0x7f916511bc00) 0 + primary-for QIODevice (0x0x7f916512dd68) + +Class QBuffer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QBuffer::QPrivateSignal (0x0x7f916511bea0) 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 (0x0x7f916512dea0) 0 + vptr=((& QBuffer::_ZTV7QBuffer) + 16u) + QIODevice (0x0x7f916512df08) 0 + primary-for QBuffer (0x0x7f916512dea0) + QObject (0x0x7f916511be40) 0 + primary-for QIODevice (0x0x7f916512df08) + +Class QByteArrayMatcher::Data + size=272 align=8 + base size=272 base align=8 +QByteArrayMatcher::Data (0x0x7f916511bf60) 0 + +Class QByteArrayMatcher + size=1040 align=8 + base size=1040 base align=8 +QByteArrayMatcher (0x0x7f916511bf00) 0 + +Class QStaticByteArrayMatcherBase::Skiptable + size=256 align=1 + base size=256 base align=1 +QStaticByteArrayMatcherBase::Skiptable (0x0x7f91652220c0) 0 + +Class QStaticByteArrayMatcherBase + size=256 align=16 + base size=256 base align=16 +QStaticByteArrayMatcherBase (0x0x7f9165222060) 0 + +Class QSharedData + size=4 align=4 + base size=4 base align=4 +QSharedData (0x0x7f91652222a0) 0 + +Class QLocale + size=8 align=8 + base size=8 base align=8 +QLocale (0x0x7f9165222480) 0 + +Class QCollatorSortKey + size=8 align=8 + base size=8 base align=8 +QCollatorSortKey (0x0x7f9165222900) 0 + +Class QCollator + size=8 align=8 + base size=8 base align=8 +QCollator (0x0x7f91652229c0) 0 + +Class QCommandLineOption + size=8 align=8 + base size=8 base align=8 +QCommandLineOption (0x0x7f9164fe99c0) 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 (0x0x7f9164fe9e40) 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 (0x0x7f91650002d8) 0 + vptr=((& QTimerEvent::_ZTV11QTimerEvent) + 16u) + QEvent (0x0x7f9164fe9ea0) 0 + primary-for QTimerEvent (0x0x7f91650002d8) + +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 (0x0x7f9165000340) 0 + vptr=((& QChildEvent::_ZTV11QChildEvent) + 16u) + QEvent (0x0x7f9164fe9f00) 0 + primary-for QChildEvent (0x0x7f9165000340) + +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 (0x0x7f91650003a8) 0 + vptr=((& QDynamicPropertyChangeEvent::_ZTV27QDynamicPropertyChangeEvent) + 16u) + QEvent (0x0x7f9164fe9f60) 0 + primary-for QDynamicPropertyChangeEvent (0x0x7f91650003a8) + +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 (0x0x7f9165000410) 0 + vptr=((& QDeferredDeleteEvent::_ZTV20QDeferredDeleteEvent) + 16u) + QEvent (0x0x7f9164c3c000) 0 + primary-for QDeferredDeleteEvent (0x0x7f9165000410) + +Class QCoreApplication::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QCoreApplication::QPrivateSignal (0x0x7f9164c3c0c0) 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 (0x0x7f9165000478) 0 + vptr=((& QCoreApplication::_ZTV16QCoreApplication) + 16u) + QObject (0x0x7f9164c3c060) 0 + primary-for QCoreApplication (0x0x7f9165000478) + +Class QCommandLineParser + size=8 align=8 + base size=8 base align=8 +QCommandLineParser (0x0x7f9164c3c120) 0 + +Class QContiguousCacheData + size=24 align=4 + base size=24 base align=4 +QContiguousCacheData (0x0x7f9164c3c180) 0 + +Class QCryptographicHash + size=8 align=8 + base size=8 base align=8 +QCryptographicHash (0x0x7f9164c3c420) 0 + +Class QDataStream + size=32 align=8 + base size=32 base align=8 +QDataStream (0x0x7f9164c3c480) 0 + +Class QtPrivate::StreamStateSaver + size=16 align=8 + base size=12 base align=8 +QtPrivate::StreamStateSaver (0x0x7f9164c3c540) 0 + +Class QDate + size=8 align=8 + base size=8 base align=8 +QDate (0x0x7f9164c3c5a0) 0 + +Class QTime + size=4 align=4 + base size=4 base align=4 +QTime (0x0x7f9164c3c840) 0 + +Class QDateTime::ShortData + size=8 align=8 + base size=8 base align=8 +QDateTime::ShortData (0x0x7f9164c3cb40) 0 + +Class QDateTime::Data + size=8 align=8 + base size=8 base align=8 +QDateTime::Data (0x0x7f9164c3cba0) 0 + +Class QDateTime + size=8 align=8 + base size=8 base align=8 +QDateTime (0x0x7f9164c3cae0) 0 + +Class QElapsedTimer + size=16 align=8 + base size=16 base align=8 +QElapsedTimer (0x0x7f9164dfb960) 0 + +Class QDeadlineTimer + size=16 align=8 + base size=16 base align=8 +QDeadlineTimer (0x0x7f9164dfb9c0) 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 (0x0x7f9164b2e600) 0 + vptr=((& QTextStream::_ZTV11QTextStream) + 16u) + +Class QTextStreamManipulator + size=40 align=8 + base size=38 base align=8 +QTextStreamManipulator (0x0x7f9164b2e8a0) 0 + +Class QtSharedPointer::NormalDeleter + size=1 align=1 + base size=0 base align=1 +QtSharedPointer::NormalDeleter (0x0x7f9164b2eae0) 0 empty + +Class QtSharedPointer::ExternalRefCountData + size=16 align=8 + base size=16 base align=8 +QtSharedPointer::ExternalRefCountData (0x0x7f9164b2ec60) 0 + +Class QDebug::Stream + size=80 align=8 + base size=76 base align=8 +QDebug::Stream (0x0x7f91648f8120) 0 + +Class QDebug + size=8 align=8 + base size=8 base align=8 +QDebug (0x0x7f91648f80c0) 0 + +Class QDebugStateSaver + size=8 align=8 + base size=8 base align=8 +QDebugStateSaver (0x0x7f91649ac300) 0 + +Class QNoDebug + size=1 align=1 + base size=0 base align=1 +QNoDebug (0x0x7f91649ac3c0) 0 empty + +Class QFileDevice::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileDevice::QPrivateSignal (0x0x7f91649ac480) 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 (0x0x7f91649ab410) 0 + vptr=((& QFileDevice::_ZTV11QFileDevice) + 16u) + QIODevice (0x0x7f91649ab478) 0 + primary-for QFileDevice (0x0x7f91649ab410) + QObject (0x0x7f91649ac420) 0 + primary-for QIODevice (0x0x7f91649ab478) + +Class QFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFile::QPrivateSignal (0x0x7f91649ac6c0) 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 (0x0x7f91649ab5b0) 0 + vptr=((& QFile::_ZTV5QFile) + 16u) + QFileDevice (0x0x7f91649ab618) 0 + primary-for QFile (0x0x7f91649ab5b0) + QIODevice (0x0x7f91649ab680) 0 + primary-for QFileDevice (0x0x7f91649ab618) + QObject (0x0x7f91649ac660) 0 + primary-for QIODevice (0x0x7f91649ab680) + +Class QFileInfo + size=8 align=8 + base size=8 base align=8 +QFileInfo (0x0x7f91649ac8a0) 0 + +Class QDir + size=8 align=8 + base size=8 base align=8 +QDir (0x0x7f91649accc0) 0 + +Class QDirIterator + size=8 align=8 + base size=8 base align=8 +QDirIterator (0x0x7f91647076c0) 0 + +Class QEasingCurve + size=8 align=8 + base size=8 base align=8 +QEasingCurve (0x0x7f9164707900) 0 + +Class QEventTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QEventTransition::QPrivateSignal (0x0x7f916442cb40) 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 (0x0x7f916442f958) 0 + vptr=((& QEventTransition::_ZTV16QEventTransition) + 16u) + QAbstractTransition (0x0x7f916442f9c0) 0 + primary-for QEventTransition (0x0x7f916442f958) + QObject (0x0x7f916442cae0) 0 + primary-for QAbstractTransition (0x0x7f916442f9c0) + +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 (0x0x7f916442fa28) 0 nearly-empty + vptr=((& QException::_ZTV10QException) + 16u) + std::exception (0x0x7f916442cba0) 0 nearly-empty + primary-for QException (0x0x7f916442fa28) + +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 (0x0x7f916442fa90) 0 nearly-empty + vptr=((& QUnhandledException::_ZTV19QUnhandledException) + 16u) + QException (0x0x7f916442faf8) 0 nearly-empty + primary-for QUnhandledException (0x0x7f916442fa90) + std::exception (0x0x7f916442cc00) 0 nearly-empty + primary-for QException (0x0x7f916442faf8) + +Class QtPrivate::ExceptionHolder + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionHolder (0x0x7f916442cc60) 0 + +Class QtPrivate::ExceptionStore + size=8 align=8 + base size=8 base align=8 +QtPrivate::ExceptionStore (0x0x7f916442cd20) 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 (0x0x7f916442cd80) 0 nearly-empty + vptr=((& QFactoryInterface::_ZTV17QFactoryInterface) + 16u) + +Class QFileSelector::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSelector::QPrivateSignal (0x0x7f916442cea0) 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 (0x0x7f916442fb60) 0 + vptr=((& QFileSelector::_ZTV13QFileSelector) + 16u) + QObject (0x0x7f916442ce40) 0 + primary-for QFileSelector (0x0x7f916442fb60) + +Class QFileSystemWatcher::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFileSystemWatcher::QPrivateSignal (0x0x7f916442cf60) 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 (0x0x7f916442fbc8) 0 + vptr=((& QFileSystemWatcher::_ZTV18QFileSystemWatcher) + 16u) + QObject (0x0x7f916442cf00) 0 + primary-for QFileSystemWatcher (0x0x7f916442fbc8) + +Class QFinalState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFinalState::QPrivateSignal (0x0x7f91644b7060) 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 (0x0x7f916442fc30) 0 + vptr=((& QFinalState::_ZTV11QFinalState) + 16u) + QAbstractState (0x0x7f916442fc98) 0 + primary-for QFinalState (0x0x7f916442fc30) + QObject (0x0x7f91644b7000) 0 + primary-for QAbstractState (0x0x7f916442fc98) + +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 (0x0x7f91644b70c0) 0 + vptr=((& QRunnable::_ZTV9QRunnable) + 16u) + +Class QBasicMutex + size=8 align=8 + base size=8 base align=8 +QBasicMutex (0x0x7f91644b7120) 0 + +Class QMutex + size=8 align=8 + base size=8 base align=8 +QMutex (0x0x7f916442fdd0) 0 + QBasicMutex (0x0x7f91644b7360) 0 + +Class QMutexLocker + size=8 align=8 + base size=8 base align=8 +QMutexLocker (0x0x7f91644b7420) 0 + +Class QtPrivate::ResultItem + size=16 align=8 + base size=16 base align=8 +QtPrivate::ResultItem (0x0x7f91644b74e0) 0 + +Class QtPrivate::ResultIteratorBase + size=16 align=8 + base size=12 base align=8 +QtPrivate::ResultIteratorBase (0x0x7f91644b7540) 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 (0x0x7f91644b7660) 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 (0x0x7f91644b76c0) 0 + vptr=((& QFutureInterfaceBase::_ZTV20QFutureInterfaceBase) + 16u) + +Class QFutureWatcherBase::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QFutureWatcherBase::QPrivateSignal (0x0x7f91644b7a20) 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 (0x0x7f91645bd1a0) 0 + vptr=((& QFutureWatcherBase::_ZTV18QFutureWatcherBase) + 16u) + QObject (0x0x7f91644b79c0) 0 + primary-for QFutureWatcherBase (0x0x7f91645bd1a0) + +Class QHistoryState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QHistoryState::QPrivateSignal (0x0x7f91644b7ba0) 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 (0x0x7f91645bd5b0) 0 + vptr=((& QHistoryState::_ZTV13QHistoryState) + 16u) + QAbstractState (0x0x7f91645bd618) 0 + primary-for QHistoryState (0x0x7f91645bd5b0) + QObject (0x0x7f91644b7b40) 0 + primary-for QAbstractState (0x0x7f91645bd618) + +Class QIdentityProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QIdentityProxyModel::QPrivateSignal (0x0x7f91644b7c60) 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 (0x0x7f91645bd680) 0 + vptr=((& QIdentityProxyModel::_ZTV19QIdentityProxyModel) + 16u) + QAbstractProxyModel (0x0x7f91645bd6e8) 0 + primary-for QIdentityProxyModel (0x0x7f91645bd680) + QAbstractItemModel (0x0x7f91645bd750) 0 + primary-for QAbstractProxyModel (0x0x7f91645bd6e8) + QObject (0x0x7f91644b7c00) 0 + primary-for QAbstractItemModel (0x0x7f91645bd750) + +Class QItemSelectionRange + size=16 align=8 + base size=16 base align=8 +QItemSelectionRange (0x0x7f91644b7cc0) 0 + +Class QItemSelectionModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QItemSelectionModel::QPrivateSignal (0x0x7f91642d4060) 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 (0x0x7f91645bdaf8) 0 + vptr=((& QItemSelectionModel::_ZTV19QItemSelectionModel) + 16u) + QObject (0x0x7f91642d4000) 0 + primary-for QItemSelectionModel (0x0x7f91645bdaf8) + +Class QItemSelection + size=8 align=8 + base size=8 base align=8 +QItemSelection (0x0x7f91645bdd00) 0 + QList (0x0x7f91645bdd68) 0 + QListSpecialMethods (0x0x7f91642d4360) 0 empty + +Class QJsonValue + size=24 align=8 + base size=20 base align=8 +QJsonValue (0x0x7f91642d4840) 0 + +Class QJsonValueRef + size=16 align=8 + base size=12 base align=8 +QJsonValueRef (0x0x7f91642d4900) 0 + +Class QJsonValuePtr + size=24 align=8 + base size=24 base align=8 +QJsonValuePtr (0x0x7f91642d49c0) 0 + +Class QJsonValueRefPtr + size=16 align=8 + base size=16 base align=8 +QJsonValueRefPtr (0x0x7f91642d4a20) 0 + +Class QJsonArray::iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::iterator (0x0x7f91642d4ae0) 0 + +Class QJsonArray::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonArray::const_iterator (0x0x7f91642d4b40) 0 + +Class QJsonArray + size=16 align=8 + base size=16 base align=8 +QJsonArray (0x0x7f91642d4a80) 0 + +Class QJsonParseError + size=8 align=4 + base size=8 base align=4 +QJsonParseError (0x0x7f91642d4c00) 0 + +Class QJsonDocument + size=8 align=8 + base size=8 base align=8 +QJsonDocument (0x0x7f91642d4c60) 0 + +Class QJsonObject::iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::iterator (0x0x7f91642d4d20) 0 + +Class QJsonObject::const_iterator + size=16 align=8 + base size=12 base align=8 +QJsonObject::const_iterator (0x0x7f91642d4d80) 0 + +Class QJsonObject + size=16 align=8 + base size=16 base align=8 +QJsonObject (0x0x7f91642d4cc0) 0 + +Class QLibrary::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QLibrary::QPrivateSignal (0x0x7f91642d4f60) 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 (0x0x7f91643e4138) 0 + vptr=((& QLibrary::_ZTV8QLibrary) + 16u) + QObject (0x0x7f91642d4f00) 0 + primary-for QLibrary (0x0x7f91643e4138) + +Class QVersionNumber::SegmentStorage + size=8 align=8 + base size=8 base align=8 +QVersionNumber::SegmentStorage (0x0x7f91640c21e0) 0 + +Class QVersionNumber + size=8 align=8 + base size=8 base align=8 +QVersionNumber (0x0x7f91640c2180) 0 + +Class QLibraryInfo + size=1 align=1 + base size=0 base align=1 +QLibraryInfo (0x0x7f9164164f00) 0 empty + +Class QPoint + size=8 align=4 + base size=8 base align=4 +QPoint (0x0x7f9164164f60) 0 + +Class QPointF + size=16 align=8 + base size=16 base align=8 +QPointF (0x0x7f91641d8240) 0 + +Class QLine + size=16 align=4 + base size=16 base align=4 +QLine (0x0x7f91641d84e0) 0 + +Class QLineF + size=32 align=8 + base size=32 base align=8 +QLineF (0x0x7f91641d8780) 0 + +Class QLinkedListData + size=32 align=8 + base size=25 base align=8 +QLinkedListData (0x0x7f91641d8a20) 0 + +Class QLockFile + size=8 align=8 + base size=8 base align=8 +QLockFile (0x0x7f9163f1a1e0) 0 + +Class QLoggingCategory::AtomicBools + size=4 align=1 + base size=4 base align=1 +QLoggingCategory::AtomicBools (0x0x7f9163f1a360) 0 + +Class QLoggingCategory + size=24 align=8 + base size=24 base align=8 +QLoggingCategory (0x0x7f9163f1a300) 0 + +Class QMargins + size=16 align=4 + base size=16 base align=4 +QMargins (0x0x7f9163f1a4e0) 0 + +Class QMarginsF + size=32 align=8 + base size=32 base align=8 +QMarginsF (0x0x7f9163f1a780) 0 + +Class QMessageAuthenticationCode + size=8 align=8 + base size=8 base align=8 +QMessageAuthenticationCode (0x0x7f9163f1aa80) 0 + +Class QMetaMethod + size=16 align=8 + base size=12 base align=8 +QMetaMethod (0x0x7f9163f1aae0) 0 + +Class QMetaEnum + size=16 align=8 + base size=12 base align=8 +QMetaEnum (0x0x7f9163f1ad80) 0 + +Class QMetaProperty + size=32 align=8 + base size=32 base align=8 +QMetaProperty (0x0x7f9163c930c0) 0 + +Class QMetaClassInfo + size=16 align=8 + base size=12 base align=8 +QMetaClassInfo (0x0x7f9163c93120) 0 + +Class QMimeData::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QMimeData::QPrivateSignal (0x0x7f9163c93420) 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 (0x0x7f9163c94270) 0 + vptr=((& QMimeData::_ZTV9QMimeData) + 16u) + QObject (0x0x7f9163c933c0) 0 + primary-for QMimeData (0x0x7f9163c94270) + +Class QMimeType + size=8 align=8 + base size=8 base align=8 +QMimeType (0x0x7f9163c93480) 0 + +Class QMimeDatabase + size=8 align=8 + base size=8 base align=8 +QMimeDatabase (0x0x7f9163c93780) 0 + +Class QObjectCleanupHandler::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QObjectCleanupHandler::QPrivateSignal (0x0x7f9163c93840) 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 (0x0x7f9163c94478) 0 + vptr=((& QObjectCleanupHandler::_ZTV21QObjectCleanupHandler) + 16u) + QObject (0x0x7f9163c937e0) 0 + primary-for QObjectCleanupHandler (0x0x7f9163c94478) + +Class QOperatingSystemVersion + size=16 align=4 + base size=16 base align=4 +QOperatingSystemVersion (0x0x7f9163c938a0) 0 + +Class QParallelAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QParallelAnimationGroup::QPrivateSignal (0x0x7f9163c93960) 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 (0x0x7f9163c94548) 0 + vptr=((& QParallelAnimationGroup::_ZTV23QParallelAnimationGroup) + 16u) + QAnimationGroup (0x0x7f9163c945b0) 0 + primary-for QParallelAnimationGroup (0x0x7f9163c94548) + QAbstractAnimation (0x0x7f9163c94618) 0 + primary-for QAnimationGroup (0x0x7f9163c945b0) + QObject (0x0x7f9163c93900) 0 + primary-for QAbstractAnimation (0x0x7f9163c94618) + +Class QPauseAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPauseAnimation::QPrivateSignal (0x0x7f9163c93a20) 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 (0x0x7f9163c94680) 0 + vptr=((& QPauseAnimation::_ZTV15QPauseAnimation) + 16u) + QAbstractAnimation (0x0x7f9163c946e8) 0 + primary-for QPauseAnimation (0x0x7f9163c94680) + QObject (0x0x7f9163c939c0) 0 + primary-for QAbstractAnimation (0x0x7f9163c946e8) + +Class QStaticPlugin + size=16 align=8 + base size=16 base align=8 +QStaticPlugin (0x0x7f9163c93c00) 0 + +Class QPluginLoader::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPluginLoader::QPrivateSignal (0x0x7f9163c93f00) 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 (0x0x7f9163c948f0) 0 + vptr=((& QPluginLoader::_ZTV13QPluginLoader) + 16u) + QObject (0x0x7f9163c93ea0) 0 + primary-for QPluginLoader (0x0x7f9163c948f0) + +Class QProcessEnvironment + size=8 align=8 + base size=8 base align=8 +QProcessEnvironment (0x0x7f9163c93f60) 0 + +Class QProcess::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QProcess::QPrivateSignal (0x0x7f9163d5e300) 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 (0x0x7f9163c94af8) 0 + vptr=((& QProcess::_ZTV8QProcess) + 16u) + QIODevice (0x0x7f9163c94b60) 0 + primary-for QProcess (0x0x7f9163c94af8) + QObject (0x0x7f9163d5e2a0) 0 + primary-for QIODevice (0x0x7f9163c94b60) + +Class QVariantAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QVariantAnimation::QPrivateSignal (0x0x7f9163d5e3c0) 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 (0x0x7f9163c94bc8) 0 + vptr=((& QVariantAnimation::_ZTV17QVariantAnimation) + 16u) + QAbstractAnimation (0x0x7f9163c94c30) 0 + primary-for QVariantAnimation (0x0x7f9163c94bc8) + QObject (0x0x7f9163d5e360) 0 + primary-for QAbstractAnimation (0x0x7f9163c94c30) + +Class QPropertyAnimation::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QPropertyAnimation::QPrivateSignal (0x0x7f9163d5e480) 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 (0x0x7f9163c94d00) 0 + vptr=((& QPropertyAnimation::_ZTV18QPropertyAnimation) + 16u) + QVariantAnimation (0x0x7f9163c94d68) 0 + primary-for QPropertyAnimation (0x0x7f9163c94d00) + QAbstractAnimation (0x0x7f9163c94dd0) 0 + primary-for QVariantAnimation (0x0x7f9163c94d68) + QObject (0x0x7f9163d5e420) 0 + primary-for QAbstractAnimation (0x0x7f9163c94dd0) + +Class QReadWriteLock + size=8 align=8 + base size=8 base align=8 +QReadWriteLock (0x0x7f9163d5e540) 0 + +Class QReadLocker + size=8 align=8 + base size=8 base align=8 +QReadLocker (0x0x7f9163d5e7e0) 0 + +Class QWriteLocker + size=8 align=8 + base size=8 base align=8 +QWriteLocker (0x0x7f9163d5e840) 0 + +Class QSize + size=8 align=4 + base size=8 base align=4 +QSize (0x0x7f9163d5e8a0) 0 + +Class QSizeF + size=16 align=8 + base size=16 base align=8 +QSizeF (0x0x7f9163d5ec00) 0 + +Class QRect + size=16 align=4 + base size=16 base align=4 +QRect (0x0x7f9163d5ef60) 0 + +Class QRectF + size=32 align=8 + base size=32 base align=8 +QRectF (0x0x7f9163afe240) 0 + +Class QRegularExpression + size=8 align=8 + base size=8 base align=8 +QRegularExpression (0x0x7f9163afe4e0) 0 + +Class QRegularExpressionMatch + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatch (0x0x7f9163afeae0) 0 + +Class QRegularExpressionMatchIterator + size=8 align=8 + base size=8 base align=8 +QRegularExpressionMatchIterator (0x0x7f9163afede0) 0 + +Class QResource + size=8 align=8 + base size=8 base align=8 +QResource (0x0x7f91638ad120) 0 + +Class QSaveFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSaveFile::QPrivateSignal (0x0x7f91638ad2a0) 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 (0x0x7f91638af068) 0 + vptr=((& QSaveFile::_ZTV9QSaveFile) + 16u) + QFileDevice (0x0x7f91638af0d0) 0 + primary-for QSaveFile (0x0x7f91638af068) + QIODevice (0x0x7f91638af138) 0 + primary-for QFileDevice (0x0x7f91638af0d0) + QObject (0x0x7f91638ad240) 0 + primary-for QIODevice (0x0x7f91638af138) + +Class QSemaphore + size=8 align=8 + base size=8 base align=8 +QSemaphore (0x0x7f91638ad360) 0 + +Class QSequentialAnimationGroup::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSequentialAnimationGroup::QPrivateSignal (0x0x7f91638ad420) 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 (0x0x7f91638af1a0) 0 + vptr=((& QSequentialAnimationGroup::_ZTV25QSequentialAnimationGroup) + 16u) + QAnimationGroup (0x0x7f91638af208) 0 + primary-for QSequentialAnimationGroup (0x0x7f91638af1a0) + QAbstractAnimation (0x0x7f91638af270) 0 + primary-for QAnimationGroup (0x0x7f91638af208) + QObject (0x0x7f91638ad3c0) 0 + primary-for QAbstractAnimation (0x0x7f91638af270) + +Class QSettings::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSettings::QPrivateSignal (0x0x7f91638ad4e0) 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 (0x0x7f91638af2d8) 0 + vptr=((& QSettings::_ZTV9QSettings) + 16u) + QObject (0x0x7f91638ad480) 0 + primary-for QSettings (0x0x7f91638af2d8) + +Class QSharedMemory::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSharedMemory::QPrivateSignal (0x0x7f91638ad5a0) 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 (0x0x7f91638af340) 0 + vptr=((& QSharedMemory::_ZTV13QSharedMemory) + 16u) + QObject (0x0x7f91638ad540) 0 + primary-for QSharedMemory (0x0x7f91638af340) + +Class QSignalMapper::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalMapper::QPrivateSignal (0x0x7f91638ad660) 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 (0x0x7f91638af3a8) 0 + vptr=((& QSignalMapper::_ZTV13QSignalMapper) + 16u) + QObject (0x0x7f91638ad600) 0 + primary-for QSignalMapper (0x0x7f91638af3a8) + +Class QSignalTransition::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSignalTransition::QPrivateSignal (0x0x7f91638ad720) 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 (0x0x7f91638af410) 0 + vptr=((& QSignalTransition::_ZTV17QSignalTransition) + 16u) + QAbstractTransition (0x0x7f91638af478) 0 + primary-for QSignalTransition (0x0x7f91638af410) + QObject (0x0x7f91638ad6c0) 0 + primary-for QAbstractTransition (0x0x7f91638af478) + +Class QSocketNotifier::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSocketNotifier::QPrivateSignal (0x0x7f91638ad7e0) 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 (0x0x7f91638af4e0) 0 + vptr=((& QSocketNotifier::_ZTV15QSocketNotifier) + 16u) + QObject (0x0x7f91638ad780) 0 + primary-for QSocketNotifier (0x0x7f91638af4e0) + +Class QSortFilterProxyModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QSortFilterProxyModel::QPrivateSignal (0x0x7f91638ad8a0) 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 (0x0x7f91638af548) 0 + vptr=((& QSortFilterProxyModel::_ZTV21QSortFilterProxyModel) + 16u) + QAbstractProxyModel (0x0x7f91638af5b0) 0 + primary-for QSortFilterProxyModel (0x0x7f91638af548) + QAbstractItemModel (0x0x7f91638af618) 0 + primary-for QAbstractProxyModel (0x0x7f91638af5b0) + QObject (0x0x7f91638ad840) 0 + primary-for QAbstractItemModel (0x0x7f91638af618) + +Class QStandardPaths + size=1 align=1 + base size=0 base align=1 +QStandardPaths (0x0x7f91638ada80) 0 empty + +Class QState::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QState::QPrivateSignal (0x0x7f91638adcc0) 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 (0x0x7f91638af7b8) 0 + vptr=((& QState::_ZTV6QState) + 16u) + QAbstractState (0x0x7f91638af820) 0 + primary-for QState (0x0x7f91638af7b8) + QObject (0x0x7f91638adc60) 0 + primary-for QAbstractState (0x0x7f91638af820) + +Class QStateMachine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStateMachine::QPrivateSignal (0x0x7f91638adde0) 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 (0x0x7f91638af9c0) 0 + vptr=((& QStateMachine::SignalEvent::_ZTVN13QStateMachine11SignalEventE) + 16u) + QEvent (0x0x7f91638ade40) 0 + primary-for QStateMachine::SignalEvent (0x0x7f91638af9c0) + +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 (0x0x7f91638afa28) 0 + vptr=((& QStateMachine::WrappedEvent::_ZTVN13QStateMachine12WrappedEventE) + 16u) + QEvent (0x0x7f91638adea0) 0 + primary-for QStateMachine::WrappedEvent (0x0x7f91638afa28) + +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 (0x0x7f91638af888) 0 + vptr=((& QStateMachine::_ZTV13QStateMachine) + 16u) + QState (0x0x7f91638af8f0) 0 + primary-for QStateMachine (0x0x7f91638af888) + QAbstractState (0x0x7f91638af958) 0 + primary-for QState (0x0x7f91638af8f0) + QObject (0x0x7f91638add80) 0 + primary-for QAbstractState (0x0x7f91638af958) + +Class QStorageInfo + size=8 align=8 + base size=8 base align=8 +QStorageInfo (0x0x7f91638adf00) 0 + +Class QAbstractConcatenable + size=1 align=1 + base size=0 base align=1 +QAbstractConcatenable (0x0x7f9163630360) 0 empty + +Class QStringListModel::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QStringListModel::QPrivateSignal (0x0x7f9163630de0) 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 (0x0x7f916367b4e0) 0 + vptr=((& QStringListModel::_ZTV16QStringListModel) + 16u) + QAbstractListModel (0x0x7f916367b548) 0 + primary-for QStringListModel (0x0x7f916367b4e0) + QAbstractItemModel (0x0x7f916367b5b0) 0 + primary-for QAbstractListModel (0x0x7f916367b548) + QObject (0x0x7f9163630d80) 0 + primary-for QAbstractItemModel (0x0x7f916367b5b0) + +Class QSystemSemaphore + size=8 align=8 + base size=8 base align=8 +QSystemSemaphore (0x0x7f9163630e40) 0 + +Class QTemporaryDir + size=8 align=8 + base size=8 base align=8 +QTemporaryDir (0x0x7f9163630f00) 0 + +Class QTemporaryFile::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTemporaryFile::QPrivateSignal (0x0x7f91636e4060) 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 (0x0x7f916367b618) 0 + vptr=((& QTemporaryFile::_ZTV14QTemporaryFile) + 16u) + QFile (0x0x7f916367b680) 0 + primary-for QTemporaryFile (0x0x7f916367b618) + QFileDevice (0x0x7f916367b6e8) 0 + primary-for QFile (0x0x7f916367b680) + QIODevice (0x0x7f916367b750) 0 + primary-for QFileDevice (0x0x7f916367b6e8) + QObject (0x0x7f91636e4000) 0 + primary-for QIODevice (0x0x7f916367b750) + +Class QTextBoundaryFinder + size=48 align=8 + base size=48 base align=8 +QTextBoundaryFinder (0x0x7f91636e40c0) 0 + +Class QTextCodec::ConverterState + size=32 align=8 + base size=32 base align=8 +QTextCodec::ConverterState (0x0x7f91636e4300) 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 (0x0x7f91636e42a0) 0 nearly-empty + vptr=((& QTextCodec::_ZTV10QTextCodec) + 16u) + +Class QTextEncoder + size=40 align=8 + base size=40 base align=8 +QTextEncoder (0x0x7f91636e44e0) 0 + +Class QTextDecoder + size=40 align=8 + base size=40 base align=8 +QTextDecoder (0x0x7f91636e4540) 0 + +Class QThread::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThread::QPrivateSignal (0x0x7f91636e4600) 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 (0x0x7f916367b958) 0 + vptr=((& QThread::_ZTV7QThread) + 16u) + QObject (0x0x7f91636e45a0) 0 + primary-for QThread (0x0x7f916367b958) + +Class QThreadPool::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QThreadPool::QPrivateSignal (0x0x7f91636e46c0) 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 (0x0x7f916367b9c0) 0 + vptr=((& QThreadPool::_ZTV11QThreadPool) + 16u) + QObject (0x0x7f91636e4660) 0 + primary-for QThreadPool (0x0x7f916367b9c0) + +Class QThreadStorageData + size=4 align=4 + base size=4 base align=4 +QThreadStorageData (0x0x7f91636e4720) 0 + +Class QTimeLine::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimeLine::QPrivateSignal (0x0x7f91636e4840) 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 (0x0x7f916367ba28) 0 + vptr=((& QTimeLine::_ZTV9QTimeLine) + 16u) + QObject (0x0x7f91636e47e0) 0 + primary-for QTimeLine (0x0x7f916367ba28) + +Class QTimer::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTimer::QPrivateSignal (0x0x7f91636e4900) 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 (0x0x7f916367ba90) 0 + vptr=((& QTimer::_ZTV6QTimer) + 16u) + QObject (0x0x7f91636e48a0) 0 + primary-for QTimer (0x0x7f916367ba90) + +Class QTimeZone::OffsetData + size=32 align=8 + base size=28 base align=8 +QTimeZone::OffsetData (0x0x7f9163408720) 0 + +Class QTimeZone + size=8 align=8 + base size=8 base align=8 +QTimeZone (0x0x7f91634086c0) 0 + +Class QTranslator::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QTranslator::QPrivateSignal (0x0x7f9163408cc0) 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 (0x0x7f9163402d00) 0 + vptr=((& QTranslator::_ZTV11QTranslator) + 16u) + QObject (0x0x7f9163408c60) 0 + primary-for QTranslator (0x0x7f9163402d00) + +Class QUrl + size=8 align=8 + base size=8 base align=8 +QUrl (0x0x7f9163408de0) 0 + +Class QUrlQuery + size=8 align=8 + base size=8 base align=8 +QUrlQuery (0x0x7f91635694e0) 0 + +Class QUuid + size=16 align=4 + base size=16 base align=4 +QUuid (0x0x7f91635697e0) 0 + +Class QWaitCondition + size=8 align=8 + base size=8 base align=8 +QWaitCondition (0x0x7f9163569a80) 0 + +Class QXmlStreamStringRef + size=16 align=8 + base size=16 base align=8 +QXmlStreamStringRef (0x0x7f9163569ae0) 0 + +Class QXmlStreamAttribute + size=80 align=8 + base size=73 base align=8 +QXmlStreamAttribute (0x0x7f9163280f00) 0 + +Class QXmlStreamAttributes + size=8 align=8 + base size=8 base align=8 +QXmlStreamAttributes (0x0x7f916329e6e8) 0 + QVector (0x0x7f91632d0300) 0 + +Class QXmlStreamNamespaceDeclaration + size=40 align=8 + base size=40 base align=8 +QXmlStreamNamespaceDeclaration (0x0x7f91632d0360) 0 + +Class QXmlStreamNotationDeclaration + size=56 align=8 + base size=56 base align=8 +QXmlStreamNotationDeclaration (0x0x7f91632d0600) 0 + +Class QXmlStreamEntityDeclaration + size=88 align=8 + base size=88 base align=8 +QXmlStreamEntityDeclaration (0x0x7f91632d08a0) 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 (0x0x7f91632d0b40) 0 nearly-empty + vptr=((& QXmlStreamEntityResolver::_ZTV24QXmlStreamEntityResolver) + 16u) + +Class QXmlStreamReader + size=8 align=8 + base size=8 base align=8 +QXmlStreamReader (0x0x7f91632d0ba0) 0 + +Class QXmlStreamWriter + size=8 align=8 + base size=8 base align=8 +QXmlStreamWriter (0x0x7f91632d0cc0) 0 + +Class QNdefRecord + size=8 align=8 + base size=8 base align=8 +QNdefRecord (0x0x7f91632d0de0) 0 + +Class QNdefFilter::Record + size=24 align=8 + base size=24 base align=8 +QNdefFilter::Record (0x0x7f91632d0f00) 0 + +Class QNdefFilter + size=8 align=8 + base size=8 base align=8 +QNdefFilter (0x0x7f91632d0ea0) 0 + +Class QNdefMessage + size=8 align=8 + base size=8 base align=8 +QNdefMessage (0x0x7f916329ea90) 0 + QList (0x0x7f916329ed00) 0 + QListSpecialMethods (0x0x7f91633df120) 0 empty + +Class QNdefNfcTextRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcTextRecord (0x0x7f916329edd0) 0 + QNdefRecord (0x0x7f91633df300) 0 + +Class QNdefNfcUriRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcUriRecord (0x0x7f9163035000) 0 + QNdefRecord (0x0x7f91633df360) 0 + +Class QNdefNfcIconRecord + size=8 align=8 + base size=8 base align=8 +QNdefNfcIconRecord (0x0x7f9163035068) 0 + QNdefRecord (0x0x7f91633df3c0) 0 + +Class QNdefNfcSmartPosterRecord + size=16 align=8 + base size=16 base align=8 +QNdefNfcSmartPosterRecord (0x0x7f91630350d0) 0 + QNdefRecord (0x0x7f91633df420) 0 + +Class QNearFieldTarget::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldTarget::QPrivateSignal (0x0x7f91633df540) 0 empty + +Class QNearFieldTarget::RequestId + size=8 align=8 + base size=8 base align=8 +QNearFieldTarget::RequestId (0x0x7f91633df5a0) 0 + +Vtable for QNearFieldTarget +QNearFieldTarget::_ZTV16QNearFieldTarget: 25u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI16QNearFieldTarget) +16 (int (*)(...))QNearFieldTarget::metaObject +24 (int (*)(...))QNearFieldTarget::qt_metacast +32 (int (*)(...))QNearFieldTarget::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 (*)(...))QNearFieldTarget::url +128 (int (*)(...))__cxa_pure_virtual +136 (int (*)(...))__cxa_pure_virtual +144 (int (*)(...))QNearFieldTarget::hasNdefMessage +152 (int (*)(...))QNearFieldTarget::readNdefMessages +160 (int (*)(...))QNearFieldTarget::writeNdefMessages +168 (int (*)(...))QNearFieldTarget::sendCommand +176 (int (*)(...))QNearFieldTarget::sendCommands +184 (int (*)(...))QNearFieldTarget::waitForRequestCompleted +192 (int (*)(...))QNearFieldTarget::handleResponse + +Class QNearFieldTarget + size=24 align=8 + base size=24 base align=8 +QNearFieldTarget (0x0x7f9163035138) 0 + vptr=((& QNearFieldTarget::_ZTV16QNearFieldTarget) + 16u) + QObject (0x0x7f91633df4e0) 0 + primary-for QNearFieldTarget (0x0x7f9163035138) + +Class QNearFieldManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldManager::QPrivateSignal (0x0x7f91633df960) 0 empty + +Vtable for QNearFieldManager +QNearFieldManager::_ZTV17QNearFieldManager: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI17QNearFieldManager) +16 (int (*)(...))QNearFieldManager::metaObject +24 (int (*)(...))QNearFieldManager::qt_metacast +32 (int (*)(...))QNearFieldManager::qt_metacall +40 (int (*)(...))QNearFieldManager::~QNearFieldManager +48 (int (*)(...))QNearFieldManager::~QNearFieldManager +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 QNearFieldManager + size=24 align=8 + base size=24 base align=8 +QNearFieldManager (0x0x7f9163035270) 0 + vptr=((& QNearFieldManager::_ZTV17QNearFieldManager) + 16u) + QObject (0x0x7f91633df900) 0 + primary-for QNearFieldManager (0x0x7f9163035270) + +Class QNearFieldShareManager::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldShareManager::QPrivateSignal (0x0x7f91633dfba0) 0 empty + +Vtable for QNearFieldShareManager +QNearFieldShareManager::_ZTV22QNearFieldShareManager: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI22QNearFieldShareManager) +16 (int (*)(...))QNearFieldShareManager::metaObject +24 (int (*)(...))QNearFieldShareManager::qt_metacast +32 (int (*)(...))QNearFieldShareManager::qt_metacall +40 (int (*)(...))QNearFieldShareManager::~QNearFieldShareManager +48 (int (*)(...))QNearFieldShareManager::~QNearFieldShareManager +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 QNearFieldShareManager + size=24 align=8 + base size=24 base align=8 +QNearFieldShareManager (0x0x7f9163035410) 0 + vptr=((& QNearFieldShareManager::_ZTV22QNearFieldShareManager) + 16u) + QObject (0x0x7f91633dfb40) 0 + primary-for QNearFieldShareManager (0x0x7f9163035410) + +Class QNearFieldShareTarget::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QNearFieldShareTarget::QPrivateSignal (0x0x7f91633dfea0) 0 empty + +Vtable for QNearFieldShareTarget +QNearFieldShareTarget::_ZTV21QNearFieldShareTarget: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI21QNearFieldShareTarget) +16 (int (*)(...))QNearFieldShareTarget::metaObject +24 (int (*)(...))QNearFieldShareTarget::qt_metacast +32 (int (*)(...))QNearFieldShareTarget::qt_metacall +40 (int (*)(...))QNearFieldShareTarget::~QNearFieldShareTarget +48 (int (*)(...))QNearFieldShareTarget::~QNearFieldShareTarget +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 QNearFieldShareTarget + size=24 align=8 + base size=24 base align=8 +QNearFieldShareTarget (0x0x7f9163035548) 0 + vptr=((& QNearFieldShareTarget::_ZTV21QNearFieldShareTarget) + 16u) + QObject (0x0x7f91633dfe40) 0 + primary-for QNearFieldShareTarget (0x0x7f9163035548) + +Class QQmlNdefRecord::QPrivateSignal + size=1 align=1 + base size=0 base align=1 +QQmlNdefRecord::QPrivateSignal (0x0x7f91633dff60) 0 empty + +Vtable for QQmlNdefRecord +QQmlNdefRecord::_ZTV14QQmlNdefRecord: 14u entries +0 (int (*)(...))0 +8 (int (*)(...))(& _ZTI14QQmlNdefRecord) +16 (int (*)(...))QQmlNdefRecord::metaObject +24 (int (*)(...))QQmlNdefRecord::qt_metacast +32 (int (*)(...))QQmlNdefRecord::qt_metacall +40 (int (*)(...))QQmlNdefRecord::~QQmlNdefRecord +48 (int (*)(...))QQmlNdefRecord::~QQmlNdefRecord +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 QQmlNdefRecord + size=24 align=8 + base size=24 base align=8 +QQmlNdefRecord (0x0x7f91630355b0) 0 + vptr=((& QQmlNdefRecord::_ZTV14QQmlNdefRecord) + 16u) + QObject (0x0x7f91633dff00) 0 + primary-for QQmlNdefRecord (0x0x7f91630355b0) + diff --git a/tests/auto/cmake/CMakeLists.txt b/tests/auto/cmake/CMakeLists.txt new file mode 100644 index 0000000..edb5105 --- /dev/null +++ b/tests/auto/cmake/CMakeLists.txt @@ -0,0 +1,48 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# This is an automatic test for the CMake configuration files. +# To run it manually, +# 1) mkdir build # Create a build directory +# 2) cd build +# 3) # Run cmake on this directory +# `$qt_prefix/bin/qt-cmake ..` or `cmake -DCMAKE_PREFIX_PATH=/path/to/qt ..` +# 4) ctest # Run ctest + +cmake_minimum_required(VERSION 3.16) +project(connectivity_cmake_tests) +enable_testing() + +set(required_packages Core Bluetooth Nfc) + +# Setup the test when called as a completely standalone project. +if(TARGET Qt6::Core) + # Tests are built as part of the repository's build tree. + # Setup paths so that the Qt packages are found. + qt_internal_set_up_build_dir_package_paths() +endif() + +find_package(Qt6 REQUIRED COMPONENTS ${required_packages}) + +# Setup common test variables which were previously set by ctest_testcase_common.prf. +set(CMAKE_MODULES_UNDER_TEST "${required_packages}") + +foreach(qt_package ${CMAKE_MODULES_UNDER_TEST}) + set(package_name "${QT_CMAKE_EXPORT_NAMESPACE}${qt_package}") + if(${package_name}_FOUND) + set(CMAKE_${qt_package}_MODULE_MAJOR_VERSION "${${package_name}_VERSION_MAJOR}") + set(CMAKE_${qt_package}_MODULE_MINOR_VERSION "${${package_name}_VERSION_MINOR}") + set(CMAKE_${qt_package}_MODULE_PATCH_VERSION "${${package_name}_VERSION_PATCH}") + endif() +endforeach() + +include("${_Qt6CTestMacros}") + +set(module_includes + Bluetooth QBluetoothAddress + Nfc QNdefRecord +) + +_qt_internal_test_module_includes( + ${module_includes} +) diff --git a/tests/auto/nfccommons/qnearfieldmanager_emulator.cpp b/tests/auto/nfccommons/qnearfieldmanager_emulator.cpp new file mode 100644 index 0000000..20e1f1f --- /dev/null +++ b/tests/auto/nfccommons/qnearfieldmanager_emulator.cpp @@ -0,0 +1,90 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "qnearfieldmanager_emulator_p.h" +#include "qnearfieldtarget_emulator_p.h" + +#include + +QT_BEGIN_NAMESPACE + +QNearFieldManagerPrivateImpl::QNearFieldManagerPrivateImpl() +{ + TagActivator *activator = TagActivator::instance(); + activator->initialize(); + + connect(activator, &TagActivator::tagActivated, this, &QNearFieldManagerPrivateImpl::tagActivated); + connect(activator, &TagActivator::tagDeactivated, this, &QNearFieldManagerPrivateImpl::tagDeactivated); +} + +QNearFieldManagerPrivateImpl::~QNearFieldManagerPrivateImpl() +{ +} + +bool QNearFieldManagerPrivateImpl::isEnabled() const +{ + return true; +} + +bool QNearFieldManagerPrivateImpl::isSupported(QNearFieldTarget::AccessMethod accessMethod) const +{ + return accessMethod == QNearFieldTarget::NdefAccess + || accessMethod == QNearFieldTarget::AnyAccess; +} + +bool QNearFieldManagerPrivateImpl::startTargetDetection(QNearFieldTarget::AccessMethod accessMethod) +{ + const bool supported = isSupported(accessMethod); + if (supported) + TagActivator::instance()->start(); + + return supported; +} + +void QNearFieldManagerPrivateImpl::stopTargetDetection(const QString &message) +{ + setUserInformation(message); + TagActivator::instance()->stop(); + emit targetDetectionStopped(); +} + +void QNearFieldManagerPrivateImpl::setUserInformation(const QString &message) +{ + emit userInformationChanged(message); +} + +void QNearFieldManagerPrivateImpl::reset() +{ + TagActivator::instance()->reset(); +} + +void QNearFieldManagerPrivateImpl::tagActivated(TagBase *tag) +{ + QNearFieldTargetPrivate *target = targets.value(tag).data(); + if (!target) { + if (dynamic_cast(tag)) + target = new TagType1(tag, this); + else if (dynamic_cast(tag)) + target = new TagType2(tag, this); + else + qFatal("Unknown emulator tag type"); + + targets.insert(tag, target); + } + + Q_EMIT targetDetected(new QNearFieldTarget(target, this)); +} + +void QNearFieldManagerPrivateImpl::tagDeactivated(TagBase *tag) +{ + QNearFieldTargetPrivate *target = targets.value(tag).data(); + if (!target) { + targets.remove(tag); + return; + } + + Q_EMIT targetLost(target->q_ptr); + QMetaObject::invokeMethod(target->q_ptr, &QNearFieldTarget::disconnected); +} + +QT_END_NAMESPACE diff --git a/tests/auto/nfccommons/qnearfieldmanager_emulator_p.h b/tests/auto/nfccommons/qnearfieldmanager_emulator_p.h new file mode 100644 index 0000000..b731694 --- /dev/null +++ b/tests/auto/nfccommons/qnearfieldmanager_emulator_p.h @@ -0,0 +1,61 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef QNEARFIELDMANAGER_EMULATOR_H +#define QNEARFIELDMANAGER_EMULATOR_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 + +QT_BEGIN_NAMESPACE + +class TagBase; +class QNearFieldManagerPrivateImpl : public QNearFieldManagerPrivate +{ + Q_OBJECT + +public: + QNearFieldManagerPrivateImpl(); + ~QNearFieldManagerPrivateImpl() override; + + bool isEnabled() const override; + + bool isSupported(QNearFieldTarget::AccessMethod accessMethod) const override; + + bool startTargetDetection(QNearFieldTarget::AccessMethod accessMethod) override; + void stopTargetDetection(const QString &message) override; + void setUserInformation(const QString &message) override; + + void reset(); + +signals: + void userInformationChanged(const QString &message); + +private slots: + void tagActivated(TagBase *tag); + void tagDeactivated(TagBase *tag); + +private: + QMap > targets; + +}; + +QT_END_NAMESPACE + +#endif // QNEARFIELDMANAGER_EMULATOR_H diff --git a/tests/auto/nfccommons/qnearfieldtagtype1.cpp b/tests/auto/nfccommons/qnearfieldtagtype1.cpp new file mode 100644 index 0000000..cad1c1e --- /dev/null +++ b/tests/auto/nfccommons/qnearfieldtagtype1.cpp @@ -0,0 +1,697 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "qnearfieldtagtype1_p.h" +#include "qtlv_p.h" + +#include +#include + +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +/*! + \class QNearFieldTagType1 + \brief The QNearFieldTagType1 class provides an interface for communicating with an NFC Tag + Type 1 tag. + + \ingroup connectivity-nfc + \inmodule QtNfc + \internal +*/ + +/*! + \enum QNearFieldTagType1::WriteMode + \brief This enum describes the write modes that are supported. + + \value EraseAndWrite The memory is erased before the new value is written. + \value WriteOnly The memory is not erased before the new value is written. The effect of + this mode is that the final value store is the bitwise or of the data + to be written and the original data value. +*/ + +/*! + \fn Type QNearFieldTagType1::type() const + \reimp +*/ + +class QNearFieldTagType1Private +{ + Q_DECLARE_PUBLIC(QNearFieldTagType1) + +public: + QNearFieldTagType1Private(QNearFieldTagType1 *q) + : q_ptr(q), m_readNdefMessageState(NotReadingNdefMessage), + m_tlvReader(nullptr), + m_writeNdefMessageState(NotWritingNdefMessage), + m_tlvWriter(nullptr) + { } + + QNearFieldTagType1 *q_ptr; + + QMap m_pendingInternalCommands; + + enum ReadNdefMessageState { + NotReadingNdefMessage, + NdefReadCheckingIdentification, + NdefReadCheckingNdefMagicNumber, + NdefReadReadingTlv + }; + + void progressToNextNdefReadMessageState(); + ReadNdefMessageState m_readNdefMessageState; + QNearFieldTarget::RequestId m_readNdefRequestId; + + QTlvReader *m_tlvReader; + QNearFieldTarget::RequestId m_nextExpectedRequestId; + + enum WriteNdefMessageState { + NotWritingNdefMessage, + NdefWriteCheckingIdentification, + NdefWriteCheckingNdefMagicNumber, + NdefWriteReadingTlv, + NdefWriteWritingTlv, + NdefWriteWritingTlvFlush + }; + + void progressToNextNdefWriteMessageState(); + WriteNdefMessageState m_writeNdefMessageState; + QNearFieldTarget::RequestId m_writeNdefRequestId; + QList m_ndefWriteMessages; + + QTlvWriter *m_tlvWriter; + + typedef QPair Tlv; + QList m_tlvs; +}; + +void QNearFieldTagType1Private::progressToNextNdefReadMessageState() +{ + Q_Q(QNearFieldTagType1); + + switch (m_readNdefMessageState) { + case NotReadingNdefMessage: + m_readNdefMessageState = NdefReadCheckingIdentification; + m_nextExpectedRequestId = q->readIdentification(); + break; + case NdefReadCheckingIdentification: { + const QByteArray data = q->requestResponse(m_nextExpectedRequestId).toByteArray(); + + if (data.isEmpty()) { + m_readNdefMessageState = NotReadingNdefMessage; + m_nextExpectedRequestId = QNearFieldTarget::RequestId(); + Q_EMIT q->error(QNearFieldTarget::NdefReadError, m_readNdefRequestId); + m_readNdefRequestId = QNearFieldTarget::RequestId(); + break; + } + + quint8 hr0 = data.at(0); + + // Check if target is a NFC TagType1 tag + if (!(hr0 & 0x10)) { + m_readNdefMessageState = NotReadingNdefMessage; + m_nextExpectedRequestId = QNearFieldTarget::RequestId(); + Q_EMIT q->error(QNearFieldTarget::NdefReadError, m_readNdefRequestId); + m_readNdefRequestId = QNearFieldTarget::RequestId(); + break; + } + + m_readNdefMessageState = NdefReadCheckingNdefMagicNumber; + m_nextExpectedRequestId = q->readByte(8); + break; + } + case NdefReadCheckingNdefMagicNumber: { + quint8 ndefMagicNumber = q->requestResponse(m_nextExpectedRequestId).toUInt(); + m_nextExpectedRequestId = QNearFieldTarget::RequestId(); + + if (ndefMagicNumber != 0xe1) { + m_readNdefMessageState = NotReadingNdefMessage; + Q_EMIT q->error(QNearFieldTarget::NdefReadError, m_readNdefRequestId); + m_readNdefRequestId = QNearFieldTarget::RequestId(); + break; + } + + m_readNdefMessageState = NdefReadReadingTlv; + delete m_tlvReader; + m_tlvReader = new QTlvReader(q); + + Q_FALLTHROUGH(); // fall through + } + case NdefReadReadingTlv: + Q_ASSERT(m_tlvReader); + while (!m_tlvReader->atEnd()) { + if (!m_tlvReader->readNext()) + break; + + // NDEF Message TLV + if (m_tlvReader->tag() == 0x03) { + Q_Q(QNearFieldTagType1); + + Q_EMIT q->ndefMessageRead(QNdefMessage::fromByteArray(m_tlvReader->data())); + } + } + + m_nextExpectedRequestId = m_tlvReader->requestId(); + if (!m_nextExpectedRequestId.isValid()) { + delete m_tlvReader; + m_tlvReader = nullptr; + m_readNdefMessageState = NotReadingNdefMessage; + Q_EMIT q->requestCompleted(m_readNdefRequestId); + m_readNdefRequestId = QNearFieldTarget::RequestId(); + } + break; + } +} + +void QNearFieldTagType1Private::progressToNextNdefWriteMessageState() +{ + Q_Q(QNearFieldTagType1); + + switch (m_writeNdefMessageState) { + case NotWritingNdefMessage: + m_writeNdefMessageState = NdefWriteCheckingIdentification; + m_nextExpectedRequestId = q->readIdentification(); + break; + case NdefWriteCheckingIdentification: { + const QByteArray data = q->requestResponse(m_nextExpectedRequestId).toByteArray(); + + if (data.isEmpty()) { + m_writeNdefMessageState = NotWritingNdefMessage; + m_nextExpectedRequestId = QNearFieldTarget::RequestId(); + Q_EMIT q->error(QNearFieldTarget::NdefWriteError, m_writeNdefRequestId); + m_writeNdefRequestId = QNearFieldTarget::RequestId(); + break; + } + + quint8 hr0 = data.at(0); + + // Check if target is a NFC TagType1 tag + if (!(hr0 & 0x10)) { + m_writeNdefMessageState = NotWritingNdefMessage; + m_nextExpectedRequestId = QNearFieldTarget::RequestId(); + Q_EMIT q->error(QNearFieldTarget::NdefWriteError, m_writeNdefRequestId); + m_writeNdefRequestId = QNearFieldTarget::RequestId(); + break; + } + + m_writeNdefMessageState = NdefWriteCheckingNdefMagicNumber; + m_nextExpectedRequestId = q->readByte(8); + break; + } + case NdefWriteCheckingNdefMagicNumber: { + quint8 ndefMagicNumber = q->requestResponse(m_nextExpectedRequestId).toUInt(); + m_nextExpectedRequestId = QNearFieldTarget::RequestId(); + + if (ndefMagicNumber != 0xe1) { + m_writeNdefMessageState = NotWritingNdefMessage; + Q_EMIT q->error(QNearFieldTarget::NdefWriteError, m_writeNdefRequestId); + m_writeNdefRequestId = QNearFieldTarget::RequestId(); + break; + } + + m_writeNdefMessageState = NdefWriteReadingTlv; + delete m_tlvReader; + m_tlvReader = new QTlvReader(q); + + Q_FALLTHROUGH(); // fall through + } + case NdefWriteReadingTlv: + Q_ASSERT(m_tlvReader); + while (!m_tlvReader->atEnd()) { + if (!m_tlvReader->readNext()) + break; + + quint8 tag = m_tlvReader->tag(); + if (tag == 0x01 || tag == 0x02 || tag == 0xfd) + m_tlvs.append(qMakePair(tag, m_tlvReader->data())); + } + + m_nextExpectedRequestId = m_tlvReader->requestId(); + if (m_nextExpectedRequestId.isValid()) + break; + + delete m_tlvReader; + m_tlvReader = nullptr; + m_writeNdefMessageState = NdefWriteWritingTlv; + + // fall through + case NdefWriteWritingTlv: + delete m_tlvWriter; + m_tlvWriter = new QTlvWriter(q); + + // write old TLVs + for (const Tlv &tlv : std::as_const(m_tlvs)) + m_tlvWriter->writeTlv(tlv.first, tlv.second); + + // write new NDEF message TLVs + for (const QNdefMessage &message : std::as_const(m_ndefWriteMessages)) + m_tlvWriter->writeTlv(0x03, message.toByteArray()); + + // write terminator TLV + m_tlvWriter->writeTlv(0xfe); + + m_writeNdefMessageState = NdefWriteWritingTlvFlush; + + // fall through + case NdefWriteWritingTlvFlush: + // flush the writer + Q_ASSERT(m_tlvWriter); + if (m_tlvWriter->process(true)) { + m_nextExpectedRequestId = QNearFieldTarget::RequestId(); + m_writeNdefMessageState = NotWritingNdefMessage; + delete m_tlvWriter; + m_tlvWriter = nullptr; + Q_EMIT q->requestCompleted(m_writeNdefRequestId); + m_writeNdefRequestId = QNearFieldTarget::RequestId(); + } else { + m_nextExpectedRequestId = m_tlvWriter->requestId(); + if (!m_nextExpectedRequestId.isValid()) { + m_writeNdefMessageState = NotWritingNdefMessage; + delete m_tlvWriter; + m_tlvWriter = nullptr; + Q_EMIT q->error(QNearFieldTarget::NdefWriteError, m_writeNdefRequestId); + m_writeNdefRequestId = QNearFieldTarget::RequestId(); + } + } + break; + } +} + +static QVariant decodeResponse(const QByteArray &command, const QByteArray &response) +{ + switch (command.at(0)) { + case 0x01: // READ + if (command.at(1) == response.at(0)) + return quint8(response.at(1)); + break; + case 0x53: { // WRITE-E + quint8 address = command.at(1); + quint8 data = command.at(2); + quint8 writeAddress = response.at(0); + quint8 writeData = response.at(1); + + return ((writeAddress == address) && (writeData == data)); + } + case 0x1a: { // WRITE-NE + quint8 address = command.at(1); + quint8 data = command.at(2); + quint8 writeAddress = response.at(0); + quint8 writeData = response.at(1); + + return ((writeAddress == address) && ((writeData & data) == data)); + } + case 0x10: { // RSEG + quint8 segmentAddress = quint8(command.at(1)) >> 4; + quint8 readSegmentAddress = quint8(response.at(0)) >> 4; + if (readSegmentAddress == segmentAddress) + return response.mid(1); + break; + } + case 0x02: { // READ8 + quint8 blockAddress = command.at(1); + quint8 readBlockAddress = response.at(0); + if (readBlockAddress == blockAddress) + return response.mid(1); + break; + } + case 0x54: { // WRITE-E8 + quint8 blockAddress = command.at(1); + QByteArray data = command.mid(2, 8); + quint8 writeBlockAddress = response.at(0); + QByteArray writeData = response.mid(1); + + return ((writeBlockAddress == blockAddress) && (writeData == data)); + } + case 0x1b: { // WRITE-NE8 + quint8 blockAddress = command.at(1); + QByteArray data = command.mid(2, 8); + quint8 writeBlockAddress = response.at(0); + QByteArray writeData = response.mid(1); + + if (writeBlockAddress != blockAddress) + return false; + + for (int i = 0; i < writeData.size(); ++i) { + if ((writeData.at(i) & data.at(i)) != data.at(i)) + return false; + } + + return true; + } + } + + return QVariant(); +} + +/*! + Constructs a new tag type 1 near field target with \a parent. +*/ +QNearFieldTagType1::QNearFieldTagType1(QObject *parent) +: QNearFieldTargetPrivate(parent), d_ptr(new QNearFieldTagType1Private(this)) +{ +} + +/*! + Destroys the tag type 1 near field target. +*/ +QNearFieldTagType1::~QNearFieldTagType1() +{ + delete d_ptr; +} + +/*! + \reimp +*/ +bool QNearFieldTagType1::hasNdefMessage() +{ + QNearFieldTarget::RequestId id = readAll(); + if (!waitForRequestCompleted(id)) + return false; + + const QByteArray data = requestResponse(id).toByteArray(); + + if (data.isEmpty()) + return false; + + quint8 hr0 = data.at(0); + + // Check if target is a NFC TagType1 tag + if (!(hr0 & 0x10)) + return false; + + // Check if NDEF Message Magic number is present + quint8 nmn = data.at(10); + if (nmn != 0xe1) + return false; + + // Check if TLV contains NDEF Message + return true; +} + +/*! + \reimp +*/ +QNearFieldTarget::RequestId QNearFieldTagType1::readNdefMessages() +{ + Q_D(QNearFieldTagType1); + + d->m_readNdefRequestId = QNearFieldTarget::RequestId(new QNearFieldTarget::RequestIdPrivate); + + if (d->m_readNdefMessageState == QNearFieldTagType1Private::NotReadingNdefMessage) { + d->progressToNextNdefReadMessageState(); + } else { + reportError(QNearFieldTarget::NdefReadError, d->m_readNdefRequestId); + } + + return d->m_readNdefRequestId; +} + +/*! + \reimp +*/ +QNearFieldTarget::RequestId QNearFieldTagType1::writeNdefMessages(const QList &messages) +{ + Q_D(QNearFieldTagType1); + + d->m_writeNdefRequestId = QNearFieldTarget::RequestId(new QNearFieldTarget::RequestIdPrivate); + + if (d->m_readNdefMessageState == QNearFieldTagType1Private::NotReadingNdefMessage && + d->m_writeNdefMessageState == QNearFieldTagType1Private::NotWritingNdefMessage) { + d->m_ndefWriteMessages = messages; + d->progressToNextNdefWriteMessageState(); + } else { + reportError(QNearFieldTarget::NdefWriteError, d->m_readNdefRequestId); + } + + return d->m_writeNdefRequestId; +} + +/*! + Returns the NFC Tag Type 1 specification version number that the tag supports. +*/ +quint8 QNearFieldTagType1::version() +{ + QNearFieldTarget::RequestId id = readByte(9); + if (!waitForRequestCompleted(id)) + return 0; + + quint8 versionNumber = requestResponse(id).toUInt(); + return versionNumber; +} + +/*! + Returns the memory size in bytes of the tag. +*/ +int QNearFieldTagType1::memorySize() +{ + QNearFieldTarget::RequestId id = readByte(10); + if (!waitForRequestCompleted(id)) + return 0; + + quint8 tms = requestResponse(id).toUInt(); + + return 8 * (tms + 1); +} + +/*! + Requests the identification bytes from the target. Returns a request id which can be used to + track the completion status of the request. + + Once the request completes successfully the response can be retrieved from the + requestResponse() function. The response of this request will be a QByteArray containing: HR0, + HR1, UID0, UID1, UID2 and UID3 in order. + + \sa requestCompleted(), waitForRequestCompleted() +*/ +QNearFieldTarget::RequestId QNearFieldTagType1::readIdentification() +{ + QByteArray command; + command.append(char(0x78)); // RID + command.append(char(0x00)); // Address (unused) + command.append(char(0x00)); // Data (unused) + command.append(uid().left(4)); // 4 bytes of UID + + return sendCommand(command); +} + +/*! + Requests all data in the static memory area of the target. Returns a request id which can be + used to track the completion status of the request. + + Once the request completes successfully the response can be retrieved from the + requestResponse() function. The response of this request will be a QByteArray containing: HR0 + and HR1 followed by the 120 bytes of data stored in the static memory area of the target. + + \sa requestCompleted(), waitForRequestCompleted() +*/ +QNearFieldTarget::RequestId QNearFieldTagType1::readAll() +{ + QByteArray command; + command.append(char(0x00)); // RALL + command.append(char(0x00)); // Address (unused) + command.append(char(0x00)); // Data (unused) + command.append(uid().left(4));// 4 bytes of UID + + return sendCommand(command); +} + +/*! + Requests a single byte from the static memory area of the tag. The \a address parameter + specifices the linear byte address to read. Returns a request id which can be used to track + the completion status of the request. + + Once the request completes successfully the response can be retrieved from the + requestResponse() function. The response of this request will be a quint8. + + \sa requestCompleted(), waitForRequestCompleted() +*/ +QNearFieldTarget::RequestId QNearFieldTagType1::readByte(quint8 address) +{ + if (address & 0x80) + return QNearFieldTarget::RequestId(); + + QByteArray command; + command.append(char(0x01)); // READ + command.append(char(address)); // Address + command.append(char(0x00)); // Data (unused) + command.append(uid().left(4)); // 4 bytes of UID + + QNearFieldTarget::RequestId id = sendCommand(command); + + Q_D(QNearFieldTagType1); + + d->m_pendingInternalCommands.insert(id, command); + + return id; +} + +/*! + Writes a single \a data byte to the linear byte \a address on the tag. If \a mode is + EraseAndWrite the byte will be erased before writing. If \a mode is WriteOnly the contents will + not be erased before writing. This is equivelant to writing the result of the bitwise OR of + \a data and the original value. + + Returns a request id which can be used to track the completion status of the request. + + Once the request completes the response can be retrieved from the requestResponse() function. + The response of this request will be a boolean value, true for success; otherwise false. + + \sa requestCompleted(), waitForRequestCompleted() +*/ +QNearFieldTarget::RequestId QNearFieldTagType1::writeByte(quint8 address, quint8 data, + WriteMode mode) +{ + if (address & 0x80) + return QNearFieldTarget::RequestId(); + + QByteArray command; + + if (mode == EraseAndWrite) + command.append(char(0x53)); // WRITE-E + else if (mode == WriteOnly) + command.append(char(0x1a)); // WRITE-NE + else + return QNearFieldTarget::RequestId(); + + command.append(char(address)); // Address + command.append(char(data)); // Data + command.append(uid().left(4)); // 4 bytes of UID + + QNearFieldTarget::RequestId id = sendCommand(command); + + Q_D(QNearFieldTagType1); + + d->m_pendingInternalCommands.insert(id, command); + + return id; +} + +/*! + Requests 128 bytes of data from the segment specified by \a segmentAddress. Returns a request + id which can be used to track the completion status of the request. + + Once the request completes successfully the response can be retrieved from the + requestResponse() function. The response of this request will be a QByteArray. + + \sa requestCompleted(), waitForRequestCompleted() +*/ +QNearFieldTarget::RequestId QNearFieldTagType1::readSegment(quint8 segmentAddress) +{ + if (segmentAddress & 0xf0) + return QNearFieldTarget::RequestId(); + + QByteArray command; + command.append(char(0x10)); // RSEG + command.append(char(segmentAddress << 4)); // Segment address + command.append(QByteArray(8, char(0x00))); // Data (unused) + command.append(uid().left(4)); // 4 bytes of UID + + QNearFieldTarget::RequestId id = sendCommand(command); + + Q_D(QNearFieldTagType1); + + d->m_pendingInternalCommands.insert(id, command); + + return id; +} + +/*! + Requests 8 bytes of data from the block specified by \a blockAddress. Returns a request id + which can be used to track the completion status of the request. + + Once the request completes successfully the response can be retrieved from the + requestResponse() function. The response of this request will be a QByteArray. + + \sa requestCompleted(), waitForRequestCompleted() +*/ +QNearFieldTarget::RequestId QNearFieldTagType1::readBlock(quint8 blockAddress) +{ + QByteArray command; + command.append(char(0x02)); // READ8 + command.append(char(blockAddress)); // Block address + command.append(QByteArray(8, char(0x00))); // Data (unused) + command.append(uid().left(4)); // 4 bytes of UID + + QNearFieldTarget::RequestId id = sendCommand(command); + + Q_D(QNearFieldTagType1); + + d->m_pendingInternalCommands.insert(id, command); + + return id; +} + +/*! + Writes 8 bytes of \a data to the block specified by \a blockAddress. If \a mode is + EraseAndWrite the bytes will be erased before writing. If \a mode is WriteOnly the contents + will not be erased before writing. This is equivelant to writing the result of the bitwise OR + of \a data and the original value. + + Returns a request id which can be used to track the completion status of the request. + + Once the request completes the response can be retrieved from the requestResponse() function. + The response of this request will be a boolean value, true for success; otherwise false. + + \sa requestCompleted(), waitForRequestCompleted() +*/ +QNearFieldTarget::RequestId QNearFieldTagType1::writeBlock(quint8 blockAddress, + const QByteArray &data, + WriteMode mode) +{ + if (data.size() != 8) + return QNearFieldTarget::RequestId(); + + QByteArray command; + + if (mode == EraseAndWrite) + command.append(char(0x54)); // WRITE-E8 + else if (mode == WriteOnly) + command.append(char(0x1b)); // WRITE-NE8 + else + return QNearFieldTarget::RequestId(); + + command.append(char(blockAddress)); // Block address + command.append(data); // Data + command.append(uid().left(4)); // 4 bytes of UID + + QNearFieldTarget::RequestId id = sendCommand(command); + + Q_D(QNearFieldTagType1); + + d->m_pendingInternalCommands.insert(id, command); + + return id; +} + +/*! + \reimp +*/ +void QNearFieldTagType1::setResponseForRequest(const QNearFieldTarget::RequestId &id, + const QVariant &response, + bool emitRequestCompleted) +{ + Q_D(QNearFieldTagType1); + + if (d->m_pendingInternalCommands.contains(id)) { + const QByteArray command = d->m_pendingInternalCommands.take(id); + + QVariant decodedResponse = decodeResponse(command, response.toByteArray()); + QNearFieldTargetPrivate::setResponseForRequest(id, decodedResponse, emitRequestCompleted); + } else { + QNearFieldTargetPrivate::setResponseForRequest(id, response, emitRequestCompleted); + } + + // continue reading / writing NDEF message + if (d->m_nextExpectedRequestId == id) { + if (d->m_readNdefMessageState != QNearFieldTagType1Private::NotReadingNdefMessage) + d->progressToNextNdefReadMessageState(); + else if (d->m_writeNdefMessageState != QNearFieldTagType1Private::NotWritingNdefMessage) + d->progressToNextNdefWriteMessageState(); + } +} + +QT_END_NAMESPACE diff --git a/tests/auto/nfccommons/qnearfieldtagtype1_p.h b/tests/auto/nfccommons/qnearfieldtagtype1_p.h new file mode 100644 index 0000000..69e37c8 --- /dev/null +++ b/tests/auto/nfccommons/qnearfieldtagtype1_p.h @@ -0,0 +1,72 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef QNEARFIELDTAGTYPE1_H +#define QNEARFIELDTAGTYPE1_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 QNearFieldTagType1Private; + +class QNearFieldTagType1 : public QNearFieldTargetPrivate +{ + Q_OBJECT + + Q_DECLARE_PRIVATE(QNearFieldTagType1) + +public: + enum WriteMode { + EraseAndWrite, + WriteOnly + }; + Q_ENUM(WriteMode) + + explicit QNearFieldTagType1(QObject *parent = nullptr); + ~QNearFieldTagType1(); + + QNearFieldTarget::Type type() const override { return QNearFieldTarget::NfcTagType1; } + + bool hasNdefMessage() override; + QNearFieldTarget::RequestId readNdefMessages() override; + QNearFieldTarget::RequestId writeNdefMessages(const QList &messages) override; + + quint8 version(); + virtual int memorySize(); + + // DIGPROTO + virtual QNearFieldTarget::RequestId readIdentification(); + + // static memory functions + virtual QNearFieldTarget::RequestId readAll(); + virtual QNearFieldTarget::RequestId readByte(quint8 address); + virtual QNearFieldTarget::RequestId writeByte(quint8 address, quint8 data, WriteMode mode = EraseAndWrite); + + // dynamic memory functions + virtual QNearFieldTarget::RequestId readSegment(quint8 segmentAddress); + virtual QNearFieldTarget::RequestId readBlock(quint8 blockAddress); + virtual QNearFieldTarget::RequestId writeBlock(quint8 blockAddress, const QByteArray &data, + WriteMode mode = EraseAndWrite); + +protected: + void setResponseForRequest(const QNearFieldTarget::RequestId &id, const QVariant &response, bool emitRequestCompleted = true) override; + +private: + QNearFieldTagType1Private *d_ptr; +}; + +QT_END_NAMESPACE + +#endif // QNEARFIELDTAGTYPE1_H diff --git a/tests/auto/nfccommons/qnearfieldtagtype2.cpp b/tests/auto/nfccommons/qnearfieldtagtype2.cpp new file mode 100644 index 0000000..fc41690 --- /dev/null +++ b/tests/auto/nfccommons/qnearfieldtagtype2.cpp @@ -0,0 +1,292 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "qnearfieldtagtype2_p.h" +#include + +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +/*! + \class QNearFieldTagType2 + \brief The QNearFieldTagType2 class provides an interface for communicating with an NFC Tag + Type 2 tag. + + \ingroup connectivity-nfc + \inmodule QtNfc + \internal +*/ + +/*! + \fn Type QNearFieldTagType2::type() const + \reimp +*/ + +struct SectorSelectState { + int timerId; // id of timer used for passive ack + quint8 sector; // sector being selected +}; + +class QNearFieldTagType2Private +{ +public: + QNearFieldTagType2Private() : m_currentSector(0) { } + + QMap m_pendingInternalCommands; + + quint8 m_currentSector; + + QMap m_pendingSectorSelectCommands; +}; + +static QVariant decodeResponse(const QByteArray &command, const QByteArray &response) +{ + quint8 opcode = command.at(0); + + switch (opcode) { + case 0xa2: // WRITE + return quint8(response.at(0)) == 0x0a; + case 0xc2: // SECTOR SELECT (Command Packet 1) + return quint8(response.at(0)) == 0x0a; + } + + return QVariant(); +} + +/*! + Constructs a new tag type 2 near field target with \a parent. +*/ +QNearFieldTagType2::QNearFieldTagType2(QObject *parent) +: QNearFieldTargetPrivate(parent), d_ptr(new QNearFieldTagType2Private) +{ +} + +/*! + Destroys the tag type 2 near field target. +*/ +QNearFieldTagType2::~QNearFieldTagType2() +{ + delete d_ptr; +} + +/*! + \reimp +*/ +bool QNearFieldTagType2::hasNdefMessage() +{ + qWarning() << Q_FUNC_INFO << "is unimplemeted"; + return false; +} + +/*! + \reimp +*/ +QNearFieldTarget::RequestId QNearFieldTagType2::readNdefMessages() +{ + return QNearFieldTarget::RequestId(); +} + +/*! + \reimp +*/ +QNearFieldTarget::RequestId QNearFieldTagType2::writeNdefMessages(const QList &messages) +{ + Q_UNUSED(messages); + + return QNearFieldTarget::RequestId(); +} + +/*! + Returns the NFC Tag Type 2 specification version number that the tag supports. +*/ +quint8 QNearFieldTagType2::version() +{ + Q_D(QNearFieldTagType2); + if (d->m_currentSector != 0) { + QNearFieldTarget::RequestId id = selectSector(0); + if (!waitForRequestCompleted(id)) + return 0; + } + + QNearFieldTarget::RequestId id = readBlock(0); + if (!waitForRequestCompleted(id)) + return 0; + + const QByteArray data = requestResponse(id).toByteArray(); + return data.at(13); +} + +/*! + Returns the memory size in bytes of the tag. +*/ +int QNearFieldTagType2::memorySize() +{ + Q_D(QNearFieldTagType2); + if (d->m_currentSector != 0) { + QNearFieldTarget::RequestId id = selectSector(0); + if (!waitForRequestCompleted(id)) + return 0; + } + + QNearFieldTarget::RequestId id = readBlock(0); + if (!waitForRequestCompleted(id)) + return 0; + + const QByteArray data = requestResponse(id).toByteArray(); + return 8 * quint8(data.at(14)); +} + +/*! + Requests 16 bytes of data starting at \a blockAddress. Returns a request id which can be used + to track the completion status of the request. + + Once the request completes successfully the response can be retrieved from the + requestResponse() function. The response of this request will be a QByteArray. + + \sa requestCompleted(), waitForRequestCompleted() +*/ +QNearFieldTarget::RequestId QNearFieldTagType2::readBlock(quint8 blockAddress) +{ + QByteArray command; + command.append(char(0x30)); // READ + command.append(char(blockAddress)); // Block address + + return sendCommand(command); +} + +/*! + Writes 4 bytes of \a data to the block at \a blockAddress. Returns a request id which can be + used to track the completion status of the request. + + Once the request completes the response can be retrieved from the requestResponse() function. + The response of this request will be a boolean value, true for success; otherwise false. + + Returns true on success; otherwise returns false. +*/ +QNearFieldTarget::RequestId QNearFieldTagType2::writeBlock(quint8 blockAddress, + const QByteArray &data) +{ + if (data.size() != 4) + return QNearFieldTarget::RequestId(); + + QByteArray command; + command.append(char(0xa2)); // WRITE + command.append(char(blockAddress)); // Block address + command.append(data); // Data + + QNearFieldTarget::RequestId id = sendCommand(command); + + Q_D(QNearFieldTagType2); + + d->m_pendingInternalCommands.insert(id, command); + + return id; +} + +/*! + Selects the \a sector upon which subsequent readBlock() and writeBlock() operations will act. + + Returns a request id which can be used to track the completion status of the request. + + Once the request completes the response can be retrieved from the requestResponse() function. + The response of this request will be a boolean value, true for success; otherwise false. + + \note this request has a passive acknowledgement mechanism. The operation is deemed successful + if no response is received within 1ms. It will therefore take a minimum of 1 millisecond for + the requestCompleted() signal to be emitted and calling waitForRequestCompleted() on the + returned request id may cause the current thread to block for up to 1 millisecond. +*/ +QNearFieldTarget::RequestId QNearFieldTagType2::selectSector(quint8 sector) +{ + QByteArray command; + command.append(char(0xc2)); // SECTOR SELECT (Command Packet 1) + command.append(char(0xff)); + + QNearFieldTarget::RequestId id = sendCommand(command); + + Q_D(QNearFieldTagType2); + + d->m_pendingInternalCommands.insert(id, command); + + SectorSelectState state; + state.timerId = -1; + state.sector = sector; + + d->m_pendingSectorSelectCommands.insert(id, state); + + return id; +} + +/*! + \reimp +*/ +void QNearFieldTagType2::setResponseForRequest(const QNearFieldTarget::RequestId &id, + const QVariant &response, + bool emitRequestCompleted) +{ + Q_D(QNearFieldTagType2); + + if (d->m_pendingInternalCommands.contains(id)) { + const QByteArray command = d->m_pendingInternalCommands.take(id); + + QVariant decodedResponse = decodeResponse(command, response.toByteArray()); + if (quint8(command.at(0)) == 0xc2 && decodedResponse.toBool()) { + // SECTOR SELECT (Command Packet 2) + SectorSelectState &state = d->m_pendingSectorSelectCommands[id]; + + QByteArray packet2; + packet2.append(char(state.sector)); + packet2.append(QByteArray(3, 0x00)); + + sendCommand(packet2); + + state.timerId = startTimer(1); + } else { + QNearFieldTargetPrivate::setResponseForRequest(id, decodedResponse, emitRequestCompleted); + } + + return; + } + + if (d->m_pendingSectorSelectCommands.contains(id)) { + if (!response.toByteArray().isEmpty()) { + d->m_pendingSectorSelectCommands.remove(id); + QNearFieldTargetPrivate::setResponseForRequest(id, false, emitRequestCompleted); + + return; + } + } + + QNearFieldTargetPrivate::setResponseForRequest(id, response, emitRequestCompleted); +} + +/*! + \internal +*/ +void QNearFieldTagType2::timerEvent(QTimerEvent *event) +{ + Q_D(QNearFieldTagType2); + + killTimer(event->timerId()); + + for (auto i = d->m_pendingSectorSelectCommands.begin(), end = d->m_pendingSectorSelectCommands.end(); i != end; ++i) { + + SectorSelectState &state = i.value(); + + if (state.timerId == event->timerId()) { + d->m_currentSector = state.sector; + + QNearFieldTargetPrivate::setResponseForRequest(i.key(), true); + + d->m_pendingSectorSelectCommands.erase(i); + break; + } + } +} + +QT_END_NAMESPACE diff --git a/tests/auto/nfccommons/qnearfieldtagtype2_p.h b/tests/auto/nfccommons/qnearfieldtagtype2_p.h new file mode 100644 index 0000000..65b9b7d --- /dev/null +++ b/tests/auto/nfccommons/qnearfieldtagtype2_p.h @@ -0,0 +1,58 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef QNEARFIELDTAGTYPE2_H +#define QNEARFIELDTAGTYPE2_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 QNearFieldTagType2Private; + +class QNearFieldTagType2 : public QNearFieldTargetPrivate +{ + Q_OBJECT + + Q_DECLARE_PRIVATE(QNearFieldTagType2) + +public: + explicit QNearFieldTagType2(QObject *parent = nullptr); + ~QNearFieldTagType2(); + + QNearFieldTarget::Type type() const override { return QNearFieldTarget::NfcTagType2; } + + bool hasNdefMessage() override; + QNearFieldTarget::RequestId readNdefMessages() override; + QNearFieldTarget::RequestId writeNdefMessages(const QList &messages) override; + + quint8 version(); + int memorySize(); + + virtual QNearFieldTarget::RequestId readBlock(quint8 blockAddress); + virtual QNearFieldTarget::RequestId writeBlock(quint8 blockAddress, const QByteArray &data); + virtual QNearFieldTarget::RequestId selectSector(quint8 sector); + + void timerEvent(QTimerEvent *event) override; + +protected: + void setResponseForRequest(const QNearFieldTarget::RequestId &id, const QVariant &response, bool emitRequestCompleted = true) override; + +private: + QNearFieldTagType2Private *d_ptr; +}; + +QT_END_NAMESPACE + +#endif // QNEARFIELDTAGTYPE2_H diff --git a/tests/auto/nfccommons/qnearfieldtarget_emulator.cpp b/tests/auto/nfccommons/qnearfieldtarget_emulator.cpp new file mode 100644 index 0000000..776ba6f --- /dev/null +++ b/tests/auto/nfccommons/qnearfieldtarget_emulator.cpp @@ -0,0 +1,279 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "qnearfieldtarget_emulator_p.h" +#include + +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +static QMutex tagMutex; +static QMap tagMap; + +Q_GLOBAL_STATIC(TagActivator, globalTagActivator) + +TagType1::TagType1(TagBase *tag, QObject *parent) +: QNearFieldTagType1(parent), tag(tag) +{ +} + +TagType1::~TagType1() +{ +} + +QByteArray TagType1::uid() const +{ + QMutexLocker locker(&tagMutex); + + return tag->uid(); +} + +QNearFieldTarget::AccessMethods TagType1::accessMethods() const +{ + return QNearFieldTarget::NdefAccess | QNearFieldTarget::TagTypeSpecificAccess; +} + +QNearFieldTarget::RequestId TagType1::sendCommand(const QByteArray &command) +{ + QMutexLocker locker(&tagMutex); + + QNearFieldTarget::RequestId id(new QNearFieldTarget::RequestIdPrivate); + + // tag not in proximity + if (!tagMap.value(tag)) { + reportError(QNearFieldTarget::TargetOutOfRangeError, id); + return id; + } + + quint16 crc = qChecksum(QByteArrayView(command.constData(), command.size()), Qt::ChecksumItuV41); + + QByteArray response = tag->processCommand(command + char(crc & 0xff) + char(crc >> 8)); + + if (response.isEmpty()) { + reportError(QNearFieldTarget::NoResponseError, id); + return id; + } + + // check crc + if (qChecksum(QByteArrayView(response.constData(), response.size()), Qt::ChecksumItuV41) != 0) { + reportError(QNearFieldTarget::ChecksumMismatchError, id); + return id; + } + + response.chop(2); + + QMetaObject::invokeMethod(this, [this, id, response] { + this->setResponseForRequest(id, response); + }, Qt::QueuedConnection); + + return id; +} + +bool TagType1::waitForRequestCompleted(const QNearFieldTarget::RequestId &id, int msecs) +{ + QCoreApplication::sendPostedEvents(this, QEvent::MetaCall); + + return QNearFieldTagType1::waitForRequestCompleted(id, msecs); +} + + +TagType2::TagType2(TagBase *tag, QObject *parent) +: QNearFieldTagType2(parent), tag(tag) +{ +} + +TagType2::~TagType2() +{ +} + +QByteArray TagType2::uid() const +{ + QMutexLocker locker(&tagMutex); + + return tag->uid(); +} + +QNearFieldTarget::AccessMethods TagType2::accessMethods() const +{ + return QNearFieldTarget::NdefAccess | QNearFieldTarget::TagTypeSpecificAccess; +} + +QNearFieldTarget::RequestId TagType2::sendCommand(const QByteArray &command) +{ + QMutexLocker locker(&tagMutex); + + QNearFieldTarget::RequestId id(new QNearFieldTarget::RequestIdPrivate); + + // tag not in proximity + if (!tagMap.value(tag)) { + reportError(QNearFieldTarget::TargetOutOfRangeError, id); + return id; + } + + quint16 crc = qChecksum(QByteArrayView(command.constData(), command.size()), Qt::ChecksumItuV41); + + QByteArray response = tag->processCommand(command + char(crc & 0xff) + char(crc >> 8)); + + if (response.isEmpty()) + return id; + + if (response.size() > 1) { + // check crc + if (qChecksum(QByteArrayView(response.constData(), response.size()), Qt::ChecksumItuV41) != 0) { + reportError(QNearFieldTarget::ChecksumMismatchError, id); + return id; + } + + response.chop(2); + } + + QMetaObject::invokeMethod(this, [this, id, response] { + this->setResponseForRequest(id, response); + }, Qt::QueuedConnection); + + return id; +} + +bool TagType2::waitForRequestCompleted(const QNearFieldTarget::RequestId &id, int msecs) +{ + QCoreApplication::sendPostedEvents(this, QEvent::MetaCall); + + return QNearFieldTagType2::waitForRequestCompleted(id, msecs); +} + +TagActivator::TagActivator() : QObject() +{ + qRegisterMetaType(); +} + +TagActivator::~TagActivator() +{ + QMutexLocker locker(&tagMutex); + qDeleteAll(tagMap.keys()); + tagMap.clear(); +} + +void TagActivator::initialize() +{ + QMutexLocker locker(&tagMutex); + + if (!tagMap.isEmpty()) + return; + +#ifndef BUILTIN_TESTDATA + QDirIterator nfcTargets(QDir::currentPath(), QStringList(QStringLiteral("*.nfc")), QDir::Files); +#else + QDirIterator nfcTargets(":/nfcdata", QStringList(QStringLiteral("*.nfc")), QDir::Files); +#endif + while (nfcTargets.hasNext()) { + const QString targetFilename = nfcTargets.next(); + + QSettings target(targetFilename, QSettings::IniFormat); + + target.beginGroup(QStringLiteral("Target")); + + const QString tagType = target.value(QStringLiteral("Type")).toString(); + + target.endGroup(); + + if (tagType == QLatin1String("TagType1")) { + NfcTagType1 *tag = new NfcTagType1; + tag->load(&target); + + tagMap.insert(tag, false); + } else if (tagType == QLatin1String("TagType2")) { + NfcTagType2 *tag = new NfcTagType2; + tag->load(&target); + + tagMap.insert(tag, false); + } else { + qWarning("Unknown tag type %s\n", qPrintable(tagType)); + } + } + + current = tagMap.end(); +} + +void TagActivator::reset() +{ + QMutexLocker locker(&tagMutex); + + stopInternal(); + + qDeleteAll(tagMap.keys()); + tagMap.clear(); +} + +void TagActivator::start() +{ + QMutexLocker locker(&tagMutex); + timerId = startTimer(1000); +} + +void TagActivator::stop() +{ + QMutexLocker locker(&tagMutex); + stopInternal(); +} + +void TagActivator::stopInternal() +{ + if (timerId != -1) { + killTimer(timerId); + timerId = -1; + } +} + +TagActivator *TagActivator::instance() +{ + return globalTagActivator(); +} + +void TagActivator::timerEvent(QTimerEvent *e) +{ + Q_UNUSED(e); + + tagMutex.lock(); + + if (current != tagMap.end()) { + if (current.key()->lastAccessTime() + 1500 > QDateTime::currentMSecsSinceEpoch()) { + tagMutex.unlock(); + return; + } + + *current = false; + + TagBase *tag = current.key(); + + tagMutex.unlock(); + Q_EMIT tagDeactivated(tag); + tagMutex.lock(); + } + + if (current != tagMap.end()) + ++current; + + if (current == tagMap.end()) + current = tagMap.begin(); + + if (current != tagMap.end()) { + *current = true; + + TagBase *tag = current.key(); + + tagMutex.unlock(); + Q_EMIT tagActivated(tag); + tagMutex.lock(); + } + + tagMutex.unlock(); +} + +QT_END_NAMESPACE diff --git a/tests/auto/nfccommons/qnearfieldtarget_emulator_p.h b/tests/auto/nfccommons/qnearfieldtarget_emulator_p.h new file mode 100644 index 0000000..4807ad2 --- /dev/null +++ b/tests/auto/nfccommons/qnearfieldtarget_emulator_p.h @@ -0,0 +1,96 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef QNEARFIELDTARGET_EMULATOR_P_H +#define QNEARFIELDTARGET_EMULATOR_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 "qnearfieldtagtype1_p.h" +#include "qnearfieldtagtype2_p.h" +#include "targetemulator_p.h" + +#include + +QT_BEGIN_NAMESPACE + +class TagType1 : public QNearFieldTagType1 +{ + Q_OBJECT + +public: + TagType1(TagBase *tag, QObject *parent = nullptr); + ~TagType1(); + + QByteArray uid() const override; + + QNearFieldTarget::AccessMethods accessMethods() const override; + + QNearFieldTarget::RequestId sendCommand(const QByteArray &command) override; + bool waitForRequestCompleted(const QNearFieldTarget::RequestId &id, int msecs); + +private: + TagBase *tag; +}; + +class TagType2 : public QNearFieldTagType2 +{ + Q_OBJECT + +public: + TagType2(TagBase *tag, QObject *parent = nullptr); + ~TagType2(); + + QByteArray uid() const override; + + QNearFieldTarget::AccessMethods accessMethods() const override; + + QNearFieldTarget::RequestId sendCommand(const QByteArray &command) override; + bool waitForRequestCompleted(const QNearFieldTarget::RequestId &id, int msecs); + +private: + TagBase *tag; +}; + +class TagActivator : public QObject +{ + Q_OBJECT + +public: + TagActivator(); + ~TagActivator(); + + void initialize(); + void reset(); + + void start(); + void stop(); + + static TagActivator *instance(); + +protected: + void timerEvent(QTimerEvent *e) override; + +signals: + void tagActivated(TagBase *tag); + void tagDeactivated(TagBase *tag); + +private: + void stopInternal(); + + QMap::Iterator current; + int timerId = -1; +}; + +QT_END_NAMESPACE + +#endif // QNEARFIELDTARGET_EMULATOR_P_H diff --git a/tests/auto/nfccommons/qtlv.cpp b/tests/auto/nfccommons/qtlv.cpp new file mode 100644 index 0000000..f7dae52 --- /dev/null +++ b/tests/auto/nfccommons/qtlv.cpp @@ -0,0 +1,496 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "qtlv_p.h" + +#include "qnearfieldtagtype1_p.h" + +#include + +#include + +QT_BEGIN_NAMESPACE + +QPair qParseReservedMemoryControlTlv(const QByteArray &tlvData) +{ + quint8 position = tlvData.at(0); + int pageAddr = position >> 4; + int byteOffset = position & 0x0f; + + int size = quint8(tlvData.at(1)); + if (size == 0) + size = 256; + + quint8 pageControl = tlvData.at(2); + int bytesPerPage = pageControl & 0x0f; + + if (!bytesPerPage) + return qMakePair(0, 0); + + int byteAddress = pageAddr * (1 << bytesPerPage) + byteOffset; + return qMakePair(byteAddress, size); +} + +QPair qParseLockControlTlv(const QByteArray &tlvData) +{ + quint8 position = tlvData.at(0); + int pageAddr = position >> 4; + int byteOffset = position & 0x0f; + + int size = quint8(tlvData.at(1)); + if (size == 0) + size = 256; + size = size / 8; + + quint8 pageControl = tlvData.at(2); + int bytesPerPage = pageControl & 0x0f; + + if (!bytesPerPage) + return qMakePair(0, 0); + + int byteAddress = pageAddr * (1 << bytesPerPage) + byteOffset; + return qMakePair(byteAddress, size); +} + +QTlvReader::QTlvReader(QNearFieldTargetPrivate *target) +: m_target(target), m_index(-1) +{ + if (qobject_cast(m_target)) { + addReservedMemory(0, 12); // skip uid, cc + addReservedMemory(104, 16); // skip reserved block D, lock block E + + addReservedMemory(120, 8); // skip reserved block F + } +} + +QTlvReader::QTlvReader(const QByteArray &data) +: m_target(0), m_rawData(data), m_index(-1) +{ +} + +void QTlvReader::addReservedMemory(int offset, int length) +{ + m_reservedMemory.insert(offset, length); +} + +/*! + Returns the number of bytes of reserved memory found so far. The actual number of reserved + bytes will not be known until atEnd() returns true. +*/ +int QTlvReader::reservedMemorySize() const +{ + int total = 0; + + QMap::ConstIterator i; + for (i = m_reservedMemory.constBegin(); i != m_reservedMemory.constEnd(); ++i) + total += i.value(); + + return total; +} + +/*! + Returns the request id that the TLV reader is currently waiting on. +*/ +QNearFieldTarget::RequestId QTlvReader::requestId() const +{ + return m_requestId; +} + +bool QTlvReader::atEnd() const +{ + if (m_index == -1) + return false; + + if (m_requestId.isValid()) + return false; + + return (m_index == m_tlvData.size()) || (tag() == 0xfe); +} + +/*! + Moves to the next TLV. Returns true on success; otherwise returns false. +*/ +bool QTlvReader::readNext() +{ + if (atEnd()) + return false; + + // Move to next TLV + if (m_index == -1) { + m_index = 0; + } else if (m_requestId.isValid()) { + // do nothing + } else if (tag() == 0x00 || tag() == 0xfe) { + ++m_index; + } else { + int tlvLength = length(); + m_index += (tlvLength < 0xff) ? tlvLength + 2 : tlvLength + 4; + } + + // Ensure that tag byte is available + if (!readMoreData(m_index)) + return false; + + // Ensure that length byte(s) are available + if (length() == -1) + return false; + + // Ensure that data bytes are available + int tlvLength = length(); + + int dataOffset = (tlvLength < 0xff) ? m_index + 2 : m_index + 4; + + if (!readMoreData(dataOffset + tlvLength - 1)) + return false; + + switch (tag()) { + case 0x01: { // Lock Control TLV + QPair locked = qParseLockControlTlv(data()); + addReservedMemory(locked.first, locked.second); + break; + } + case 0x02: { // Reserved Memory Control TLV + QPair reserved = qParseReservedMemoryControlTlv(data()); + addReservedMemory(reserved.first, reserved.second); + break; + } + } + + return true; +} + +quint8 QTlvReader::tag() const +{ + return m_tlvData.at(m_index); +} + +int QTlvReader::length() +{ + if (tag() == 0x00 || tag() == 0xfe) + return 0; + + if (!readMoreData(m_index + 1)) + return -1; + + quint8 shortLength = m_tlvData.at(m_index + 1); + if (shortLength != 0xff) + return shortLength; + + if (!readMoreData(m_index + 3)) + return -1; + + quint16 longLength = (quint8(m_tlvData.at(m_index + 2)) << 8) | + quint8(m_tlvData.at(m_index + 3)); + + if (longLength < 0xff || longLength == 0xffff) { + qWarning("Invalid 3 byte length"); + return 0; + } + + return longLength; +} + +QByteArray QTlvReader::data() +{ + int tlvLength = length(); + + int dataOffset = (tlvLength < 0xff) ? m_index + 2 : m_index + 4; + + if (!readMoreData(dataOffset + tlvLength - 1)) + return QByteArray(); + + return m_tlvData.mid(dataOffset, tlvLength); +} + +bool QTlvReader::readMoreData(int sparseOffset) +{ + while (sparseOffset >= m_tlvData.size()) { + int absOffset = absoluteOffset(m_tlvData.size()); + + QByteArray data; + + if (!m_rawData.isEmpty()) { + data = m_rawData.mid(absOffset, dataLength(absOffset)); + } else if (QNearFieldTagType1 *tag = qobject_cast(m_target)) { + quint8 segment = absOffset / 128; + + if (m_requestId.isValid()) { + QVariant v = m_target->requestResponse(m_requestId); + if (!v.isValid()) + return false; + + m_requestId = QNearFieldTarget::RequestId(); + + data = v.toByteArray(); + + if (absOffset < 120) + data = data.mid(2); + + int length = dataLength(absOffset); + + data = data.mid(absOffset - (segment * 128), length); + } else { + m_requestId = (absOffset < 120) ? tag->readAll() : tag->readSegment(segment); + + return false; + } + } + + if (data.isEmpty() && sparseOffset >= m_tlvData.size()) + return false; + + m_tlvData.append(data); + } + + return true; +} + +int QTlvReader::absoluteOffset(int sparseOffset) const +{ + int absoluteOffset = sparseOffset; + const QList offsets = m_reservedMemory.keys(); + for (const int offset : offsets) { + if (offset <= absoluteOffset) + absoluteOffset += m_reservedMemory.value(offset); + } + + return absoluteOffset; +} + +/*! + Returns the length of the contiguous non-reserved data block starting from absolute offset + \a startOffset. -1 is return as the length of the last contiguous data block. +*/ +int QTlvReader::dataLength(int startOffset) const +{ + const QList offsets = m_reservedMemory.keys(); + for (const int offset : offsets) { + if (offset <= startOffset) + continue; + + return offset - startOffset; + } + + return -1; +} + + +QTlvWriter::QTlvWriter(QNearFieldTargetPrivate *target) +: m_target(target), m_rawData(0), m_index(0), m_tagMemorySize(-1) +{ + if (qobject_cast(m_target)) { + addReservedMemory(0, 12); // skip uid, cc + addReservedMemory(104, 16); // skip reserved block D, lock block E + + addReservedMemory(120, 8); // skip reserved block F + } +} + +QTlvWriter::QTlvWriter(QByteArray *data) +: m_target(0), m_rawData(data), m_index(0), m_tagMemorySize(-1) +{ +} + +QTlvWriter::~QTlvWriter() +{ + if (m_rawData) + process(true); +} + +void QTlvWriter::addReservedMemory(int offset, int length) +{ + m_reservedMemory.insert(offset, length); +} + +void QTlvWriter::writeTlv(quint8 tagType, const QByteArray &data) +{ + m_buffer.append(tagType); + + if (tagType != 0x00 && tagType != 0xfe) { + int length = data.size(); + if (length < 0xff) { + m_buffer.append(quint8(length)); + } else { + m_buffer.append(char(0xff)); + m_buffer.append(quint16(length) >> 8); + m_buffer.append(quint16(length) & 0x00ff); + } + + m_buffer.append(data); + } + + process(); + + switch (tagType) { + case 0x01: { // Lock Control TLV + QPair locked = qParseLockControlTlv(data); + addReservedMemory(locked.first, locked.second); + break; + } + case 0x02: { // Reserved Memory Control TLV + QPair reserved = qParseReservedMemoryControlTlv(data); + addReservedMemory(reserved.first, reserved.second); + break; + } + } +} + +/*! + Processes more of the TLV writer process. Returns true if the TLVs have been successfully + written to the target or buffer; otherwise returns false. + + A false return value indicates that an NFC request is pending (if requestId() returns a valid + request identifier) or the write process has failed (requestId() returns an invalid request + identifier). +*/ +bool QTlvWriter::process(bool all) +{ + if (m_requestId.isValid()) { + QVariant v = m_target->requestResponse(m_requestId); + if (!v.isValid()) + return false; + } + + if (m_tagMemorySize == -1) { + if (m_rawData) + m_tagMemorySize = m_rawData->size(); + else if (QNearFieldTagType1 *tag = qobject_cast(m_target)) { + if (m_requestId.isValid()) { + m_tagMemorySize = 8 * (tag->requestResponse(m_requestId).toUInt() + 1); + m_requestId = QNearFieldTarget::RequestId(); + } else { + m_requestId = tag->readByte(10); + return false; + } + } + } + + while (!m_buffer.isEmpty()) { + int spaceRemaining = moveToNextAvailable(); + if (spaceRemaining < 1) + return false; + + int length = qMin(spaceRemaining, m_buffer.size()); + + if (m_rawData) { + m_rawData->replace(m_index, length, m_buffer); + m_index += length; + m_buffer = m_buffer.mid(length); + } else if (QNearFieldTagType1 *tag = qobject_cast(m_target)) { + int bufferIndex = 0; + + // static memory - can only use writeByte() + while (m_index < 120 && bufferIndex < length) { + if (m_requestId.isValid()) { + if (!m_target->requestResponse(m_requestId).toBool()) + return false; + + m_requestId = QNearFieldTarget::RequestId(); + + ++m_index; + ++bufferIndex; + } else { + m_requestId = tag->writeByte(m_index, m_buffer.at(bufferIndex)); + m_buffer = m_buffer.mid(bufferIndex); + return false; + } + } + + + // dynamic memory - writeBlock() full + while (m_index >= 120 && (m_index % 8 == 0) && bufferIndex + 8 < length) { + if (m_requestId.isValid()) { + if (!m_target->requestResponse(m_requestId).toBool()) + return false; + + m_requestId = QNearFieldTarget::RequestId(); + + m_index += 8; + bufferIndex += 8; + } else { + m_requestId = tag->writeBlock(m_index / 8, m_buffer.mid(bufferIndex, 8)); + m_buffer = m_buffer.mid(bufferIndex); + return false; + } + } + + // partial block + int currentBlock = m_index / 8; + int nextBlock = currentBlock + 1; + int currentBlockStart = currentBlock * 8; + int nextBlockStart = nextBlock * 8; + + int fillLength = qMin(nextBlockStart - m_index, spaceRemaining - bufferIndex); + + if (fillLength && (all || m_buffer.size() - bufferIndex >= fillLength) && + (m_buffer.size() != bufferIndex)) { + // sufficient data available + if (m_requestId.isValid()) { + const QVariant v = tag->requestResponse(m_requestId); + if (v.typeId() == QMetaType::QByteArray) { + // read in block + QByteArray block = v.toByteArray(); + + int fill = qMin(fillLength, m_buffer.size() - bufferIndex); + + for (int i = m_index - currentBlockStart; i < fill; ++i) + block[i] = m_buffer.at(bufferIndex++); + + // now write block + m_requestId = tag->writeBlock(currentBlock, block); + return false; + } else if (v.typeId() == QMetaType::Bool) { + m_requestId = QNearFieldTarget::RequestId(); + int fill = qMin(fillLength, m_buffer.size() - bufferIndex); + bufferIndex = fill - (m_index - currentBlockStart); + + // write complete + if (!v.toBool()) + return false; + } + } else { + // read in block + m_requestId = tag->readBlock(currentBlock); + m_buffer = m_buffer.mid(bufferIndex); + return false; + } + } + + m_buffer = m_buffer.mid(bufferIndex); + } + } + + return true; +} + +QNearFieldTarget::RequestId QTlvWriter::requestId() const +{ + return m_requestId; +} + +int QTlvWriter::moveToNextAvailable() +{ + int length = -1; + + // move index to next available byte + QMap::ConstIterator i; + for (i = m_reservedMemory.constBegin(); i != m_reservedMemory.constEnd(); ++i) { + if (m_index < i.key()) { + length = i.key() - m_index; + break; + } else if (m_index == i.key()) { + m_index += i.value(); + } else if (m_index > i.key() && m_index < (i.key() + i.value())) { + m_index = i.key() + i.value(); + } + } + + if (length == -1) + return m_tagMemorySize - m_index; + + Q_ASSERT(length != -1); + + return length; +} + +QT_END_NAMESPACE diff --git a/tests/auto/nfccommons/qtlv_p.h b/tests/auto/nfccommons/qtlv_p.h new file mode 100644 index 0000000..58119ec --- /dev/null +++ b/tests/auto/nfccommons/qtlv_p.h @@ -0,0 +1,96 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef QTLV_P_H +#define QTLV_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 QNearFieldTarget; +class QTlvReader +{ +public: + explicit QTlvReader(QNearFieldTargetPrivate *target); + explicit QTlvReader(const QByteArray &data); + + void addReservedMemory(int offset, int length); + int reservedMemorySize() const; + + QNearFieldTarget::RequestId requestId() const; + + bool atEnd() const; + + bool readNext(); + + quint8 tag() const; + int length(); + QByteArray data(); + +private: + bool readMoreData(int sparseOffset); + int absoluteOffset(int sparseOffset) const; + int dataLength(int startOffset) const; + + QNearFieldTargetPrivate *m_target; + QByteArray m_rawData; + QNearFieldTarget::RequestId m_requestId; + + QByteArray m_tlvData; + int m_index; + QMap m_reservedMemory; +}; + +class QTlvWriter +{ +public: + explicit QTlvWriter(QNearFieldTargetPrivate *target); + explicit QTlvWriter(QByteArray *data); + ~QTlvWriter(); + + void addReservedMemory(int offset, int length); + + void writeTlv(quint8 tag, const QByteArray &data = QByteArray()); + + bool process(bool all = false); + + QNearFieldTarget::RequestId requestId() const; + +private: + int moveToNextAvailable(); + + QNearFieldTargetPrivate *m_target; + QByteArray *m_rawData; + + int m_index; + int m_tagMemorySize; + QMap m_reservedMemory; + + QByteArray m_buffer; + + QNearFieldTarget::RequestId m_requestId; +}; + +QPair qParseReservedMemoryControlTlv(const QByteArray &tlvData); +QPair qParseLockControlTlv(const QByteArray &tlvData); + +QT_END_NAMESPACE + +#endif // QTLV_P_H diff --git a/tests/auto/nfccommons/targetemulator.cpp b/tests/auto/nfccommons/targetemulator.cpp new file mode 100644 index 0000000..f19d460 --- /dev/null +++ b/tests/auto/nfccommons/targetemulator.cpp @@ -0,0 +1,345 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "targetemulator_p.h" + +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +TagBase::TagBase() +: lastAccess(0) +{ +} + +TagBase::~TagBase() +{ +} + +NfcTagType1::NfcTagType1() +: hr0(0x11), hr1(0x00), memory(120, '\0') +{ + // Locked blocks + memory[(0x0e << 3) | 0x00] = 0x01; + memory[(0x0e << 3) | 0x01] = 0x60; +} + +NfcTagType1::~NfcTagType1() +{ +} + +void NfcTagType1::load(QSettings *settings) +{ + settings->beginGroup(QStringLiteral("TagType1")); + + hr0 = settings->value(QStringLiteral("HR0"), 0x11).toUInt(); + + if (!(hr0 & 0x10)) { + settings->endGroup(); + return; + } + + hr1 = settings->value(QStringLiteral("HR1"), 0x00).toUInt(); + + memory = settings->value(QStringLiteral("Data")).toByteArray(); + + //quint8 nmn = memory.at(8); + + quint8 vno = memory.at(9); + if (vno != 0x10) + qWarning("Only NFC TagType1 v1.0 behavior is supported."); + + quint8 tms = memory.at(10); + if (memory.size() != 8 * (tms + 1)) + qWarning("Static memory size does not match TMS value."); + + quint8 rwa = memory.at(11); + switch (rwa >> 4) { + case 0: + // Unrestricted read access tag + break; + default: + // tag with unknown read attributes + ; + } + + switch (rwa & 0x0f) { + case 0: + // Unrestricted write access tag + break; + case 0x0f: + // Read only tag + break; + default: + // tag with unknown write attributes + ; + } + + settings->endGroup(); +} + +QByteArray NfcTagType1::uid() const +{ + lastAccess = QDateTime::currentMSecsSinceEpoch(); + + return memory.left(7); +} + +quint8 NfcTagType1::readData(quint8 block, quint8 byte) +{ + return memory.at((block << 3) | byte); +} + +QByteArray NfcTagType1::processCommand(const QByteArray &command) +{ + lastAccess = QDateTime::currentMSecsSinceEpoch(); + + QByteArray response; + + bool tagType1 = (hr0 & 0xf0) == 0x10; + bool dynamic = (hr0 & 0x0f) != 0x01; + + if (command.size() == 9) { + // static memory model command + quint8 opcode = command.at(0); + quint8 address = command.at(1); + quint8 data = command.at(2); + QByteArray uid = command.mid(3, 4); + + // check checksum + if (qChecksum(QByteArrayView(command.constData(), command.size()), Qt::ChecksumItuV41) != 0) + return QByteArray(); + + // check UID + if (uid != memory.left(4)) + return QByteArray(); + + switch (opcode) { + case 0x00: // RALL + response.append(hr0); + response.append(hr1); + response.append(memory.left(120)); + break; + case 0x01: // READ + response.append(address); + if (address & 0x80) + response.append(char(0x00)); + else + response.append(memory.at(address)); + break; + case 0x53: { // WRITE-E + quint8 block = address >> 3; + if (block == 0x00 || block == 0x0d || block == 0x0e) // locked blocks + break; + + quint16 lock = (readData(0x0e, 0x01) << 8) | readData(0x0e, 0x00); + if ((0x01 << block) & lock) // locked blocks + break; + + // FIXME: Test dynamic lock bytes + + memory[address] = data; + + response.append(address); + response.append(data); + break; + } + case 0x1a: { // WRITE-NE + quint8 block = address >> 3; + if (block == 0x00 || block == 0x0d) // locked blocks + break; + + quint16 lock = (readData(0x0e, 0x01) << 8) | readData(0x0e, 0x00); + if ((0x01 << block) & lock) // locked blocks + break; + + + // FIXME: Test dynamic lock bytes + + memory[address] = memory.at(address) | data; + + response.append(address); + response.append(memory.at(address)); + break; + } + case 0x78: // RID + response.append(hr0); + response.append(hr1); + response.append(memory.left(4)); + break; + } + } else if (tagType1 && dynamic && command.size() == 16) { + // dynamic memory model command + quint8 opcode = command.at(0); + quint8 address = command.at(1); + QByteArray data = command.mid(2, 8); + QByteArray uid = command.mid(10, 4); + + // check checksum + if (qChecksum(QByteArrayView(command.constData(), command.size()), Qt::ChecksumItuV41) != 0) + return QByteArray(); + + // check UID + if (uid != memory.left(4)) + return QByteArray(); + + switch (opcode) { + case 0x10: // RSEG + response.append(address); + response.append(memory.mid(128 * (address >> 4), 128)); + break; + case 0x02: // READ8 + response.append(address); + response.append(memory.mid(8 * address, 8)); + break; + case 0x54: { // WRITE-E8 + // locked blocks + if (address == 0x00 || address == 0x0d || address == 0x0e || address == 0x0f) + break; + + quint16 lock = (readData(0x0e, 0x01) << 8) | readData(0x0e, 0x00); + if (address <= 0x0e && ((0x01 << address) & lock)) // locked blocks + break; + + // FIXME: Test dynamic lock bytes + + memory.replace(address * 8, 8, data); + + response.append(address); + response.append(memory.mid(address * 8, 8)); + break; + } + case 0x1b: // WRITE-NE8 + // locked blocks + if (address == 0x00 || address == 0x0d || address == 0x0e || address == 0x0f) + break; + + quint16 lock = (readData(0x0e, 0x01) << 8) | readData(0x0e, 0x00); + if (address <= 0x0e && ((0x01 << address) & lock)) // locked blocks + break; + + // FIXME: Test dynamic lock bytes + + for (int i = 0; i < 8; ++i) + memory[address * 8 + i] = memory.at(address * 8 + i) | data.at(i); + + response.append(address); + response.append(memory.mid(address * 8, 8)); + break; + } + } + + if (!response.isEmpty()) { + quint16 crc = qChecksum(QByteArrayView(response.constData(), response.size()), Qt::ChecksumItuV41); + response.append(quint8(crc & 0xff)); + response.append(quint8(crc >> 8)); + } + + return response; +} + + +NfcTagType2::NfcTagType2() +: memory(64, 0x00), currentSector(0), expectPacket2(false) +{ +} + +NfcTagType2::~NfcTagType2() +{ +} + +void NfcTagType2::load(QSettings *settings) +{ + settings->beginGroup(QStringLiteral("TagType2")); + + memory = settings->value(QStringLiteral("Data")).toByteArray(); + + settings->endGroup(); +} + +QByteArray NfcTagType2::uid() const +{ + lastAccess = QDateTime::currentMSecsSinceEpoch(); + + return memory.left(3) + memory.mid(4, 4); +} + +#define NACK QByteArray("\x05") +#define ACK QByteArray("\x0a") + +QByteArray NfcTagType2::processCommand(const QByteArray &command) +{ + lastAccess = QDateTime::currentMSecsSinceEpoch(); + + QByteArray response; + + // check checksum + if (qChecksum(QByteArrayView(command.constData(), command.size()), Qt::ChecksumItuV41) != 0) + return QByteArray(); + + if (expectPacket2) { + expectPacket2 = false; + quint8 sector = command.at(0); + if (sector * 1024 > memory.size()) + return NACK; + else { + currentSector = sector; + return QByteArray(); + } + } + + quint8 opcode = command.at(0); + + switch (opcode) { + case 0x30: { // READ BLOCK + quint8 block = command.at(1); + int absoluteBlock = currentSector * 256 + block; + + response.append(memory.mid(absoluteBlock * 4, 16)); + if (response.size() != 16) + response.append(QByteArray(16 - response.size(), '\0')); + + break; + } + case 0xa2: { // WRITE BLOCK + quint8 block = command.at(1); + int absoluteBlock = currentSector * 256 + block; + + // locked blocks + if (absoluteBlock == 0 || absoluteBlock == 1) + return NACK; + + const QByteArray data = command.mid(2, 4); + + memory.replace(absoluteBlock * 4, 4, data); + + return ACK; + } + case 0xc2: // SECTOR SELECT - Packet 1 + if (memory.size() > 1024) { + expectPacket2 = true; + return ACK; + } + + return NACK; + default: + qDebug() << "Unknown opcode for Tag Type 2" << Qt::hex << opcode; + qDebug() << "command:" << command.toHex(); + + return NACK; + ; + } + + if (!response.isEmpty()) { + quint16 crc = qChecksum(QByteArrayView(response.constData(), response.size()), Qt::ChecksumItuV41); + response.append(quint8(crc & 0xff)); + response.append(quint8(crc >> 8)); + } + + return response; +} + +QT_END_NAMESPACE diff --git a/tests/auto/nfccommons/targetemulator_p.h b/tests/auto/nfccommons/targetemulator_p.h new file mode 100644 index 0000000..f77a0b3 --- /dev/null +++ b/tests/auto/nfccommons/targetemulator_p.h @@ -0,0 +1,88 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef TARGETEMULATOR_P_H +#define TARGETEMULATOR_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_FORWARD_DECLARE_CLASS(QSettings) + +QT_BEGIN_NAMESPACE + +class TagBase +{ +public: + TagBase(); + virtual ~TagBase(); + + virtual void load(QSettings *settings) = 0; + + virtual QByteArray processCommand(const QByteArray &command) = 0; + + virtual QByteArray uid() const = 0; + + qint64 lastAccessTime() const { return lastAccess; } + +protected: + mutable qint64 lastAccess; +}; + +class NfcTagType1 : public TagBase +{ +public: + NfcTagType1(); + ~NfcTagType1(); + + void load(QSettings *settings) override; + + QByteArray processCommand(const QByteArray &command) override; + + QByteArray uid() const override; + +private: + quint8 readData(quint8 block, quint8 byte); + + quint8 hr0; + quint8 hr1; + + QByteArray memory; +}; + +class NfcTagType2 : public TagBase +{ +public: + NfcTagType2(); + ~NfcTagType2(); + + void load(QSettings *settings) override; + + QByteArray processCommand(const QByteArray &command) override; + + QByteArray uid() const override; + +private: + QByteArray memory; + quint8 currentSector; + bool expectPacket2; +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(TagBase *) + +#endif // TARGETEMULATOR_P_H diff --git a/tests/auto/nfcdata/Qt Labs Website Tag Type1.nfc b/tests/auto/nfcdata/Qt Labs Website Tag Type1.nfc new file mode 100644 index 0000000..6840fbd --- /dev/null +++ b/tests/auto/nfcdata/Qt Labs Website Tag Type1.nfc @@ -0,0 +1,8 @@ +[Target] +Name=Qt Labs Website Tag +Type=TagType1 + +[TagType1] +HR0=17 +HR1=0 +Data=@ByteArray(wfUD3\"\x11\0\xe1\x10\xe\0\x3(\x91\x1\rT\x5\x65n_USQt LabsQ\x1\x13U\x3labs.qt.nokia.com/\xfe\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x1`\0\0\0\0\0\0) diff --git a/tests/auto/nfcdata/Qt Website Tag Type1.nfc b/tests/auto/nfcdata/Qt Website Tag Type1.nfc new file mode 100644 index 0000000..1a6c92d --- /dev/null +++ b/tests/auto/nfcdata/Qt Website Tag Type1.nfc @@ -0,0 +1,9 @@ +[Target] +Name=Qt Website Tag +UID=11:22:33:44:55:66:77 +Type=TagType1 + +[TagType1] +HR0=18 +HR1=0 +Data="@ByteArray(\x11\"3DUfw\0\xe1\x10\xff\0\x3\xff\x4*\x82\t\0\0\x3\xc0image/png\x89PNG\r\n\x1a\n\0\0\0\rIHDR\0\0\0\x39\0\0\0\x43\b\x3\0\0\0\x11\x7f]\x10\0\0\0\x1sRGB\0\xae\xce\x1c\xe9\0\0\0\xc0PLTE\x2\x43\x11\x2\x46\x1a\x4I\b\x1I#\0K\x1e\x11K'\0\0\0\0\0\0\0\0\0\x1`\0\0\0\0\0\0\0\0\0\0\0\0\0\0T\x1a\x1V\v\x10S,\x10`#\x1eZ8\xen\x10*cA\x13q\0\x1bv\x13:qO,\x82\x16\x39\x80\x42.\x8c\x1b.\x91\xfO\x7f\x63.\x95\x3;\x96\"8\x9b\x18\x36\x9f\x2^\x8bpB\xa2\x1a\x45\xa4\x1d\x43\xab\x17J\xa9\"M\xaa\x18m\x99}N\xb2\x14V\xae\x32\x80\xa1\x8bj\xadY`\xb3\x43x\xafos\xbcQy\xbeZ\x93\xb1\x9f{\xbf\x64\x92\xba\x8f\x88\xc5i\x9e\xbc\xa8\x93\xcbz\x9b\xce\x88\xb7\xcd\xbf\xba\xd0\xc2\xb1\xda\x9a\xb3\xdb\xa4\xcb\xd9\xcd\xc2\xe1\xb0\xc8\xe4\xba\xcc\xe8\xc5\xdb\xe5\xdf\xdb\xee\xd3\xe0\xf4\xd0\xe9\xf0\xec\xe8\xf3\xe1\xeb\xf6\xea\xf7\xfa\xf6\xfc\xfe\xfb\xfe\xff\xfc\xfe\x35:\x8c\0\0\0\x1\x62KGD\0\x88\x5\x1dH\0\0\0\tpHYs\0\0\v\x13\0\0\v\x13\x1\0\x9a\x9c\x18\0\0\0\atIME\a\xda\n\x1c\x5\f\t\xfc\xacP,\0\0\x2yIDATH\xc7\xed\x97k{\xda \x14\xc7\xf1\xb2\xdaj\x1b\x9dNE!q\xb4\xce\xe8\x66\xb4\xad\xb9\x38\x3\xe5\xfb\x7f\xab\x2\x41\x1bS\r\xb8\xe7\xd9\x9e\xbd\xf0\xbcJb~\xf9\xc3\xb9q\x4\xfcO\r\\\xc9\xff\x9e\x64\xec_k\xb2\xe7\xc7\xc9\x8f\xc5l\xb1\n\xb7\xf4\"2i\x83j\xf\x66\xe6N\xfd \x8c\xa9\x1d\xb9k\x82\xfa\x10#m\x12\x1fK\xfe\x35NM\xe4\b\xd4\x9c\x3\x98\xe3!\"\x8ag\xe7\xc8\xddm\xbd\xde\xf3\xd0)\x1bK}Df\xc1k\x94\xe3\xf\xe4\x6TnP\xa9\x65\xfa\xdbO\xe4\xdaHfxt\x82\xac\xe7I\xf7\x1c\x19\x97\x93\x18\xf6\x91\xeb\x8a\xf5]Jz\xf_\x97\t\xa5\xdb\xd0\xd7,\x96.\xb2!\x1b\xa3\x37\xfd\x34&\n\xed<\xf9S\x1b\xb2\x31\xfa\x88Z*P\xdc\xfd\x92\xf0\xd4Lb\xa7\xb9S\xcc\xcf\x39\xe3\x8cG\x82l\xdds\x1b\x12\x81G\x1\b\xb1~\xe3\x9b\xfc\xc1\x87\x9e\\D\xea\x9aH\xdc\xa9%\xf2>\x80\xde\0\xac\x95\xe8\x10\xcc\x5\t\x95\xb7\xca\xc8\x46[\xddO\xc7\xc8\x13\xa2\x42\xfdn\x92\x88\xe5\xd3U\xe0\x1bV[\x9d\xc8\xd7\xa9X\x9c\xda\x1f\xe7m\xf5@\xd8\xb6\x9c\x94Kc\xd9[\xd8\xb9\x95>\x9a\xd8\x91XnN\x6\x12\xea-3\x1e\xb6\x64\x94\xe8j\x15\x94\x93\xdd\xca\x46\xde\x46P_3\xfe\xfb\xa1\xc9,<\x84;\x95\xa4H:Mn\x11\x95}P\xc2O$\xfa\x8b\xe4\xb9\xd5\x1a\xc9\x13\x1e\xb2$\a\xe0\xb9\x18\x15G\xf9\xd6\x44zC\xb0U*4\xab\x37\x99<\xc1\x83\x1d\xe9\x65\xb5\xc5\xc9!og\x96\x9aZ\x88/ r\xab#!O\x89&\xb1\xa9\xcat\xe2\x86\x87\xfaT\xdfz\xe3~\xe7\xc9-\xdf\xa7\xaeJ\xee\xf7\xb3~\xe4\xc3\xaeJ\xe\xb6\x63\xc4\xd0\x87\x6\x95\xb5\x42\xd7\x42[H\x8avYU\x85\xc7\x99\xe8\x66\xa5}H\xb5\xb0\xfd\xc9#\x13\x1dw\xef\x96\x8c\xa5\xd1/c\xd7\xf4\x9c\xfb\x8d~\x1a\xb9\xd2-\x18\xf5\bA\xa6>\xa4T{\xad\xd1&kc\xfb\x8f\x8d\xa1\xdd\xb9\x82\xbe\x37T(W\xf0\xd2\x13\tyY\xb1\xb1`ZD\xb7\xa6SP'\xa1\xf2g\xde\b3\x91\"\xdb\xd5N\v$\f\xb8QS\x86\"\xa5\x34&G \xa1\x66\x32;}\vc\xc2\x34\xe5\xdc\x66Np\x8f\x46\v1\x9a\xc4'\xa7\x9aS\x13\x6\xfc`\xd2\xf3\x93\xd4\xf1T\x93g\x98i\x6\x9b\x83\x9b#\xe6%J\x99\xe5\xc4\xb8\xac\xf6\xed\x98\"\xc9\xf8za\xc7\\\xffu\\\xc9\xbc\xbd\x3\x80M\xdfk\x14\xf5\x10\xdf\0\0\0\0IEND\xae\x42`\x82\x11\x1\x10T\x5\x65n_USQt Website\x11\x1\x1dT\x5ja_JPQt\xe3\x81\xae\xe3\x83\x9b\xe3\x83\xbc\xe3\x83\xa0\xe3\x83\x9a\xe3\x83\xbc\xe3\x82\xb8\x11\x1\x10T\x5nb_NOQt WebsideQ\x1\xeU\x3qt.nokia.com/\xfe\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0)" diff --git a/tests/auto/qbluetoothaddress/CMakeLists.txt b/tests/auto/qbluetoothaddress/CMakeLists.txt new file mode 100644 index 0000000..0bf39ee --- /dev/null +++ b/tests/auto/qbluetoothaddress/CMakeLists.txt @@ -0,0 +1,19 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## tst_qbluetoothaddress Test: +##################################################################### + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qbluetoothaddress LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qbluetoothaddress + SOURCES + tst_qbluetoothaddress.cpp + LIBRARIES + Qt::Bluetooth +) diff --git a/tests/auto/qbluetoothaddress/tst_qbluetoothaddress.cpp b/tests/auto/qbluetoothaddress/tst_qbluetoothaddress.cpp new file mode 100644 index 0000000..8e1c903 --- /dev/null +++ b/tests/auto/qbluetoothaddress/tst_qbluetoothaddress.cpp @@ -0,0 +1,213 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include + +#include + +#include + +QT_USE_NAMESPACE + +class tst_QBluetoothAddress : public QObject +{ + Q_OBJECT + +public: + tst_QBluetoothAddress(); + ~tst_QBluetoothAddress(); + +private slots: + void tst_construction_data(); + void tst_construction(); + + void tst_assignment(); + + void tst_comparison_data(); + void tst_comparison(); + + void tst_lessThan_data(); + void tst_lessThan(); + + void tst_clear_data(); + void tst_clear(); +}; + +tst_QBluetoothAddress::tst_QBluetoothAddress() +{ +} + +tst_QBluetoothAddress::~tst_QBluetoothAddress() +{ +} + +void tst_QBluetoothAddress::tst_construction_data() +{ + QTest::addColumn("addressUInt"); + QTest::addColumn("addressS12"); + QTest::addColumn("addressS17"); + + QTest::newRow("11:22:33:44:55:66") << Q_UINT64_C(0x112233445566) << QString("112233445566") << QString("11:22:33:44:55:66"); + QTest::newRow("AA:BB:CC:DD:EE:FF") << Q_UINT64_C(0xAABBCCDDEEFF) << QString("AABBCCDDEEFF") << QString("AA:BB:CC:DD:EE:FF"); + QTest::newRow("aa:bb:cc:dd:ee:ff") << Q_UINT64_C(0xAABBCCDDEEFF) << QString("aabbccddeeff") << QString("AA:BB:CC:DD:EE:FF"); + QTest::newRow("FF:FF:FF:FF:FF:FF") << Q_UINT64_C(0xFFFFFFFFFFFF) << QString("FFFFFFFFFFFF") << QString("FF:FF:FF:FF:FF:FF"); +} + +void tst_QBluetoothAddress::tst_construction() +{ + QFETCH(quint64, addressUInt); + QFETCH(QString, addressS12); + QFETCH(QString, addressS17); + + { + QBluetoothAddress address; + + QVERIFY(address.isNull()); + } + + { + /* construct from quint64 */ + QBluetoothAddress address(addressUInt); + + QVERIFY(!address.isNull()); + + QVERIFY(address.toUInt64() == addressUInt); + + QCOMPARE(address.toString(), addressS17); + } + + { + /* construct from string without colons */ + QBluetoothAddress address(addressS12); + + QVERIFY(!address.isNull()); + + QVERIFY(address.toUInt64() == addressUInt); + + QCOMPARE(address.toString(), addressS17); + } + + { + /* construct from string with colons */ + QBluetoothAddress address(addressS17); + + QVERIFY(!address.isNull()); + + QVERIFY(address.toUInt64() == addressUInt); + + QCOMPARE(address.toString(), addressS17); + } + + { + QString empty; + QBluetoothAddress address(empty); + + QVERIFY(address.isNull()); + } + + { + QBluetoothAddress address(addressUInt); + + QBluetoothAddress copy(address); + + QVERIFY(address.toUInt64() == copy.toUInt64()); + } +} + +void tst_QBluetoothAddress::tst_assignment() +{ + QBluetoothAddress address(Q_UINT64_C(0x112233445566)); + + { + QBluetoothAddress copy = address; + + QCOMPARE(address.toUInt64(), copy.toUInt64()); + } + + { + QBluetoothAddress copy1; + QBluetoothAddress copy2; + + QVERIFY(copy1.isNull()); + QVERIFY(copy2.isNull()); + + copy1 = copy2 = address; + + QVERIFY(!copy1.isNull()); + QVERIFY(!copy2.isNull()); + + QVERIFY(address.toUInt64() == copy1.toUInt64()); + QVERIFY(address.toUInt64() == copy2.toUInt64()); + + copy1.clear(); + QVERIFY(copy1.isNull()); + QVERIFY2(copy1 != address, "Verify that copy1 is a copy of address, the d_ptr are being copied"); + } +} + +void tst_QBluetoothAddress::tst_comparison_data() +{ + QTest::addColumn("address1"); + QTest::addColumn("address2"); + QTest::addColumn("result"); + + QTest::newRow("invalid == invalid") << QBluetoothAddress() << QBluetoothAddress() << true; + QTest::newRow("valid != invalid") << QBluetoothAddress(Q_UINT64_C(0x112233445566)) << QBluetoothAddress() << false; + QTest::newRow("valid == valid") << QBluetoothAddress(Q_UINT64_C(0x112233445566)) << QBluetoothAddress(Q_UINT64_C(0x112233445566)) << true; +} + +void tst_QBluetoothAddress::tst_comparison() +{ + QFETCH(QBluetoothAddress, address1); + QFETCH(QBluetoothAddress, address2); + QFETCH(bool, result); + + QCOMPARE(address1 == address2, result); + QCOMPARE(address2 == address1, result); + QCOMPARE(address1 != address2, !result); + QCOMPARE(address2 != address1, !result); +} + +void tst_QBluetoothAddress::tst_lessThan_data() +{ + QTest::addColumn("address1"); + QTest::addColumn("address2"); + QTest::addColumn("result"); + + QTest::newRow("invalid < invalid") << QBluetoothAddress() << QBluetoothAddress() << false; + QTest::newRow("invalid < valid") << QBluetoothAddress() << QBluetoothAddress(Q_UINT64_C(0x112233445566)) << true; + QTest::newRow("valid < invalid") << QBluetoothAddress(Q_UINT64_C(0x112233445566)) << QBluetoothAddress() << false; + QTest::newRow("valid < valid") << QBluetoothAddress(Q_UINT64_C(0x112233445566)) << QBluetoothAddress(Q_UINT64_C(0xAABBCCDDEEFF)) << true; + QTest::newRow("valid < valid") << QBluetoothAddress(Q_UINT64_C(0xAABBCCDDEEFF)) << QBluetoothAddress(Q_UINT64_C(0x112233445566)) << false; +} + +void tst_QBluetoothAddress::tst_lessThan() +{ + QFETCH(QBluetoothAddress, address1); + QFETCH(QBluetoothAddress, address2); + QFETCH(bool, result); + + QCOMPARE(address1 < address2, result); +} + +void tst_QBluetoothAddress::tst_clear_data() +{ + QTest::addColumn("addressS17"); + + QTest::newRow("FF:00:F3:25:00:00") << QString("FF:00:F3:25:00:00"); +} + +void tst_QBluetoothAddress::tst_clear() +{ + QFETCH(QString, addressS17); + + QBluetoothAddress address(addressS17); + QVERIFY(!address.isNull()); + address.clear(); + QVERIFY(address.toString() == QString("00:00:00:00:00:00")); +} + +QTEST_MAIN(tst_QBluetoothAddress) + +#include "tst_qbluetoothaddress.moc" + diff --git a/tests/auto/qbluetoothdevicediscoveryagent/CMakeLists.txt b/tests/auto/qbluetoothdevicediscoveryagent/CMakeLists.txt new file mode 100644 index 0000000..9a43e90 --- /dev/null +++ b/tests/auto/qbluetoothdevicediscoveryagent/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## tst_qbluetoothdevicediscoveryagent Test: +##################################################################### + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qbluetoothdevicediscoveryagent LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qbluetoothdevicediscoveryagent + SOURCES + tst_qbluetoothdevicediscoveryagent.cpp + LIBRARIES + Qt::BluetoothPrivate +) + +## Scopes: +##################################################################### + +qt_internal_extend_target(tst_qbluetoothdevicediscoveryagent CONDITION MACOS + LIBRARIES + Qt::Widgets +) + +set_target_properties(tst_qbluetoothdevicediscoveryagent PROPERTIES + MACOSX_BUNDLE TRUE +) + +if (APPLE AND NOT IOS) + # Ninja has trouble with relative paths, convert to absolute as a workaround + get_filename_component(SHARED_PLIST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../shared ABSOLUTE) + set_target_properties(tst_qbluetoothdevicediscoveryagent PROPERTIES + MACOSX_BUNDLE_INFO_PLIST "${SHARED_PLIST_DIR}/Info.macos.plist" + ) +endif() diff --git a/tests/auto/qbluetoothdevicediscoveryagent/tst_qbluetoothdevicediscoveryagent.cpp b/tests/auto/qbluetoothdevicediscoveryagent/tst_qbluetoothdevicediscoveryagent.cpp new file mode 100644 index 0000000..d866ec5 --- /dev/null +++ b/tests/auto/qbluetoothdevicediscoveryagent/tst_qbluetoothdevicediscoveryagent.cpp @@ -0,0 +1,587 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include + +#include +#include +#include +#include + +#include "../../shared/bttestutil_p.h" +#include +#include +#include +#include + +#if QT_CONFIG(permissions) +#include +#include +#include +#endif // permissions + +#include + +QT_USE_NAMESPACE + +/* + * Some parts of this test require a remote and discoverable Bluetooth + * device. Setting the BT_TEST_DEVICE environment variable will + * set the test up to fail if it cannot find a remote device. + * BT_TEST_DEVICE should contain the address of the device the + * test expects to find. Ensure that the device is running + * in discovery mode. + **/ + +// Maximum time to for bluetooth device scan +const int MaxScanTime = 5 * 60 * 1000; // 5 minutes in ms + +//Bluez needs at least 10s for a device discovery to be cancelled +const int MaxWaitForCancelTime = 15 * 1000; // 15 seconds in ms + +#ifdef Q_OS_ANDROID +// Android is sometimes unable to cancel immediately +const int WaitBeforeStopTime = 200; +#endif + +class tst_QBluetoothDeviceDiscoveryAgent : public QObject +{ + Q_OBJECT + +public: + tst_QBluetoothDeviceDiscoveryAgent(); + ~tst_QBluetoothDeviceDiscoveryAgent(); + +public slots: + void deviceDiscoveryDebug(const QBluetoothDeviceInfo &info); + void finished(); + +private slots: + void initTestCase(); + + void tst_invalidBtAddress(); + + void tst_startStopDeviceDiscoveries(); + + void tst_deviceDiscovery(); + + void tst_discoveryTimeout(); + + void tst_discoveryMethods(); +private: + qsizetype noOfLocalDevices; + using DiscoveryAgentPtr = std::unique_ptr; +#if QT_CONFIG(permissions) + Qt::PermissionStatus permissionStatus = Qt::PermissionStatus::Undetermined; +#endif +}; + +tst_QBluetoothDeviceDiscoveryAgent::tst_QBluetoothDeviceDiscoveryAgent() +{ + QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true")); + qRegisterMetaType(); +#if QT_CONFIG(permissions) + permissionStatus = qApp->checkPermission(QBluetoothPermission{}); + + const bool ciRun = qEnvironmentVariable("QTEST_ENVIRONMENT").split(' ').contains("ci"); + if (!ciRun && permissionStatus == Qt::PermissionStatus::Undetermined) { + QTestEventLoop loop; + qApp->requestPermission(QBluetoothPermission{}, [this, &loop](const QPermission &permission){ + permissionStatus = permission.status(); + loop.exitLoop(); + }); + if (permissionStatus == Qt::PermissionStatus::Undetermined) + loop.enterLoopMSecs(30000); + } +#endif // QT_CONFIG(permissions) +} + +tst_QBluetoothDeviceDiscoveryAgent::~tst_QBluetoothDeviceDiscoveryAgent() +{ +} + +void tst_QBluetoothDeviceDiscoveryAgent::initTestCase() +{ + qRegisterMetaType(); + + noOfLocalDevices = QBluetoothLocalDevice::allDevices().size(); + + if (!noOfLocalDevices) + return; + + // turn on BT in case it is not on + QBluetoothLocalDevice *device = new QBluetoothLocalDevice(); + if (device->hostMode() == QBluetoothLocalDevice::HostPoweredOff) { + QSignalSpy hostModeSpy(device, SIGNAL(hostModeStateChanged(QBluetoothLocalDevice::HostMode))); + QVERIFY(hostModeSpy.isEmpty()); + device->powerOn(); + int connectTime = 5000; // ms + while (hostModeSpy.isEmpty() && connectTime > 0) { + QTest::qWait(500); + connectTime -= 500; + } + QVERIFY(!hostModeSpy.isEmpty()); + } + QBluetoothLocalDevice::HostMode hostMode= device->hostMode(); + QVERIFY(hostMode == QBluetoothLocalDevice::HostConnectable + || hostMode == QBluetoothLocalDevice::HostDiscoverable + || hostMode == QBluetoothLocalDevice::HostDiscoverableLimitedInquiry); + delete device; +} + +void tst_QBluetoothDeviceDiscoveryAgent::tst_invalidBtAddress() +{ + DiscoveryAgentPtr discoveryAgent(new QBluetoothDeviceDiscoveryAgent( + QBluetoothAddress(QStringLiteral("11:11:11:11:11:11")))); + + QCOMPARE(discoveryAgent->error(), QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError); + discoveryAgent->start(); + QCOMPARE(discoveryAgent->isActive(), false); + +#if QT_CONFIG(permissions) + if (permissionStatus != Qt::PermissionStatus::Granted) + return; +#endif + + discoveryAgent.reset(new QBluetoothDeviceDiscoveryAgent(QBluetoothAddress())); + QCOMPARE(discoveryAgent->error(), QBluetoothDeviceDiscoveryAgent::NoError); + if (!QBluetoothLocalDevice::allDevices().isEmpty()) { + discoveryAgent->start(); + QCOMPARE(discoveryAgent->isActive(), true); + } +} + +void tst_QBluetoothDeviceDiscoveryAgent::deviceDiscoveryDebug(const QBluetoothDeviceInfo &info) +{ + qDebug() << "Discovered device:" << info.address().toString() << info.name(); +} + +void tst_QBluetoothDeviceDiscoveryAgent::tst_startStopDeviceDiscoveries() +{ + if (androidBluetoothEmulator()) + QSKIP("Skipping test on Android 12+ emulator, CI can timeout waiting for user input"); + + QBluetoothDeviceDiscoveryAgent discoveryAgent; + + QVERIFY(discoveryAgent.error() == discoveryAgent.NoError); + QVERIFY(discoveryAgent.errorString().isEmpty()); + QVERIFY(!discoveryAgent.isActive()); + QVERIFY(discoveryAgent.discoveredDevices().isEmpty()); + + QSignalSpy finishedSpy(&discoveryAgent, SIGNAL(finished())); + QSignalSpy cancelSpy(&discoveryAgent, SIGNAL(canceled())); + QSignalSpy errorSpy(&discoveryAgent, + SIGNAL(errorOccurred(QBluetoothDeviceDiscoveryAgent::Error))); + + // Starting case 1: start-stop, expecting cancel signal + // we should have no errors at this point. + QVERIFY(errorSpy.isEmpty()); + + discoveryAgent.start(); +#if QT_CONFIG(permissions) + if (permissionStatus != Qt::PermissionStatus::Granted) { + // If bluetooth is OFF, the permission does not get checked (e.g. on Darwin), + // but not to depend on the order in which errors generated, we + // do not compare error value with MissionPermissionsError here. + return; + } +#endif + + if (errorSpy.isEmpty()) { + QVERIFY(discoveryAgent.isActive()); + QCOMPARE(discoveryAgent.errorString(), QString()); + QCOMPARE(discoveryAgent.error(), QBluetoothDeviceDiscoveryAgent::NoError); + } else { + QCOMPARE(noOfLocalDevices, 0); + QVERIFY(!discoveryAgent.isActive()); + QVERIFY(!discoveryAgent.errorString().isEmpty()); + QVERIFY(discoveryAgent.error() != QBluetoothDeviceDiscoveryAgent::NoError); + QSKIP("No local Bluetooth device available. Skipping remaining part of test."); + } + // cancel current request. +#ifdef Q_OS_ANDROID + // Android sometimes can't cancel immediately (~on the same millisecond), + // but instead a "pending cancel" happens, which means the discovery will be + // canceled at a later point in time. When this happens the Android backend + // also emits an immediate errorOccurred(). While this seems to be as intended, + // as a result many parts of this test function may fail (not always). + // + // In this test function we wait some milliseconds between start() and stop() to + // bypass this behavior difference. This is to avoid complex iffery (Android itself + // can behave differently every time) and ifdeffery (Q_OS_ANDROID) in the test + QTest::qWait(WaitBeforeStopTime); +#endif + discoveryAgent.stop(); + + // Wait for up to MaxWaitForCancelTime for the cancel to finish + QTRY_VERIFY_WITH_TIMEOUT(!cancelSpy.isEmpty(), MaxWaitForCancelTime); + + // we should not be active anymore + QVERIFY(!discoveryAgent.isActive()); + QVERIFY(errorSpy.isEmpty()); + QCOMPARE(cancelSpy.size(), 1); + cancelSpy.clear(); + // Starting case 2: start-start-stop, expecting cancel signal + discoveryAgent.start(); + // we should be active now + QVERIFY(discoveryAgent.isActive()); + QVERIFY(errorSpy.isEmpty()); + // start again. should this be error? + discoveryAgent.start(); + QVERIFY(discoveryAgent.isActive()); + QVERIFY(errorSpy.isEmpty()); + // stop +#ifdef Q_OS_ANDROID + QTest::qWait(WaitBeforeStopTime); +#endif + discoveryAgent.stop(); + + // Wait for up to MaxWaitForCancelTime for the cancel to finish + QTRY_VERIFY_WITH_TIMEOUT(!cancelSpy.isEmpty(), MaxWaitForCancelTime); + + // we should not be active anymore + QVERIFY(!discoveryAgent.isActive()); + QVERIFY(errorSpy.isEmpty()); + + QCOMPARE(cancelSpy.size(), 1); + cancelSpy.clear(); + + // Starting case 3: stop + discoveryAgent.stop(); + QVERIFY(!discoveryAgent.isActive()); + QVERIFY(errorSpy.isEmpty()); + + // Don't expect finished signal and no error + QVERIFY(finishedSpy.isEmpty()); + QVERIFY(discoveryAgent.error() == discoveryAgent.NoError); + QVERIFY(discoveryAgent.errorString().isEmpty()); + + /* + Starting case 4: start-stop-start-stop: + We are testing that two subsequent stop() calls reduce total number + of cancel() signals to 1 if the true cancellation requires + asynchronous function calls (signal consolidation); otherwise we + expect 2x cancel() signal. + + Examples are: + - Bluez4 (event loop needs to run for cancel) + - Bluez5 (no event loop required) + */ + + bool immediateSignal = false; + discoveryAgent.start(); + QVERIFY(discoveryAgent.isActive()); + QVERIFY(errorSpy.isEmpty()); + // cancel current request. +#ifdef Q_OS_ANDROID + QTest::qWait(WaitBeforeStopTime); +#endif + discoveryAgent.stop(); + //should only have triggered cancel() if stop didn't involve the event loop + if (cancelSpy.size() == 1) immediateSignal = true; + + // start a new one + discoveryAgent.start(); + // we should be active now + QVERIFY(discoveryAgent.isActive()); + QVERIFY(errorSpy.isEmpty()); + // stop +#ifdef Q_OS_ANDROID + QTest::qWait(WaitBeforeStopTime); +#endif + discoveryAgent.stop(); + if (immediateSignal) + QCOMPARE(cancelSpy.size(), 2); + + // Wait for up to MaxWaitForCancelTime for the cancel to finish + QTRY_VERIFY_WITH_TIMEOUT(!cancelSpy.isEmpty(), MaxWaitForCancelTime); + + // we should not be active anymore + QVERIFY(!discoveryAgent.isActive()); + QVERIFY(errorSpy.isEmpty()); + + // should only have 1 cancel + if (immediateSignal) + QCOMPARE(cancelSpy.size(), 2); + else + QCOMPARE(cancelSpy.size(), 1); + cancelSpy.clear(); + + // Starting case 5: start-stop-start: expecting finished signal & no cancel + discoveryAgent.start(); + QVERIFY(discoveryAgent.isActive()); + QVERIFY(errorSpy.isEmpty()); + // cancel current request. +#ifdef Q_OS_ANDROID + QTest::qWait(WaitBeforeStopTime); +#endif + discoveryAgent.stop(); + // start a new one + discoveryAgent.start(); + // we should be active now + QVERIFY(discoveryAgent.isActive()); + QVERIFY(errorSpy.isEmpty()); + + // Wait for up to MaxScanTime for the scan to finish + QTRY_VERIFY_WITH_TIMEOUT(!finishedSpy.isEmpty(), MaxScanTime); + + // we should not be active anymore + QVERIFY(!discoveryAgent.isActive()); + QVERIFY(errorSpy.isEmpty()); + // should only have 1 cancel + QCOMPARE(finishedSpy.size(), 1); + + // On OS X, stop is synchronous (signal will be emitted immediately). + if (!immediateSignal) + QVERIFY(cancelSpy.isEmpty()); +} + +void tst_QBluetoothDeviceDiscoveryAgent::finished() +{ + qDebug() << "Finished called"; +} + +void tst_QBluetoothDeviceDiscoveryAgent::tst_deviceDiscovery() +{ + { + //Run test in case of multiple Bluetooth adapters + QBluetoothLocalDevice localDevice; + //We will use default adapter if there is no other adapter + QBluetoothAddress address = localDevice.address(); + + QBluetoothDeviceDiscoveryAgent discoveryAgent(address); + QVERIFY(discoveryAgent.error() == discoveryAgent.NoError); + QVERIFY(discoveryAgent.errorString().isEmpty()); + QVERIFY(!discoveryAgent.isActive()); + + QVERIFY(discoveryAgent.discoveredDevices().isEmpty()); + + QSignalSpy finishedSpy(&discoveryAgent, SIGNAL(finished())); + QSignalSpy errorSpy(&discoveryAgent, + SIGNAL(errorOccurred(QBluetoothDeviceDiscoveryAgent::Error))); + QSignalSpy discoveredSpy(&discoveryAgent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo))); +// connect(&discoveryAgent, SIGNAL(finished()), this, SLOT(finished())); +// connect(&discoveryAgent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)), +// this, SLOT(deviceDiscoveryDebug(QBluetoothDeviceInfo))); + + discoveryAgent.start(); + + if (!errorSpy.isEmpty()) { +#if QT_CONFIG(permissions) + if (permissionStatus == Qt::PermissionStatus::Granted) +#endif + + QCOMPARE(noOfLocalDevices, 0); + QVERIFY(!discoveryAgent.isActive()); + QSKIP("No local Bluetooth device available. Skipping remaining part of test."); + } + + QVERIFY(discoveryAgent.isActive()); + + // Wait for up to MaxScanTime for the scan to finish + int scanTime = MaxScanTime; + while (finishedSpy.isEmpty() && scanTime > 0) { + QTest::qWait(15000); + scanTime -= 15000; + } + + // verify that we are finished + QVERIFY(!discoveryAgent.isActive()); + // stop + discoveryAgent.stop(); + QVERIFY(!discoveryAgent.isActive()); + qDebug() << "Scan time left:" << scanTime; + // Expect finished signal with no error + QVERIFY(finishedSpy.size() == 1); + QVERIFY(errorSpy.isEmpty()); + QVERIFY(discoveryAgent.error() == discoveryAgent.NoError); + QVERIFY(discoveryAgent.errorString().isEmpty()); + + // verify that the list is as big as the signals received. + // discoveredSpy might have more events as some devices are found multiple times, + // leading to messages like + // "Almost Duplicate "88:C6:26:F5:3E:E2" "88-C6-26-F5-3E-E2" - replacing in place" + QVERIFY(discoveredSpy.size() >= discoveryAgent.discoveredDevices().size()); + // verify that there really was some devices in the array + + const QString remote = qEnvironmentVariable("BT_TEST_DEVICE"); + QBluetoothAddress remoteDevice; + if (!remote.isEmpty()) { + remoteDevice = QBluetoothAddress(remote); + QVERIFY2(!remote.isNull(), "Expecting valid Bluetooth address to be passed via BT_TEST_DEVICE"); + } else { + qWarning() << "Not using a remote device for testing. Set BT_TEST_DEVICE env to run extended tests involving a remote device"; + } + + if (!remoteDevice.isNull()) + QVERIFY(!discoveredSpy.isEmpty()); + // All returned QBluetoothDeviceInfo should be valid. + while (!discoveredSpy.isEmpty()) { + const QBluetoothDeviceInfo info = + qvariant_cast(discoveredSpy.takeFirst().at(0)); + QVERIFY(info.isValid()); + } + } +} + + +void tst_QBluetoothDeviceDiscoveryAgent::tst_discoveryTimeout() +{ + QBluetoothDeviceDiscoveryAgent agent; + + // check default values +#if defined(Q_OS_MACOS) || defined(Q_OS_IOS) || defined(Q_OS_ANDROID) || QT_CONFIG(winrt_bt) \ + || QT_CONFIG(bluez) + QCOMPARE(agent.lowEnergyDiscoveryTimeout(), 40000); + agent.setLowEnergyDiscoveryTimeout(-1); // negative ignored + QCOMPARE(agent.lowEnergyDiscoveryTimeout(), 40000); + agent.setLowEnergyDiscoveryTimeout(20000); + QCOMPARE(agent.lowEnergyDiscoveryTimeout(), 20000); +#else + QCOMPARE(agent.lowEnergyDiscoveryTimeout(), -1); + agent.setLowEnergyDiscoveryTimeout(20000); // feature not supported -> ignored + QCOMPARE(agent.lowEnergyDiscoveryTimeout(), -1); +#endif +} + +void tst_QBluetoothDeviceDiscoveryAgent::tst_discoveryMethods() +{ + if (androidBluetoothEmulator()) + QSKIP("Skipping test on Android 12+ emulator, CI can timeout waiting for user input"); + + const QBluetoothLocalDevice localDevice; + if (localDevice.allDevices().size() != 1) { + // On iOS it returns 0 but we still have working BT. +#ifndef Q_OS_IOS + QSKIP("This test expects exactly one local device working"); +#endif + } + + const QBluetoothDeviceDiscoveryAgent::DiscoveryMethods + supportedMethods = QBluetoothDeviceDiscoveryAgent::supportedDiscoveryMethods(); + + QVERIFY(supportedMethods != QBluetoothDeviceDiscoveryAgent::NoMethod); + + QBluetoothDeviceDiscoveryAgent::DiscoveryMethod + unsupportedMethods = QBluetoothDeviceDiscoveryAgent::NoMethod; + QBluetoothDeviceInfo::CoreConfiguration + expectedConfiguration = QBluetoothDeviceInfo::BaseRateAndLowEnergyCoreConfiguration; + + if (supportedMethods == QBluetoothDeviceDiscoveryAgent::ClassicMethod) { + unsupportedMethods = QBluetoothDeviceDiscoveryAgent::LowEnergyMethod; + expectedConfiguration = QBluetoothDeviceInfo::BaseRateCoreConfiguration; + } else if (supportedMethods == QBluetoothDeviceDiscoveryAgent::LowEnergyMethod) { + unsupportedMethods = QBluetoothDeviceDiscoveryAgent::ClassicMethod; + expectedConfiguration = QBluetoothDeviceInfo::LowEnergyCoreConfiguration; + } + + QBluetoothDeviceDiscoveryAgent agent; + QSignalSpy finishedSpy(&agent, SIGNAL(finished())); + QSignalSpy errorSpy(&agent, SIGNAL(errorOccurred(QBluetoothDeviceDiscoveryAgent::Error))); + QSignalSpy discoveredSpy(&agent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo))); + + // NoMethod - should just immediately return: + agent.start(QBluetoothDeviceDiscoveryAgent::NoMethod); + QCOMPARE(agent.error(), QBluetoothDeviceDiscoveryAgent::NoError); + QVERIFY(!agent.isActive()); + QCOMPARE(finishedSpy.size(), 0); + QCOMPARE(errorSpy.size(), 0); + QCOMPARE(discoveredSpy.size(), 0); + + if (unsupportedMethods != QBluetoothDeviceDiscoveryAgent::NoMethod) { + agent.start(unsupportedMethods); + QCOMPARE(agent.error(), QBluetoothDeviceDiscoveryAgent::UnsupportedDiscoveryMethod); + QVERIFY(!agent.isActive()); + QVERIFY(finishedSpy.isEmpty()); + QCOMPARE(errorSpy.size(), 1); + errorSpy.clear(); + QVERIFY(discoveredSpy.isEmpty()); + } + + // Start discovery, probably both Classic and LE methods: + agent.start(supportedMethods); +#if QT_CONFIG(permissions) + if (permissionStatus != Qt::PermissionStatus::Granted) { + QCOMPARE(agent.error(), QBluetoothDeviceDiscoveryAgent::MissingPermissionsError); + QSKIP("The remaining test requires the Bluetooth permission granted"); + } +#endif + QVERIFY(agent.isActive()); + QVERIFY(errorSpy.isEmpty()); + +#define RUN_DISCOVERY(maxTimeout, step, condition) \ + for (int scanTime = maxTimeout; (condition) && scanTime > 0; scanTime -= step) \ + QTest::qWait(step); + + // Wait for up to MaxScanTime for the scan to finish + const int timeStep = 15000; + RUN_DISCOVERY(MaxScanTime, timeStep, finishedSpy.isEmpty()) + + QVERIFY(!agent.isActive()); + QVERIFY(errorSpy.size() <= 1); + + if (errorSpy.size()) { + // For example, old iOS device could report it supports LE method, + // but it actually does not. + QVERIFY(supportedMethods == QBluetoothDeviceDiscoveryAgent::LowEnergyMethod); + QCOMPARE(agent.error(), QBluetoothDeviceDiscoveryAgent::UnsupportedDiscoveryMethod); + } else { + QVERIFY(finishedSpy.size() == 1); + QVERIFY(agent.error() == QBluetoothDeviceDiscoveryAgent::NoError); + QVERIFY(agent.errorString().isEmpty()); + + while (!discoveredSpy.isEmpty()) { + const QBluetoothDeviceInfo info = + qvariant_cast(discoveredSpy.takeFirst().at(0)); + QVERIFY(info.isValid()); + // on Android we do find devices with unknown configuration + if (info.coreConfigurations() != QBluetoothDeviceInfo::UnknownCoreConfiguration) + QVERIFY(info.coreConfigurations() & expectedConfiguration); + } + } + + if (unsupportedMethods != QBluetoothDeviceDiscoveryAgent::NoMethod) + return; + + // Both methods were reported as supported. We already tested them + // above, now let's test first Classic then LE. + finishedSpy.clear(); + errorSpy.clear(); + discoveredSpy.clear(); + + agent.start(QBluetoothDeviceDiscoveryAgent::ClassicMethod); + QVERIFY(agent.isActive()); + QVERIFY(errorSpy.isEmpty()); + QCOMPARE(agent.error(), QBluetoothDeviceDiscoveryAgent::NoError); + + RUN_DISCOVERY(MaxScanTime, timeStep, finishedSpy.isEmpty()) + + QVERIFY(!agent.isActive()); + QVERIFY(errorSpy.isEmpty()); + QCOMPARE(finishedSpy.size(), 1); + + finishedSpy.clear(); + discoveredSpy.clear(); + + agent.start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod); + QVERIFY(agent.isActive()); + QVERIFY(errorSpy.isEmpty()); + + RUN_DISCOVERY(MaxScanTime, timeStep, finishedSpy.isEmpty() && errorSpy.isEmpty()) + + QVERIFY(!agent.isActive()); + QVERIFY(errorSpy.size() <= 1); + + if (errorSpy.size()) { + QCOMPARE(agent.error(), QBluetoothDeviceDiscoveryAgent::UnsupportedDiscoveryMethod); + qDebug() << "QBluetoothDeviceDiscoveryAgent::supportedDiscoveryMethods is inaccurate" + " on your platform/with your device, LowEnergyMethod is not supported"; + } else { + QCOMPARE(agent.error(), QBluetoothDeviceDiscoveryAgent::NoError); + QCOMPARE(finishedSpy.size(), 1); + } +} + +QTEST_MAIN(tst_QBluetoothDeviceDiscoveryAgent) + +#include "tst_qbluetoothdevicediscoveryagent.moc" diff --git a/tests/auto/qbluetoothdeviceinfo/CMakeLists.txt b/tests/auto/qbluetoothdeviceinfo/CMakeLists.txt new file mode 100644 index 0000000..3b775bf --- /dev/null +++ b/tests/auto/qbluetoothdeviceinfo/CMakeLists.txt @@ -0,0 +1,19 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## tst_qbluetoothdeviceinfo Test: +##################################################################### + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qbluetoothdeviceinfo LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qbluetoothdeviceinfo + SOURCES + tst_qbluetoothdeviceinfo.cpp + LIBRARIES + Qt::Bluetooth +) diff --git a/tests/auto/qbluetoothdeviceinfo/tst_qbluetoothdeviceinfo.cpp b/tests/auto/qbluetoothdeviceinfo/tst_qbluetoothdeviceinfo.cpp new file mode 100644 index 0000000..8748789 --- /dev/null +++ b/tests/auto/qbluetoothdeviceinfo/tst_qbluetoothdeviceinfo.cpp @@ -0,0 +1,528 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include + +#include +#include + +#include +#include +#include +#include + +QT_USE_NAMESPACE + +Q_DECLARE_METATYPE(QBluetoothDeviceInfo::ServiceClasses) +Q_DECLARE_METATYPE(QBluetoothDeviceInfo::MajorDeviceClass) +Q_DECLARE_METATYPE(QBluetoothDeviceInfo::CoreConfiguration) + +class tst_QBluetoothDeviceInfo : public QObject +{ + Q_OBJECT + +public: + tst_QBluetoothDeviceInfo(); + ~tst_QBluetoothDeviceInfo(); + +private slots: + void initTestCase(); + + void tst_construction_data(); + void tst_construction(); + + void tst_assignment_data(); + void tst_assignment(); + + void tst_serviceUuids(); + + void tst_cached(); + + void tst_flags(); + + void tst_manufacturerData(); +}; + +tst_QBluetoothDeviceInfo::tst_QBluetoothDeviceInfo() +{ +} + +tst_QBluetoothDeviceInfo::~tst_QBluetoothDeviceInfo() +{ +} + +void tst_QBluetoothDeviceInfo::initTestCase() +{ + qRegisterMetaType(); + qRegisterMetaType(); + // start Bluetooth if not started + QBluetoothLocalDevice *device = new QBluetoothLocalDevice(); + device->powerOn(); + delete device; +} + +void tst_QBluetoothDeviceInfo::tst_construction_data() +{ + QTest::addColumn("address"); + QTest::addColumn("name"); + QTest::addColumn("classOfDevice"); + QTest::addColumn("serviceClasses"); + QTest::addColumn("majorDeviceClass"); + QTest::addColumn("minorDeviceClass"); + QTest::addColumn("coreConfiguration"); + // On OS X and iOS there are no real addresses + // with Core Bluetooth, only 'uuids' (128-bit) generated by Apple instead. + QTest::addColumn("deviceUuid"); + const QBluetoothUuid leDeviceUuid(QString("6C903349-31E2-40EF-826B-1E62C0D884E2")); + + // bits 12-8 Major + // bits 7-2 Minor + // bits 1-0 0 + + QTest::newRow("0x000000 COD") << QBluetoothAddress("000000000000") << "My Bluetooth Device" + << quint32(0x000000) + << QBluetoothDeviceInfo::ServiceClasses(QBluetoothDeviceInfo::NoService) + << QBluetoothDeviceInfo::MiscellaneousDevice + << quint8(QBluetoothDeviceInfo::UncategorizedMiscellaneous) + << QBluetoothDeviceInfo::BaseRateCoreConfiguration + << leDeviceUuid; + QTest::newRow("0x000100 COD") << QBluetoothAddress("000000000000") << "My Bluetooth Device" + << quint32(0x000100) + << QBluetoothDeviceInfo::ServiceClasses(QBluetoothDeviceInfo::NoService) + << QBluetoothDeviceInfo::ComputerDevice + << quint8(QBluetoothDeviceInfo::UncategorizedComputer) + << QBluetoothDeviceInfo::BaseRateCoreConfiguration + << leDeviceUuid; + QTest::newRow("0x000104 COD") << QBluetoothAddress("000000000000") << "My Bluetooth Device" + << quint32(0x000104) + << QBluetoothDeviceInfo::ServiceClasses(QBluetoothDeviceInfo::NoService) + << QBluetoothDeviceInfo::ComputerDevice + << quint8(QBluetoothDeviceInfo::DesktopComputer) + << QBluetoothDeviceInfo::BaseRateAndLowEnergyCoreConfiguration + << leDeviceUuid; + QTest::newRow("0x000118 COD") << QBluetoothAddress("000000000000") << "My Bluetooth Device" + << quint32(0x000118) + << QBluetoothDeviceInfo::ServiceClasses(QBluetoothDeviceInfo::NoService) + << QBluetoothDeviceInfo::ComputerDevice + << quint8(QBluetoothDeviceInfo::WearableComputer) + << QBluetoothDeviceInfo::BaseRateAndLowEnergyCoreConfiguration + << leDeviceUuid; + QTest::newRow("0x000200 COD") << QBluetoothAddress("000000000000") << "My Bluetooth Device" << quint32(0x000200) + << QBluetoothDeviceInfo::ServiceClasses(QBluetoothDeviceInfo::NoService) + << QBluetoothDeviceInfo::PhoneDevice + << quint8(QBluetoothDeviceInfo::UncategorizedPhone) + << QBluetoothDeviceInfo::BaseRateAndLowEnergyCoreConfiguration + << leDeviceUuid; + QTest::newRow("0x000204 COD") << QBluetoothAddress("000000000000") << "My Bluetooth Device" + << quint32(0x000204) + << QBluetoothDeviceInfo::ServiceClasses(QBluetoothDeviceInfo::NoService) + << QBluetoothDeviceInfo::PhoneDevice + << quint8(QBluetoothDeviceInfo::CellularPhone) + << QBluetoothDeviceInfo::BaseRateAndLowEnergyCoreConfiguration + << leDeviceUuid; + QTest::newRow("0x000214 COD") << QBluetoothAddress("000000000000") << "My Bluetooth Device" << quint32(0x000214) + << QBluetoothDeviceInfo::ServiceClasses(QBluetoothDeviceInfo::NoService) + << QBluetoothDeviceInfo::PhoneDevice + << quint8(QBluetoothDeviceInfo::CommonIsdnAccessPhone) + << QBluetoothDeviceInfo::BaseRateAndLowEnergyCoreConfiguration + << leDeviceUuid; + QTest::newRow("0x000300 COD") << QBluetoothAddress("000000000000") << "My Bluetooth Device" + << quint32(0x000300) + << QBluetoothDeviceInfo::ServiceClasses(QBluetoothDeviceInfo::NoService) + << QBluetoothDeviceInfo::NetworkDevice + << quint8(QBluetoothDeviceInfo::NetworkFullService) + << QBluetoothDeviceInfo::BaseRateAndLowEnergyCoreConfiguration + << leDeviceUuid; + QTest::newRow("0x000320 COD") << QBluetoothAddress("000000000000") << "My Bluetooth Device" + << quint32(0x000320) + << QBluetoothDeviceInfo::ServiceClasses(QBluetoothDeviceInfo::NoService) + << QBluetoothDeviceInfo::NetworkDevice + << quint8(QBluetoothDeviceInfo::NetworkLoadFactorOne) + << QBluetoothDeviceInfo::BaseRateAndLowEnergyCoreConfiguration + << leDeviceUuid; + QTest::newRow("0x0003E0 COD") << QBluetoothAddress("000000000000") << "My Bluetooth Device" + << quint32(0x0003E0) + << QBluetoothDeviceInfo::ServiceClasses(QBluetoothDeviceInfo::NoService) + << QBluetoothDeviceInfo::NetworkDevice + << quint8(QBluetoothDeviceInfo::NetworkNoService) + << QBluetoothDeviceInfo::BaseRateAndLowEnergyCoreConfiguration + << leDeviceUuid; + QTest::newRow("0x000400 COD") << QBluetoothAddress("000000000000") << "My Bluetooth Device" + << quint32(0x000400) + << QBluetoothDeviceInfo::ServiceClasses(QBluetoothDeviceInfo::NoService) + << QBluetoothDeviceInfo::AudioVideoDevice + << quint8(QBluetoothDeviceInfo::UncategorizedAudioVideoDevice) + << QBluetoothDeviceInfo::BaseRateAndLowEnergyCoreConfiguration + << leDeviceUuid; + QTest::newRow("0x000448 COD") << QBluetoothAddress("000000000000") << "My Bluetooth Device" + << quint32(0x000448) + << QBluetoothDeviceInfo::ServiceClasses(QBluetoothDeviceInfo::NoService) + << QBluetoothDeviceInfo::AudioVideoDevice + << quint8(QBluetoothDeviceInfo::GamingDevice) + << QBluetoothDeviceInfo::BaseRateAndLowEnergyCoreConfiguration + << leDeviceUuid; + QTest::newRow("0x000500 COD") << QBluetoothAddress("000000000000") << "My Bluetooth Device" + << quint32(0x000500) + << QBluetoothDeviceInfo::ServiceClasses(QBluetoothDeviceInfo::NoService) + << QBluetoothDeviceInfo::PeripheralDevice + << quint8(QBluetoothDeviceInfo::UncategorizedPeripheral) + << QBluetoothDeviceInfo::BaseRateAndLowEnergyCoreConfiguration + << leDeviceUuid; + QTest::newRow("0x0005D8 COD") << QBluetoothAddress("000000000000") << "My Bluetooth Device" + << quint32(0x0005D8) + << QBluetoothDeviceInfo::ServiceClasses(QBluetoothDeviceInfo::NoService) + << QBluetoothDeviceInfo::PeripheralDevice + << quint8(QBluetoothDeviceInfo::KeyboardWithPointingDevicePeripheral | QBluetoothDeviceInfo::CardReaderPeripheral) + << QBluetoothDeviceInfo::BaseRateAndLowEnergyCoreConfiguration + << leDeviceUuid; + QTest::newRow("0x000600 COD") << QBluetoothAddress("000000000000") << "My Bluetooth Device" + << quint32(0x000600) + << QBluetoothDeviceInfo::ServiceClasses(QBluetoothDeviceInfo::NoService) + << QBluetoothDeviceInfo::ImagingDevice + << quint8(QBluetoothDeviceInfo::UncategorizedImagingDevice) + << QBluetoothDeviceInfo::BaseRateAndLowEnergyCoreConfiguration + << leDeviceUuid; + QTest::newRow("0x000680 COD") << QBluetoothAddress("000000000000") << "My Bluetooth Device" + << quint32(0x000680) + << QBluetoothDeviceInfo::ServiceClasses(QBluetoothDeviceInfo::NoService) + << QBluetoothDeviceInfo::ImagingDevice + << quint8(QBluetoothDeviceInfo::ImagePrinter) + << QBluetoothDeviceInfo::LowEnergyCoreConfiguration + << leDeviceUuid; + QTest::newRow("0x000700 COD") << QBluetoothAddress("000000000000") << "My Bluetooth Device" + << quint32(0x000700) + << QBluetoothDeviceInfo::ServiceClasses(QBluetoothDeviceInfo::NoService) + << QBluetoothDeviceInfo::WearableDevice + << quint8(QBluetoothDeviceInfo::UncategorizedWearableDevice) + << QBluetoothDeviceInfo::LowEnergyCoreConfiguration + << leDeviceUuid; + QTest::newRow("0x000714 COD") << QBluetoothAddress("000000000000") << "My Bluetooth Device" + << quint32(0x000714) + << QBluetoothDeviceInfo::ServiceClasses(QBluetoothDeviceInfo::NoService) + << QBluetoothDeviceInfo::WearableDevice + << quint8(QBluetoothDeviceInfo::WearableGlasses) + << QBluetoothDeviceInfo::LowEnergyCoreConfiguration + << leDeviceUuid; + QTest::newRow("0x000800 COD") << QBluetoothAddress("000000000000") << "My Bluetooth Device" + << quint32(0x000800) + << QBluetoothDeviceInfo::ServiceClasses(QBluetoothDeviceInfo::NoService) + << QBluetoothDeviceInfo::ToyDevice + << quint8(QBluetoothDeviceInfo::UncategorizedToy) + << QBluetoothDeviceInfo::LowEnergyCoreConfiguration + << leDeviceUuid; + QTest::newRow("0x000814 COD") << QBluetoothAddress("000000000000") << "My Bluetooth Device" + << quint32(0x000814) + << QBluetoothDeviceInfo::ServiceClasses(QBluetoothDeviceInfo::NoService) + << QBluetoothDeviceInfo::ToyDevice + << quint8(QBluetoothDeviceInfo::ToyGame) + << QBluetoothDeviceInfo::LowEnergyCoreConfiguration + << leDeviceUuid; + QTest::newRow("0x001f00 COD") << QBluetoothAddress("000000000000") << "My Bluetooth Device" + << quint32(0x001f00) + << QBluetoothDeviceInfo::ServiceClasses(QBluetoothDeviceInfo::NoService) + << QBluetoothDeviceInfo::UncategorizedDevice + << quint8(0) + << QBluetoothDeviceInfo::LowEnergyCoreConfiguration + << leDeviceUuid; + QTest::newRow("0x002000 COD") << QBluetoothAddress("000000000000") << "My Bluetooth Device" + << quint32(0x002000) + << QBluetoothDeviceInfo::ServiceClasses(QBluetoothDeviceInfo::PositioningService) + << QBluetoothDeviceInfo::MiscellaneousDevice + << quint8(QBluetoothDeviceInfo::UncategorizedMiscellaneous) + << QBluetoothDeviceInfo::LowEnergyCoreConfiguration + << leDeviceUuid; + QTest::newRow("0x100000 COD") << QBluetoothAddress("000000000000") << "My Bluetooth Device" + << quint32(0x100000) + << QBluetoothDeviceInfo::ServiceClasses(QBluetoothDeviceInfo::InformationService) + << QBluetoothDeviceInfo::MiscellaneousDevice + << quint8(QBluetoothDeviceInfo::UncategorizedMiscellaneous) + << QBluetoothDeviceInfo::LowEnergyCoreConfiguration + << leDeviceUuid; + QTest::newRow("0xFFE000 COD") << QBluetoothAddress("000000000000") << "My Bluetooth Device" + << quint32(0xFFE000) + << QBluetoothDeviceInfo::ServiceClasses(QBluetoothDeviceInfo::AllServices) + << QBluetoothDeviceInfo::MiscellaneousDevice + << quint8(QBluetoothDeviceInfo::UncategorizedMiscellaneous) + << QBluetoothDeviceInfo::LowEnergyCoreConfiguration + << leDeviceUuid; +} + +void tst_QBluetoothDeviceInfo::tst_construction() +{ + { + QBluetoothDeviceInfo deviceInfo; + + QVERIFY(!deviceInfo.isValid()); + QVERIFY(deviceInfo.coreConfigurations() + == QBluetoothDeviceInfo::UnknownCoreConfiguration); + } + + { + QFETCH(QBluetoothAddress, address); + QFETCH(QString, name); + QFETCH(quint32, classOfDevice); + QFETCH(QBluetoothDeviceInfo::ServiceClasses, serviceClasses); + QFETCH(QBluetoothDeviceInfo::MajorDeviceClass, majorDeviceClass); + QFETCH(quint8, minorDeviceClass); + QFETCH(QBluetoothDeviceInfo::CoreConfiguration, coreConfiguration); + QFETCH(QBluetoothUuid, deviceUuid); + + QBluetoothDeviceInfo deviceInfo(address, name, classOfDevice); + QVERIFY(deviceInfo.isValid()); + + QCOMPARE(deviceInfo.address(), address); + QCOMPARE(deviceInfo.name(), name); + QCOMPARE(deviceInfo.serviceClasses(), serviceClasses); + QCOMPARE(deviceInfo.majorDeviceClass(), majorDeviceClass); + QCOMPARE(deviceInfo.minorDeviceClass(), minorDeviceClass); + QCOMPARE(deviceInfo.coreConfigurations(), QBluetoothDeviceInfo::UnknownCoreConfiguration); + + deviceInfo.setCoreConfigurations(coreConfiguration); + QCOMPARE(deviceInfo.coreConfigurations(), coreConfiguration); + + deviceInfo.setDeviceUuid(deviceUuid); + QCOMPARE(deviceInfo.deviceUuid(), deviceUuid); + + QBluetoothDeviceInfo copyInfo(deviceInfo); + QVERIFY(copyInfo.isValid()); + + QCOMPARE(copyInfo.address(), address); + QCOMPARE(copyInfo.name(), name); + QCOMPARE(copyInfo.serviceClasses(), serviceClasses); + QCOMPARE(copyInfo.majorDeviceClass(), majorDeviceClass); + QCOMPARE(copyInfo.minorDeviceClass(), minorDeviceClass); + QCOMPARE(copyInfo.coreConfigurations(), coreConfiguration); + QCOMPARE(copyInfo.deviceUuid(), deviceUuid); + } + + { + // Test construction from the device unique UUID, without an address. + QFETCH(QString, name); + QFETCH(quint32, classOfDevice); + QFETCH(QBluetoothDeviceInfo::ServiceClasses, serviceClasses); + QFETCH(QBluetoothDeviceInfo::MajorDeviceClass, majorDeviceClass); + QFETCH(quint8, minorDeviceClass); + QFETCH(QBluetoothDeviceInfo::CoreConfiguration, coreConfiguration); + QFETCH(QBluetoothUuid, deviceUuid); + + QBluetoothDeviceInfo deviceInfo(deviceUuid, name, classOfDevice); + QVERIFY(deviceInfo.isValid()); + + QCOMPARE(deviceInfo.name(), name); + QCOMPARE(deviceInfo.serviceClasses(), serviceClasses); + QCOMPARE(deviceInfo.majorDeviceClass(), majorDeviceClass); + QCOMPARE(deviceInfo.minorDeviceClass(), minorDeviceClass); + QCOMPARE(deviceInfo.coreConfigurations(), QBluetoothDeviceInfo::UnknownCoreConfiguration); + + deviceInfo.setCoreConfigurations(coreConfiguration); + QCOMPARE(deviceInfo.coreConfigurations(), coreConfiguration); + + QBluetoothDeviceInfo copyInfo(deviceInfo); + QVERIFY(copyInfo.isValid()); + + QCOMPARE(copyInfo.name(), name); + QCOMPARE(copyInfo.serviceClasses(), serviceClasses); + QCOMPARE(copyInfo.majorDeviceClass(), majorDeviceClass); + QCOMPARE(copyInfo.minorDeviceClass(), minorDeviceClass); + QCOMPARE(copyInfo.coreConfigurations(), coreConfiguration); + QCOMPARE(copyInfo.deviceUuid(), deviceUuid); + } +} + +void tst_QBluetoothDeviceInfo::tst_assignment_data() +{ + tst_construction_data(); +} + +void tst_QBluetoothDeviceInfo::tst_assignment() +{ + QFETCH(QBluetoothAddress, address); + QFETCH(QString, name); + QFETCH(quint32, classOfDevice); + QFETCH(QBluetoothDeviceInfo::ServiceClasses, serviceClasses); + QFETCH(QBluetoothDeviceInfo::MajorDeviceClass, majorDeviceClass); + QFETCH(quint8, minorDeviceClass); + QFETCH(QBluetoothDeviceInfo::CoreConfiguration, coreConfiguration); + QFETCH(QBluetoothUuid, deviceUuid); + + QBluetoothDeviceInfo deviceInfo(address, name, classOfDevice); + + deviceInfo.setDeviceUuid(deviceUuid); + deviceInfo.setCoreConfigurations(coreConfiguration); + + QVERIFY(deviceInfo.isValid()); + + { + QBluetoothDeviceInfo copyInfo = deviceInfo; + + QVERIFY(copyInfo.isValid()); + + QCOMPARE(copyInfo.address(), address); + QCOMPARE(copyInfo.name(), name); + QCOMPARE(copyInfo.serviceClasses(), serviceClasses); + QCOMPARE(copyInfo.majorDeviceClass(), majorDeviceClass); + QCOMPARE(copyInfo.minorDeviceClass(), minorDeviceClass); + QCOMPARE(copyInfo.coreConfigurations(), coreConfiguration); + QCOMPARE(copyInfo.deviceUuid(), deviceUuid); + } + + { + QBluetoothDeviceInfo copyInfo; + + QVERIFY(!copyInfo.isValid()); + + copyInfo = deviceInfo; + + QVERIFY(copyInfo.isValid()); + + QCOMPARE(copyInfo.address(), address); + QCOMPARE(copyInfo.name(), name); + QCOMPARE(copyInfo.serviceClasses(), serviceClasses); + QCOMPARE(copyInfo.majorDeviceClass(), majorDeviceClass); + QCOMPARE(copyInfo.minorDeviceClass(), minorDeviceClass); + QCOMPARE(copyInfo.coreConfigurations(), coreConfiguration); + QCOMPARE(copyInfo.deviceUuid(), deviceUuid); + } + + { + QBluetoothDeviceInfo copyInfo1; + QBluetoothDeviceInfo copyInfo2; + + QVERIFY(!copyInfo1.isValid()); + QVERIFY(!copyInfo2.isValid()); + + copyInfo1 = copyInfo2 = deviceInfo; + + QVERIFY(copyInfo1.isValid()); + QVERIFY(copyInfo2.isValid()); + QVERIFY(QBluetoothDeviceInfo() != copyInfo1); + + QCOMPARE(copyInfo1.address(), address); + QCOMPARE(copyInfo2.address(), address); + QCOMPARE(copyInfo1.name(), name); + QCOMPARE(copyInfo2.name(), name); + QCOMPARE(copyInfo1.serviceClasses(), serviceClasses); + QCOMPARE(copyInfo2.serviceClasses(), serviceClasses); + QCOMPARE(copyInfo1.majorDeviceClass(), majorDeviceClass); + QCOMPARE(copyInfo2.majorDeviceClass(), majorDeviceClass); + QCOMPARE(copyInfo1.minorDeviceClass(), minorDeviceClass); + QCOMPARE(copyInfo2.minorDeviceClass(), minorDeviceClass); + QCOMPARE(copyInfo1.coreConfigurations(), coreConfiguration); + QCOMPARE(copyInfo2.coreConfigurations(), coreConfiguration); + QCOMPARE(copyInfo1.deviceUuid(), deviceUuid); + QCOMPARE(copyInfo2.deviceUuid(), deviceUuid); + } + + { + QBluetoothDeviceInfo testDeviceInfo; + QVERIFY(testDeviceInfo == QBluetoothDeviceInfo()); + } +} + +void tst_QBluetoothDeviceInfo::tst_serviceUuids() +{ + QBluetoothDeviceInfo deviceInfo; + QBluetoothDeviceInfo copyInfo = deviceInfo; + + QList servicesList; + servicesList.append(QBluetoothUuid::ProtocolUuid::L2cap); + servicesList.append(QBluetoothUuid::ProtocolUuid::Rfcomm); + QVERIFY(!servicesList.isEmpty()); + + deviceInfo.setServiceUuids(servicesList); + QVERIFY(!deviceInfo.serviceUuids().isEmpty()); + deviceInfo.setServiceUuids(QList()); + QCOMPARE(deviceInfo.serviceUuids().size(), 0); +} + +void tst_QBluetoothDeviceInfo::tst_cached() +{ + QBluetoothDeviceInfo deviceInfo(QBluetoothAddress("AABBCCDDEEFF"), + QString("My Bluetooth Device"), quint32(0x002000)); + QBluetoothDeviceInfo copyInfo = deviceInfo; + + QVERIFY(!deviceInfo.isCached()); + deviceInfo.setCached(true); + QVERIFY(deviceInfo.isCached()); + QVERIFY(deviceInfo != copyInfo); + + deviceInfo.setCached(false); + QVERIFY(!(deviceInfo.isCached())); +} + +void tst_QBluetoothDeviceInfo::tst_flags() +{ + QBluetoothDeviceInfo::CoreConfigurations flags1(QBluetoothDeviceInfo::LowEnergyCoreConfiguration); + QBluetoothDeviceInfo::CoreConfigurations flags2(QBluetoothDeviceInfo::BaseRateCoreConfiguration); + QBluetoothDeviceInfo::CoreConfigurations result; + + // test QFlags &operator|=(QFlags f) + result = flags1 | flags2; + QVERIFY(result.testFlag(QBluetoothDeviceInfo::LowEnergyCoreConfiguration)); + QVERIFY(result.testFlag(QBluetoothDeviceInfo::BaseRateCoreConfiguration)); + + // test QFlags &operator|=(Enum f) + result = flags1 | QBluetoothDeviceInfo::BaseRateCoreConfiguration; + QVERIFY(result.testFlag(QBluetoothDeviceInfo::LowEnergyCoreConfiguration)); + QVERIFY(result.testFlag(QBluetoothDeviceInfo::BaseRateCoreConfiguration)); + + // test Q_DECLARE_OPERATORS_FOR_FLAGS(QBluetoothDeviceInfo::CoreConfigurations) + result = QBluetoothDeviceInfo::BaseRateCoreConfiguration | flags1; + QVERIFY(result.testFlag(QBluetoothDeviceInfo::LowEnergyCoreConfiguration)); + QVERIFY(result.testFlag(QBluetoothDeviceInfo::BaseRateCoreConfiguration)); + + QBluetoothDeviceInfo::ServiceClasses serviceFlag1(QBluetoothDeviceInfo::AudioService); + QBluetoothDeviceInfo::ServiceClasses serviceFlag2(QBluetoothDeviceInfo::CapturingService); + QBluetoothDeviceInfo::ServiceClasses serviceResult; + + // test QFlags &operator|=(QFlags f) + serviceResult = serviceFlag1 | serviceFlag2; + QVERIFY(serviceResult.testFlag(QBluetoothDeviceInfo::AudioService)); + QVERIFY(serviceResult.testFlag(QBluetoothDeviceInfo::CapturingService)); + + // test QFlags &operator|=(Enum f) + serviceResult = serviceFlag1 | QBluetoothDeviceInfo::CapturingService; + QVERIFY(serviceResult.testFlag(QBluetoothDeviceInfo::AudioService)); + QVERIFY(serviceResult.testFlag(QBluetoothDeviceInfo::CapturingService)); + + // test Q_DECLARE_OPERATORS_FOR_FLAGS(QBluetoothDeviceInfo::ServiceClasses) + serviceResult = QBluetoothDeviceInfo::CapturingService | serviceFlag1; + QVERIFY(serviceResult.testFlag(QBluetoothDeviceInfo::AudioService)); + QVERIFY(serviceResult.testFlag(QBluetoothDeviceInfo::CapturingService)); +} + +void tst_QBluetoothDeviceInfo::tst_manufacturerData() +{ + const int manufacturerAVM = 0x1F; + + QBluetoothDeviceInfo info; + QVERIFY(info.manufacturerIds().isEmpty()); + QVERIFY(info.manufacturerData(manufacturerAVM).isNull()); + + QVERIFY(info.setManufacturerData(manufacturerAVM, QByteArray::fromHex("ABCD"))); + QVERIFY(!info.setManufacturerData(manufacturerAVM, QByteArray::fromHex("ABCD"))); + QCOMPARE(info.manufacturerData(manufacturerAVM), QByteArray::fromHex("ABCD")); + auto temp = info.manufacturerData(); + QCOMPARE(temp.keys().size(), 1); + QCOMPARE(temp.values().size(), 1); + QCOMPARE(temp.values(), QList() << QByteArray::fromHex("ABCD")); + + QVERIFY(info.setManufacturerData(manufacturerAVM, QByteArray::fromHex("CDEF"))); + QVERIFY(!info.setManufacturerData(manufacturerAVM, QByteArray::fromHex("ABCD"))); + QVERIFY(!info.setManufacturerData(manufacturerAVM, QByteArray::fromHex("CDEF"))); + + temp = info.manufacturerData(); + QCOMPARE(temp.keys().size(), 2); + QCOMPARE(temp.values().size(), 2); + auto list = temp.values(); + + QCOMPARE(QSet (list.begin(), list.end()), + QSet() << QByteArray::fromHex("ABCD") << QByteArray::fromHex("CDEF")); + + // return latest entry + QCOMPARE(info.manufacturerData(manufacturerAVM), QByteArray::fromHex("CDEF")); +} + +QTEST_MAIN(tst_QBluetoothDeviceInfo) + +#include "tst_qbluetoothdeviceinfo.moc" diff --git a/tests/auto/qbluetoothhostinfo/CMakeLists.txt b/tests/auto/qbluetoothhostinfo/CMakeLists.txt new file mode 100644 index 0000000..7ab4e9c --- /dev/null +++ b/tests/auto/qbluetoothhostinfo/CMakeLists.txt @@ -0,0 +1,19 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## tst_qbluetoothhostinfo Test: +##################################################################### + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qbluetoothhostinfo LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qbluetoothhostinfo + SOURCES + tst_qbluetoothhostinfo.cpp + LIBRARIES + Qt::Bluetooth +) diff --git a/tests/auto/qbluetoothhostinfo/tst_qbluetoothhostinfo.cpp b/tests/auto/qbluetoothhostinfo/tst_qbluetoothhostinfo.cpp new file mode 100644 index 0000000..ce03564 --- /dev/null +++ b/tests/auto/qbluetoothhostinfo/tst_qbluetoothhostinfo.cpp @@ -0,0 +1,214 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include + +#include +#include + +#include + +QT_USE_NAMESPACE + +class tst_QBluetoothHostInfo : public QObject +{ + Q_OBJECT + +public: + tst_QBluetoothHostInfo(); + ~tst_QBluetoothHostInfo(); + +private slots: + void tst_address_data(); + void tst_address(); + + void tst_name_data(); + void tst_name(); + + void tst_construction_data(); + void tst_construction(); + + void tst_copy(); + + void tst_compare_data(); + void tst_compare(); +}; + +tst_QBluetoothHostInfo::tst_QBluetoothHostInfo() +{ +} + +tst_QBluetoothHostInfo::~tst_QBluetoothHostInfo() +{ +} + +void tst_QBluetoothHostInfo::tst_address() +{ + QFETCH(QString, addressString); + + QBluetoothAddress address(addressString); + QVERIFY(!address.isNull()); + QCOMPARE(address.toString(), addressString); + + QBluetoothHostInfo info; + QBluetoothAddress result = info.address(); + QVERIFY(result.isNull()); + info.setAddress(address); + QCOMPARE(info.address().toString(), addressString); + +} + +void tst_QBluetoothHostInfo::tst_address_data() +{ + QTest::addColumn("addressString"); + + QTest::newRow("11:22:33:44:55:66") << QString("11:22:33:44:55:66"); + QTest::newRow("AA:BB:CC:DD:EE:FF") << QString("AA:BB:CC:DD:EE:FF"); + QTest::newRow("aa:bb:cc:dd:ee:ff") << QString("AA:BB:CC:DD:EE:FF"); + QTest::newRow("FF:FF:FF:FF:FF:FF") << QString("FF:FF:FF:FF:FF:FF"); +} + +void tst_QBluetoothHostInfo::tst_name() +{ + QFETCH(QString, name); + + QBluetoothHostInfo info; + QString result = info.name(); + QVERIFY(result.isNull()); + QVERIFY(result.isEmpty()); + + info.setName(name); + QCOMPARE(info.name(), name); +} + +void tst_QBluetoothHostInfo::tst_name_data() +{ + QTest::addColumn("name"); + + QTest::newRow("empty/default name") << QString(); + QTest::newRow("empty name") << QString(""); + QTest::newRow("ABCD") << QString("ABCD"); + QTest::newRow("Very long name") << QString("ThisIsAVeryLongNameString-abcdefghijklmnopqrstuvwxyz"); + QTest::newRow("special chars") << QString("gh\nfg i-+.,/;"); +} + +void tst_QBluetoothHostInfo::tst_construction_data() +{ + QTest::addColumn("btAddress"); + QTest::addColumn("name"); + QTest::addColumn("validBtAddress"); + + QTest::newRow("11:22:33:44:55:66") << QString("11:22:33:44:55:66") << QString() << true; + QTest::newRow("AA:BB:CC:DD:EE:FF") << QString("AA:BB:CC:DD:EE:FF") << QString("") << true; + QTest::newRow("aa:bb:cc:dd:ee:ff") << QString("AA:BB:CC:DD:EE:FF") << QString("foobar") << true; + QTest::newRow("FF:FF:FF:FF:FF:FF") << QString("FF:FF:FF:FF:FF:FF") << QString("WeUseAlongStringAsName_FFFFFFFFFFFFFFFFFFFF") << true; + QTest::newRow("00:00:00:00:00:00") << QString("00:00:00:00:00:00") << QString("foobar2") << false; +} + +void tst_QBluetoothHostInfo::tst_construction() +{ + QFETCH(QString, btAddress); + QFETCH(QString, name); + QFETCH(bool, validBtAddress); + + QBluetoothAddress empty; + QVERIFY(empty.isNull()); + + QBluetoothHostInfo setter; + QBluetoothAddress addr(btAddress); + setter.setName(name); + setter.setAddress(addr); + QCOMPARE(setter.name(), name); + QCOMPARE(setter.address().toString(), btAddress); + QCOMPARE(setter.address().isNull(), !validBtAddress); + + setter.setAddress(empty); + QCOMPARE(setter.name(), name); + QCOMPARE(setter.address().toString(), QString("00:00:00:00:00:00")); + QCOMPARE(setter.address().isNull(), true); + + setter.setName(QString()); + QCOMPARE(setter.name(), QString()); + QCOMPARE(setter.address().toString(), QString("00:00:00:00:00:00")); + QCOMPARE(setter.address().isNull(), true); + + setter.setAddress(addr); + QCOMPARE(setter.name(), QString()); + QCOMPARE(setter.address().toString(), btAddress); + QCOMPARE(setter.address().isNull(), !validBtAddress); +} + +void tst_QBluetoothHostInfo::tst_copy() +{ + QBluetoothHostInfo original; + original.setAddress(QBluetoothAddress("11:22:33:44:55:66")); + original.setName(QStringLiteral("FunkyName")); + + QBluetoothHostInfo assignConstructor(original); + QCOMPARE(assignConstructor.name(), original.name()); + QCOMPARE(assignConstructor.address(), original.address()); + + QBluetoothHostInfo assignOperator; + assignOperator = original; + QCOMPARE(assignOperator.name(), original.name()); + QCOMPARE(assignOperator.address(), original.address()); +} + +void tst_QBluetoothHostInfo::tst_compare_data() +{ + QTest::addColumn("btAddress1"); + QTest::addColumn("name1"); + QTest::addColumn("btAddress2"); + QTest::addColumn("name2"); + QTest::addColumn("sameHostInfo"); + + QTest::newRow("11:22:33:44:55:66 - same") << QString("11:22:33:44:55:66") << QString("same") + << QString("11:22:33:44:55:66") << QString("same") + << true; + QTest::newRow("11:22:33:44:55:66 - address") << QString("11:22:33:44:55:66") << QString("same") + << QString("11:22:33:44:55:77") << QString("same") + << false; + QTest::newRow("11:22:33:44:55:66 - name") << QString("11:22:33:44:55:66") << QString("same") + << QString("11:22:33:44:55:66") << QString("different") + << false; + QTest::newRow("11:22:33:44:55:66 - name/address") << QString("11:22:33:44:55:66") << QString("same") + << QString("11:22:33:44:55:77") << QString("different") + << false; + QTest::newRow("empty") << QString() << QString() << QString() << QString() << true; + QTest::newRow("empty left") << QString() << QString() + << QString("11:22:33:44:55:66") << QString("same") << false; + QTest::newRow("empty right") << QString("11:22:33:44:55:66") << QString("same") + << QString() << QString() << false; + QTest::newRow("00:00:00:00:00:00") << QString("00:00:00:00:00:00") << QString("foobar1") + << QString("") << QString("foobar1") << true; + QTest::newRow("00:00:00:00:00:00") << QString("00:00:00:00:00:00") << QString("foobar1") + << QString("") << QString("foobar2") << false; + QTest::newRow("00:00:00:00:00:00") << QString("00:00:00:00:00:00") << QString("") + << QString("") << QString("") << true; +} + +void tst_QBluetoothHostInfo::tst_compare() +{ + QFETCH(QString, btAddress1); + QFETCH(QString, name1); + QFETCH(QString, btAddress2); + QFETCH(QString, name2); + QFETCH(bool, sameHostInfo); + + QVERIFY(QBluetoothHostInfo() == QBluetoothHostInfo()); + + QBluetoothHostInfo info1; + info1.setAddress(QBluetoothAddress(btAddress1)); + info1.setName(name1); + + QBluetoothHostInfo info2; + info2.setAddress(QBluetoothAddress(btAddress2)); + info2.setName(name2); + + QCOMPARE(info1 == info2, sameHostInfo); + QCOMPARE(info1 != info2, !sameHostInfo); +} + +QTEST_MAIN(tst_QBluetoothHostInfo) + +#include "tst_qbluetoothhostinfo.moc" diff --git a/tests/auto/qbluetoothlocaldevice/CMakeLists.txt b/tests/auto/qbluetoothlocaldevice/CMakeLists.txt new file mode 100644 index 0000000..6b38e25 --- /dev/null +++ b/tests/auto/qbluetoothlocaldevice/CMakeLists.txt @@ -0,0 +1,27 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## tst_qbluetoothlocaldevice Test: +##################################################################### + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qbluetoothlocaldevice LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qbluetoothlocaldevice + SOURCES + tst_qbluetoothlocaldevice.cpp + LIBRARIES + Qt::BluetoothPrivate +) + +## Scopes: +##################################################################### + +qt_internal_extend_target(tst_qbluetoothlocaldevice CONDITION MACOS + LIBRARIES + Qt::Widgets +) diff --git a/tests/auto/qbluetoothlocaldevice/tst_qbluetoothlocaldevice.cpp b/tests/auto/qbluetoothlocaldevice/tst_qbluetoothlocaldevice.cpp new file mode 100644 index 0000000..b434cbf --- /dev/null +++ b/tests/auto/qbluetoothlocaldevice/tst_qbluetoothlocaldevice.cpp @@ -0,0 +1,517 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include + +#include +#include +#include "../../shared/bttestutil_p.h" + +#include +#include +#include + +QT_USE_NAMESPACE + +/* + * Running the manual tests requires another Bluetooth device in the vincinity. + * The remote device's address must be passed via the BT_TEST_DEVICE env variable. + * Every pairing request must be accepted within a 10s interval of appearing. + * If BT_TEST_DEVICE is not set manual tests will be skipped. + **/ + +class tst_QBluetoothLocalDevice : public QObject +{ + Q_OBJECT + +public: + tst_QBluetoothLocalDevice(); + ~tst_QBluetoothLocalDevice(); + +private slots: + void initTestCase(); + void tst_powerOn(); + void tst_powerOff(); + void tst_hostModes(); + void tst_hostModes_data(); + void tst_address(); + void tst_name(); + void tst_isValid(); + void tst_allDevices(); + void tst_construction(); + void tst_pairingStatus_data(); + void tst_pairingStatus(); + void tst_pairDevice_data(); + void tst_pairDevice(); + void tst_connectedDevices(); + +private: + QBluetoothAddress remoteDevice; + qsizetype numDevices = 0; + bool expectRemoteDevice = false; +}; + +tst_QBluetoothLocalDevice::tst_QBluetoothLocalDevice() +{ + if (androidBluetoothEmulator()) + return; + numDevices = QBluetoothLocalDevice::allDevices().size(); + const QString remote = qgetenv("BT_TEST_DEVICE"); + if (!remote.isEmpty()) { + remoteDevice = QBluetoothAddress(remote); + expectRemoteDevice = true; + qWarning() << "Using remote device " << remote << " for testing. Ensure that the device is discoverable for pairing requests"; + } else { + qWarning() << "Not using any remote device for testing. Set BT_TEST_DEVICE env to run manual tests involving a remote device"; + } +} + +tst_QBluetoothLocalDevice::~tst_QBluetoothLocalDevice() +{ +} + +void tst_QBluetoothLocalDevice::initTestCase() +{ + if (expectRemoteDevice) { + //test passed Bt address here since we cannot do that in the ctor + QVERIFY2(!remoteDevice.isNull(), "BT_TEST_DEVICE is not a valid Bluetooth address" ); + } +} + +void tst_QBluetoothLocalDevice::tst_powerOn() +{ + if (androidBluetoothEmulator()) + QSKIP("Skipping test on Android 12+ emulator, CI can timeout waiting for user input"); +#ifdef Q_OS_MACOS + QSKIP("Not possible on OS X"); +#endif + if (numDevices == 0) + QSKIP("Skipping test due to missing Bluetooth device"); + + QBluetoothLocalDevice localDevice; + if (localDevice.hostMode() != QBluetoothLocalDevice::HostPoweredOff) { + // Ensure device is OFF so we can test switching it ON + localDevice.setHostMode(QBluetoothLocalDevice::HostPoweredOff); + // On Android user may need to authorize the transition, hence a longer timeout + QTRY_VERIFY_WITH_TIMEOUT(localDevice.hostMode() + == QBluetoothLocalDevice::HostPoweredOff, 15000); + // Allow possible mode-change signal(s) to arrive (QTRY_COMPARE polls the + // host mode in a loop, and thus may return before the host mode change signal) + QTest::qWait(1000); + } + + QSignalSpy hostModeSpy(&localDevice, SIGNAL(hostModeStateChanged(QBluetoothLocalDevice::HostMode))); + // there should be no changes yet + QVERIFY(hostModeSpy.isValid()); + QVERIFY(hostModeSpy.isEmpty()); + + localDevice.powerOn(); + // On Android user may need to authorize the transition => longer timeout. + QTRY_VERIFY_WITH_TIMEOUT(!hostModeSpy.isEmpty(), 15000); + QVERIFY(localDevice.hostMode() + != QBluetoothLocalDevice::HostPoweredOff); +} + +void tst_QBluetoothLocalDevice::tst_powerOff() +{ + if (androidBluetoothEmulator()) + QSKIP("Skipping test on Android 12+ emulator, CI can timeout waiting for user input"); +#ifdef Q_OS_MACOS + QSKIP("Not possible on OS X"); +#endif + if (numDevices == 0) + QSKIP("Skipping test due to missing Bluetooth device"); + + QBluetoothLocalDevice localDevice; + if (localDevice.hostMode() == QBluetoothLocalDevice::HostPoweredOff) { + // Ensure device is ON so we can test switching it OFF + localDevice.powerOn(); + // On Android user may need to authorize the transition => longer timeout. + QTRY_VERIFY_WITH_TIMEOUT(localDevice.hostMode() + != QBluetoothLocalDevice::HostPoweredOff, 15000); + // Allow possible mode-change signal(s) to arrive (QTRY_COMPARE polls the + // host mode in a loop, and thus may return before the host mode change signal) + QTest::qWait(1000); + } + + QSignalSpy hostModeSpy(&localDevice, SIGNAL(hostModeStateChanged(QBluetoothLocalDevice::HostMode))); + // there should be no changes yet + QVERIFY(hostModeSpy.isValid()); + QVERIFY(hostModeSpy.isEmpty()); + + localDevice.setHostMode(QBluetoothLocalDevice::HostPoweredOff); + // On Android user may need to authorize the transition => longer timeout. + QTRY_VERIFY_WITH_TIMEOUT(!hostModeSpy.isEmpty(), 15000); + QVERIFY(localDevice.hostMode() + == QBluetoothLocalDevice::HostPoweredOff); +} + +void tst_QBluetoothLocalDevice::tst_hostModes_data() +{ + QTest::addColumn("hostModeExpected"); + QTest::addColumn("expectSignal"); +#if defined(Q_OS_WIN) + // On Windows local device does not support HostDiscoverable as a separate mode + QTest::newRow("HostPoweredOff1") << QBluetoothLocalDevice::HostPoweredOff << false; + QTest::newRow("HostConnectable1") << QBluetoothLocalDevice::HostConnectable << true; + QTest::newRow("HostConnectable2") << QBluetoothLocalDevice::HostConnectable << false; + QTest::newRow("HostPoweredOff3") << QBluetoothLocalDevice::HostPoweredOff << true; + QTest::newRow("HostPoweredOff3") << QBluetoothLocalDevice::HostPoweredOff << false; + return; +#elif defined(Q_OS_ANDROID) + if (QNativeInterface::QAndroidApplication::sdkVersion() >= 31) { + // On Android-12 (API Level 31+) it seems the device's bluetooth visibility setting + // defines if we enter "HostDiscoverable" (visible true) or "HostConnectable" + // (visible false). Here we assume that the visibility setting is true. For lower + // Android versions the default testdata rows are fine + qDebug() << "On this Android version the bluetooth visibility setting is assumed true"; + QTest::newRow("HostDiscoverable1") << QBluetoothLocalDevice::HostDiscoverable << true; + QTest::newRow("HostPoweredOff1") << QBluetoothLocalDevice::HostPoweredOff << true; + QTest::newRow("HostPoweredOff2") << QBluetoothLocalDevice::HostPoweredOff << false; + QTest::newRow("HostDiscoverable2") << QBluetoothLocalDevice::HostDiscoverable << true; + QTest::newRow("HostPoweredOff3") << QBluetoothLocalDevice::HostPoweredOff << true; + QTest::newRow("HostDiscoverable3") << QBluetoothLocalDevice::HostDiscoverable << true; + QTest::newRow("HostDiscoverable4") << QBluetoothLocalDevice::HostDiscoverable << false; + return; + } +#endif + QTest::newRow("HostDiscoverable1") << QBluetoothLocalDevice::HostDiscoverable << true; + QTest::newRow("HostPoweredOff1") << QBluetoothLocalDevice::HostPoweredOff << true; + QTest::newRow("HostPoweredOff2") << QBluetoothLocalDevice::HostPoweredOff << false; + QTest::newRow("HostConnectable1") << QBluetoothLocalDevice::HostConnectable << true; + QTest::newRow("HostConnectable2") << QBluetoothLocalDevice::HostConnectable << false; + QTest::newRow("HostDiscoverable2") << QBluetoothLocalDevice::HostDiscoverable << true; + QTest::newRow("HostConnectable3") << QBluetoothLocalDevice::HostConnectable << true; + QTest::newRow("HostPoweredOff3") << QBluetoothLocalDevice::HostPoweredOff << true; + QTest::newRow("HostDiscoverable3") << QBluetoothLocalDevice::HostDiscoverable << true; + QTest::newRow("HostDiscoverable4") << QBluetoothLocalDevice::HostDiscoverable << false; + QTest::newRow("HostConnectable4") << QBluetoothLocalDevice::HostConnectable << true; +} + +void tst_QBluetoothLocalDevice::tst_hostModes() +{ + if (androidBluetoothEmulator()) + QSKIP("Skipping test on Android 12+ emulator, CI can timeout waiting for user input"); +#ifdef Q_OS_MACOS + QSKIP("Not possible on OS X"); +#endif + QFETCH(QBluetoothLocalDevice::HostMode, hostModeExpected); + QFETCH(bool, expectSignal); + + if (numDevices == 0) + QSKIP("Skipping test due to missing Bluetooth device"); + + QBluetoothLocalDevice localDevice; + + static bool firstIteration = true; + if (firstIteration) { + // On the first iteration establish a known hostmode so that the test + // function can reliably test changes to it + firstIteration = false; + if (localDevice.hostMode() != QBluetoothLocalDevice::HostPoweredOff) { + localDevice.setHostMode(QBluetoothLocalDevice::HostPoweredOff); + // On Android user may need to authorize the transition => longer timeout. + QTRY_VERIFY_WITH_TIMEOUT(localDevice.hostMode() + == QBluetoothLocalDevice::HostPoweredOff, 15000); + // Allow possible mode-change signal(s) to arrive (QTRY_COMPARE polls the + // host mode in a loop, and thus may return before the host mode change signal). + QTest::qWait(1000); + } + } + + QSignalSpy hostModeSpy(&localDevice, + SIGNAL(hostModeStateChanged(QBluetoothLocalDevice::HostMode))); + // there should be no changes yet + QVERIFY(hostModeSpy.isValid()); + QVERIFY(hostModeSpy.isEmpty()); + + // Switch the bluetooth mode and verify it changes + localDevice.setHostMode(hostModeExpected); + // Manual interaction may be needed (for example on Android you may + // need to authorize a permission) => hence a longer timeout. + // If you see a fail on Android here, please see the comment in _data() + QTRY_COMPARE_WITH_TIMEOUT(localDevice.hostMode(), hostModeExpected, 15000); + // Allow possible mode-change signal(s) to arrive (QTRY_COMPARE polls the + // host mode in a loop, and thus may return before the host mode change signal). + QTest::qWait(1000); + + // Verify that signals are as expected + if (expectSignal) { + QVERIFY(hostModeSpy.size() > 0); + // Verify that the last signal contained the right mode + auto arguments = hostModeSpy.takeLast(); + auto hostMode = qvariant_cast(arguments.at(0)); + QCOMPARE(hostMode, hostModeExpected); + } else { + QCOMPARE(hostModeSpy.size(), 0); + } +} + +void tst_QBluetoothLocalDevice::tst_address() +{ + if (numDevices == 0) + QSKIP("Skipping test due to missing Bluetooth device"); + + QBluetoothLocalDevice localDevice; + QVERIFY(!localDevice.address().toString().isEmpty()); + QVERIFY(!localDevice.address().isNull()); +} +void tst_QBluetoothLocalDevice::tst_name() +{ + if (numDevices == 0) + QSKIP("Skipping test due to missing Bluetooth device"); + + QBluetoothLocalDevice localDevice; + QVERIFY(!localDevice.name().isEmpty()); +} +void tst_QBluetoothLocalDevice::tst_isValid() +{ + if (androidBluetoothEmulator()) + QSKIP("Skipping test on Android 12+ emulator, CI can timeout waiting for user input"); +#if defined(Q_OS_MACOS) || QT_CONFIG(winrt_bt) + // On OS X we can have a valid device (device.isValid() == true), + // that has neither a name nor a valid address - this happens + // if a Bluetooth adapter is OFF. + if (numDevices == 0) + QSKIP("Skipping test due to missing Bluetooth device"); +#endif + + QBluetoothLocalDevice localDevice; + QBluetoothAddress invalidAddress("FF:FF:FF:FF:FF:FF"); + + const QList devices = QBluetoothLocalDevice::allDevices(); + if (!devices.isEmpty()) { + QVERIFY(localDevice.isValid()); + bool defaultFound = false; + for (qsizetype i = 0; i < devices.size(); ++i) { + QVERIFY(devices.at(i).address() != invalidAddress); + if (devices.at(i).address() == localDevice.address() ) { + defaultFound = true; + } else { + QBluetoothLocalDevice otherDevice(devices.at(i).address()); + QVERIFY(otherDevice.isValid()); + } + } + QVERIFY(defaultFound); + } else { + QVERIFY(!localDevice.isValid()); + } + + //ensure common behavior of invalid local device + QBluetoothLocalDevice invalidLocalDevice(invalidAddress); + QVERIFY(!invalidLocalDevice.isValid()); + QCOMPARE(invalidLocalDevice.address(), QBluetoothAddress()); + QCOMPARE(invalidLocalDevice.name(), QString()); + QCOMPARE(invalidLocalDevice.pairingStatus(QBluetoothAddress()), QBluetoothLocalDevice::Unpaired ); + QCOMPARE(invalidLocalDevice.hostMode(), QBluetoothLocalDevice::HostPoweredOff); +} + +void tst_QBluetoothLocalDevice::tst_allDevices() +{ + //nothing we can really test here +} +void tst_QBluetoothLocalDevice::tst_construction() +{ + if (numDevices == 0) + QSKIP("Skipping test due to missing Bluetooth device"); + + QBluetoothLocalDevice localDevice; + QVERIFY(localDevice.isValid()); + + QBluetoothLocalDevice anotherDevice(QBluetoothAddress(000000000000)); + QVERIFY(anotherDevice.isValid()); + QVERIFY(anotherDevice.address().toUInt64() != 0); + +} + +void tst_QBluetoothLocalDevice::tst_pairDevice_data() +{ + QTest::addColumn("deviceAddress"); + QTest::addColumn("pairingExpected"); + //waiting time larger for manual tests -> requires device interaction + QTest::addColumn("pairingWaitTime"); + QTest::addColumn("expectErrorSignal"); + + QTest::newRow("UnPaired Device: DUMMY->unpaired") << QBluetoothAddress("11:00:00:00:00:00") + << QBluetoothLocalDevice::Unpaired << 1000 << false; + //Bluez5 may have to do a device search which can take up to 20s + QTest::newRow("UnPaired Device: DUMMY->paired") << QBluetoothAddress("11:00:00:00:00:00") + << QBluetoothLocalDevice::Paired << 21000 << true; + QTest::newRow("UnPaired Device: DUMMY") << QBluetoothAddress() + << QBluetoothLocalDevice::Unpaired << 1000 << true; + + if (!remoteDevice.isNull()) { + // Unpairing is quick but pairing level upgrade requires manual interaction + // on both devices. Therefore the timeouts are higher for the changes + // which require manual interaction. + QTest::newRow("UnParing Test device 1") << QBluetoothAddress(remoteDevice) + << QBluetoothLocalDevice::Unpaired << 5000 << false; + //Bluez5 may have to do a device search which can take up to 20s + QTest::newRow("Pairing Test Device") << QBluetoothAddress(remoteDevice) + << QBluetoothLocalDevice::Paired << 30000 << false; + QTest::newRow("Pairing upgrade for Authorization") << QBluetoothAddress(remoteDevice) + << QBluetoothLocalDevice::AuthorizedPaired << 5000 << false; + QTest::newRow("Unpairing Test device 2") << QBluetoothAddress(remoteDevice) + << QBluetoothLocalDevice::Unpaired << 5000 << false; + QTest::newRow("Authorized Pairing") << QBluetoothAddress(remoteDevice) + << QBluetoothLocalDevice::AuthorizedPaired << 30000 << false; + QTest::newRow("Pairing Test Device after Authorization Pairing") << QBluetoothAddress(remoteDevice) + << QBluetoothLocalDevice::Paired << 5000 << false; + + QTest::newRow("Pairing Test Device after Authorization2") << QBluetoothAddress(remoteDevice) + << QBluetoothLocalDevice::Paired << 5000 << false; //same again + QTest::newRow("Unpairing Test device 3") << QBluetoothAddress(remoteDevice) + << QBluetoothLocalDevice::Unpaired << 5000 << false; + QTest::newRow("UnParing Test device 4") << QBluetoothAddress(remoteDevice) + << QBluetoothLocalDevice::Unpaired << 5000 << false; + } +} + +void tst_QBluetoothLocalDevice::tst_pairDevice() +{ + if (androidBluetoothEmulator()) + QSKIP("Skipping test on Android 12+ emulator, CI can timeout waiting for user input"); +#if defined(Q_OS_MACOS) + QSKIP("The pair device test fails on macOS"); +#endif + QFETCH(QBluetoothAddress, deviceAddress); + QFETCH(QBluetoothLocalDevice::Pairing, pairingExpected); + QFETCH(int, pairingWaitTime); + QFETCH(bool, expectErrorSignal); + + if (numDevices == 0) + QSKIP("Skipping test due to missing Bluetooth device"); + + QBluetoothLocalDevice localDevice; + //powerOn if not already + if (localDevice.hostMode() == QBluetoothLocalDevice::HostPoweredOff) { + localDevice.powerOn(); + QTRY_VERIFY(localDevice.hostMode() != QBluetoothLocalDevice::HostPoweredOff); + } + + QSignalSpy pairingSpy(&localDevice, SIGNAL(pairingFinished(QBluetoothAddress,QBluetoothLocalDevice::Pairing)) ); + QSignalSpy errorSpy(&localDevice, SIGNAL(errorOccurred(QBluetoothLocalDevice::Error))); + // there should be no signals yet + QVERIFY(pairingSpy.isValid()); + QVERIFY(pairingSpy.isEmpty()); + QVERIFY(errorSpy.isValid()); + QVERIFY(errorSpy.isEmpty()); + + QVERIFY(localDevice.isValid()); + + localDevice.requestPairing(deviceAddress, pairingExpected); + + // The above function triggers async interaction with the user on two machines. + // Responding takes time. Let's adjust the subsequent timeout dyncamically based on + // the need of the operation + if (expectErrorSignal) { + QTRY_VERIFY_WITH_TIMEOUT(!errorSpy.isEmpty(), pairingWaitTime); + QVERIFY(pairingSpy.isEmpty()); + QList arguments = errorSpy.first(); + QBluetoothLocalDevice::Error e = qvariant_cast(arguments.at(0)); + QCOMPARE(e, QBluetoothLocalDevice::PairingError); + } else { + QTRY_VERIFY_WITH_TIMEOUT(!pairingSpy.isEmpty(), pairingWaitTime); + QVERIFY(errorSpy.isEmpty()); + + // test the actual signal values. + QList arguments = pairingSpy.takeFirst(); + QBluetoothAddress address = qvariant_cast(arguments.at(0)); + QBluetoothLocalDevice::Pairing pairingResult = qvariant_cast(arguments.at(1)); + QCOMPARE(deviceAddress, address); + // Verify that the local device pairing status and the signal value match + QCOMPARE(pairingResult, localDevice.pairingStatus(deviceAddress)); +#ifndef Q_OS_WIN + // On Windows the resulting pairing mode may differ from test's "expected" as the + // decision is up to Windows. +#ifdef Q_OS_ANDROID + // On Android we always use "Paired" + if (pairingExpected == QBluetoothLocalDevice::AuthorizedPaired) + pairingExpected = QBluetoothLocalDevice::Paired; +#endif + QCOMPARE(pairingResult, pairingExpected); + QCOMPARE(localDevice.pairingStatus(deviceAddress), pairingExpected); +#endif + } +} + +void tst_QBluetoothLocalDevice::tst_connectedDevices() +{ +#if defined(Q_OS_MACOS) + QSKIP("The connectedDevices test fails on macOS"); +#endif + if (numDevices == 0) + QSKIP("Skipping test due to missing Bluetooth device"); + if (remoteDevice.isNull()) + QSKIP("This test only makes sense with remote device"); + + QBluetoothLocalDevice localDevice; + // powerOn if not already + if (localDevice.hostMode() == QBluetoothLocalDevice::HostPoweredOff) { + localDevice.powerOn(); + QTRY_VERIFY(localDevice.hostMode() != QBluetoothLocalDevice::HostPoweredOff); + } + + QSignalSpy pairingSpy(&localDevice, &QBluetoothLocalDevice::pairingFinished); + + // Make sure that the remote device is not paired + localDevice.requestPairing(remoteDevice, QBluetoothLocalDevice::Unpaired); + QTRY_VERIFY(!pairingSpy.isEmpty()); + + QList connectedDevices = localDevice.connectedDevices(); + QVERIFY(!connectedDevices.contains(remoteDevice)); + + QSignalSpy deviceConnectedSpy(&localDevice, &QBluetoothLocalDevice::deviceConnected); + QSignalSpy deviceDisconnectedSpy(&localDevice, &QBluetoothLocalDevice::deviceDisconnected); + + // Now pair with the device. We should have a deviceConnected signal. + pairingSpy.clear(); + localDevice.requestPairing(remoteDevice, QBluetoothLocalDevice::Paired); + // Manual confirmation for pairing might be required + QTRY_VERIFY_WITH_TIMEOUT(!pairingSpy.isEmpty(), 30000); + QTRY_VERIFY(!deviceConnectedSpy.isEmpty()); + QList arguments = deviceConnectedSpy.takeFirst(); + auto address = arguments.at(0).value(); + QCOMPARE(address, remoteDevice); + + connectedDevices = localDevice.connectedDevices(); + QVERIFY(connectedDevices.contains(remoteDevice)); + + // Unpair again. We should have a deviceDisconnected signal. + pairingSpy.clear(); + localDevice.requestPairing(remoteDevice, QBluetoothLocalDevice::Unpaired); + QTRY_VERIFY(!pairingSpy.isEmpty()); + QTRY_VERIFY(!deviceDisconnectedSpy.isEmpty()); + arguments = deviceDisconnectedSpy.takeFirst(); + address = arguments.at(0).value(); + QCOMPARE(address, remoteDevice); + + connectedDevices = localDevice.connectedDevices(); + QVERIFY(!connectedDevices.contains(remoteDevice)); +} + +void tst_QBluetoothLocalDevice::tst_pairingStatus_data() +{ + QTest::addColumn("deviceAddress"); + QTest::addColumn("pairingExpected"); + + QTest::newRow("UnPaired Device: DUMMY") << QBluetoothAddress("11:00:00:00:00:00") + << QBluetoothLocalDevice::Unpaired; + QTest::newRow("Invalid device") << QBluetoothAddress() << QBluetoothLocalDevice::Unpaired; + //valid devices are already tested by tst_pairDevice() +} + +void tst_QBluetoothLocalDevice::tst_pairingStatus() +{ + QFETCH(QBluetoothAddress, deviceAddress); + QFETCH(QBluetoothLocalDevice::Pairing, pairingExpected); + + if (numDevices == 0) + QSKIP("Skipping test due to missing Bluetooth device"); + + QBluetoothLocalDevice localDevice; + QCOMPARE(pairingExpected, localDevice.pairingStatus(deviceAddress)); +} +QTEST_MAIN(tst_QBluetoothLocalDevice) + +#include "tst_qbluetoothlocaldevice.moc" diff --git a/tests/auto/qbluetoothserver/CMakeLists.txt b/tests/auto/qbluetoothserver/CMakeLists.txt new file mode 100644 index 0000000..f1e29b0 --- /dev/null +++ b/tests/auto/qbluetoothserver/CMakeLists.txt @@ -0,0 +1,30 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## tst_qbluetoothserver Test: +##################################################################### + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qbluetoothserver LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qbluetoothserver + SOURCES + tst_qbluetoothserver.cpp + LIBRARIES + Qt::BluetoothPrivate +) + +#### Keys ignored in scope 1:.:.:qbluetoothserver.pro:: +# OTHER_FILES = "README.txt" + +## Scopes: +##################################################################### + +qt_internal_extend_target(tst_qbluetoothserver CONDITION MACOS + LIBRARIES + Qt::Widgets +) diff --git a/tests/auto/qbluetoothserver/tst_qbluetoothserver.cpp b/tests/auto/qbluetoothserver/tst_qbluetoothserver.cpp new file mode 100644 index 0000000..ed56d49 --- /dev/null +++ b/tests/auto/qbluetoothserver/tst_qbluetoothserver.cpp @@ -0,0 +1,219 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include + +#include + +#include "../../shared/bttestutil_p.h" +#include +#include +#include +#include + +QT_USE_NAMESPACE + +Q_DECLARE_METATYPE(QBluetooth::SecurityFlags) + +class tst_QBluetoothServer : public QObject +{ + Q_OBJECT + +public: + tst_QBluetoothServer(); + ~tst_QBluetoothServer(); + +private slots: + void initTestCase(); + void cleanupTestCase(); + + void tst_construction(); + + void tst_receive_data(); + void tst_receive(); + + void setHostMode(const QBluetoothAddress &localAdapter, QBluetoothLocalDevice::HostMode newHostMode); + +private: + QBluetoothLocalDevice *localDevice = nullptr; + QBluetoothLocalDevice::HostMode initialHostMode; +}; + +tst_QBluetoothServer::tst_QBluetoothServer() +{ +} + +tst_QBluetoothServer::~tst_QBluetoothServer() +{ +} + +void tst_QBluetoothServer::setHostMode(const QBluetoothAddress &localAdapter, + QBluetoothLocalDevice::HostMode newHostMode) +{ + QBluetoothLocalDevice device(localAdapter); + QSignalSpy hostModeSpy(&device, SIGNAL(hostModeStateChanged(QBluetoothLocalDevice::HostMode))); + + if (!device.isValid()) + return; + + if (device.hostMode() == newHostMode) + return; + + //We distinguish powerOn() and setHostMode(HostConnectable) because + //Android uses different permission levels, we want to avoid interaction with user + //which implies usage of powerOn -> unfortunately powerOn() is not equivalent to HostConnectable + //Unfortunately the discoverable mode always requires a user confirmation + switch (newHostMode) { + case QBluetoothLocalDevice::HostPoweredOff: + case QBluetoothLocalDevice::HostDiscoverable: + case QBluetoothLocalDevice::HostDiscoverableLimitedInquiry: + device.setHostMode(newHostMode); + break; + case QBluetoothLocalDevice::HostConnectable: + device.powerOn(); + break; + } + + int connectTime = 5000; // ms + while (hostModeSpy.isEmpty() && connectTime > 0) { + QTest::qWait(500); + connectTime -= 500; + } +} + +void tst_QBluetoothServer::initTestCase() +{ + if (androidBluetoothEmulator()) + QSKIP("Skipping test on Android 12+ emulator, CI can timeout waiting for user input"); + qRegisterMetaType(); + qRegisterMetaType(); + + localDevice = new QBluetoothLocalDevice(this); + + QBluetoothLocalDevice device; + if (!device.isValid()) + return; + + initialHostMode = device.hostMode(); +#ifdef Q_OS_MACOS + if (initialHostMode == QBluetoothLocalDevice::HostPoweredOff) + return; +#endif + + setHostMode(device.address(), QBluetoothLocalDevice::HostConnectable); + + QBluetoothLocalDevice::HostMode hostMode= localDevice->hostMode(); + + QVERIFY(hostMode != QBluetoothLocalDevice::HostPoweredOff); +} + +void tst_QBluetoothServer::cleanupTestCase() +{ + if (localDevice) + setHostMode(localDevice->address(), initialHostMode); +} + +void tst_QBluetoothServer::tst_construction() +{ + { + QBluetoothServer server(QBluetoothServiceInfo::RfcommProtocol); + + QVERIFY(!server.isListening()); + QCOMPARE(server.maxPendingConnections(), 1); + QVERIFY(!server.hasPendingConnections()); + QVERIFY(server.nextPendingConnection() == 0); + QCOMPARE(server.error(), QBluetoothServer::NoError); + QCOMPARE(server.serverType(), QBluetoothServiceInfo::RfcommProtocol); + } + + { + QBluetoothServer server(QBluetoothServiceInfo::L2capProtocol); + + QVERIFY(!server.isListening()); + QCOMPARE(server.maxPendingConnections(), 1); + QVERIFY(!server.hasPendingConnections()); + QVERIFY(server.nextPendingConnection() == 0); + QCOMPARE(server.error(), QBluetoothServer::NoError); + QCOMPARE(server.serverType(), QBluetoothServiceInfo::L2capProtocol); + } +} + +void tst_QBluetoothServer::tst_receive_data() +{ + QTest::addColumn("hostmode"); + QTest::newRow("offline mode") << QBluetoothLocalDevice::HostPoweredOff; + QTest::newRow("online mode") << QBluetoothLocalDevice::HostConnectable; +} + +void tst_QBluetoothServer::tst_receive() +{ + QFETCH(QBluetoothLocalDevice::HostMode, hostmode); + + QBluetoothLocalDevice localDev; +#ifdef Q_OS_MACOS + if (localDev.hostMode() == QBluetoothLocalDevice::HostPoweredOff) + QSKIP("On OS X this test requires Bluetooth adapter ON"); +#endif + const QBluetoothAddress address = localDev.address(); + + bool localDeviceAvailable = localDev.isValid(); + + if (localDeviceAvailable) { + // setHostMode is noop on OS X and winrt. + setHostMode(address, hostmode); + + if (hostmode == QBluetoothLocalDevice::HostPoweredOff) { +#if !defined(Q_OS_MACOS) && !QT_CONFIG(winrt_bt) + QCOMPARE(localDevice->hostMode(), hostmode); +#endif + } else { + QVERIFY(localDevice->hostMode() != QBluetoothLocalDevice::HostPoweredOff); + } + } + QBluetoothServer server(QBluetoothServiceInfo::RfcommProtocol); + QSignalSpy errorSpy(&server, SIGNAL(errorOccurred(QBluetoothServer::Error))); + + bool result = server.listen(address, 20); // port == 20 + QTest::qWait(1000); + + if (!result) { +#ifndef Q_OS_ANDROID + // Disable address check on Android as an actual device always returns + // a valid address, while the emulator doesn't + QCOMPARE(server.serverAddress(), QBluetoothAddress()); +#endif + QCOMPARE(server.serverPort(), quint16(0)); + QVERIFY(!errorSpy.isEmpty()); + QVERIFY(!server.isListening()); + if (!localDeviceAvailable) { + QVERIFY(server.error() != QBluetoothServer::NoError); + } else { + //local device but poweredOff + QCOMPARE(server.error(), QBluetoothServer::PoweredOffError); + } + return; + } + + QVERIFY(result); + +#if !QT_CONFIG(winrt_bt) + QVERIFY(!QBluetoothLocalDevice::allDevices().isEmpty()); +#endif + QCOMPARE(server.error(), QBluetoothServer::NoError); + QCOMPARE(server.serverAddress(), address); + QCOMPARE(server.serverPort(), quint16(20)); + QVERIFY(server.isListening()); + QVERIFY(!server.hasPendingConnections()); + + server.close(); + QCOMPARE(server.error(), QBluetoothServer::NoError); + QVERIFY(server.serverAddress() == address || server.serverAddress() == QBluetoothAddress()); + QVERIFY(server.serverPort() == 0); + QVERIFY(!server.isListening()); + QVERIFY(!server.hasPendingConnections()); +} + + +QTEST_MAIN(tst_QBluetoothServer) + +#include "tst_qbluetoothserver.moc" diff --git a/tests/auto/qbluetoothservicediscoveryagent/CMakeLists.txt b/tests/auto/qbluetoothservicediscoveryagent/CMakeLists.txt new file mode 100644 index 0000000..76cd469 --- /dev/null +++ b/tests/auto/qbluetoothservicediscoveryagent/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## tst_qbluetoothservicediscoveryagent Test: +##################################################################### + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qbluetoothservicediscoveryagent LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qbluetoothservicediscoveryagent + SOURCES + tst_qbluetoothservicediscoveryagent.cpp + LIBRARIES + Qt::Bluetooth +) + +## Scopes: +##################################################################### + +qt_internal_extend_target(tst_qbluetoothservicediscoveryagent CONDITION MACOS + LIBRARIES + Qt::Widgets +) + +set_target_properties(tst_qbluetoothservicediscoveryagent PROPERTIES + MACOSX_BUNDLE TRUE +) + +if (APPLE AND NOT IOS) + # Ninja has trouble with relative paths, convert to absolute as a workaround + get_filename_component(SHARED_PLIST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../shared ABSOLUTE) + set_target_properties(tst_qbluetoothservicediscoveryagent PROPERTIES + MACOSX_BUNDLE_INFO_PLIST "${SHARED_PLIST_DIR}/Info.macos.plist" + ) +endif() diff --git a/tests/auto/qbluetoothservicediscoveryagent/tst_qbluetoothservicediscoveryagent.cpp b/tests/auto/qbluetoothservicediscoveryagent/tst_qbluetoothservicediscoveryagent.cpp new file mode 100644 index 0000000..0438246 --- /dev/null +++ b/tests/auto/qbluetoothservicediscoveryagent/tst_qbluetoothservicediscoveryagent.cpp @@ -0,0 +1,463 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include + +#include +#include +#include +#include +#include "../../shared/bttestutil_p.h" + +#include +#include +#include +#include +#include +#include + +QT_USE_NAMESPACE + +// Maximum time to for bluetooth device scan +const int MaxScanTime = 5 * 60 * 1000; // 5 minutes in ms + +class tst_QBluetoothServiceDiscoveryAgent : public QObject +{ + Q_OBJECT + +public: + tst_QBluetoothServiceDiscoveryAgent(); + ~tst_QBluetoothServiceDiscoveryAgent(); + +public slots: + void deviceDiscoveryDebug(const QBluetoothDeviceInfo &info); + void serviceDiscoveryDebug(const QBluetoothServiceInfo &info); + void serviceError(const QBluetoothServiceDiscoveryAgent::Error err); + +private slots: + void initTestCase(); + + void tst_invalidBtAddress(); + void tst_serviceDiscovery_data(); + void tst_serviceDiscovery(); + void tst_serviceDiscoveryStop(); + void tst_serviceDiscoveryAdapters(); + +private: + QList devices; + bool localDeviceAvailable; +}; + +tst_QBluetoothServiceDiscoveryAgent::tst_QBluetoothServiceDiscoveryAgent() +{ + QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true")); + if (androidBluetoothEmulator()) + return; + // start Bluetooth if not started +#ifndef Q_OS_MACOS + QBluetoothLocalDevice *device = new QBluetoothLocalDevice(); + localDeviceAvailable = device->isValid(); + if (localDeviceAvailable) { + device->powerOn(); + // wait for the device to switch bluetooth mode. + QTest::qWait(1000); + } + delete device; +#else + QBluetoothLocalDevice device; + localDeviceAvailable = QBluetoothLocalDevice().hostMode() != QBluetoothLocalDevice::HostPoweredOff; +#endif + + qRegisterMetaType(); + qRegisterMetaType >(); + qRegisterMetaType(); + qRegisterMetaType(); + +} + +tst_QBluetoothServiceDiscoveryAgent::~tst_QBluetoothServiceDiscoveryAgent() +{ +} + +void tst_QBluetoothServiceDiscoveryAgent::deviceDiscoveryDebug(const QBluetoothDeviceInfo &info) +{ + qDebug() << "Discovered device:" << info.address().toString() << info.name(); +} + + +void tst_QBluetoothServiceDiscoveryAgent::serviceError(const QBluetoothServiceDiscoveryAgent::Error err) +{ + qDebug() << "Service discovery error" << err; +} + +void tst_QBluetoothServiceDiscoveryAgent::initTestCase() +{ + if (androidBluetoothEmulator()) + QSKIP("Skipping test on Android 12+ emulator, CI can timeout waiting for user input"); + + if (localDeviceAvailable) { + QBluetoothDeviceDiscoveryAgent discoveryAgent; + + QSignalSpy finishedSpy(&discoveryAgent, SIGNAL(finished())); + QSignalSpy errorSpy(&discoveryAgent, + SIGNAL(errorOccurred(QBluetoothDeviceDiscoveryAgent::Error))); + QSignalSpy discoveredSpy(&discoveryAgent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo))); + + discoveryAgent.start(QBluetoothDeviceDiscoveryAgent::ClassicMethod); + + // Wait for up to MaxScanTime for the scan to finish + int scanTime = MaxScanTime; + while (finishedSpy.isEmpty() && scanTime > 0) { + QTest::qWait(1000); + scanTime -= 1000; + } + + // Expect finished signal with no error + QVERIFY(finishedSpy.size() == 1); + QVERIFY(errorSpy.isEmpty()); + + devices = discoveryAgent.discoveredDevices(); + } +} + +void tst_QBluetoothServiceDiscoveryAgent::tst_serviceDiscoveryStop() +{ + if (!localDeviceAvailable) + QSKIP("This test requires Bluetooth adapter in powered ON state"); + + QBluetoothServiceDiscoveryAgent discoveryAgent; + QSignalSpy finishedSpy(&discoveryAgent, SIGNAL(finished())); + QSignalSpy canceledSpy(&discoveryAgent, SIGNAL(canceled())); + + // Verify we get the correct signals on start-stop + discoveryAgent.start(QBluetoothServiceDiscoveryAgent::FullDiscovery); + QVERIFY(discoveryAgent.isActive()); + discoveryAgent.stop(); + QTRY_COMPARE(canceledSpy.size(), 1); + QVERIFY(!discoveryAgent.isActive()); + // Wait a bit to see that there are no latent signals + QTest::qWait(200); + QCOMPARE(canceledSpy.size(), 1); + QCOMPARE(finishedSpy.size(), 0); +} + + +void tst_QBluetoothServiceDiscoveryAgent::tst_invalidBtAddress() +{ +#ifdef Q_OS_MACOS + if (!localDeviceAvailable) + QSKIP("On OS X this test requires Bluetooth adapter in powered ON state"); +#endif + QBluetoothServiceDiscoveryAgent *discoveryAgent = new QBluetoothServiceDiscoveryAgent(QBluetoothAddress("11:11:11:11:11:11")); + + QCOMPARE(discoveryAgent->error(), QBluetoothServiceDiscoveryAgent::InvalidBluetoothAdapterError); + discoveryAgent->start(); + QCOMPARE(discoveryAgent->isActive(), false); + delete discoveryAgent; + + discoveryAgent = new QBluetoothServiceDiscoveryAgent(QBluetoothAddress()); + QCOMPARE(discoveryAgent->error(), QBluetoothServiceDiscoveryAgent::NoError); + if (!QBluetoothLocalDevice::allDevices().isEmpty()) { + discoveryAgent->start(); + QCOMPARE(discoveryAgent->isActive(), true); + } + delete discoveryAgent; +} + +void tst_QBluetoothServiceDiscoveryAgent::serviceDiscoveryDebug(const QBluetoothServiceInfo &info) +{ + qDebug() << "Discovered service on" + << info.device().name() << info.device().address().toString(); + qDebug() << "\tService name:" << info.serviceName() << "cached" << info.device().isCached(); + qDebug() << "\tDescription:" + << info.attribute(QBluetoothServiceInfo::ServiceDescription).toString(); + qDebug() << "\tProvider:" << info.attribute(QBluetoothServiceInfo::ServiceProvider).toString(); + qDebug() << "\tL2CAP protocol service multiplexer:" << info.protocolServiceMultiplexer(); + qDebug() << "\tRFCOMM server channel:" << info.serverChannel(); +} + +#if 0 +static void dumpAttributeVariant(const QVariant &var, const QString indent) +{ + if (!var.isValid()) { + qDebug("%sEmpty", indent.toLocal8Bit().constData()); + return; + } + + if (var.typeId() == qMetaTypeId()) { + qDebug("%sSequence", indent.toLocal8Bit().constData()); + const QBluetoothServiceInfo::Sequence *sequence = static_cast(var.data()); + for (const QVariant &v : *sequence) + dumpAttributeVariant(v, indent + '\t'); + } else if (var.typeId() == qMetaTypeId()) { + qDebug("%sAlternative", indent.toLocal8Bit().constData()); + const QBluetoothServiceInfo::Alternative *alternative = static_cast(var.data()); + for (const QVariant &v : *alternative) + dumpAttributeVariant(v, indent + '\t'); + } else if (var.typeId() == qMetaTypeId()) { + QBluetoothUuid uuid = var.value(); + switch (uuid.minimumSize()) { + case 0: + qDebug("%suuid NULL", indent.toLocal8Bit().constData()); + break; + case 2: + qDebug("%suuid %04x", indent.toLocal8Bit().constData(), uuid.toUInt16()); + break; + case 4: + qDebug("%suuid %08x", indent.toLocal8Bit().constData(), uuid.toUInt32()); + break; + case 16: { + qDebug("%suuid %s", indent.toLocal8Bit().constData(), uuid.toByteArray(QUuid::Id128).constData()); + break; + } + default: + qDebug("%suuid ???", indent.toLocal8Bit().constData()); + } + } else { + switch (var.typeId()) { + case QMetaType::UInt: + qDebug("%suint %u", indent.toLocal8Bit().constData(), var.toUInt()); + break; + case QMetaType::Int: + qDebug("%sint %d", indent.toLocal8Bit().constData(), var.toInt()); + break; + case QMetaType::QString: + qDebug("%sstring %s", indent.toLocal8Bit().constData(), var.toString().toLocal8Bit().constData()); + break; + case QMetaType::Bool: + qDebug("%sbool %d", indent.toLocal8Bit().constData(), var.toBool()); + break; + case QMetaType::QUrl: + qDebug("%surl %s", indent.toLocal8Bit().constData(), var.toUrl().toString().toLocal8Bit().constData()); + break; + default: + qDebug("%sunknown", indent.toLocal8Bit().constData()); + } + } +} + +static inline void dumpServiceInfoAttributes(const QBluetoothServiceInfo &info) +{ + const QList attributes = info.attributes(); + for (quint16 id : attributes) { + dumpAttributeVariant(info.attribute(id), QString("\t")); + } +} +#endif + + +void tst_QBluetoothServiceDiscoveryAgent::tst_serviceDiscovery_data() +{ + if (devices.isEmpty()) + QSKIP("This test requires an in-range bluetooth device"); + + QTest::addColumn("deviceInfo"); + QTest::addColumn >("uuidFilter"); + QTest::addColumn("serviceDiscoveryError"); + + // Only need to test the first 5 live devices + int max = 5; + for (const QBluetoothDeviceInfo &info : std::as_const(devices)) { + if (info.isCached()) + continue; + QTest::newRow("default filter") << info << QList() + << QBluetoothServiceDiscoveryAgent::NoError; + if (!--max) + break; + //QTest::newRow("public browse group") << info << (QList() << QBluetoothUuid::ServiceClassUuid::PublicBrowseGroup); + //QTest::newRow("l2cap") << info << (QList() << QBluetoothUuid::ProtocolUuid::L2cap); + } + QTest::newRow("all devices") << QBluetoothDeviceInfo() << QList() + << QBluetoothServiceDiscoveryAgent::NoError; +} + +void tst_QBluetoothServiceDiscoveryAgent::tst_serviceDiscoveryAdapters() +{ + QBluetoothLocalDevice localDevice; + const QList adapters = localDevice.allDevices(); + if (adapters.size() > 1) { + if (devices.isEmpty()) + QSKIP("This test requires an in-range bluetooth device"); + + QVarLengthArray addresses; + + for (const auto &adapter : adapters) { + addresses.append(adapter.address()); + } + QBluetoothServer server(QBluetoothServiceInfo::RfcommProtocol); + QBluetoothUuid uuid(QBluetoothUuid::ProtocolUuid::Ftp); + server.listen(addresses[0]); + QBluetoothServiceInfo serviceInfo; + serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceName, "serviceName"); + QBluetoothServiceInfo::Sequence publicBrowse; + publicBrowse << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ServiceClassUuid::PublicBrowseGroup)); + serviceInfo.setAttribute(QBluetoothServiceInfo::BrowseGroupList, publicBrowse); + + QBluetoothServiceInfo::Sequence profileSequence; + QBluetoothServiceInfo::Sequence classId; + classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ServiceClassUuid::SerialPort)); + classId << QVariant::fromValue(quint16(0x100)); + profileSequence.append(QVariant::fromValue(classId)); + serviceInfo.setAttribute(QBluetoothServiceInfo::BluetoothProfileDescriptorList, + profileSequence); + + serviceInfo.setServiceUuid(uuid); + + QBluetoothServiceInfo::Sequence protocolDescriptorList; + QBluetoothServiceInfo::Sequence protocol; + protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ProtocolUuid::L2cap)); + protocolDescriptorList.append(QVariant::fromValue(protocol)); + protocol.clear(); + + protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ProtocolUuid::Rfcomm)) + << QVariant::fromValue(quint8(server.serverPort())); + + protocolDescriptorList.append(QVariant::fromValue(protocol)); + serviceInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, + protocolDescriptorList); + QVERIFY(serviceInfo.registerService()); + + QVERIFY(server.isListening()); + qDebug() << "Scanning address " << addresses[0].toString(); + QBluetoothServiceDiscoveryAgent discoveryAgent(addresses[1]); + bool setAddress = discoveryAgent.setRemoteAddress(addresses[0]); + + QVERIFY(setAddress); + + QVERIFY(!discoveryAgent.isActive()); + + QVERIFY(discoveryAgent.discoveredServices().isEmpty()); + + QSignalSpy finishedSpy(&discoveryAgent, SIGNAL(finished())); + + discoveryAgent.start(); + int scanTime = MaxScanTime; + while (finishedSpy.isEmpty() && scanTime > 0) { + QTest::qWait(1000); + scanTime -= 1000; + } + + const QList discServices = discoveryAgent.discoveredServices(); + QVERIFY(!discServices.empty()); + + qsizetype counter = 0; + for (const QBluetoothServiceInfo &service : discServices) { + if (uuid == service.serviceUuid()) + counter++; + } + QCOMPARE(counter, 1); + } + +} + + +void tst_QBluetoothServiceDiscoveryAgent::tst_serviceDiscovery() +{ + if (devices.isEmpty()) + QSKIP("This test requires an in-range bluetooth device"); + + QFETCH(QBluetoothDeviceInfo, deviceInfo); + QFETCH(QList, uuidFilter); + QFETCH(QBluetoothServiceDiscoveryAgent::Error, serviceDiscoveryError); + + QBluetoothLocalDevice localDevice; + qDebug() << "Scanning address" << deviceInfo.address().toString() << deviceInfo.name(); + QBluetoothServiceDiscoveryAgent discoveryAgent(localDevice.address()); + bool setAddress = discoveryAgent.setRemoteAddress(deviceInfo.address()); + + QVERIFY(setAddress); + + QVERIFY(!discoveryAgent.isActive()); + + QVERIFY(discoveryAgent.discoveredServices().isEmpty()); + + QVERIFY(discoveryAgent.uuidFilter().isEmpty()); + + discoveryAgent.setUuidFilter(uuidFilter); + + QVERIFY(discoveryAgent.uuidFilter() == uuidFilter); + + QSignalSpy finishedSpy(&discoveryAgent, SIGNAL(finished())); + QSignalSpy errorSpy(&discoveryAgent, + SIGNAL(errorOccurred(QBluetoothServiceDiscoveryAgent::Error))); + QSignalSpy discoveredSpy(&discoveryAgent, SIGNAL(serviceDiscovered(QBluetoothServiceInfo))); + connect(&discoveryAgent, SIGNAL(errorOccurred(QBluetoothServiceDiscoveryAgent::Error)), this, + SLOT(serviceError(QBluetoothServiceDiscoveryAgent::Error))); + + discoveryAgent.start(QBluetoothServiceDiscoveryAgent::FullDiscovery); + + /* + * Either we wait for discovery agent to run its course (e.g. Bluez 4) or + * we have an immediate result (e.g. Bluez 5) + */ + QVERIFY(discoveryAgent.isActive() || !finishedSpy.isEmpty()); + + // Wait for up to MaxScanTime for the scan to finish + int scanTime = 20000; + while (finishedSpy.isEmpty() && scanTime > 0) { + QTest::qWait(1000); + scanTime -= 1000; + } + + if (discoveryAgent.error()) { + qDebug() << "Device failed to respond to SDP, skipping device" << discoveryAgent.error() << discoveryAgent.errorString(); + return; + } + + QVERIFY(discoveryAgent.error() == serviceDiscoveryError); + QVERIFY(discoveryAgent.errorString() == QString()); + + // Expect finished signal with no error + if (scanTime) + QVERIFY(finishedSpy.size() == 1); + + QVERIFY(errorSpy.isEmpty()); + + //if (!discoveryAgent.discoveredServices().isEmpty() && expected_failures++ <2){ + if (discoveredSpy.isEmpty()) { + qDebug() << "Device failed to return any results, skipping device" << discoveryAgent.discoveredServices().size(); + return; + } + + // All returned QBluetoothServiceInfo should be valid. + bool servicesFound = !discoveredSpy.isEmpty(); + while (!discoveredSpy.isEmpty()) { + const QVariant v = discoveredSpy.takeFirst().at(0); + // Work around limitation in QMetaType and moc. + // QBluetoothServiceInfo is registered with metatype as QBluetoothServiceInfo + // moc sees it as the unqualified QBluetoothServiceInfo. + if (v.userType() == qMetaTypeId()) + { + const QBluetoothServiceInfo info = + *reinterpret_cast(v.constData()); + + QVERIFY(info.isValid()); + QVERIFY(!info.isRegistered()); + +#if 0 + qDebug() << info.device().name() << info.device().address().toString(); + qDebug() << "\tService name:" << info.serviceName(); + if (info.protocolServiceMultiplexer() >= 0) + qDebug() << "\tL2CAP protocol service multiplexer:" << info.protocolServiceMultiplexer(); + if (info.serverChannel() >= 0) + qDebug() << "\tRFCOMM server channel:" << info.serverChannel(); + //dumpServiceInfoAttributes(info); +#endif + } else { + QFAIL("Unknown type returned by service discovery"); + } + + } + + if (servicesFound) + QVERIFY(!discoveryAgent.discoveredServices().isEmpty()); + discoveryAgent.clear(); + QVERIFY(discoveryAgent.discoveredServices().isEmpty()); + + discoveryAgent.stop(); + QVERIFY(!discoveryAgent.isActive()); +} + +QTEST_MAIN(tst_QBluetoothServiceDiscoveryAgent) + +#include "tst_qbluetoothservicediscoveryagent.moc" diff --git a/tests/auto/qbluetoothserviceinfo/CMakeLists.txt b/tests/auto/qbluetoothserviceinfo/CMakeLists.txt new file mode 100644 index 0000000..6974a03 --- /dev/null +++ b/tests/auto/qbluetoothserviceinfo/CMakeLists.txt @@ -0,0 +1,32 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## tst_qbluetoothserviceinfo Test: +##################################################################### + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qbluetoothserviceinfo LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qbluetoothserviceinfo + SOURCES + tst_qbluetoothserviceinfo.cpp + LIBRARIES + Qt::Bluetooth +) + +## Scopes: +##################################################################### + +qt_internal_extend_target(tst_qbluetoothserviceinfo CONDITION MACOS + LIBRARIES + Qt::Widgets +) + +qt_internal_extend_target(tst_qbluetoothserviceinfo CONDITION ANDROID AND NOT ANDROID_EMBEDDED + DEFINES + QT_ANDROID_BLUETOOTH +) diff --git a/tests/auto/qbluetoothserviceinfo/tst_qbluetoothserviceinfo.cpp b/tests/auto/qbluetoothserviceinfo/tst_qbluetoothserviceinfo.cpp new file mode 100644 index 0000000..11d1dd4 --- /dev/null +++ b/tests/auto/qbluetoothserviceinfo/tst_qbluetoothserviceinfo.cpp @@ -0,0 +1,437 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +QT_USE_NAMESPACE + +Q_DECLARE_METATYPE(QBluetoothUuid::ProtocolUuid) +Q_DECLARE_METATYPE(QUuid) +Q_DECLARE_METATYPE(QBluetoothServiceInfo::Protocol) + +class tst_QBluetoothServiceInfo : public QObject +{ + Q_OBJECT + +public: + tst_QBluetoothServiceInfo(); + ~tst_QBluetoothServiceInfo(); + +private slots: + void initTestCase(); + + void tst_construction(); + + void tst_assignment_data(); + void tst_assignment(); + + void tst_serviceClassUuids(); + + void tst_writeByteArray(); +}; + +tst_QBluetoothServiceInfo::tst_QBluetoothServiceInfo() +{ +} + +tst_QBluetoothServiceInfo::~tst_QBluetoothServiceInfo() +{ +} + +void tst_QBluetoothServiceInfo::initTestCase() +{ + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); +} + +void tst_QBluetoothServiceInfo::tst_construction() +{ + const QString serviceName("My Service"); + const QString alternateServiceName("Another ServiceName"); + const QBluetoothDeviceInfo deviceInfo(QBluetoothAddress("001122334455"), "Test Device", 0); + const QBluetoothDeviceInfo alternatedeviceInfo(QBluetoothAddress("554433221100"), "Test Device2", 0); + + QList protUuids; + //list taken from qbluetoothuuid.h + protUuids << QBluetoothUuid::ProtocolUuid::Sdp; + protUuids << QBluetoothUuid::ProtocolUuid::Udp; + protUuids << QBluetoothUuid::ProtocolUuid::Rfcomm; + protUuids << QBluetoothUuid::ProtocolUuid::Tcp; + protUuids << QBluetoothUuid::ProtocolUuid::TcsBin; + protUuids << QBluetoothUuid::ProtocolUuid::TcsAt; + protUuids << QBluetoothUuid::ProtocolUuid::Att; + protUuids << QBluetoothUuid::ProtocolUuid::Obex; + protUuids << QBluetoothUuid::ProtocolUuid::Ip; + protUuids << QBluetoothUuid::ProtocolUuid::Ftp; + protUuids << QBluetoothUuid::ProtocolUuid::Http; + protUuids << QBluetoothUuid::ProtocolUuid::Wsp; + protUuids << QBluetoothUuid::ProtocolUuid::Bnep; + protUuids << QBluetoothUuid::ProtocolUuid::Upnp; + protUuids << QBluetoothUuid::ProtocolUuid::Hidp; + protUuids << QBluetoothUuid::ProtocolUuid::HardcopyControlChannel; + protUuids << QBluetoothUuid::ProtocolUuid::HardcopyDataChannel; + protUuids << QBluetoothUuid::ProtocolUuid::HardcopyNotification; + protUuids << QBluetoothUuid::ProtocolUuid::Avctp; + protUuids << QBluetoothUuid::ProtocolUuid::Avdtp; + protUuids << QBluetoothUuid::ProtocolUuid::Cmtp; + protUuids << QBluetoothUuid::ProtocolUuid::UdiCPlain; + protUuids << QBluetoothUuid::ProtocolUuid::McapControlChannel; + protUuids << QBluetoothUuid::ProtocolUuid::McapDataChannel; + protUuids << QBluetoothUuid::ProtocolUuid::L2cap; + + { + QBluetoothServiceInfo serviceInfo; + + QVERIFY(!serviceInfo.isValid()); + QVERIFY(!serviceInfo.isComplete()); + QVERIFY(!serviceInfo.isRegistered()); + QCOMPARE(serviceInfo.serviceName(), QString()); + QCOMPARE(serviceInfo.serviceDescription(), QString()); + QCOMPARE(serviceInfo.serviceProvider(), QString()); + QCOMPARE(serviceInfo.serviceUuid(), QBluetoothUuid()); + QCOMPARE(serviceInfo.serviceClassUuids().size(), 0); + QCOMPARE(serviceInfo.attributes().size(), 0); + QCOMPARE(serviceInfo.serverChannel(), -1); + QCOMPARE(serviceInfo.protocolServiceMultiplexer(), -1); + + for (QBluetoothUuid::ProtocolUuid u : std::as_const(protUuids)) + QCOMPARE(serviceInfo.protocolDescriptor(u).size(), 0); + } + + { + QBluetoothServiceInfo serviceInfo; + serviceInfo.setServiceName(serviceName); + serviceInfo.setDevice(deviceInfo); + + QVERIFY(serviceInfo.isValid()); + QVERIFY(!serviceInfo.isComplete()); + QVERIFY(!serviceInfo.isRegistered()); + + QCOMPARE(serviceInfo.serviceName(), serviceName); + QCOMPARE(serviceInfo.device().address(), deviceInfo.address()); + + QBluetoothServiceInfo copyInfo(serviceInfo); + + QVERIFY(copyInfo.isValid()); + QVERIFY(!copyInfo.isComplete()); + QVERIFY(!copyInfo.isRegistered()); + + QCOMPARE(copyInfo.serviceName(), serviceName); + QCOMPARE(copyInfo.device().address(), deviceInfo.address()); + + + copyInfo.setAttribute(QBluetoothServiceInfo::ServiceName, alternateServiceName); + copyInfo.setDevice(alternatedeviceInfo); + QCOMPARE(copyInfo.serviceName(), alternateServiceName); + QCOMPARE(copyInfo.attribute(QBluetoothServiceInfo::ServiceName).toString(), alternateServiceName); + QCOMPARE(serviceInfo.serviceName(), alternateServiceName); + QCOMPARE(copyInfo.device().address(), alternatedeviceInfo.address()); + QCOMPARE(serviceInfo.device().address(), alternatedeviceInfo.address()); + + for (QBluetoothUuid::ProtocolUuid u : std::as_const(protUuids)) + QCOMPARE(serviceInfo.protocolDescriptor(u).size(), 0); + for (QBluetoothUuid::ProtocolUuid u : std::as_const(protUuids)) + QCOMPARE(copyInfo.protocolDescriptor(u).size(), 0); + } +} + +void tst_QBluetoothServiceInfo::tst_assignment_data() +{ + QTest::addColumn("uuid"); + QTest::addColumn("protocolUuid"); + QTest::addColumn("serviceInfoProtocol"); + QTest::addColumn("protocolSupported"); + + bool l2cpSupported = true; + //some platforms don't support L2CP +#if defined(QT_ANDROID_BLUETOOTH) || defined(Q_OS_WIN) + l2cpSupported = false; +#endif + +#if defined(Q_OS_MACOS) + l2cpSupported = QOperatingSystemVersion::current() < QOperatingSystemVersion::MacOSMonterey; +#endif + + QTest::newRow("assignment_data_l2cp") + << QUuid(0x67c8770b, 0x44f1, 0x410a, 0xab, 0x9a, 0xf9, 0xb5, 0x44, 0x6f, 0x13, 0xee) + << QBluetoothUuid::ProtocolUuid::L2cap << QBluetoothServiceInfo::L2capProtocol << l2cpSupported; + QTest::newRow("assignment_data_rfcomm") + << QUuid(0x67c8770b, 0x44f1, 0x410a, 0xab, 0x9a, 0xf9, 0xb5, 0x44, 0x6f, 0x13, 0xee) + << QBluetoothUuid::ProtocolUuid::Rfcomm << QBluetoothServiceInfo::RfcommProtocol << true; + +} + +void tst_QBluetoothServiceInfo::tst_assignment() +{ + QFETCH(QUuid, uuid); + QFETCH(QBluetoothUuid::ProtocolUuid, protocolUuid); + QFETCH(QBluetoothServiceInfo::Protocol, serviceInfoProtocol); + QFETCH(bool, protocolSupported); + + const QString serviceName("My Service"); + const QBluetoothDeviceInfo deviceInfo(QBluetoothAddress("001122334455"), "Test Device", 0); + + QBluetoothServiceInfo serviceInfo; + serviceInfo.setServiceName(serviceName); + serviceInfo.setDevice(deviceInfo); + + QVERIFY(serviceInfo.isValid()); + QVERIFY(!serviceInfo.isRegistered()); + QVERIFY(!serviceInfo.isComplete()); + + { + QBluetoothServiceInfo copyInfo = serviceInfo; + + QVERIFY(copyInfo.isValid()); + QVERIFY(!copyInfo.isRegistered()); + QVERIFY(!copyInfo.isComplete()); + + QCOMPARE(copyInfo.serviceName(), serviceName); + QCOMPARE(copyInfo.device().address(), deviceInfo.address()); + } + + { + QBluetoothServiceInfo copyInfo; + + QVERIFY(!copyInfo.isValid()); + QVERIFY(!copyInfo.isRegistered()); + QVERIFY(!copyInfo.isComplete()); + + copyInfo = serviceInfo; + + QVERIFY(copyInfo.isValid()); + QVERIFY(!copyInfo.isRegistered()); + QVERIFY(!copyInfo.isComplete()); + + QCOMPARE(copyInfo.serviceName(), serviceName); + QCOMPARE(copyInfo.device().address(), deviceInfo.address()); + } + + { + QBluetoothServiceInfo copyInfo1; + QBluetoothServiceInfo copyInfo2; + + QVERIFY(!copyInfo1.isValid()); + QVERIFY(!copyInfo1.isRegistered()); + QVERIFY(!copyInfo1.isComplete()); + QVERIFY(!copyInfo2.isValid()); + QVERIFY(!copyInfo2.isRegistered()); + QVERIFY(!copyInfo2.isComplete()); + + copyInfo1 = copyInfo2 = serviceInfo; + + QVERIFY(copyInfo1.isValid()); + QVERIFY(!copyInfo1.isRegistered()); + QVERIFY(!copyInfo1.isComplete()); + QVERIFY(copyInfo2.isValid()); + QVERIFY(!copyInfo2.isRegistered()); + QVERIFY(!copyInfo2.isComplete()); + + QCOMPARE(copyInfo1.serviceName(), serviceName); + QCOMPARE(copyInfo2.serviceName(), serviceName); + QCOMPARE(copyInfo1.device().address(), deviceInfo.address()); + QCOMPARE(copyInfo2.device().address(), deviceInfo.address()); + } + + { + QBluetoothServiceInfo copyInfo; + QVERIFY(!copyInfo.isValid()); + QVERIFY(!copyInfo.isRegistered()); + QVERIFY(!copyInfo.isComplete()); + copyInfo = serviceInfo; + QVERIFY(copyInfo.contains(QBluetoothServiceInfo::ServiceName)); + + copyInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, QBluetoothUuid(uuid)); + QVERIFY(copyInfo.contains(QBluetoothServiceInfo::ProtocolDescriptorList)); + QVERIFY(copyInfo.isComplete()); + QVERIFY(!copyInfo.attributes().isEmpty()); + + copyInfo.removeAttribute(QBluetoothServiceInfo::ProtocolDescriptorList); + QVERIFY(!copyInfo.contains(QBluetoothServiceInfo::ProtocolDescriptorList)); + QVERIFY(!copyInfo.isComplete()); + } + + { + QBluetoothServiceInfo copyInfo; + QVERIFY(!copyInfo.isValid()); + copyInfo = serviceInfo; + + QVERIFY(copyInfo.serverChannel() == -1); + QVERIFY(copyInfo.protocolServiceMultiplexer() == -1); + + QBluetoothServiceInfo::Sequence protocolDescriptorList; + QBluetoothServiceInfo::Sequence protocol; + protocol << QVariant::fromValue(QBluetoothUuid(protocolUuid)); + protocolDescriptorList.append(QVariant::fromValue(protocol)); + protocol.clear(); + + protocolDescriptorList.append(QVariant::fromValue(protocol)); + copyInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, + protocolDescriptorList); + if (serviceInfoProtocol == QBluetoothServiceInfo::L2capProtocol) { + QVERIFY(copyInfo.serverChannel() == -1); + QVERIFY(copyInfo.protocolServiceMultiplexer() != -1); + } else if (serviceInfoProtocol == QBluetoothServiceInfo::RfcommProtocol) { + QVERIFY(copyInfo.serverChannel() != -1); + QVERIFY(copyInfo.protocolServiceMultiplexer() == -1); + } + + QVERIFY(copyInfo.socketProtocol() == serviceInfoProtocol); + } + + { + QBluetoothServiceInfo copyInfo; + + QVERIFY(!copyInfo.isValid()); + copyInfo = serviceInfo; + copyInfo.setServiceUuid(QBluetoothUuid::ServiceClassUuid::SerialPort); + QVERIFY(!copyInfo.isRegistered()); + + // start Bluetooth if not started + QBluetoothLocalDevice device; + if (device.isValid()) { + device.powerOn(); + int waitPowerOnMs = 1000; + while (device.hostMode() == QBluetoothLocalDevice::HostPoweredOff && waitPowerOnMs) { + QTest::qWait(100); + waitPowerOnMs -= 100; + } + } + + if (device.hostMode() == QBluetoothLocalDevice::HostPoweredOff) { + QSKIP("Skipping test due to missing or powered OFF Bluetooth device"); + } else if (protocolSupported) { + QBluetoothServer server(serviceInfoProtocol); + QVERIFY(server.listen()); + QTRY_VERIFY_WITH_TIMEOUT(server.isListening(), 5000); + QVERIFY(server.serverPort() > 0); + + QBluetoothServiceInfo::Sequence protocolDescriptorList; + QBluetoothServiceInfo::Sequence protocol; + protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ProtocolUuid::L2cap)); + + if (serviceInfoProtocol == QBluetoothServiceInfo::L2capProtocol) { + protocol << QVariant::fromValue(server.serverPort()); + protocolDescriptorList.append(QVariant::fromValue(protocol)); + } else if (serviceInfoProtocol == QBluetoothServiceInfo::RfcommProtocol) { + protocolDescriptorList.append(QVariant::fromValue(protocol)); + protocol.clear(); + protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ProtocolUuid::Rfcomm)) + << QVariant::fromValue(quint8(server.serverPort())); + protocolDescriptorList.append(QVariant::fromValue(protocol)); + } + + serviceInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, + protocolDescriptorList); + +#if defined(Q_OS_MACOS) + // bluetoothd on Monterey does not want to register a record if there is no + // ServiceClassIDList provided. + if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMonterey) { + // Nothing seems to help with L2CAP though: + if (serviceInfoProtocol == QBluetoothServiceInfo::RfcommProtocol) { + QBluetoothServiceInfo::Sequence classIds; + classIds << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ServiceClassUuid::SerialPort)); + copyInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classIds); + } + } +#endif // Q_OS_MACOS + + QVERIFY(copyInfo.registerService()); + QVERIFY(copyInfo.isRegistered()); + QVERIFY(serviceInfo.isRegistered()); + QBluetoothServiceInfo secondCopy; + secondCopy = copyInfo; + QVERIFY(secondCopy.isRegistered()); + + QVERIFY(secondCopy.unregisterService()); + QVERIFY(!copyInfo.isRegistered()); + QVERIFY(!secondCopy.isRegistered()); + QVERIFY(!serviceInfo.isRegistered()); + QVERIFY(server.isListening()); + server.close(); + QVERIFY(!server.isListening()); + } + } +} + +void tst_QBluetoothServiceInfo::tst_serviceClassUuids() +{ + QBluetoothServiceInfo info; + QCOMPARE(info.serviceClassUuids().size(), 0); + + QBluetoothServiceInfo::Sequence classIds; + classIds << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ServiceClassUuid::SerialPort)); + QCOMPARE(classIds.size(), 1); + + QBluetoothUuid uuid(QString("e8e10f95-1a70-4b27-9ccf-02010264e9c8")); + classIds.prepend(QVariant::fromValue(uuid)); + QCOMPARE(classIds.size(), 2); + QCOMPARE(classIds.at(0).value(), uuid); + + info.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classIds); + QList svclids = info.serviceClassUuids(); + QCOMPARE(svclids.size(), 2); + QCOMPARE(svclids.at(0), uuid); + QCOMPARE(svclids.at(1), QBluetoothUuid(QBluetoothUuid::ServiceClassUuid::SerialPort)); +} + +static QByteArray debugOutput; + +void debugHandler(QtMsgType type, const QMessageLogContext &, const QString &msg) +{ + switch (type) { + case QtDebugMsg : + debugOutput = msg.toLocal8Bit(); + break; + default: + break; + } +} + +void tst_QBluetoothServiceInfo::tst_writeByteArray() +{ + // We cannot directly test the produced XML output for Bluez + // as there no public API to retrieve it and it would be Bluez specific. + // However we can check the debug output. + // It should contain a qbyteArray rather than a string. In the XML the QByteArray + // is converted to a text tag with hex encoding. + + const QByteArray expected("\n (518)\tSequence\n (518)\t\tSequence\n (518)\t\t\tuchar 34\n (518)\t\t\tbytearray 05010906a101850105079508750119e029e7150025018102950175088103050795067508150026ff00190029ff8100050895057501190129059102950175039103c005010902a10185020901a1000509190129031500250175019503810275059501810105010930093109381581257f750895038106c0c0\n"); + + const QByteArray hidDescriptor = + QByteArray::fromHex("05010906a101850105079508750119e029e7150025018102950175088103050795067508150026FF00190029FF8100050895057501190129059102950175039103c005010902a10185020901a1000509190129031500250175019503810275059501810105010930093109381581257f750895038106c0c0"); + const QBluetoothServiceInfo::Sequence hidDescriptorList({ + QVariant::fromValue(quint8(0x22)), // Report type + QByteArray(hidDescriptor) // Descriptor array + }); + const QBluetoothServiceInfo::Sequence hidDescriptorListSeq({ + QVariant::fromValue(hidDescriptorList) + }); + QBluetoothServiceInfo srvInfo; + srvInfo.setAttribute(0x0206, QVariant::fromValue(hidDescriptorListSeq)); + + const QVariant attribute = srvInfo.attribute(0x0206); + debugOutput.clear(); + qInstallMessageHandler(debugHandler); + qDebug() << srvInfo; + qInstallMessageHandler(nullptr); + QCOMPARE(debugOutput, expected); +} + +QTEST_MAIN(tst_QBluetoothServiceInfo) + +#include "tst_qbluetoothserviceinfo.moc" diff --git a/tests/auto/qbluetoothsocket/CMakeLists.txt b/tests/auto/qbluetoothsocket/CMakeLists.txt new file mode 100644 index 0000000..59b6a8f --- /dev/null +++ b/tests/auto/qbluetoothsocket/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## tst_qbluetoothsocket Test: +##################################################################### + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qbluetoothsocket LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qbluetoothsocket + SOURCES + tst_qbluetoothsocket.cpp + LIBRARIES + Qt::BluetoothPrivate + Qt::Network +) + +#### Keys ignored in scope 1:.:.:qbluetoothsocket.pro:: +# OTHER_FILES = "README.txt" +# testcase.timeout = "250" + +## Scopes: +##################################################################### + +qt_internal_extend_target(tst_qbluetoothsocket CONDITION MACOS + DEFINES + QT_OSX_BLUETOOTH + LIBRARIES + Qt::Widgets +) + +qt_internal_extend_target(tst_qbluetoothsocket CONDITION ANDROID AND NOT ANDROID_EMBEDDED + DEFINES + QT_ANDROID_BLUETOOTH +) diff --git a/tests/auto/qbluetoothsocket/README.txt b/tests/auto/qbluetoothsocket/README.txt new file mode 100644 index 0000000..d04324d --- /dev/null +++ b/tests/auto/qbluetoothsocket/README.txt @@ -0,0 +1,7 @@ +This test requires bttestui running on a remote machine, and for it to +be discoverable and connectable to the device under test. The bttestui +should run an rfcomm server (see UI option SListenUuid). + +bttestui is available in tests/bttestui. + +The unit test attempts to use service discovery to locate bttestui. diff --git a/tests/auto/qbluetoothsocket/tst_qbluetoothsocket.cpp b/tests/auto/qbluetoothsocket/tst_qbluetoothsocket.cpp new file mode 100644 index 0000000..d88e64e --- /dev/null +++ b/tests/auto/qbluetoothsocket/tst_qbluetoothsocket.cpp @@ -0,0 +1,574 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include + +#include + +#include +#include +#include +#include +#include +#if QT_CONFIG(bluez) +#include +#endif + +QT_USE_NAMESPACE + +Q_DECLARE_METATYPE(QBluetoothServiceInfo::Protocol) + +//same uuid as tests/bttestui +#define TEST_SERVICE_UUID "e8e10f95-1a70-4b27-9ccf-02010264e9c8" + +// Max time to wait for connection + +static const int MaxConnectTime = 60 * 1000; // 1 minute in ms +static const int MaxReadWriteTime = 60 * 1000; // 1 minute in ms + +class tst_QBluetoothSocket : public QObject +{ + Q_OBJECT + +public: + enum ClientConnectionShutdown { + Error, + Disconnect, + Close, + Abort, + }; + + tst_QBluetoothSocket(); + ~tst_QBluetoothSocket(); + +private slots: + void initTestCase(); + + void tst_construction_data(); + void tst_construction(); + + void tst_serviceConnection(); + + void tst_clientCommunication_data(); + void tst_clientCommunication(); + + void tst_error(); + + void tst_preferredSecurityFlags(); + + void tst_unsupportedProtocolError(); + +public slots: + void serviceDiscovered(const QBluetoothServiceInfo &info); + void finished(); + void error(QBluetoothServiceDiscoveryAgent::Error error); +private: + bool done_discovery; + bool localDeviceFound; + QBluetoothDeviceInfo remoteDevice; + QBluetoothHostInfo localDevice; + QBluetoothServiceInfo remoteServiceInfo; + +}; + +Q_DECLARE_METATYPE(tst_QBluetoothSocket::ClientConnectionShutdown) + +tst_QBluetoothSocket::tst_QBluetoothSocket() +{ + qRegisterMetaType(); + qRegisterMetaType(); + + localDeviceFound = false; // true if we have a local adapter + done_discovery = false; //true if we found remote device + + //Enable logging to facilitate debugging in case of error + QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true")); +} + +tst_QBluetoothSocket::~tst_QBluetoothSocket() +{ +} + +void tst_QBluetoothSocket::initTestCase() +{ + // setup Bluetooth env + const QList foundDevices = QBluetoothLocalDevice::allDevices(); + if (foundDevices.isEmpty()) { + qWarning() << "Missing local device"; + return; + } else { + localDevice = foundDevices.at(0); + qDebug() << "Local device" << localDevice.name() << localDevice.address().toString(); + } + + localDeviceFound = true; + + //start the device + QBluetoothLocalDevice device(localDevice.address()); + device.powerOn(); + + + //find the remote test server + //the remote test server is tests/bttestui + + // Go find the server + QBluetoothServiceDiscoveryAgent *sda = new QBluetoothServiceDiscoveryAgent(this); + connect(sda, SIGNAL(serviceDiscovered(QBluetoothServiceInfo)), this, SLOT(serviceDiscovered(QBluetoothServiceInfo))); + connect(sda, SIGNAL(errorOccurred(QBluetoothServiceDiscoveryAgent::Error)), this, + SLOT(error(QBluetoothServiceDiscoveryAgent::Error))); + connect(sda, SIGNAL(finished()), this, SLOT(finished())); + + qDebug() << "Starting discovery"; + + sda->setUuidFilter(QBluetoothUuid(QString(TEST_SERVICE_UUID))); + sda->start(QBluetoothServiceDiscoveryAgent::FullDiscovery); + + for (int connectTime = MaxConnectTime; !done_discovery && connectTime > 0; connectTime -= 1000) + QTest::qWait(1000); + + sda->stop(); + + if (!remoteDevice.isValid()) { + qWarning() << "#########################"; + qWarning() << "Unable to find test service"; + qWarning() << "Remote device may have to be changed into Discoverable mode"; + qWarning() << "#########################"; + } + + delete sda; +} + +void tst_QBluetoothSocket::error(QBluetoothServiceDiscoveryAgent::Error error) +{ + qDebug() << "Received error" << error; + done_discovery = true; +} + +void tst_QBluetoothSocket::finished() +{ + qDebug() << "Finished"; + done_discovery = true; +} + +void tst_QBluetoothSocket::serviceDiscovered(const QBluetoothServiceInfo &info) +{ + qDebug() << "Found test service on:" << info.device().name() << info.device().address().toString(); + remoteDevice = info.device(); + remoteServiceInfo = info; + done_discovery = true; +} + +void tst_QBluetoothSocket::tst_construction_data() +{ + QTest::addColumn("socketType"); + + QTest::newRow("unknown protocol") << QBluetoothServiceInfo::UnknownProtocol; + QTest::newRow("rfcomm socket") << QBluetoothServiceInfo::RfcommProtocol; + QTest::newRow("l2cap socket") << QBluetoothServiceInfo::L2capProtocol; +} + +void tst_QBluetoothSocket::tst_construction() +{ + QFETCH(QBluetoothServiceInfo::Protocol, socketType); + + { + QBluetoothSocket socket; + + QCOMPARE(socket.socketType(), QBluetoothServiceInfo::UnknownProtocol); + QCOMPARE(socket.error(), QBluetoothSocket::SocketError::NoSocketError); + QCOMPARE(socket.errorString(), QString()); + QCOMPARE(socket.peerAddress(), QBluetoothAddress()); + QCOMPARE(socket.peerName(), QString()); + QCOMPARE(socket.peerPort(), quint16(0)); + QCOMPARE(socket.state(), QBluetoothSocket::SocketState::UnconnectedState); + QCOMPARE(socket.socketDescriptor(), -1); + QCOMPARE(socket.bytesAvailable(), 0); + QCOMPARE(socket.bytesToWrite(), 0); + QCOMPARE(socket.canReadLine(), false); + QCOMPARE(socket.isSequential(), true); + QCOMPARE(socket.atEnd(), true); + QCOMPARE(socket.pos(), 0); + QCOMPARE(socket.size(), 0); + QCOMPARE(socket.isOpen(), false); + QCOMPARE(socket.isReadable(), false); + QCOMPARE(socket.isWritable(), false); + QCOMPARE(socket.openMode(), QIODevice::NotOpen); + + QByteArray array = socket.readAll(); + QVERIFY(array.isEmpty()); + + char buffer[10]; + int returnValue = socket.read((char*)&buffer, 10); + QCOMPARE(returnValue, -1); + } + + { + QBluetoothSocket socket(socketType); + QCOMPARE(socket.socketType(), socketType); + } +} + +void tst_QBluetoothSocket::tst_serviceConnection() +{ + if (!remoteServiceInfo.isValid()) + QSKIP("Remote service not found"); + + /* Construction */ + QBluetoothSocket socket; + + QSignalSpy stateSpy(&socket, SIGNAL(stateChanged(QBluetoothSocket::SocketState))); + + QCOMPARE(socket.socketType(), QBluetoothServiceInfo::UnknownProtocol); + QCOMPARE(socket.state(), QBluetoothSocket::SocketState::UnconnectedState); + + /* Connection */ + QSignalSpy connectedSpy(&socket, SIGNAL(connected())); + QSignalSpy errorSpy(&socket, SIGNAL(errorOccurred(QBluetoothSocket::SocketError))); + + QCOMPARE(socket.openMode(), QIODevice::NotOpen); + QCOMPARE(socket.isWritable(), false); + QCOMPARE(socket.isReadable(), false); + QCOMPARE(socket.isOpen(), false); + + socket.connectToService(remoteServiceInfo); + + QCOMPARE(stateSpy.size(), 1); + QCOMPARE(stateSpy.takeFirst().at(0).value(), QBluetoothSocket::SocketState::ConnectingState); + QCOMPARE(socket.state(), QBluetoothSocket::SocketState::ConnectingState); + + stateSpy.clear(); + + int connectTime = MaxConnectTime; + while (connectedSpy.isEmpty() && errorSpy.isEmpty() && connectTime > 0) { + QTest::qWait(1000); + connectTime -= 1000; + } + + if (!errorSpy.isEmpty()) { + qDebug() << errorSpy.takeFirst().at(0).toInt(); + QSKIP("Connection error"); + } + QCOMPARE(connectedSpy.size(), 1); + QCOMPARE(stateSpy.size(), 1); + QCOMPARE(stateSpy.takeFirst().at(0).value(), QBluetoothSocket::SocketState::ConnectedState); + QCOMPARE(socket.state(), QBluetoothSocket::SocketState::ConnectedState); + + QCOMPARE(socket.isWritable(), true); + QCOMPARE(socket.isReadable(), true); + QCOMPARE(socket.isOpen(), true); + + stateSpy.clear(); + + //check the peer & local info + QCOMPARE(socket.localAddress(), localDevice.address()); + QCOMPARE(socket.localName(), localDevice.name()); +#ifdef Q_OS_WIN + // On Windows the socket peer name (aka remotehost display name) seems to be + // formed from the BT address and not necessarily the remoteDevice name + QVERIFY(!socket.peerName().isEmpty()); +#else + QCOMPARE(socket.peerName(), remoteDevice.name()); +#endif + QCOMPARE(socket.peerAddress(), remoteDevice.address()); + + /* Disconnection */ + QSignalSpy disconnectedSpy(&socket, SIGNAL(disconnected())); + + socket.abort(); // close() tested by other functions + QCOMPARE(socket.isWritable(), false); + QCOMPARE(socket.isReadable(), false); + QCOMPARE(socket.isOpen(), false); + QCOMPARE(socket.openMode(), QIODevice::NotOpen); + + QVERIFY(!stateSpy.isEmpty()); + QCOMPARE(stateSpy.takeFirst().at(0).value(), QBluetoothSocket::SocketState::ClosingState); + + int disconnectTime = MaxConnectTime; + while (disconnectedSpy.isEmpty() && disconnectTime > 0) { + QTest::qWait(1000); + disconnectTime -= 1000; + } + + QCOMPARE(disconnectedSpy.size(), 1); + QCOMPARE(stateSpy.size(), 1); + QCOMPARE(stateSpy.takeFirst().at(0).value(), QBluetoothSocket::SocketState::UnconnectedState); + + // The remote service needs time to close the connection and resume listening + QTest::qSleep(100); +} + +void tst_QBluetoothSocket::tst_clientCommunication_data() +{ + QTest::addColumn("data"); + + { + QStringList data; + data << QStringLiteral("Echo: Test line one.\n"); + data << QStringLiteral("Echo: Test line two, with longer data.\n"); + + QTest::newRow("two line test") << data; + } +} + +void tst_QBluetoothSocket::tst_clientCommunication() +{ + if (!remoteServiceInfo.isValid()) + QSKIP("Remote service not found"); + QFETCH(QStringList, data); + + /* Construction */ + QBluetoothSocket socket(QBluetoothServiceInfo::RfcommProtocol); + + QSignalSpy stateSpy(&socket, SIGNAL(stateChanged(QBluetoothSocket::SocketState))); + + QCOMPARE(socket.socketType(), QBluetoothServiceInfo::RfcommProtocol); + QCOMPARE(socket.state(), QBluetoothSocket::SocketState::UnconnectedState); + + /* Connection */ + QSignalSpy connectedSpy(&socket, SIGNAL(connected())); + + QCOMPARE(socket.isWritable(), false); + QCOMPARE(socket.isReadable(), false); + QCOMPARE(socket.isOpen(), false); + QCOMPARE(socket.openMode(), QIODevice::NotOpen); + socket.connectToService(remoteServiceInfo); + + QCOMPARE(stateSpy.size(), 1); + QCOMPARE(qvariant_cast(stateSpy.takeFirst().at(0)), QBluetoothSocket::SocketState::ConnectingState); + QCOMPARE(socket.state(), QBluetoothSocket::SocketState::ConnectingState); + + stateSpy.clear(); + + int connectTime = MaxConnectTime; + while (connectedSpy.isEmpty() && connectTime > 0) { + QTest::qWait(1000); + connectTime -= 1000; + } + + QCOMPARE(socket.isWritable(), true); + QCOMPARE(socket.isReadable(), true); + QCOMPARE(socket.isOpen(), true); + + QCOMPARE(connectedSpy.size(), 1); + QCOMPARE(stateSpy.size(), 1); + QCOMPARE(qvariant_cast(stateSpy.takeFirst().at(0)), QBluetoothSocket::SocketState::ConnectedState); + QCOMPARE(socket.state(), QBluetoothSocket::SocketState::ConnectedState); + + stateSpy.clear(); + + /* Read / Write */ + QCOMPARE(socket.bytesToWrite(), qint64(0)); + QCOMPARE(socket.bytesAvailable(), qint64(0)); + + { + /* Send line by line with event loop */ + for (const QString &line : std::as_const(data)) { + QSignalSpy readyReadSpy(&socket, SIGNAL(readyRead())); + QSignalSpy bytesWrittenSpy(&socket, SIGNAL(bytesWritten(qint64))); + + qint64 dataWritten = socket.write(line.toUtf8()); + + if (socket.openMode() & QIODevice::Unbuffered) + QCOMPARE(socket.bytesToWrite(), qint64(0)); + else + QCOMPARE(socket.bytesToWrite(), qint64(line.size())); + + QCOMPARE(dataWritten, qint64(line.size())); + + int readWriteTime = MaxReadWriteTime; + while ((bytesWrittenSpy.isEmpty() || readyReadSpy.isEmpty()) && readWriteTime > 0) { + QTest::qWait(1000); + readWriteTime -= 1000; + } + + QCOMPARE(bytesWrittenSpy.size(), 1); + QCOMPARE(bytesWrittenSpy.at(0).at(0).toLongLong(), qint64(line.size())); + + readWriteTime = MaxReadWriteTime; + while (readyReadSpy.isEmpty() && readWriteTime > 0) { + QTest::qWait(1000); + readWriteTime -= 1000; + } + + QCOMPARE(readyReadSpy.size(), 1); + + if (socket.openMode() & QIODevice::Unbuffered) + QVERIFY(socket.bytesAvailable() <= qint64(line.size())); + else + QCOMPARE(socket.bytesAvailable(), qint64(line.size())); + + QVERIFY(socket.canReadLine()); + + QByteArray echoed = socket.readAll(); + + QCOMPARE(line.toUtf8(), echoed); + } + } + + QCOMPARE(socket.isWritable(), true); + QCOMPARE(socket.isReadable(), true); + QCOMPARE(socket.isOpen(), true); + + { + /* Send all at once */ + QSignalSpy readyReadSpy(&socket, SIGNAL(readyRead())); + QSignalSpy bytesWrittenSpy(&socket, SIGNAL(bytesWritten(qint64))); + + QString joined = data.join(QString()); + qint64 dataWritten = socket.write(joined.toUtf8()); + + if (socket.openMode() & QIODevice::Unbuffered) + QCOMPARE(socket.bytesToWrite(), qint64(0)); + else + QCOMPARE(socket.bytesToWrite(), qint64(joined.size())); + + QCOMPARE(dataWritten, qint64(joined.size())); + + int readWriteTime = MaxReadWriteTime; + while ((bytesWrittenSpy.isEmpty() || readyReadSpy.isEmpty()) && readWriteTime > 0) { + QTest::qWait(1000); + readWriteTime -= 1000; + } + + QCOMPARE(bytesWrittenSpy.size(), 1); + QCOMPARE(bytesWrittenSpy.at(0).at(0).toLongLong(), qint64(joined.size())); + QVERIFY(!readyReadSpy.isEmpty()); + + if (socket.openMode() & QIODevice::Unbuffered) + QVERIFY(socket.bytesAvailable() <= qint64(joined.size())); + else + QCOMPARE(socket.bytesAvailable(), qint64(joined.size())); + + QVERIFY(socket.canReadLine()); + + QByteArray echoed = socket.readAll(); + + QCOMPARE(joined.toUtf8(), echoed); + } + + /* Disconnection */ + QSignalSpy disconnectedSpy(&socket, SIGNAL(disconnected())); + + socket.disconnectFromService(); + + QCOMPARE(socket.isWritable(), false); + QCOMPARE(socket.isReadable(), false); + QCOMPARE(socket.isOpen(), false); + QCOMPARE(socket.openMode(), QIODevice::NotOpen); + + int disconnectTime = MaxConnectTime; + while (disconnectedSpy.isEmpty() && disconnectTime > 0) { + QTest::qWait(1000); + disconnectTime -= 1000; + } + + QCOMPARE(disconnectedSpy.size(), 1); + QCOMPARE(stateSpy.size(), 2); + QCOMPARE(qvariant_cast(stateSpy.takeFirst().at(0)), QBluetoothSocket::SocketState::ClosingState); + QCOMPARE(qvariant_cast(stateSpy.takeFirst().at(0)), QBluetoothSocket::SocketState::UnconnectedState); + + // The remote service needs time to close the connection and resume listening + QTest::qSleep(100); +} + +void tst_QBluetoothSocket::tst_error() +{ + QBluetoothSocket socket; + QSignalSpy errorSpy(&socket, SIGNAL(errorOccurred(QBluetoothSocket::SocketError))); + QCOMPARE(errorSpy.size(), 0); + const QBluetoothSocket::SocketError e = socket.error(); + + QVERIFY(e == QBluetoothSocket::SocketError::NoSocketError); + + QVERIFY(socket.errorString() == QString()); +} + +void tst_QBluetoothSocket::tst_preferredSecurityFlags() +{ + QBluetoothSocket socket; + + //test default values +#if defined(QT_ANDROID_BLUETOOTH) || defined(QT_OSX_BLUETOOTH) + QCOMPARE(socket.preferredSecurityFlags(), QBluetooth::Security::Secure); +#elif QT_CONFIG(bluez) + // The bluezdbus socket uses "NoSecurity" by default, whereas the non-dbus bluez + // socket uses "Authorization" by default + if (bluetoothdVersion() >= QVersionNumber(5, 46)) + QCOMPARE(socket.preferredSecurityFlags(), QBluetooth::Security::NoSecurity); + else + QCOMPARE(socket.preferredSecurityFlags(), QBluetooth::Security::Authorization); +#else + QCOMPARE(socket.preferredSecurityFlags(), QBluetooth::Security::NoSecurity); +#endif + + socket.setPreferredSecurityFlags(QBluetooth::Security::Authentication + | QBluetooth::Security::Encryption); + +#if defined(QT_OSX_BLUETOOTH) + QCOMPARE(socket.preferredSecurityFlags(), QBluetooth::Security::Secure); +#else + QCOMPARE(socket.preferredSecurityFlags(), + QBluetooth::Security::Encryption | QBluetooth::Security::Authentication); +#endif +} + +void tst_QBluetoothSocket::tst_unsupportedProtocolError() +{ +#if defined(QT_ANDROID_BLUETOOTH) + QSKIP("Android platform (re)sets RFCOMM socket type, nothing to test"); +#endif + // This socket has 'UnknownProtocol' socketType. + // Any attempt to connectToService should end in + // UnsupportedProtocolError. + QBluetoothSocket socket; + QCOMPARE(socket.socketType(), QBluetoothServiceInfo::UnknownProtocol); + QVERIFY(socket.error() == QBluetoothSocket::SocketError::NoSocketError); + QVERIFY(socket.errorString() == QString()); + + QSignalSpy errorSpy(&socket, SIGNAL(errorOccurred(QBluetoothSocket::SocketError))); + + // 1. Stop early with 'UnsupportedProtocolError'. + QBluetoothServiceInfo dummyServiceInfo; + socket.connectToService(dummyServiceInfo, QIODevice::ReadWrite); + QTRY_COMPARE_WITH_TIMEOUT(errorSpy.size(), 1, 1000); + QCOMPARE(errorSpy.size(), 1); + QCOMPARE(errorSpy.takeFirst().at(0).toInt(), int(QBluetoothSocket::SocketError::UnsupportedProtocolError)); + QVERIFY(socket.errorString().size() != 0); + QCOMPARE(socket.state(), QBluetoothSocket::SocketState::UnconnectedState); + + errorSpy.clear(); + + // 2. Stop early with UnsupportedProtocolError (before testing an invalid address/port). + socket.connectToService(QBluetoothAddress(), 1, QIODevice::ReadWrite); + QTRY_COMPARE_WITH_TIMEOUT(errorSpy.size(), 1, 1000); + QCOMPARE(errorSpy.size(), 1); +#if QT_CONFIG(bluez) + // Bluez dbus socket does not support connecting to port and gives different error code + if (bluetoothdVersion() >= QVersionNumber(5, 46)) { + QCOMPARE(errorSpy.takeFirst().at(0).toInt(), + int(QBluetoothSocket::SocketError::ServiceNotFoundError)); + } else { + QCOMPARE(errorSpy.takeFirst().at(0).toInt(), + int(QBluetoothSocket::SocketError::UnsupportedProtocolError)); + } +#else + QCOMPARE(errorSpy.takeFirst().at(0).toInt(), int(QBluetoothSocket::SocketError::UnsupportedProtocolError)); +#endif + QVERIFY(socket.errorString().size() != 0); + QCOMPARE(socket.state(), QBluetoothSocket::SocketState::UnconnectedState); + + errorSpy.clear(); + + // 3. Stop early (ignoring an invalid address/uuid). + socket.connectToService(QBluetoothAddress(), QBluetoothUuid(), QIODevice::ReadWrite); + QTRY_COMPARE_WITH_TIMEOUT(errorSpy.size(), 1, 1000); + QCOMPARE(errorSpy.size(), 1); + QCOMPARE(errorSpy.takeFirst().at(0).toInt(), int(QBluetoothSocket::SocketError::UnsupportedProtocolError)); + QVERIFY(socket.errorString().size() != 0); + QCOMPARE(socket.state(), QBluetoothSocket::SocketState::UnconnectedState); +} + +QTEST_MAIN(tst_QBluetoothSocket) + +#include "tst_qbluetoothsocket.moc" + diff --git a/tests/auto/qbluetoothuuid/CMakeLists.txt b/tests/auto/qbluetoothuuid/CMakeLists.txt new file mode 100644 index 0000000..de98130 --- /dev/null +++ b/tests/auto/qbluetoothuuid/CMakeLists.txt @@ -0,0 +1,20 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## tst_qbluetoothuuid Test: +##################################################################### + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qbluetoothuuid LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qbluetoothuuid + SOURCES + tst_qbluetoothuuid.cpp + LIBRARIES + Qt::Bluetooth + Qt::CorePrivate +) diff --git a/tests/auto/qbluetoothuuid/tst_qbluetoothuuid.cpp b/tests/auto/qbluetoothuuid/tst_qbluetoothuuid.cpp new file mode 100644 index 0000000..377f788 --- /dev/null +++ b/tests/auto/qbluetoothuuid/tst_qbluetoothuuid.cpp @@ -0,0 +1,390 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include +#include + +#include + +#include + +#if defined(Q_OS_DARWIN) +#include +#endif + +#if defined(Q_OS_UNIX) +# include +# include +#endif + +QT_USE_NAMESPACE + +class tst_QBluetoothUuid : public QObject +{ + Q_OBJECT + +public: + tst_QBluetoothUuid(); + ~tst_QBluetoothUuid(); + +private slots: + void initTestCase(); + + void tst_construction(); + void tst_assignment(); + void tst_conversion_data(); + void tst_conversion(); + void tst_comparison_data(); + void tst_comparison(); +}; + +tst_QBluetoothUuid::tst_QBluetoothUuid() +{ +} + +tst_QBluetoothUuid::~tst_QBluetoothUuid() +{ +} + +void tst_QBluetoothUuid::initTestCase() +{ +} + +void tst_QBluetoothUuid::tst_construction() +{ + { + QBluetoothUuid nullUuid; + + QVERIFY(nullUuid.isNull()); + } + + { + QBluetoothUuid uuid(QBluetoothUuid::ServiceClassUuid::PublicBrowseGroup); + + QVERIFY(!uuid.isNull()); + + bool ok; + quint16 uuid16; + + uuid16 = uuid.toUInt16(&ok); + + QVERIFY(ok); + QCOMPARE(uuid16, static_cast(QBluetoothUuid::ServiceClassUuid::PublicBrowseGroup)); + } + + { + QBluetoothUuid uuid(QBluetoothUuid::ServiceClassUuid::PublicBrowseGroup); + + QBluetoothUuid copy(uuid); + + QCOMPARE(uuid.toUInt16(), copy.toUInt16()); + } + + { + QBluetoothUuid uuid(QBluetoothUuid::ProtocolUuid::L2cap); + + QVERIFY(!uuid.isNull()); + + bool ok; + quint16 uuid16; + + uuid16 = uuid.toUInt16(&ok); + + QVERIFY(ok); + QCOMPARE(uuid16, static_cast(QBluetoothUuid::ProtocolUuid::L2cap)); + } + + { + QUuid uuid(0x67c8770b, 0x44f1, 0x410a, 0xab, 0x9a, 0xf9, 0xb5, 0x44, 0x6f, 0x13, 0xee); + QBluetoothUuid btUuid(uuid); + QVERIFY(!btUuid.isNull()); + + QString uuidString(btUuid.toString()); + QVERIFY(!uuidString.isEmpty()); + QCOMPARE(uuidString, QString("{67c8770b-44f1-410a-ab9a-f9b5446f13ee}")); + } + + { + QBluetoothUuid btUuid(QString("67c8770b-44f1-410a-ab9a-f9b5446f13ee")); + QVERIFY(!btUuid.isNull()); + + QString uuidString(btUuid.toString()); + QVERIFY(!uuidString.isEmpty()); + QCOMPARE(uuidString, QString("{67c8770b-44f1-410a-ab9a-f9b5446f13ee}")); + } + + { + QBluetoothUuid btUuid(QString("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")); + QVERIFY(btUuid.isNull()); + } +} + +void tst_QBluetoothUuid::tst_assignment() +{ + QBluetoothUuid uuid(QBluetoothUuid::ServiceClassUuid::PublicBrowseGroup); + + { + QBluetoothUuid copy = uuid; + + QCOMPARE(uuid.toUInt16(), copy.toUInt16()); + } + + { + QBluetoothUuid copy1; + QBluetoothUuid copy2; + + QVERIFY(copy1.isNull()); + QVERIFY(copy2.isNull()); + + copy1 = copy2 = uuid; + + QVERIFY(!copy1.isNull()); + QVERIFY(!copy2.isNull()); + + QCOMPARE(uuid.toUInt16(), copy1.toUInt16()); + QCOMPARE(uuid.toUInt16(), copy2.toUInt16()); + } +} + +#define BASEUUID "-0000-1000-8000-00805F9B34FB" + +void tst_QBluetoothUuid::tst_conversion_data() +{ + QTest::addColumn("constructUuid16"); + QTest::addColumn("uuid16"); + QTest::addColumn("constructUuid32"); + QTest::addColumn("uuid32"); + QTest::addColumn("constructUuid128"); + QTest::addColumn("uuid128"); + QTest::addColumn("uuidS"); + + static const auto uuid128_32 = [](quint8 a, quint8 b, quint8 c, quint8 d) { + QUuid::Id128Bytes x = { + { + a, b, c, d, + 0x00, 0x00, + 0x10, 0x00, + 0x80, 0x00, + 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB + } + }; + return x; + }; + + auto newRow32 = [](const char *name, quint8 a, quint8 b, quint8 c, quint8 d, const char *s) { + auto uuid128 = uuid128_32(a, b, c, d); + quint32 uuid32 = a << 24 | b << 16 | c << 8 | d; + quint16 uuid16; \ + bool constructUuid16 = (a == 0) && (b == 0); + if (constructUuid16) + uuid16 = c << 8 | d; + else + uuid16 = 0; + QTest::newRow(name) << constructUuid16 << uuid16 << true << uuid32 << true << uuid128 + << (QLatin1Char('{') + QLatin1String(s) + QLatin1Char('}')); + }; + + auto newRow16 = [](const char *name, quint8 a, quint8 b, const char *s) { + auto uuid128 = uuid128_32(0, 0, a, b); + quint32 uuid32 = a << 8 | b; + quint16 uuid16 = a << 8 | b; + QTest::newRow(name) << true << uuid16 << true << uuid32 << true << uuid128 + << (QLatin1Char('{') + QLatin1String(s) + QLatin1Char('}')); + }; + + newRow32("base uuid", 0x00, 0x00, 0x00, 0x00, "00000000" BASEUUID); + newRow16("0x0001", 0x00, 0x01, "00000001" BASEUUID); + newRow16("0xffff", 0xff, 0xff, "0000FFFF" BASEUUID); + newRow32("0x00010000", 0x00, 0x01, 0x00, 0x00, "00010000" BASEUUID); + newRow32("0x0001ffff", 0x00, 0x01, 0xff, 0xff, "0001FFFF" BASEUUID); + newRow32("0xffff0000", 0xff, 0xff, 0x00, 0x00, "FFFF0000" BASEUUID); + newRow32("0xffffffff", 0xff, 0xff, 0xff, 0xff, "FFFFFFFF" BASEUUID); + + { + QUuid::Id128Bytes uuid128 = { + { + 0x00, 0x11, 0x22, 0x33, + 0x44, 0x55, + 0x66, 0x77, + 0x88, 0x99, + 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff + } + }; + + QTest::newRow("00112233-4455-6677-8899-AABBCCDDEEFF") + << false << quint16(0) << false << quint32(0) << true << uuid128 + << QStringLiteral("{00112233-4455-6677-8899-AABBCCDDEEFF}"); + } +} + +void tst_QBluetoothUuid::tst_conversion() +{ + QFETCH(bool, constructUuid16); + QFETCH(quint16, uuid16); + QFETCH(bool, constructUuid32); + QFETCH(quint32, uuid32); + QFETCH(bool, constructUuid128); + QFETCH(QUuid::Id128Bytes, uuid128); + QFETCH(QString, uuidS); + + int minimumSize = 16; + if (constructUuid16) + minimumSize = 2; + else if (constructUuid32) + minimumSize = 4; + +#if defined(Q_OS_DARWIN) +#define CHECK_PLATFORM_CONVERSION(qtUuid) \ + const QMacAutoReleasePool pool; \ + CBUUID *nativeUuid = qtUuid.toCBUUID(); \ + QVERIFY(nativeUuid); \ + QCOMPARE(qtUuid, QBluetoothUuid::fromCBUUID(nativeUuid)); +#else +#define CHECK_PLATFORM_CONVERSION(qtUuid) +#endif // Q_OS_DARWIN + + if (constructUuid16) { + QBluetoothUuid uuid(uuid16); + + QCOMPARE(uuid, QBluetoothUuid(QStringView{uuidS})); + + bool ok; + + QCOMPARE(uuid.toUInt16(&ok), uuid16); + QVERIFY(ok); + + QCOMPARE(uuid.toUInt32(&ok), uuid32); + QVERIFY(ok); + + QVERIFY(memcmp(uuid.toBytes().data, uuid128.data, 16) == 0); + + QCOMPARE(uuid.toString().toUpper(), uuidS.toUpper()); + + QCOMPARE(uuid.minimumSize(), minimumSize); + + CHECK_PLATFORM_CONVERSION(uuid) + } + + if (constructUuid32) { + QBluetoothUuid uuid(uuid32); + + QCOMPARE(uuid, QBluetoothUuid(QLatin1StringView{uuidS.toLatin1()})); + + bool ok; + + quint16 tmp = uuid.toUInt16(&ok); + QCOMPARE(ok, constructUuid16); + if (ok) { + QCOMPARE(tmp, uuid16); + } + + QCOMPARE(uuid.toUInt32(&ok), uuid32); + QVERIFY(ok); + + QVERIFY(memcmp(uuid.toBytes().data, uuid128.data, 16) == 0); + + QCOMPARE(uuid.toString().toUpper(), uuidS.toUpper()); + + QCOMPARE(uuid.minimumSize(), minimumSize); + + CHECK_PLATFORM_CONVERSION(uuid) + } + + if (constructUuid128) { + QBluetoothUuid uuid(uuid128); + + QCOMPARE(uuid, QBluetoothUuid(QUtf8StringView{uuidS.toUtf8()})); + + bool ok; + + quint16 tmpUuid16 = uuid.toUInt16(&ok); + QCOMPARE(ok, constructUuid16); + if (ok) + QCOMPARE(tmpUuid16, uuid16); + + quint32 tmpUuid32 = uuid.toUInt32(&ok); + QCOMPARE(ok, constructUuid32); + if (ok) + QCOMPARE(tmpUuid32, uuid32); + + QVERIFY(memcmp(uuid.toBytes().data, uuid128.data, 16) == 0); + + QCOMPARE(uuid.toString().toUpper(), uuidS.toUpper()); + + QCOMPARE(uuid.minimumSize(), minimumSize); + + CHECK_PLATFORM_CONVERSION(uuid) + } +#undef CHECK_PLATFORM_CONVERSION +} + +void tst_QBluetoothUuid::tst_comparison_data() +{ + tst_conversion_data(); +} + +void tst_QBluetoothUuid::tst_comparison() +{ + QFETCH(bool, constructUuid16); + QFETCH(quint16, uuid16); + QFETCH(bool, constructUuid32); + QFETCH(quint32, uuid32); + QFETCH(bool, constructUuid128); + QFETCH(QUuid::Id128Bytes, uuid128); + + QVERIFY(QBluetoothUuid() == QBluetoothUuid()); + + if (constructUuid16) { + QBluetoothUuid quuid16(uuid16); + QBluetoothUuid quuid32(uuid32); + QBluetoothUuid quuid128(uuid128); + + QVERIFY(quuid16.toUInt16() == uuid16); + QVERIFY(quuid16.toUInt32() == uuid32); + + QVERIFY(quuid16 == quuid32); + QVERIFY(quuid16 == quuid128); + + QVERIFY(quuid32 == quuid16); + QVERIFY(quuid128 == quuid16); + } + + if (constructUuid32) { + QBluetoothUuid quuid32(uuid32); + QBluetoothUuid quuid128(uuid128); + + QVERIFY(quuid32.toUInt32() == uuid32); + QVERIFY(quuid32 == quuid128); + + QVERIFY(quuid128 == quuid32); + } + + if (constructUuid128) { + QBluetoothUuid quuid128(uuid128); + + for (int var = 0; var < 16; ++var) { + QVERIFY(quuid128.toBytes().data[var] == uuid128.data[var]); + } + + // check that toUInt128() call returns the value in the same format as + // QUuid::Id128Bytes, no matter what version we use (it can be + // QUuid::toUint128() on platforms that define __SIZEOF_INT128__ or + // QBluetoothUuid::toUint128() on other platforms). + const quint128 i128 = quuid128.toUInt128(); + static_assert(sizeof(i128) == 16); // uint128 or QUuid::Id128Bytes + uchar dst[16]; + memcpy(dst, &i128, sizeof(i128)); + for (int var = 0; var < 16; ++var) + QCOMPARE_EQ(dst[var], uuid128.data[var]); + + // check that we always have a c-tor taking quint128 + QBluetoothUuid other{i128}; + const auto bytes = other.toBytes(); + for (int var = 0; var < 16; ++var) + QCOMPARE_EQ(bytes.data[var], uuid128.data[var]); + } +} + +QTEST_MAIN(tst_QBluetoothUuid) + +#include "tst_qbluetoothuuid.moc" diff --git a/tests/auto/qlowenergycharacteristic/CMakeLists.txt b/tests/auto/qlowenergycharacteristic/CMakeLists.txt new file mode 100644 index 0000000..7089c5c --- /dev/null +++ b/tests/auto/qlowenergycharacteristic/CMakeLists.txt @@ -0,0 +1,31 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## tst_qlowenergycharacteristic Test: +##################################################################### + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qlowenergycharacteristic LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qlowenergycharacteristic + SOURCES + tst_qlowenergycharacteristic.cpp + LIBRARIES + Qt::Bluetooth +) + +set_target_properties(tst_qlowenergycharacteristic PROPERTIES + MACOSX_BUNDLE TRUE +) + +if (APPLE AND NOT IOS) + # Ninja has trouble with relative paths, convert to absolute as a workaround + get_filename_component(SHARED_PLIST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../shared ABSOLUTE) + set_target_properties(tst_qlowenergycharacteristic PROPERTIES + MACOSX_BUNDLE_INFO_PLIST "${SHARED_PLIST_DIR}/Info.macos.plist" + ) +endif() diff --git a/tests/auto/qlowenergycharacteristic/tst_qlowenergycharacteristic.cpp b/tests/auto/qlowenergycharacteristic/tst_qlowenergycharacteristic.cpp new file mode 100644 index 0000000..ea87d10 --- /dev/null +++ b/tests/auto/qlowenergycharacteristic/tst_qlowenergycharacteristic.cpp @@ -0,0 +1,345 @@ +// Copyright (C) 2016 BlackBerry Limited all rights reserved +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include +#include + +#include + +#include +#include +#include +#include + +QT_USE_NAMESPACE + +// This define must be set if the platform provides access to GATT handles +// otherwise it must not be defined. As of now the two supported platforms +// (Android and Bluez/Linux) provide access or some notion of it. +#define HANDLES_PROVIDED_BY_PLATFORM + +#ifdef HANDLES_PROVIDED_BY_PLATFORM +#define HANDLE_VERIFY(stmt) QVERIFY(stmt) +#else +#define HANDLE_VERIFY(stmt) +#endif + +class tst_QLowEnergyCharacteristic : public QObject +{ + Q_OBJECT + +public: + tst_QLowEnergyCharacteristic(); + ~tst_QLowEnergyCharacteristic(); + +protected slots: + void deviceDiscovered(const QBluetoothDeviceInfo &info); + +private slots: + void initTestCase(); + void cleanupTestCase(); + void tst_constructionDefault(); + void tst_assignCompare(); + +private: + QList remoteLeDevices; + QLowEnergyController *globalControl; + QLowEnergyService *globalService; +}; + +tst_QLowEnergyCharacteristic::tst_QLowEnergyCharacteristic() : + globalControl(0), globalService(0) +{ + QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true")); + qRegisterMetaType(); +} + +tst_QLowEnergyCharacteristic::~tst_QLowEnergyCharacteristic() +{ +} + +void tst_QLowEnergyCharacteristic::initTestCase() +{ +#if defined(Q_OS_MACOS) + QSKIP("The low energy characteristic tests fail on macOS"); +#endif + if (QBluetoothLocalDevice::allDevices().isEmpty()) { + qWarning("No local adapter, not discovering remote devices"); + return; + } + + QBluetoothLocalDevice device; + if (device.hostMode() == QBluetoothLocalDevice::HostPoweredOff) { + // Attempt to switch Bluetooth ON + device.powerOn(); + QTest::qWait(1000); + if (device.hostMode() == QBluetoothLocalDevice::HostPoweredOff) { + qWarning("Bluetooth couldn't be switched ON, not discovering remote devices"); + return; + } + } + + // find an arbitrary low energy device in vicinity + // find an arbitrary service with characteristic + QBluetoothDeviceDiscoveryAgent *devAgent = new QBluetoothDeviceDiscoveryAgent(this); + connect(devAgent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)), + this, SLOT(deviceDiscovered(QBluetoothDeviceInfo))); + + QSignalSpy errorSpy(devAgent, SIGNAL(errorOccurred(QBluetoothDeviceDiscoveryAgent::Error))); + QVERIFY(errorSpy.isValid()); + QVERIFY(errorSpy.isEmpty()); + + QSignalSpy spy(devAgent, SIGNAL(finished())); + QVERIFY(spy.isValid()); + QVERIFY(spy.isEmpty()); + + devAgent->start(); + QTRY_VERIFY_WITH_TIMEOUT(!spy.isEmpty(), 100000); + + // find first service with descriptor + QLowEnergyController *controller = 0; + for (const QBluetoothDeviceInfo &remoteDevice : std::as_const(remoteLeDevices)) { + controller = QLowEnergyController::createCentral(remoteDevice, this); + qDebug() << "Connecting to" << remoteDevice.name() + << remoteDevice.address() << remoteDevice.deviceUuid(); + controller->connectToDevice(); + QTRY_IMPL(controller->state() != QLowEnergyController::ConnectingState, + 50000); + if (controller->state() != QLowEnergyController::ConnectedState) { + // any error and we skip + delete controller; + qDebug() << "Skipping device"; + continue; + } + + QSignalSpy discoveryFinishedSpy(controller, SIGNAL(discoveryFinished())); + QSignalSpy stateSpy(controller, SIGNAL(stateChanged(QLowEnergyController::ControllerState))); + controller->discoverServices(); + QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.size() == 1, 10000); + QCOMPARE(stateSpy.size(), 2); + QCOMPARE(stateSpy.at(0).at(0).value(), + QLowEnergyController::DiscoveringState); + QCOMPARE(stateSpy.at(1).at(0).value(), + QLowEnergyController::DiscoveredState); + + const QList leServiceUuids = controller->services(); + for (const QBluetoothUuid &leServiceUuid : leServiceUuids) { + QLowEnergyService *leService = controller->createServiceObject(leServiceUuid, this); + if (!leService) + continue; + + leService->discoverDetails(); + QTRY_VERIFY_WITH_TIMEOUT( + leService->state() == QLowEnergyService::RemoteServiceDiscovered, 10000); + + const QList chars = leService->characteristics(); + for (const QLowEnergyCharacteristic &ch : chars) { + if (!ch.descriptors().isEmpty()) { + globalService = leService; + globalControl = controller; + qWarning() << "Found service with descriptor" << remoteDevice.address() + << globalService->serviceName() << globalService->serviceUuid(); + break; + } + } + + if (globalControl) + break; + else + delete leService; + } + + if (globalControl) + break; + + delete controller; + } + + if (!globalControl) { + qWarning() << "Test limited due to missing remote QLowEnergyDescriptor." + << "Please ensure the Bluetooth Low Energy device is advertising its services."; + } +} + +void tst_QLowEnergyCharacteristic::cleanupTestCase() +{ + if (globalControl) + globalControl->disconnectFromDevice(); +} + +void tst_QLowEnergyCharacteristic::deviceDiscovered(const QBluetoothDeviceInfo &info) +{ + if (info.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration) + remoteLeDevices.append(info); +} + +void tst_QLowEnergyCharacteristic::tst_constructionDefault() +{ + QLowEnergyCharacteristic characteristic; + QVERIFY(!characteristic.isValid()); + QCOMPARE(characteristic.value(), QByteArray()); + QVERIFY(characteristic.uuid().isNull()); + QCOMPARE(characteristic.name(), QString()); + QCOMPARE(characteristic.descriptors().size(), 0); + QCOMPARE(characteristic.descriptor(QBluetoothUuid()), + QLowEnergyDescriptor()); + QCOMPARE(characteristic.descriptor(QBluetoothUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration)), + QLowEnergyDescriptor()); + QCOMPARE(characteristic.descriptor(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration), + QLowEnergyDescriptor()); + QCOMPARE(characteristic.properties(), QLowEnergyCharacteristic::Unknown); + + QLowEnergyCharacteristic copyConstructed(characteristic); + QVERIFY(!copyConstructed.isValid()); + QCOMPARE(copyConstructed.value(), QByteArray()); + QVERIFY(copyConstructed.uuid().isNull()); + QCOMPARE(copyConstructed.name(), QString()); + QCOMPARE(copyConstructed.descriptors().size(), 0); + QCOMPARE(copyConstructed.properties(), QLowEnergyCharacteristic::Unknown); + + QVERIFY(copyConstructed == characteristic); + QVERIFY(characteristic == copyConstructed); + QVERIFY(!(copyConstructed != characteristic)); + QVERIFY(!(characteristic != copyConstructed)); + + QLowEnergyCharacteristic assigned; + + QVERIFY(assigned == characteristic); + QVERIFY(characteristic == assigned); + QVERIFY(!(assigned != characteristic)); + QVERIFY(!(characteristic != assigned)); + + assigned = characteristic; + QVERIFY(!assigned.isValid()); + QCOMPARE(assigned.value(), QByteArray()); + QVERIFY(assigned.uuid().isNull()); + QCOMPARE(assigned.name(), QString()); + QCOMPARE(assigned.descriptors().size(), 0); + QCOMPARE(assigned.properties(), QLowEnergyCharacteristic::Unknown); + + QVERIFY(assigned == characteristic); + QVERIFY(characteristic == assigned); + QVERIFY(!(assigned != characteristic)); + QVERIFY(!(characteristic != assigned)); +} + +void tst_QLowEnergyCharacteristic::tst_assignCompare() +{ + if (!globalService) + QSKIP("No characteristic found."); + + QLowEnergyCharacteristic target; + QVERIFY(!target.isValid()); + QCOMPARE(target.value(), QByteArray()); + QVERIFY(target.uuid().isNull()); + QCOMPARE(target.name(), QString()); + QCOMPARE(target.descriptors().size(), 0); + QCOMPARE(target.properties(), QLowEnergyCharacteristic::Unknown); + + qsizetype indexWithDescriptor = -1; + const QList chars = globalService->characteristics(); + QVERIFY(!chars.isEmpty()); + for (qsizetype i = 0; i < chars.size(); ++i) { + const QLowEnergyCharacteristic specific = + globalService->characteristic(chars[i].uuid()); + QVERIFY(specific.isValid()); + QCOMPARE(specific, chars[i]); + if (!chars[i].descriptors().isEmpty()) { + indexWithDescriptor = i; + break; + } + } + + if (chars.isEmpty()) + QSKIP("No suitable characteristic found despite prior indication."); + + bool noDescriptors = (indexWithDescriptor == -1); + if (noDescriptors) + indexWithDescriptor = 0; // just choose one + + // test assignment operator + target = chars[indexWithDescriptor]; + QVERIFY(target.isValid()); + QVERIFY(!target.name().isEmpty()); + QVERIFY(!target.uuid().isNull()); + QVERIFY(target.properties() != QLowEnergyCharacteristic::Unknown); + if (target.properties() & QLowEnergyCharacteristic::Read) + QVERIFY(!target.value().isEmpty()); + if (!noDescriptors) + QVERIFY(!target.descriptors().isEmpty()); + + QVERIFY(target == chars[indexWithDescriptor]); + QVERIFY(chars[indexWithDescriptor] == target); + QVERIFY(!(target != chars[indexWithDescriptor])); + QVERIFY(!(chars[indexWithDescriptor] != target)); + + QCOMPARE(target.isValid(), chars[indexWithDescriptor].isValid()); + QCOMPARE(target.name(), chars[indexWithDescriptor].name()); + QCOMPARE(target.uuid(), chars[indexWithDescriptor].uuid()); + QCOMPARE(target.value(), chars[indexWithDescriptor].value()); + QCOMPARE(target.properties(), chars[indexWithDescriptor].properties()); + { + const auto targetDescriptors = target.descriptors(); + const auto referenceDescriptors = chars[indexWithDescriptor].descriptors(); + QCOMPARE(targetDescriptors.size(), referenceDescriptors.size()); + for (qsizetype i = 0; i < targetDescriptors.size(); ++i) { + const QLowEnergyDescriptor ref = referenceDescriptors[i]; + QCOMPARE(targetDescriptors[i].name(), ref.name()); + QCOMPARE(targetDescriptors[i].isValid(), ref.isValid()); + QCOMPARE(targetDescriptors[i].type(), ref.type()); + QCOMPARE(targetDescriptors[i].uuid(), ref.uuid()); + QCOMPARE(targetDescriptors[i].value(), ref.value()); + + const QLowEnergyDescriptor ref2 = chars[indexWithDescriptor].descriptor(ref.uuid()); + QCOMPARE(ref, ref2); + } + } + + // test copy constructor + QLowEnergyCharacteristic copyConstructed(target); + QCOMPARE(copyConstructed.isValid(), chars[indexWithDescriptor].isValid()); + QCOMPARE(copyConstructed.name(), chars[indexWithDescriptor].name()); + QCOMPARE(copyConstructed.uuid(), chars[indexWithDescriptor].uuid()); + QCOMPARE(copyConstructed.value(), chars[indexWithDescriptor].value()); + QCOMPARE(copyConstructed.properties(), chars[indexWithDescriptor].properties()); + QCOMPARE(copyConstructed.descriptors().size(), + chars[indexWithDescriptor].descriptors().size()); + + QVERIFY(copyConstructed == target); + QVERIFY(target == copyConstructed); + QVERIFY(!(copyConstructed != target)); + QVERIFY(!(target != copyConstructed)); + + // test invalidation + QLowEnergyCharacteristic invalid; + target = invalid; + QVERIFY(!target.isValid()); + QCOMPARE(target.value(), QByteArray()); + QVERIFY(target.uuid().isNull()); + QCOMPARE(target.name(), QString()); + QCOMPARE(target.descriptors().size(), 0); + QCOMPARE(target.properties(), QLowEnergyCharacteristic::Unknown); + + QVERIFY(invalid == target); + QVERIFY(target == invalid); + QVERIFY(!(invalid != target)); + QVERIFY(!(target != invalid)); + + QVERIFY(!(chars[indexWithDescriptor] == target)); + QVERIFY(!(target == chars[indexWithDescriptor])); + QVERIFY(chars[indexWithDescriptor] != target); + QVERIFY(target != chars[indexWithDescriptor]); + + if (chars.size() >= 2) { + // at least two characteristics + QVERIFY(!(chars[0] == chars[1])); + QVERIFY(!(chars[1] == chars[0])); + QVERIFY(chars[0] != chars[1]); + QVERIFY(chars[1] != chars[0]); + } +} + +QTEST_MAIN(tst_QLowEnergyCharacteristic) + +#include "tst_qlowenergycharacteristic.moc" diff --git a/tests/auto/qlowenergycontroller-gattserver/CMakeLists.txt b/tests/auto/qlowenergycontroller-gattserver/CMakeLists.txt new file mode 100644 index 0000000..5659ea8 --- /dev/null +++ b/tests/auto/qlowenergycontroller-gattserver/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(server) +add_subdirectory(test) diff --git a/tests/auto/qlowenergycontroller-gattserver/README b/tests/auto/qlowenergycontroller-gattserver/README new file mode 100644 index 0000000..bd63ef8 --- /dev/null +++ b/tests/auto/qlowenergycontroller-gattserver/README @@ -0,0 +1,10 @@ +This test is split into a server and a client part. The former is supplying data, and +the latter is implementing the actual test application. +To run a full test, follow these steps: + 1) Start the server application on some machine that has a Bluetooth LE adapter + and is close enough to the client machine. + 2) On the client machine, set the QT_BT_GATTSERVER_TEST_ADDRESS environment variable + to the address of the Bluetooth adapter on the server machine. + 3) Run the test on the client. +If you skip steps 1) or 2), only a few unit tests will be run. These do not require the +test machine to have a Bluetooth adapter. diff --git a/tests/auto/qlowenergycontroller-gattserver/server/CMakeLists.txt b/tests/auto/qlowenergycontroller-gattserver/server/CMakeLists.txt new file mode 100644 index 0000000..3dc4672 --- /dev/null +++ b/tests/auto/qlowenergycontroller-gattserver/server/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## server Binary: +##################################################################### + +qt_internal_add_executable(qlecontroller-server + GUI + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" + SOURCES + qlowenergycontroller-gattserver.cpp + LIBRARIES + Qt::Bluetooth +) diff --git a/tests/auto/qlowenergycontroller-gattserver/server/qlowenergycontroller-gattserver.cpp b/tests/auto/qlowenergycontroller-gattserver/server/qlowenergycontroller-gattserver.cpp new file mode 100644 index 0000000..9eda2c0 --- /dev/null +++ b/tests/auto/qlowenergycontroller-gattserver/server/qlowenergycontroller-gattserver.cpp @@ -0,0 +1,216 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static QByteArray deviceName() { return "Qt GATT server"; } + +static QScopedPointer leController; +typedef QSharedPointer ServicePtr; +static QHash services; +static int descriptorWriteCount = 0; +static int disconnectCount = 0; +static QBluetoothAddress remoteDevice; + +void addService(const QLowEnergyServiceData &serviceData) +{ + const ServicePtr service(leController->addService(serviceData)); + Q_ASSERT(service); + services.insert(service->serviceUuid(), service); +} + +void addRunningSpeedService() +{ + QLowEnergyServiceData serviceData; + serviceData.setUuid(QBluetoothUuid::ServiceClassUuid::RunningSpeedAndCadence); + serviceData.setType(QLowEnergyServiceData::ServiceTypePrimary); + + QLowEnergyDescriptorData desc; + desc.setUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration); + desc.setValue(QByteArray(2, 0)); // Default: No indication, no notification. + QLowEnergyCharacteristicData charData; + charData.setUuid(QBluetoothUuid::CharacteristicType::RSCMeasurement); + charData.addDescriptor(desc); + charData.setProperties(QLowEnergyCharacteristic::Notify); + QByteArray value(4, 0); + value[0] = 1 << 2; // "Running", no optional fields. + charData.setValue(value); + serviceData.addCharacteristic(charData); + + charData = QLowEnergyCharacteristicData(); + charData.setUuid(QBluetoothUuid::CharacteristicType::RSCFeature); + charData.setProperties(QLowEnergyCharacteristic::Read); + value = QByteArray(2, 0); + qToLittleEndian(1 << 2, reinterpret_cast(value.data())); + charData.setValue(value); + serviceData.addCharacteristic(charData); + addService(serviceData); +} + +void addGenericAccessService() +{ + QLowEnergyServiceData serviceData; + serviceData.setUuid(QBluetoothUuid::ServiceClassUuid::GenericAccess); + serviceData.setType(QLowEnergyServiceData::ServiceTypePrimary); + + QLowEnergyCharacteristicData charData; + charData.setUuid(QBluetoothUuid::CharacteristicType::DeviceName); + charData.setProperties(QLowEnergyCharacteristic::Read | QLowEnergyCharacteristic::Write); + charData.setValue(deviceName()); + serviceData.addCharacteristic(charData); + + charData = QLowEnergyCharacteristicData(); + charData.setUuid(QBluetoothUuid::CharacteristicType::Appearance); + charData.setProperties(QLowEnergyCharacteristic::Read); + QByteArray value(2, 0); + qToLittleEndian(128, reinterpret_cast(value.data())); // Generic computer. + charData.setValue(value); + serviceData.addCharacteristic(charData); + + serviceData.addIncludedService(services.value(QBluetoothUuid::ServiceClassUuid::RunningSpeedAndCadence).data()); + addService(serviceData); +} + +void addCustomService() +{ + QLowEnergyServiceData serviceData; + serviceData.setUuid(QBluetoothUuid(quint16(0x2000))); + serviceData.setType(QLowEnergyServiceData::ServiceTypePrimary); + + QLowEnergyCharacteristicData charData; + charData.setUuid(QBluetoothUuid(quint16(0x5000))); // Made up. + charData.setProperties(QLowEnergyCharacteristic::Read); + charData.setValue(QByteArray(1024, 'x')); // Long value to test "Read Blob". + serviceData.addCharacteristic(charData); + + charData.setUuid(QBluetoothUuid(quint16(0x5001))); + charData.setProperties(QLowEnergyCharacteristic::Read); + charData.setReadConstraints( + QBluetooth::AttAccessConstraint::AttAuthorizationRequired); // To test read failure. + serviceData.addCharacteristic(charData); + charData.setValue("something"); + + charData.setUuid(QBluetoothUuid(quint16(0x5002))); + charData.setProperties(QLowEnergyCharacteristic::Read | QLowEnergyCharacteristic::Indicate); + charData.setReadConstraints(QBluetooth::AttAccessConstraints()); + const QLowEnergyDescriptorData desc(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration, + QByteArray(2, 0)); + charData.addDescriptor(desc); + serviceData.addCharacteristic(charData); + + charData.setUuid(QBluetoothUuid(quint16(0x5003))); + charData.setProperties(QLowEnergyCharacteristic::Read | QLowEnergyCharacteristic::Notify); + serviceData.addCharacteristic(charData); + + charData.setUuid(QBluetoothUuid(quint16(0x5004))); + charData.setProperties(QLowEnergyCharacteristic::Read | QLowEnergyCharacteristic::WriteSigned); + charData.setDescriptors(QList()); + charData.setValue("initial"); + serviceData.addCharacteristic(charData); + + addService(serviceData); + + // service with full 128 bit custom uuids + QLowEnergyServiceData serviceData128; + serviceData128.setUuid(QBluetoothUuid(QString("c47774c7-f237-4523-8968-e4ae75431daf"))); + serviceData128.setType(QLowEnergyServiceData::ServiceTypePrimary); + + QLowEnergyCharacteristicData charData128; + charData128.setUuid(QBluetoothUuid(QString("c0ad61b1-79e7-42f9-ace0-0a9aa0d0a4f8"))); + charData128.setProperties(QLowEnergyCharacteristic::Read); + charData128.setValue(QByteArray(15, 'a')); + serviceData128.addCharacteristic(charData128); + + addService(serviceData128); +} + +void startAdvertising() +{ + QLowEnergyAdvertisingParameters params; + params.setMode(QLowEnergyAdvertisingParameters::AdvInd); + QLowEnergyAdvertisingData data; + data.setDiscoverability(QLowEnergyAdvertisingData::DiscoverabilityLimited); + data.setServices(services.keys()); + data.setIncludePowerLevel(true); + data.setLocalName(deviceName()); + leController->startAdvertising(params, data); +} + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + leController.reset(QLowEnergyController::createPeripheral()); + addRunningSpeedService(); + addGenericAccessService(); + addCustomService(); + startAdvertising(); + + const ServicePtr customService = services.value(QBluetoothUuid(quint16(0x2000))); + Q_ASSERT(customService); + + const auto stateChangedHandler = [customService]() { + switch (leController->state()) { + case QLowEnergyController::ConnectedState: + remoteDevice = leController->remoteAddress(); + break; + case QLowEnergyController::UnconnectedState: { + if (++disconnectCount == 2) { + qApp->quit(); + break; + } + Q_ASSERT(disconnectCount == 1); + const QLowEnergyCharacteristic indicatableChar + = customService->characteristic(QBluetoothUuid(quint16(0x5002))); + Q_ASSERT(indicatableChar.isValid()); + customService->writeCharacteristic(indicatableChar, "indicated2"); + Q_ASSERT(indicatableChar.value() == "indicated2"); + const QLowEnergyCharacteristic notifiableChar + = customService->characteristic(QBluetoothUuid(quint16(0x5003))); + Q_ASSERT(notifiableChar.isValid()); + customService->writeCharacteristic(notifiableChar, "notified2"); + Q_ASSERT(notifiableChar.value() == "notified2"); + startAdvertising(); + break; + } + default: + break; + } + }; + + QObject::connect(leController.data(), &QLowEnergyController::stateChanged, stateChangedHandler); + const auto descriptorWriteHandler = [customService]() { + if (++descriptorWriteCount != 2) + return; + const QLowEnergyCharacteristic indicatableChar + = customService->characteristic(QBluetoothUuid(quint16(0x5002))); + Q_ASSERT(indicatableChar.isValid()); + customService->writeCharacteristic(indicatableChar, "indicated"); + Q_ASSERT(indicatableChar.value() == "indicated"); + const QLowEnergyCharacteristic notifiableChar + = customService->characteristic(QBluetoothUuid(quint16(0x5003))); + Q_ASSERT(notifiableChar.isValid()); + customService->writeCharacteristic(notifiableChar, "notified"); + Q_ASSERT(notifiableChar.value() == "notified"); + QLowEnergyConnectionParameters connParams; + connParams.setIntervalRange(30, 62.5); + connParams.setLatency(5); + connParams.setSupervisionTimeout(5500); + leController->requestConnectionUpdate(connParams); + }; + QObject::connect(customService.data(), &QLowEnergyService::descriptorWritten, + descriptorWriteHandler); + + return app.exec(); +} diff --git a/tests/auto/qlowenergycontroller-gattserver/test/CMakeLists.txt b/tests/auto/qlowenergycontroller-gattserver/test/CMakeLists.txt new file mode 100644 index 0000000..1e01efb --- /dev/null +++ b/tests/auto/qlowenergycontroller-gattserver/test/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## tst_qlowenergycontroller-gattserver Test: +##################################################################### + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qlowenergycontroller-gattserver LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qlowenergycontroller-gattserver + SOURCES + tst_qlowenergycontroller-gattserver.cpp + LIBRARIES + Qt::Bluetooth + Qt::BluetoothPrivate +) + +## Scopes: +##################################################################### + +qt_internal_extend_target(tst_qlowenergycontroller-gattserver CONDITION QT_FEATURE_linux_crypto_api + DEFINES + CONFIG_LINUX_CRYPTO_API +) + +qt_internal_extend_target(tst_qlowenergycontroller-gattserver CONDITION QT_FEATURE_bluez_le + DEFINES + CONFIG_BLUEZ_LE +) + +qt_internal_extend_target(tst_qlowenergycontroller-gattserver CONDITION boot2qt + DEFINES + CHECK_CMAC_SUPPORT +) diff --git a/tests/auto/qlowenergycontroller-gattserver/test/tst_qlowenergycontroller-gattserver.cpp b/tests/auto/qlowenergycontroller-gattserver/test/tst_qlowenergycontroller-gattserver.cpp new file mode 100644 index 0000000..bd72611 --- /dev/null +++ b/tests/auto/qlowenergycontroller-gattserver/test/tst_qlowenergycontroller-gattserver.cpp @@ -0,0 +1,670 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include + +#ifdef Q_OS_LINUX +#include +#endif + +#include +#include + +using namespace QBluetooth; + +class TestQLowEnergyControllerGattServer : public QObject +{ + Q_OBJECT + +private slots: + void initTestCase(); + + // Static, local stuff goes here. + void advertisingParameters(); + void advertisingData(); + void cmacVerifier(); + void cmacVerifier_data(); + void connectionParameters(); + void controllerType(); + void serviceData(); + + // Interaction with actual GATT server goes here. Order is relevant. + void advertisedData(); + void serverCommunication(); + +private: + QBluetoothAddress m_serverAddress; + QBluetoothDeviceInfo m_serverInfo; + QScopedPointer m_leController; + +#if defined(CHECK_CMAC_SUPPORT) + bool checkCmacSupport(const QUuid::Id128Bytes& csrkMsb); +#endif +}; + + +void TestQLowEnergyControllerGattServer::initTestCase() +{ + //QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true")); + const QString serverAddress = qgetenv("QT_BT_GATTSERVER_TEST_ADDRESS"); + if (serverAddress.isEmpty()) + return; + m_serverAddress = QBluetoothAddress(serverAddress); + QVERIFY(!m_serverAddress.isNull()); +} + +void TestQLowEnergyControllerGattServer::advertisingParameters() +{ + QLowEnergyAdvertisingParameters params; + QCOMPARE(params, QLowEnergyAdvertisingParameters()); + QCOMPARE(params.filterPolicy(), QLowEnergyAdvertisingParameters::IgnoreWhiteList); + QCOMPARE(params.minimumInterval(), 1280); + QCOMPARE(params.maximumInterval(), 1280); + QCOMPARE(params.mode(), QLowEnergyAdvertisingParameters::AdvInd); + QVERIFY(params.whiteList().isEmpty()); + + params.setInterval(100, 200); + QCOMPARE(params.minimumInterval(), 100); + QCOMPARE(params.maximumInterval(), 200); + params.setInterval(200, 100); + QCOMPARE(params.minimumInterval(), 200); + QCOMPARE(params.maximumInterval(), 200); + + params.setMode(QLowEnergyAdvertisingParameters::AdvScanInd); + QCOMPARE(params.mode(), QLowEnergyAdvertisingParameters::AdvScanInd); + + const auto whiteList = QList() + << QLowEnergyAdvertisingParameters::AddressInfo(QBluetoothAddress(), + QLowEnergyController::PublicAddress); + params.setWhiteList(whiteList, QLowEnergyAdvertisingParameters::UseWhiteListForConnecting); + QCOMPARE(params.whiteList(), whiteList); + QCOMPARE(params.filterPolicy(), QLowEnergyAdvertisingParameters::UseWhiteListForConnecting); + QVERIFY(params != QLowEnergyAdvertisingParameters()); + + // verify default ctor + QLowEnergyAdvertisingParameters::AddressInfo info; + QVERIFY(info.address == QBluetoothAddress()); + QVERIFY(info.type == QLowEnergyController::PublicAddress); +} + +void TestQLowEnergyControllerGattServer::advertisingData() +{ + QLowEnergyAdvertisingData data; + QCOMPARE(data, QLowEnergyAdvertisingData()); + QCOMPARE(data.discoverability(), QLowEnergyAdvertisingData::DiscoverabilityNone); + QCOMPARE(data.includePowerLevel(), false); + QCOMPARE(data.localName(), QString()); + QCOMPARE(data.manufacturerData(), QByteArray()); + QCOMPARE(data.manufacturerId(), QLowEnergyAdvertisingData::invalidManufacturerId()); + QVERIFY(data.services().isEmpty()); + + data.setDiscoverability(QLowEnergyAdvertisingData::DiscoverabilityLimited); + QCOMPARE(data.discoverability(), QLowEnergyAdvertisingData::DiscoverabilityLimited); + + data.setIncludePowerLevel(true); + QCOMPARE(data.includePowerLevel(), true); + + data.setLocalName("A device name"); + QCOMPARE(data.localName(), QString("A device name")); + + data.setManufacturerData(0xfffd, "some data"); + QCOMPARE(data.manufacturerId(), quint16(0xfffd)); + QCOMPARE(data.manufacturerData(), QByteArray("some data")); + + const auto services = QList() << QBluetoothUuid::ServiceClassUuid::CurrentTimeService + << QBluetoothUuid::ServiceClassUuid::DeviceInformation; + data.setServices(services); + QCOMPARE(data.services(), services); + + QByteArray rawData(7, 'x'); + data.setRawData(rawData); + QCOMPARE(data.rawData(), rawData); + + QVERIFY(data != QLowEnergyAdvertisingData()); +} + +void TestQLowEnergyControllerGattServer::cmacVerifier() +{ +#if defined(CONFIG_LINUX_CRYPTO_API) && defined(QT_BUILD_INTERNAL) && defined(CONFIG_BLUEZ_LE) + // Test data comes from spec v4.2, Vol 3, Part H, Appendix D.1 + const QUuid::Id128Bytes csrk = { + { 0x3c, 0x4f, 0xcf, 0x09, 0x88, 0x15, 0xf7, 0xab, + 0xa6, 0xd2, 0xae, 0x28, 0x16, 0x15, 0x7e, 0x2b } + }; + QFETCH(QByteArray, message); + QFETCH(quint64, expectedMac); + +#if defined(CHECK_CMAC_SUPPORT) + if (!checkCmacSupport(csrk)) { + QSKIP("Needed socket options not available. Running qemu?"); + } +#endif + + const bool success = LeCmacCalculator().verify(message, csrk, expectedMac); + QVERIFY(success); +#else // CONFIG_LINUX_CRYPTO_API + QSKIP("CMAC verification test only applicable for developer builds on Linux " + "with BlueZ and crypto API"); +#endif // Q_OS_LINUX +} + +#if defined(CHECK_CMAC_SUPPORT) +#include +#include +#include + +bool TestQLowEnergyControllerGattServer::checkCmacSupport(const QUuid::Id128Bytes& csrk) +{ + bool retval = false; +#if defined(CONFIG_LINUX_CRYPTO_API) && defined(QT_BUILD_INTERNAL) && defined(CONFIG_BLUEZ_LE) + QUuid::Id128Bytes csrkMsb; + std::reverse_copy(std::begin(csrk.data), std::end(csrk.data), std::begin(csrkMsb.data)); + + int testSocket = socket(AF_ALG, SOCK_SEQPACKET, 0); + if (testSocket != -1) { + sockaddr_alg sa; + using namespace std; + memset(&sa, 0, sizeof sa); + sa.salg_family = AF_ALG; + strcpy(reinterpret_cast(sa.salg_type), "hash"); + strcpy(reinterpret_cast(sa.salg_name), "cmac(aes)"); + if (::bind(testSocket, reinterpret_cast(&sa), sizeof sa) != -1) { + if (setsockopt(testSocket, 279 /* SOL_ALG */, ALG_SET_KEY, csrkMsb.data, sizeof csrkMsb) != -1) { + retval = true; + } else { + qWarning("Needed socket options (SOL_ALG) not available"); + } + } else { + qWarning("bind() failed for crypto socket:"); + } + close(testSocket); + } else { + qWarning("Unable to create test socket"); + } +#endif + return retval; +} +#endif + +void TestQLowEnergyControllerGattServer::cmacVerifier_data() +{ + QTest::addColumn("message"); + QTest::addColumn("expectedMac"); + QTest::newRow("D1.1") << QByteArray() << Q_UINT64_C(0xbb1d6929e9593728); + QTest::newRow("D1.2") << QByteArray::fromHex("2a179373117e3de9969f402ee2bec16b") + << Q_UINT64_C(0x070a16b46b4d4144); + QByteArray messageD13 = QByteArray::fromHex("6bc1bee22e409f96e93d7e117393172aae2d8a57" + "1e03ac9c9eb76fac45af8e5130c81c46a35ce411"); + std::reverse(messageD13.begin(), messageD13.end()); + QTest::newRow("D1.3") << messageD13 << Q_UINT64_C(0xdfa66747de9ae630); + QByteArray messageD14 = QByteArray::fromHex("6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411e5fbc1191a0a52ef" + "f69f2445df4f9b17ad2b417be66c3710"); + std::reverse(messageD14.begin(), messageD14.end()); + QTest::newRow("D1.4") << messageD14 << Q_UINT64_C(0x51f0bebf7e3b9d92); +} + +void TestQLowEnergyControllerGattServer::connectionParameters() +{ + QLowEnergyConnectionParameters connParams; + QCOMPARE(connParams, QLowEnergyConnectionParameters()); + connParams.setIntervalRange(8, 9); + QCOMPARE(connParams.minimumInterval(), double(8)); + QCOMPARE(connParams.maximumInterval(), double(9)); + connParams.setIntervalRange(9, 8); + QCOMPARE(connParams.minimumInterval(), double(9)); + QCOMPARE(connParams.maximumInterval(), double(9)); + connParams.setLatency(50); + QCOMPARE(connParams.latency(), 50); + connParams.setSupervisionTimeout(1000); + QCOMPARE(connParams.supervisionTimeout(), 1000); + const QLowEnergyConnectionParameters cp2 = connParams; + QCOMPARE(cp2, connParams); + QLowEnergyConnectionParameters cp3; + QVERIFY(cp3 != connParams); + cp3 = connParams; + QCOMPARE(cp3, connParams); +} + +void TestQLowEnergyControllerGattServer::advertisedData() +{ + if (m_serverAddress.isNull()) + QSKIP("No server address provided"); + QBluetoothDeviceDiscoveryAgent discoveryAgent; + discoveryAgent.start(); + QSignalSpy spy(&discoveryAgent, SIGNAL(finished())); + QVERIFY(spy.wait(30000)); + const QList devices = discoveryAgent.discoveredDevices(); + const auto it = std::find_if(devices.constBegin(), devices.constEnd(), + [this](const QBluetoothDeviceInfo &device) { return device.address() == m_serverAddress; }); + QVERIFY(it != devices.constEnd()); + m_serverInfo = *it; + + // BlueZ seems to interfere with the advertising in some way, so that in addition to the name + // we set, the host name of the machine is also sent. Therefore we cannot guarantee that "our" + // name is seen on the scanning machine. + // QCOMPARE(m_serverInfo.name(), QString("Qt GATT server")); + + QVERIFY(m_serverInfo.serviceUuids().size() >= 3); + QVERIFY(m_serverInfo.serviceUuids().contains(QBluetoothUuid::ServiceClassUuid::GenericAccess)); + QVERIFY(m_serverInfo.serviceUuids().contains(QBluetoothUuid::ServiceClassUuid::RunningSpeedAndCadence)); + QVERIFY(m_serverInfo.serviceUuids().contains(QBluetoothUuid(quint16(0x2000)))); +} + +void TestQLowEnergyControllerGattServer::serverCommunication() +{ + if (m_serverAddress.isNull()) + QSKIP("No server address provided"); + m_leController.reset(QLowEnergyController::createCentral(m_serverInfo)); + QVERIFY(!m_leController.isNull()); + m_leController->connectToDevice(); + QScopedPointer spy(new QSignalSpy(m_leController.data(), + &QLowEnergyController::connected)); + QVERIFY(spy->wait(30000)); + m_leController->discoverServices(); + spy.reset(new QSignalSpy(m_leController.data(), &QLowEnergyController::discoveryFinished)); + QVERIFY(spy->wait(30000)); + const QList serviceUuids = m_leController->services(); + QCOMPARE(serviceUuids.size(), 4); + QVERIFY(serviceUuids.contains(QBluetoothUuid::ServiceClassUuid::GenericAccess)); + QVERIFY(serviceUuids.contains(QBluetoothUuid::ServiceClassUuid::RunningSpeedAndCadence)); + QVERIFY(serviceUuids.contains(QBluetoothUuid(quint16(0x2000)))); + QVERIFY(serviceUuids.contains(QBluetoothUuid(QString("c47774c7-f237-4523-8968-e4ae75431daf")))); + + const QScopedPointer genericAccessService( + m_leController->createServiceObject(QBluetoothUuid::ServiceClassUuid::GenericAccess)); + QVERIFY(!genericAccessService.isNull()); + genericAccessService->discoverDetails(); + while (genericAccessService->state() != QLowEnergyService::RemoteServiceDiscovered) { + spy.reset(new QSignalSpy(genericAccessService.data(), &QLowEnergyService::stateChanged)); + QVERIFY(spy->wait(3000)); + } + QCOMPARE(genericAccessService->includedServices().size(), 1); + QCOMPARE(genericAccessService->includedServices().first(), + QBluetoothUuid(QBluetoothUuid::ServiceClassUuid::RunningSpeedAndCadence)); + QCOMPARE(genericAccessService->characteristics().size(), 2); + const QLowEnergyCharacteristic deviceNameChar + = genericAccessService->characteristic(QBluetoothUuid::CharacteristicType::DeviceName); + QVERIFY(deviceNameChar.isValid()); + QCOMPARE(deviceNameChar.descriptors().size(), 0); + QCOMPARE(deviceNameChar.properties(), + QLowEnergyCharacteristic::Read | QLowEnergyCharacteristic::Write); + QCOMPARE(deviceNameChar.value().constData(), "Qt GATT server"); + const QLowEnergyCharacteristic appearanceChar + = genericAccessService->characteristic(QBluetoothUuid::CharacteristicType::Appearance); + QVERIFY(appearanceChar.isValid()); + QCOMPARE(appearanceChar.descriptors().size(), 0); + QCOMPARE(appearanceChar.properties(), QLowEnergyCharacteristic::Read); + auto value = qFromLittleEndian(reinterpret_cast( + appearanceChar.value().constData())); + QCOMPARE(value, quint16(128)); + + const QScopedPointer runningSpeedService( + m_leController->createServiceObject(QBluetoothUuid::ServiceClassUuid::RunningSpeedAndCadence)); + QVERIFY(!runningSpeedService.isNull()); + runningSpeedService->discoverDetails(); + while (runningSpeedService->state() != QLowEnergyService::RemoteServiceDiscovered) { + spy.reset(new QSignalSpy(runningSpeedService.data(), &QLowEnergyService::stateChanged)); + QVERIFY(spy->wait(3000)); + } + QCOMPARE(runningSpeedService->includedServices().size(), 0); + QCOMPARE(runningSpeedService->characteristics().size(), 2); + QLowEnergyCharacteristic measurementChar + = runningSpeedService->characteristic(QBluetoothUuid::CharacteristicType::RSCMeasurement); + QVERIFY(measurementChar.isValid()); + QCOMPARE(measurementChar.descriptors().size(), 1); + const QLowEnergyDescriptor clientConfigDesc + = measurementChar.descriptor(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration); + QVERIFY(clientConfigDesc.isValid()); + QCOMPARE(clientConfigDesc.value(), QByteArray(2, 0)); + QCOMPARE(measurementChar.properties(), QLowEnergyCharacteristic::Notify); + QCOMPARE(measurementChar.value(), QByteArray()); // Empty because Read property not set + QLowEnergyCharacteristic featureChar + = runningSpeedService->characteristic(QBluetoothUuid::CharacteristicType::RSCFeature); + QVERIFY(featureChar.isValid()); + QCOMPARE(featureChar.descriptors().size(), 0); + QCOMPARE(featureChar.properties(), QLowEnergyCharacteristic::Read); + value = qFromLittleEndian(reinterpret_cast( + featureChar.value().constData())); + QCOMPARE(value, quint16(1 << 2)); + + // 128 bit custom uuid service + QBluetoothUuid serviceUuid128(QString("c47774c7-f237-4523-8968-e4ae75431daf")); + QBluetoothUuid charUuid128(QString("c0ad61b1-79e7-42f9-ace0-0a9aa0d0a4f8")); + QScopedPointer customService128( + m_leController->createServiceObject(serviceUuid128)); + QVERIFY(!customService128.isNull()); + customService128->discoverDetails(); + while (customService128->state() != QLowEnergyService::RemoteServiceDiscovered) { + spy.reset(new QSignalSpy(customService128.data(), &QLowEnergyService::stateChanged)); + QVERIFY(spy->wait(5000)); + } + QCOMPARE(customService128->serviceUuid(), serviceUuid128); + QCOMPARE(customService128->includedServices().size(), 0); + QCOMPARE(customService128->characteristics().size(), 1); + QLowEnergyCharacteristic customChar128 + = customService128->characteristic(charUuid128); + QVERIFY(customChar128.isValid()); + QCOMPARE(customChar128.descriptors().size(), 0); + QCOMPARE(customChar128.value(), QByteArray(15, 'a')); + + QScopedPointer customService( + m_leController->createServiceObject(QBluetoothUuid(quint16(0x2000)))); + QVERIFY(!customService.isNull()); + customService->discoverDetails(); + while (customService->state() != QLowEnergyService::RemoteServiceDiscovered) { + spy.reset(new QSignalSpy(customService.data(), &QLowEnergyService::stateChanged)); + QVERIFY(spy->wait(5000)); + } + QCOMPARE(customService->includedServices().size(), 0); + QCOMPARE(customService->characteristics().size(), 5); + QLowEnergyCharacteristic customChar + = customService->characteristic(QBluetoothUuid(quint16(0x5000))); + QVERIFY(customChar.isValid()); + QCOMPARE(customChar.descriptors().size(), 0); + QCOMPARE(customChar.value(), QByteArray(1024, 'x')); + + QLowEnergyCharacteristic customChar2 + = customService->characteristic(QBluetoothUuid(quint16(0x5001))); + QVERIFY(customChar2.isValid()); + QCOMPARE(customChar2.descriptors().size(), 0); + QCOMPARE(customChar2.value(), QByteArray()); // Was not readable due to authorization requirement. + + QLowEnergyCharacteristic customChar3 + = customService->characteristic(QBluetoothUuid(quint16(0x5002))); + QVERIFY(customChar3.isValid()); + QCOMPARE(customChar3.properties(), + QLowEnergyCharacteristic::Read | QLowEnergyCharacteristic::Indicate); + QCOMPARE(customChar3.descriptors().size(), 1); + QLowEnergyDescriptor cc3ClientConfig + = customChar3.descriptor(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration); + QVERIFY(cc3ClientConfig.isValid()); + + QLowEnergyCharacteristic customChar4 + = customService->characteristic(QBluetoothUuid(quint16(0x5003))); + QVERIFY(customChar4.isValid()); + QCOMPARE(customChar4.properties(), + QLowEnergyCharacteristic::Read | QLowEnergyCharacteristic::Notify); + QCOMPARE(customChar4.descriptors().size(), 1); + QLowEnergyDescriptor cc4ClientConfig + = customChar4.descriptor(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration); + QVERIFY(cc4ClientConfig.isValid()); + + QLowEnergyCharacteristic customChar5 + = customService->characteristic(QBluetoothUuid(quint16(0x5004))); + QVERIFY(customChar5.isValid()); + QCOMPARE(customChar5.properties(), + QLowEnergyCharacteristic::Read | QLowEnergyCharacteristic::WriteSigned); + QCOMPARE(customChar5.descriptors().size(), 0); + QCOMPARE(customChar5.value(), QByteArray("initial")); + + customService->writeCharacteristic(customChar, "whatever"); + spy.reset(new QSignalSpy(customService.data(), &QLowEnergyService::errorOccurred)); + QVERIFY(spy->wait(3000)); + QCOMPARE(customService->error(), QLowEnergyService::CharacteristicWriteError); + + spy.reset(new QSignalSpy(customService.data(), &QLowEnergyService::errorOccurred)); + customService->writeCharacteristic(customChar5, "1", QLowEnergyService::WriteSigned); + + // error might happen immediately or once event loop comes back + bool wasError = (!spy->isEmpty() || spy->wait(3000)); // + + if (!wasError) { + // Signed write is done twice to test the sign counter stuff. + // Note: We assume here that the link is not encrypted, as this information is not exported. + customService->readCharacteristic(customChar5); + spy.reset(new QSignalSpy(customService.data(), &QLowEnergyService::characteristicRead)); + QVERIFY(spy->wait(3000)); + QCOMPARE(customChar5.value(), QByteArray("1")); + customService->writeCharacteristic(customChar5, "2", QLowEnergyService::WriteSigned); + customService->readCharacteristic(customChar5); + spy.reset(new QSignalSpy(customService.data(), &QLowEnergyService::characteristicRead)); + QVERIFY(spy->wait(3000)); + QCOMPARE(customChar5.value(), QByteArray("2")); + } else { + QCOMPARE(customService->error(), QLowEnergyService::CharacteristicWriteError); + } + + QByteArray indicateValue(2, 0); + qToLittleEndian(2, reinterpret_cast(indicateValue.data())); + customService->writeDescriptor(cc3ClientConfig, indicateValue); + spy.reset(new QSignalSpy(customService.data(), &QLowEnergyService::descriptorWritten)); + QVERIFY(spy->wait(3000)); + + QByteArray notifyValue(2, 0); + qToLittleEndian(1, reinterpret_cast(notifyValue.data())); + customService->writeDescriptor(cc4ClientConfig, notifyValue); + spy.reset(new QSignalSpy(customService.data(), &QLowEnergyService::descriptorWritten)); + QVERIFY(spy->wait(3000)); + + // Server now changes the characteristic values. + + spy.reset(new QSignalSpy(customService.data(), &QLowEnergyService::characteristicChanged)); + QVERIFY(spy->wait(3000)); + if (spy->size() == 1) + QVERIFY(spy->wait(3000)); + QCOMPARE(customChar3.value().constData(), "indicated"); + QCOMPARE(customChar4.value().constData(), "notified"); + + // signal requires root privileges on Linux + spy.reset(new QSignalSpy(m_leController.data(), &QLowEnergyController::connectionUpdated)); + QVERIFY(spy->wait(5000)); + + m_leController->disconnectFromDevice(); + + if (m_leController->state() != QLowEnergyController::UnconnectedState) { + spy.reset(new QSignalSpy(m_leController.data(), &QLowEnergyController::stateChanged)); + QVERIFY(spy->wait(3000)); + } + QCOMPARE(m_leController->state(), QLowEnergyController::UnconnectedState); + + // Server now changes the characteristic values again while we're offline. + // Note: We cannot test indications and notifications for this case, as the client does + // not cache the old information and thus does not yet know the characteristics + // at the time the notification/indication is received. + + QTest::qWait(3000); + m_leController->connectToDevice(); + spy.reset(new QSignalSpy(m_leController.data(), &QLowEnergyController::connected)); + QVERIFY(spy->wait(30000)); + m_leController->discoverServices(); + spy.reset(new QSignalSpy(m_leController.data(), &QLowEnergyController::discoveryFinished)); + QVERIFY(spy->wait(30000)); + customService.reset(m_leController->createServiceObject(QBluetoothUuid(quint16(0x2000)))); + QVERIFY(!customService.isNull()); + customService->discoverDetails(); + while (customService->state() != QLowEnergyService::RemoteServiceDiscovered) { + spy.reset(new QSignalSpy(customService.data(), &QLowEnergyService::stateChanged)); + QVERIFY(spy->wait(5000)); + } + customChar3 = customService->characteristic(QBluetoothUuid(quint16(0x5002))); + QVERIFY(customChar3.isValid()); + QCOMPARE(customChar3.value().constData(), "indicated2"); + customChar4 = customService->characteristic(QBluetoothUuid(quint16(0x5003))); + QVERIFY(customChar4.isValid()); + QCOMPARE(customChar4.value().constData(), "notified2"); + cc3ClientConfig = customChar3.descriptor(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration); + QVERIFY(cc3ClientConfig.isValid()); + cc4ClientConfig = customChar4.descriptor(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration); + QVERIFY(cc4ClientConfig.isValid()); + + const bool isBonded = QBluetoothLocalDevice().pairingStatus(m_serverAddress) + != QBluetoothLocalDevice::Unpaired; + if (isBonded) { + QCOMPARE(cc3ClientConfig.value(), indicateValue); + QCOMPARE(cc4ClientConfig.value(), notifyValue); + + // Do a third signed write to test sign counter persistence. + customChar5 = customService->characteristic(QBluetoothUuid(quint16(0x5004))); + QVERIFY(customChar5.isValid()); + QCOMPARE(customChar5.value(), QByteArray("2")); + customService->writeCharacteristic(customChar5, "3", QLowEnergyService::WriteSigned); + customService->readCharacteristic(customChar5); + spy.reset(new QSignalSpy(customService.data(), &QLowEnergyService::characteristicRead)); + QVERIFY(spy->wait(3000)); + QCOMPARE(customChar5.value(), QByteArray("3")); + + } else { + QCOMPARE(cc3ClientConfig.value(), QByteArray(2, 0)); + QCOMPARE(cc4ClientConfig.value(), QByteArray(2, 0)); + } +} + +void TestQLowEnergyControllerGattServer::controllerType() +{ + const QScopedPointer controller(QLowEnergyController::createPeripheral()); + QVERIFY(!controller.isNull()); + QCOMPARE(controller->role(), QLowEnergyController::PeripheralRole); +} + +void TestQLowEnergyControllerGattServer::serviceData() +{ + QLowEnergyDescriptorData descData; + QVERIFY(!descData.isValid()); + + descData.setUuid(QBluetoothUuid::DescriptorType::ValidRange); + QCOMPARE(descData.uuid(), QBluetoothUuid(QBluetoothUuid::DescriptorType::ValidRange)); + QVERIFY(descData.isValid()); + QVERIFY(descData != QLowEnergyDescriptorData()); + + descData.setValue("xyz"); + QCOMPARE(descData.value().constData(), "xyz"); + + descData.setReadPermissions(true, AttAccessConstraint::AttAuthenticationRequired); + QCOMPARE(descData.isReadable(), true); + QCOMPARE(descData.readConstraints(), AttAccessConstraint::AttAuthenticationRequired); + + descData.setWritePermissions(false); + QCOMPARE(descData.isWritable(), false); + + QLowEnergyDescriptorData descData2(QBluetoothUuid::DescriptorType::ReportReference, "abc"); + QVERIFY(descData2 != QLowEnergyDescriptorData()); + QVERIFY(descData2.isValid()); + QCOMPARE(descData2.uuid(), QBluetoothUuid(QBluetoothUuid::DescriptorType::ReportReference)); + QCOMPARE(descData2.value().constData(), "abc"); + + QLowEnergyCharacteristicData charData; + QVERIFY(!charData.isValid()); + + charData.setUuid(QBluetoothUuid::CharacteristicType::BatteryLevel); + QVERIFY(charData != QLowEnergyCharacteristicData()); + QCOMPARE(charData.uuid(), QBluetoothUuid(QBluetoothUuid::CharacteristicType::BatteryLevel)); + QVERIFY(charData.isValid()); + + charData.setValue("value"); + QCOMPARE(charData.value().constData(), "value"); + + charData.setValueLength(4, 7); + QCOMPARE(charData.minimumValueLength(), 4); + QCOMPARE(charData.maximumValueLength(), 7); + charData.setValueLength(5, 2); + QCOMPARE(charData.minimumValueLength(), 5); + QCOMPARE(charData.maximumValueLength(), 5); + + const QLowEnergyCharacteristic::PropertyTypes props + = QLowEnergyCharacteristic::Read | QLowEnergyCharacteristic::WriteSigned; + charData.setProperties(props); + QCOMPARE(charData.properties(), props); + + charData.setReadConstraints(AttAccessConstraint::AttEncryptionRequired); + QCOMPARE(charData.readConstraints(), AttAccessConstraint::AttEncryptionRequired); + charData.setWriteConstraints(AttAccessConstraint::AttAuthenticationRequired + | AttAccessConstraint::AttAuthorizationRequired); + QCOMPARE(charData.writeConstraints(), + AttAccessConstraint::AttAuthenticationRequired + | AttAccessConstraint::AttAuthorizationRequired); + + charData.addDescriptor(descData); + QCOMPARE(charData.descriptors().size(), 1); + charData.setDescriptors(QList()); + QCOMPARE(charData.descriptors().size(), 0); + charData.setDescriptors(QList() << descData << descData2); + QLowEnergyDescriptorData descData3(QBluetoothUuid::DescriptorType::ExternalReportReference, "someval"); + charData.addDescriptor(descData3); + charData.addDescriptor(QLowEnergyDescriptorData()); // Invalid. + QCOMPARE(charData.descriptors(), + QList() << descData << descData2 << descData3); + + QLowEnergyServiceData secondaryData; + QVERIFY(!secondaryData.isValid()); + + secondaryData.setUuid(QBluetoothUuid::ServiceClassUuid::SerialPort); + QCOMPARE(secondaryData.uuid(), QBluetoothUuid(QBluetoothUuid::ServiceClassUuid::SerialPort)); + QVERIFY(secondaryData.isValid()); + QVERIFY(secondaryData != QLowEnergyServiceData()); + + secondaryData.setType(QLowEnergyServiceData::ServiceTypeSecondary); + QCOMPARE(secondaryData.type(), QLowEnergyServiceData::ServiceTypeSecondary); + + secondaryData.addCharacteristic(charData); + QCOMPARE(secondaryData.characteristics().size(), 1); + secondaryData.setCharacteristics(QList()); + QCOMPARE(secondaryData.characteristics().size(), 0); + secondaryData.setCharacteristics(QList() + << charData << QLowEnergyCharacteristicData()); + QCOMPARE(secondaryData.characteristics(), QList() << charData); + + QLowEnergyServiceData backupData; + backupData.setUuid(QBluetoothUuid::ServiceClassUuid::SerialPort); + QCOMPARE(backupData.uuid(), QBluetoothUuid(QBluetoothUuid::ServiceClassUuid::SerialPort)); + QVERIFY(backupData.isValid()); + QVERIFY(backupData != QLowEnergyServiceData()); + + backupData.setType(QLowEnergyServiceData::ServiceTypeSecondary); + QCOMPARE(backupData.type(), QLowEnergyServiceData::ServiceTypeSecondary); + + backupData.setCharacteristics(QList() + << charData << QLowEnergyCharacteristicData()); + QCOMPARE(backupData.characteristics(), QList() << charData); + QVERIFY(backupData == secondaryData); + +#ifdef Q_OS_DARWIN + QSKIP("GATT server functionality not implemented for Apple platforms"); +#endif + const QScopedPointer controller(QLowEnergyController::createPeripheral()); + QVERIFY(!controller->addService(QLowEnergyServiceData())); + const QScopedPointer secondaryService(controller->addService(secondaryData)); + QVERIFY(!secondaryService.isNull()); + QCOMPARE(secondaryService->serviceUuid(), secondaryData.uuid()); + const QList characteristics = secondaryService->characteristics(); + QCOMPARE(characteristics.size(), 1); + QCOMPARE(characteristics.first().uuid(), charData.uuid()); + const QList descriptors = characteristics.first().descriptors(); + QCOMPARE(descriptors.size(), 3); + const auto inUuids = QSet() << descData.uuid() << descData2.uuid() + << descData3.uuid(); + QSet outUuids; + for (const QLowEnergyDescriptor &desc : descriptors) + outUuids << desc.uuid(); + QCOMPARE(inUuids, outUuids); + + QLowEnergyServiceData primaryData; + primaryData.setUuid(QBluetoothUuid::ServiceClassUuid::Headset); + primaryData.addIncludedService(secondaryService.data()); + const QScopedPointer primaryService(controller->addService(primaryData)); + QVERIFY(!primaryService.isNull()); + QCOMPARE(primaryService->characteristics().size(), 0); + const QList includedServices = primaryService->includedServices(); + QCOMPARE(includedServices.size(), 1); + QCOMPARE(includedServices.first(), secondaryService->serviceUuid()); +} + +QTEST_MAIN(TestQLowEnergyControllerGattServer) + +#include "tst_qlowenergycontroller-gattserver.moc" diff --git a/tests/auto/qlowenergycontroller/CMakeLists.txt b/tests/auto/qlowenergycontroller/CMakeLists.txt new file mode 100644 index 0000000..f374088 --- /dev/null +++ b/tests/auto/qlowenergycontroller/CMakeLists.txt @@ -0,0 +1,44 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## tst_qlowenergycontroller Test: +##################################################################### + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qlowenergycontroller LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qlowenergycontroller + SOURCES + tst_qlowenergycontroller.cpp + LIBRARIES + Qt::BluetoothPrivate +) + +## Scopes: +##################################################################### + +qt_internal_extend_target(tst_qlowenergycontroller CONDITION ANDROID + LIBRARIES + Qt::Widgets +) + +qt_internal_extend_target(tst_qlowenergycontroller CONDITION IOS OR MACOS + LIBRARIES + Qt::Widgets +) + +set_target_properties(tst_qlowenergycontroller PROPERTIES + MACOSX_BUNDLE TRUE +) + +if (APPLE AND NOT IOS) + # Ninja has trouble with relative paths, convert to absolute as a workaround + get_filename_component(SHARED_PLIST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../shared ABSOLUTE) + set_target_properties(tst_qlowenergycontroller PROPERTIES + MACOSX_BUNDLE_INFO_PLIST "${SHARED_PLIST_DIR}/Info.macos.plist" + ) +endif() diff --git a/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp b/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp new file mode 100644 index 0000000..18365c9 --- /dev/null +++ b/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp @@ -0,0 +1,2821 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include + +#include +#if QT_CONFIG(bluez) +#include +#endif +#include +#include +#include +#include +#include +#include + +#if QT_CONFIG(permissions) +#include +#include + +#include +#endif + +#include + +/*! + This test requires a TI sensor tag with Firmware version: 1.5 (Oct 23 2013). + Since revision updates change user strings and even shift handles around + other versions than the above are unlikely to succeed. Please update the + sensor tag before continuing. + + The TI sensor can be updated using the related iOS app. The Android version + doesn't seem to update at this point in time. + */ + +QT_USE_NAMESPACE + +class tst_QLowEnergyController : public QObject +{ + Q_OBJECT + +public: + tst_QLowEnergyController(); + ~tst_QLowEnergyController(); + +private slots: + void initTestCase(); + void init(); + void cleanupTestCase(); + void tst_emptyCtor(); + void tst_connect(); + void tst_concurrentDiscovery(); + void tst_defaultBehavior(); + void tst_writeCharacteristic(); + void tst_writeCharacteristicNoResponse(); + void tst_readWriteDescriptor(); + void tst_customProgrammableDevice(); + void tst_errorCases(); + void tst_rssiError(); +private: + void verifyServiceProperties(const QLowEnergyService *info); + bool verifyClientCharacteristicValue(const QByteArray& value); + + QBluetoothDeviceDiscoveryAgent *devAgent; + QBluetoothAddress remoteDevice; + QBluetoothDeviceInfo remoteDeviceInfo; + QList foundServices; + bool isBluezDbusLE = false; +#if QT_CONFIG(permissions) + Qt::PermissionStatus permissionStatus = Qt::PermissionStatus::Undetermined; +#endif +}; + +tst_QLowEnergyController::tst_QLowEnergyController() +{ + //QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true")); +#ifndef Q_OS_MAC + // Core Bluetooth (OS X and iOS) does not work with addresses, + // making the code below useless. + const QString remote = qgetenv("BT_TEST_DEVICE"); + if (!remote.isEmpty()) { + remoteDevice = QBluetoothAddress(remote); + qWarning() << "Using remote device " << remote << " for testing. Ensure that the device is discoverable for pairing requests"; + } else { + qWarning() << "Not using any remote device for testing. Set BT_TEST_DEVICE env to run manual tests involving a remote device"; + } +#endif + +#if QT_CONFIG(bluez) + // This debug is needed to determine runtime configuration in the Qt CI. + isBluezDbusLE = (bluetoothdVersion() >= QVersionNumber(5, 42)); + qDebug() << "isDBusBluez:" << isBluezDbusLE; +#endif + +#if QT_CONFIG(permissions) + // FIXME: for Android, set additional parameters for scan and connect + // permissions. + permissionStatus = qApp->checkPermission(QBluetoothPermission{}); + // Note: even with missing Bluetooth permission, we still can run tests on + // LE controller to test its logic/errors it emits, even if we cannot scan + // and cannot connect. + const bool ciRun = qEnvironmentVariable("QTEST_ENVIRONMENT").split(' ').contains("ci"); + if (!ciRun && permissionStatus == Qt::PermissionStatus::Undetermined) { + QTestEventLoop loop; + qApp->requestPermission(QBluetoothPermission{}, [this, &loop](const QPermission &permission){ + permissionStatus = permission.status(); + loop.exitLoop(); + }); + if (permissionStatus == Qt::PermissionStatus::Undetermined) + loop.enterLoopMSecs(30000); + } +#endif // QT_CONFIG(permissions) +} + +tst_QLowEnergyController::~tst_QLowEnergyController() +{ + +} + +void tst_QLowEnergyController::initTestCase() +{ +#if !defined(Q_OS_MAC) + if (remoteDevice.isNull() +#if !QT_CONFIG(winrt_bt) + || QBluetoothLocalDevice::allDevices().isEmpty()) { +#else + ) { +#endif + qWarning("No remote device or local adapter found."); + return; + } +#elif defined(Q_OS_MACOS) + // allDevices is always empty on iOS: + if (QBluetoothLocalDevice::allDevices().isEmpty()) { + qWarning("No local adapter found."); + return; + } +#endif + + // QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true")); + devAgent = new QBluetoothDeviceDiscoveryAgent(this); + devAgent->setLowEnergyDiscoveryTimeout(5000); + + QSignalSpy finishedSpy(devAgent, SIGNAL(finished())); + // there should be no changes yet + QVERIFY(finishedSpy.isValid()); + QVERIFY(finishedSpy.isEmpty()); + + bool deviceFound = false; + devAgent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod); +#if QT_CONFIG(permissions) + if (permissionStatus != Qt::PermissionStatus::Granted) { + QCOMPARE(devAgent->error(), QBluetoothDeviceDiscoveryAgent::MissingPermissionsError); + return; + } +#endif + QTRY_VERIFY_WITH_TIMEOUT(!finishedSpy.isEmpty(), 30000); + const QList infos = devAgent->discoveredDevices(); + for (const QBluetoothDeviceInfo &info : infos) { +#ifndef Q_OS_MAC + if (info.address() == remoteDevice) { +#else + // On OS X/iOS the only way to find the device we are + // interested in - is to use device's name. + if (info.name().contains("Sensor") && info.name().contains("Tag")) { +#endif + remoteDeviceInfo = info; + deviceFound = true; + break; + } + } + + if (!deviceFound || !remoteDeviceInfo.isValid()) + qWarning() << "The sensor tag device was not found, will skip most of the test"; + + // These are the services exported by the TI SensorTag +#ifndef Q_OS_MAC + // Core Bluetooth somehow ignores/hides/fails to discover these services. + if (!isBluezDbusLE) // Bluez LE Dbus intentionally hides 0x1800 service + foundServices << QBluetoothUuid(QString("00001800-0000-1000-8000-00805f9b34fb")); + foundServices << QBluetoothUuid(QString("00001801-0000-1000-8000-00805f9b34fb")); +#endif + foundServices << QBluetoothUuid(QString("0000180a-0000-1000-8000-00805f9b34fb")); + foundServices << QBluetoothUuid(QString("0000ffe0-0000-1000-8000-00805f9b34fb")); + foundServices << QBluetoothUuid(QString("f000aa00-0451-4000-b000-000000000000")); + foundServices << QBluetoothUuid(QString("f000aa10-0451-4000-b000-000000000000")); + foundServices << QBluetoothUuid(QString("f000aa20-0451-4000-b000-000000000000")); + foundServices << QBluetoothUuid(QString("f000aa30-0451-4000-b000-000000000000")); + foundServices << QBluetoothUuid(QString("f000aa40-0451-4000-b000-000000000000")); + foundServices << QBluetoothUuid(QString("f000aa50-0451-4000-b000-000000000000")); + foundServices << QBluetoothUuid(QString("f000aa60-0451-4000-b000-000000000000")); + foundServices << QBluetoothUuid(QString("f000ccc0-0451-4000-b000-000000000000")); + foundServices << QBluetoothUuid(QString("f000ffc0-0451-4000-b000-000000000000")); +} + +/* + * Executed in between each test function call. + */ +void tst_QLowEnergyController::init() +{ +#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(Q_OS_TVOS) + /* + * Add a delay to give Android/iOS stack time to catch up in between + * the multiple connect/disconnects within each test function. + */ + QTest::qWait(2000); +#endif +} + +void tst_QLowEnergyController::cleanupTestCase() +{ + +} + +void tst_QLowEnergyController::tst_emptyCtor() +{ + { + QScopedPointer control(QLowEnergyController::createCentral(QBluetoothDeviceInfo())); + QSignalSpy connectedSpy(control.data(), SIGNAL(connected())); + QSignalSpy stateSpy(control.data(), SIGNAL(stateChanged(QLowEnergyController::ControllerState))); + QSignalSpy errorSpy(control.data(), SIGNAL(errorOccurred(QLowEnergyController::Error))); +#if QT_CONFIG(bluez) + QBluetoothLocalDevice localDevice; + // With bluez Kernel ATT interface we get the error already at construction time if the + // device does not have a bluetooth adapter + if (!isBluezDbusLE && !localDevice.isValid()) + QCOMPARE(control->error(), QLowEnergyController::InvalidBluetoothAdapterError); + else + QCOMPARE(control->error(), QLowEnergyController::NoError); +#else + QCOMPARE(control->error(), QLowEnergyController::NoError); +#endif + control->connectToDevice(); + + QTRY_VERIFY_WITH_TIMEOUT(!errorSpy.isEmpty(), 10000); + + QVERIFY(connectedSpy.isEmpty()); + QVERIFY(stateSpy.isEmpty()); + + QLowEnergyController::Error lastError = errorSpy[0].at(0).value(); + QVERIFY(lastError == QLowEnergyController::UnknownRemoteDeviceError + || lastError == QLowEnergyController::InvalidBluetoothAdapterError); + } + + { + QScopedPointer control(QLowEnergyController::createCentral( + QBluetoothDeviceInfo(), QBluetoothAddress(), this)); + QSignalSpy connectedSpy(control.data(), SIGNAL(connected())); + QSignalSpy stateSpy(control.data(), SIGNAL(stateChanged(QLowEnergyController::ControllerState))); + QSignalSpy errorSpy(control.data(), SIGNAL(errorOccurred(QLowEnergyController::Error))); +#if QT_CONFIG(bluez) + QBluetoothLocalDevice localDevice; + if (!isBluezDbusLE && !localDevice.isValid()) + QCOMPARE(control->error(), QLowEnergyController::InvalidBluetoothAdapterError); + else + QCOMPARE(control->error(), QLowEnergyController::NoError); +#else + QCOMPARE(control->error(), QLowEnergyController::NoError); +#endif + + control->connectToDevice(); + + QTRY_VERIFY_WITH_TIMEOUT(!errorSpy.isEmpty(), 10000); + + QVERIFY(connectedSpy.isEmpty()); + QVERIFY(stateSpy.isEmpty()); + + QLowEnergyController::Error lastError = errorSpy[0].at(0).value(); + QVERIFY(lastError == QLowEnergyController::UnknownRemoteDeviceError // if local device on platform found + || lastError == QLowEnergyController::InvalidBluetoothAdapterError); // otherwise, e.g. fallback backend + } +} + +void tst_QLowEnergyController::tst_connect() +{ + QList localAdapters = QBluetoothLocalDevice::allDevices(); + +#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) || QT_CONFIG(winrt_bt) + if (!remoteDeviceInfo.isValid()) +#else + if (localAdapters.isEmpty() || !remoteDeviceInfo.isValid()) +#endif + QSKIP("No local Bluetooth or remote BTLE device found. Skipping test."); + + QScopedPointer control(QLowEnergyController::createCentral(remoteDeviceInfo)); + QCOMPARE(remoteDeviceInfo.deviceUuid(), control->remoteDeviceUuid()); + QCOMPARE(control->role(), QLowEnergyController::CentralRole); + QSignalSpy connectedSpy(control.data(), SIGNAL(connected())); + QSignalSpy disconnectedSpy(control.data(), SIGNAL(disconnected())); + if (remoteDeviceInfo.name().isEmpty()) + QVERIFY(control->remoteName().isEmpty()); + else + QCOMPARE(control->remoteName(), remoteDeviceInfo.name()); + +#if !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) && !QT_CONFIG(winrt_bt) + const QBluetoothAddress localAdapter = localAdapters.at(0).address(); + QCOMPARE(control->localAddress(), localAdapter); + QVERIFY(!control->localAddress().isNull()); +#endif +#ifndef Q_OS_MAC + QCOMPARE(control->remoteAddress(), remoteDevice); +#endif + QCOMPARE(control->state(), QLowEnergyController::UnconnectedState); + QCOMPARE(control->error(), QLowEnergyController::NoError); + QVERIFY(control->errorString().isEmpty()); + QCOMPARE(disconnectedSpy.size(), 0); + QCOMPARE(connectedSpy.size(), 0); + QVERIFY(control->services().isEmpty()); + + bool wasError = false; + control->connectToDevice(); + QTRY_IMPL(control->state() != QLowEnergyController::ConnectingState, + 10000) + + QCOMPARE(disconnectedSpy.size(), 0); + if (control->error() != QLowEnergyController::NoError) { + //error during connect + QCOMPARE(connectedSpy.size(), 0); + QCOMPARE(control->state(), QLowEnergyController::UnconnectedState); + wasError = true; + } else if (control->state() == QLowEnergyController::ConnectingState) { + //timeout + QCOMPARE(connectedSpy.size(), 0); + QVERIFY(control->errorString().isEmpty()); + QCOMPARE(control->error(), QLowEnergyController::NoError); + QVERIFY(control->services().isEmpty()); + QSKIP("Connection to LE device cannot be established. Skipping test."); + return; + } else { + QCOMPARE(control->state(), QLowEnergyController::ConnectedState); + QCOMPARE(connectedSpy.size(), 1); + QCOMPARE(control->error(), QLowEnergyController::NoError); + QVERIFY(control->errorString().isEmpty()); + } + + QVERIFY(control->services().isEmpty()); + + QList savedReferences; + + if (!wasError) { + QSignalSpy discoveryFinishedSpy(control.data(), SIGNAL(discoveryFinished())); + QSignalSpy serviceFoundSpy(control.data(), SIGNAL(serviceDiscovered(QBluetoothUuid))); + QSignalSpy stateSpy(control.data(), SIGNAL(stateChanged(QLowEnergyController::ControllerState))); + control->discoverServices(); + QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.size() == 1, 20000); + QCOMPARE(stateSpy.size(), 2); + QCOMPARE(stateSpy.at(0).at(0).value(), + QLowEnergyController::DiscoveringState); + QCOMPARE(stateSpy.at(1).at(0).value(), + QLowEnergyController::DiscoveredState); + + QVERIFY(!serviceFoundSpy.isEmpty()); + QVERIFY(serviceFoundSpy.size() >= foundServices.size()); + QVERIFY(!serviceFoundSpy.isEmpty()); + QList listing; + for (qsizetype i = 0; i < serviceFoundSpy.size(); ++i) { + const QVariant v = serviceFoundSpy[i].at(0); + listing.append(v.value()); + } + + for (const QBluetoothUuid &uuid : std::as_const(foundServices)) { + QVERIFY2(listing.contains(uuid), + uuid.toString().toLatin1()); + + QLowEnergyService *service = control->createServiceObject(uuid); + QVERIFY2(service, uuid.toString().toLatin1()); + savedReferences.append(service); + QCOMPARE(service->type(), QLowEnergyService::PrimaryService); + QCOMPARE(service->state(), QLowEnergyService::RemoteService); + } + + // unrelated uuids don't return valid service object + // invalid service uuid + QVERIFY(!control->createServiceObject(QBluetoothUuid())); + // some random uuid + QVERIFY(!control->createServiceObject( + QBluetoothUuid(QBluetoothUuid::CharacteristicType::DeviceName))); + + // initiate characteristic discovery + for (QLowEnergyService *service : std::as_const(savedReferences)) { + qDebug() << "Discovering" << service->serviceUuid(); + QSignalSpy stateSpy(service, + SIGNAL(stateChanged(QLowEnergyService::ServiceState))); + QSignalSpy errorSpy(service, SIGNAL(errorOccurred(QLowEnergyService::ServiceError))); + service->discoverDetails(); + + QTRY_VERIFY_WITH_TIMEOUT( + service->state() == QLowEnergyService::RemoteServiceDiscovered, 10000); + + QCOMPARE(errorSpy.size(), 0); //no error + QCOMPARE(stateSpy.size(), 2); // + + verifyServiceProperties(service); + } + + // ensure that related service objects share same state + for (QLowEnergyService* originalService : std::as_const(savedReferences)) { + QLowEnergyService *newService = control->createServiceObject( + originalService->serviceUuid()); + QVERIFY(newService); + QCOMPARE(newService->state(), QLowEnergyService::RemoteServiceDiscovered); + delete newService; + } + } + + // Finish off + control->disconnectFromDevice(); + QTRY_VERIFY_WITH_TIMEOUT( + control->state() == QLowEnergyController::UnconnectedState, + 10000); + + if (wasError) { + QCOMPARE(disconnectedSpy.size(), 0); + } else { + QCOMPARE(disconnectedSpy.size(), 1); + // after disconnect all service references must be invalid + for (const QLowEnergyService *entry : std::as_const(savedReferences)) { + const QBluetoothUuid &uuid = entry->serviceUuid(); + QVERIFY2(entry->state() == QLowEnergyService::InvalidService, + uuid.toString().toLatin1()); + + //after disconnect all related characteristics and descriptors are invalid + QList chars = entry->characteristics(); + for (qsizetype i = 0; i < chars.size(); ++i) { + QCOMPARE(chars.at(i).isValid(), false); + QList descriptors = chars[i].descriptors(); + for (qsizetype j = 0; j < descriptors.size(); ++j) + QCOMPARE(descriptors[j].isValid(), false); + } + } + } + + qDeleteAll(savedReferences); + savedReferences.clear(); +} + +void tst_QLowEnergyController::tst_concurrentDiscovery() +{ +#if !defined(Q_OS_MACOS) && !QT_CONFIG(winrt_bt) + QList localAdapters = QBluetoothLocalDevice::allDevices(); + if (localAdapters.isEmpty()) + QSKIP("No local Bluetooth device found. Skipping test."); +#endif + + if (!remoteDeviceInfo.isValid()) + QSKIP("No remote BTLE device found. Skipping test."); + QScopedPointer control(QLowEnergyController::createCentral(remoteDeviceInfo)); + + + QCOMPARE(control->state(), QLowEnergyController::UnconnectedState); + QCOMPARE(control->error(), QLowEnergyController::NoError); + + control->connectToDevice(); + { + QTRY_IMPL(control->state() != QLowEnergyController::ConnectingState, + 30000) + } + + if (control->state() == QLowEnergyController::ConnectingState + || control->error() != QLowEnergyController::NoError) { + // default BTLE backend forever hangs in ConnectingState + QSKIP("Cannot connect to remote device"); + } + + QCOMPARE(control->state(), QLowEnergyController::ConnectedState); + + // 2. new controller to same device fails + { + + QScopedPointer control2( + QLowEnergyController::createCentral(remoteDeviceInfo)); + control2->connectToDevice(); + { + QTRY_IMPL(control2->state() != QLowEnergyController::ConnectingState, + 30000) + } + +#if defined(Q_OS_ANDROID) || defined(Q_OS_DARWIN) || QT_CONFIG(winrt_bt) + QCOMPARE(control->state(), QLowEnergyController::ConnectedState); + QCOMPARE(control2->state(), QLowEnergyController::ConnectedState); + control2->disconnectFromDevice(); + QTest::qWait(3000); + QCOMPARE(control->state(), QLowEnergyController::ConnectedState); + QCOMPARE(control2->state(), QLowEnergyController::UnconnectedState); +#else + if (!isBluezDbusLE) { + // see QTBUG-42519 + // Linux non-DBus GATT cannot maintain two controller connections at the same time + QCOMPARE(control->state(), QLowEnergyController::UnconnectedState); + QCOMPARE(control2->state(), QLowEnergyController::ConnectedState); + control2->disconnectFromDevice(); + QTRY_COMPARE(control2->state(), QLowEnergyController::UnconnectedState); + QTRY_COMPARE(control2->error(), QLowEnergyController::NoError); + + // reconnect control + control->connectToDevice(); + { + QTRY_VERIFY_WITH_TIMEOUT(control->state() != QLowEnergyController::ConnectingState, + 30000); + } + QCOMPARE(control->state(), QLowEnergyController::ConnectedState); + } else { + QCOMPARE(control->state(), QLowEnergyController::ConnectedState); + QCOMPARE(control2->state(), QLowEnergyController::ConnectedState); + QTRY_COMPARE(control2->error(), QLowEnergyController::NoError); + control2->disconnectFromDevice(); + QTRY_COMPARE(control2->state(), QLowEnergyController::UnconnectedState); + QTRY_COMPARE(control->error(), QLowEnergyController::NoError); + QTRY_COMPARE(control2->error(), QLowEnergyController::NoError); + QTRY_COMPARE(control->state(), QLowEnergyController::UnconnectedState); + + // reconnect control + control->connectToDevice(); + { + QTRY_VERIFY_WITH_TIMEOUT(control->state() != QLowEnergyController::ConnectingState, + 30000); + } + QCOMPARE(control->state(), QLowEnergyController::ConnectedState); + } +#endif + } + + /* We are testing that we can run service discovery on the same device + * for multiple services at the same time. + * */ + + QSignalSpy discoveryFinishedSpy(control.data(), SIGNAL(discoveryFinished())); + QSignalSpy stateSpy(control.data(), SIGNAL(stateChanged(QLowEnergyController::ControllerState))); + control->discoverServices(); + QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.size() == 1, 20000); + QCOMPARE(stateSpy.size(), 2); + QCOMPARE(stateSpy.at(0).at(0).value(), + QLowEnergyController::DiscoveringState); + QCOMPARE(stateSpy.at(1).at(0).value(), + QLowEnergyController::DiscoveredState); + + // pick MAX_SERVICES_SAME_TIME_ACCESS services + // and discover them at the same time +#define MAX_SERVICES_SAME_TIME_ACCESS 3 + QLowEnergyService *services[MAX_SERVICES_SAME_TIME_ACCESS]; + + QVERIFY(control->services().size() >= MAX_SERVICES_SAME_TIME_ACCESS); + + QList uuids = control->services(); + + // initialize services + for (int i = 0; icreateServiceObject(uuids.at(i), this); + QVERIFY(services[i]); + } + + // start complete discovery + for (int i = 0; idiscoverDetails(); + + // wait until discovery done + for (int i = 0; iserviceUuid(); + QTRY_VERIFY_WITH_TIMEOUT( + services[i]->state() == QLowEnergyService::RemoteServiceDiscovered, + 30000); + } + + // verify discovered services + for (int i = 0; icontains(QLowEnergyCharacteristic())); + QVERIFY(!services[i]->contains(QLowEnergyDescriptor())); + } + + control->disconnectFromDevice(); + QTRY_VERIFY_WITH_TIMEOUT(control->state() == QLowEnergyController::UnconnectedState, + 30000); + discoveryFinishedSpy.clear(); + + // redo the discovery with same controller + QLowEnergyService *services_second[MAX_SERVICES_SAME_TIME_ACCESS]; + control->connectToDevice(); + { + QTRY_IMPL(control->state() != QLowEnergyController::ConnectingState, + 30000); + } + + QCOMPARE(control->state(), QLowEnergyController::ConnectedState); + stateSpy.clear(); + control->discoverServices(); + QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.size() == 1, 20000); + QCOMPARE(stateSpy.size(), 2); + QCOMPARE(stateSpy.at(0).at(0).value(), + QLowEnergyController::DiscoveringState); + QCOMPARE(stateSpy.at(1).at(0).value(), + QLowEnergyController::DiscoveredState); + + // get all details + for (int i = 0; icreateServiceObject(uuids.at(i), this); + QVERIFY(services_second[i]->parent() == this); + QVERIFY(services[i]); + QVERIFY(services_second[i]->state() == QLowEnergyService::RemoteService); + services_second[i]->discoverDetails(); + } + + // wait until discovery done + for (int i = 0; iserviceUuid(); + QTRY_VERIFY_WITH_TIMEOUT( + services_second[i]->state() == QLowEnergyService::RemoteServiceDiscovered, + 30000); + QCOMPARE(services_second[i]->serviceName(), services[i]->serviceName()); + QCOMPARE(services_second[i]->serviceUuid(), services[i]->serviceUuid()); + } + + // verify discovered services (1st and 2nd round) + for (int i = 0; i chars = services[i]->characteristics(); + for (qsizetype j = 0; j < chars.size(); ++j) { + QCOMPARE(chars.at(j).isValid(), false); + QVERIFY(services[i]->contains(chars[j])); + QVERIFY(!services_second[i]->contains(chars[j])); + const QList descriptors = chars[j].descriptors(); + for (qsizetype k = 0; k < descriptors.size(); ++k) { + QCOMPARE(descriptors[k].isValid(), false); + services[i]->contains(descriptors[k]); + QVERIFY(!services_second[i]->contains(chars[j])); + } + } + + QCOMPARE(services[i]->serviceUuid(), services_second[i]->serviceUuid()); + QCOMPARE(services[i]->serviceName(), services_second[i]->serviceName()); + QCOMPARE(services[i]->type(), services_second[i]->type()); + QVERIFY(services[i]->state() == QLowEnergyService::InvalidService); + QVERIFY(services_second[i]->state() == QLowEnergyService::RemoteServiceDiscovered); + } + + // cleanup + for (int i = 0; idisconnectFromDevice(); + QTRY_COMPARE(control->state(), QLowEnergyController::UnconnectedState); + QCOMPARE(control->error(), QLowEnergyController::NoError); +} + +void tst_QLowEnergyController::verifyServiceProperties( + const QLowEnergyService *info) +{ + if (info->serviceUuid() == + QBluetoothUuid(QString("00001800-0000-1000-8000-00805f9b34fb"))) { + qDebug() << "Verifying GAP Service"; + QList chars = info->characteristics(); + QCOMPARE(chars.size(), 5); + + // Device Name + QString temp("00002a00-0000-1000-8000-00805f9b34fb"); + QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp)); + QCOMPARE(chars[0].properties(), QLowEnergyCharacteristic::Read); + QCOMPARE(chars[0].value(), QByteArray::fromHex("544920424c452053656e736f7220546167")); + QVERIFY(chars[0].isValid()); + QCOMPARE(chars[0].descriptors().size(), 0); + QVERIFY(info->contains(chars[0])); + + // Appearance + temp = QString("00002a01-0000-1000-8000-00805f9b34fb"); + QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp)); + QCOMPARE(chars[1].properties(), QLowEnergyCharacteristic::Read); + QCOMPARE(chars[1].value(), QByteArray::fromHex("0000")); + QVERIFY(chars[1].isValid()); + QCOMPARE(chars[1].descriptors().size(), 0); + QVERIFY(info->contains(chars[1])); + + // Peripheral Privacy Flag + temp = QString("00002a02-0000-1000-8000-00805f9b34fb"); + QCOMPARE(chars[2].uuid(), QBluetoothUuid(temp)); + QVERIFY(chars[2].properties() & QLowEnergyCharacteristic::Read); + QCOMPARE(chars[2].value(), QByteArray::fromHex("00")); + QVERIFY(chars[2].isValid()); + QCOMPARE(chars[2].descriptors().size(), 0); + QVERIFY(info->contains(chars[2])); + + // Reconnection Address + temp = QString("00002a03-0000-1000-8000-00805f9b34fb"); + QCOMPARE(chars[3].uuid(), QBluetoothUuid(temp)); + //Early firmware version had this characteristic as Read|Write and may fail + QCOMPARE(chars[3].properties(), QLowEnergyCharacteristic::Write); + if (chars[3].properties() & QLowEnergyCharacteristic::Read) + QCOMPARE(chars[3].value(), QByteArray::fromHex("000000000000")); + else + QCOMPARE(chars[3].value(), QByteArray()); + QVERIFY(chars[3].isValid()); + QCOMPARE(chars[3].descriptors().size(), 0); + QVERIFY(info->contains(chars[3])); + + // Peripheral Preferred Connection Parameters + temp = QString("00002a04-0000-1000-8000-00805f9b34fb"); + QCOMPARE(chars[4].uuid(), QBluetoothUuid(temp)); + QCOMPARE(chars[4].properties(), QLowEnergyCharacteristic::Read); + QCOMPARE(chars[4].value(), QByteArray::fromHex("5000a0000000e803")); + QVERIFY(chars[4].isValid()); + QCOMPARE(chars[4].descriptors().size(), 0); + QVERIFY(info->contains(chars[4])); + } else if (info->serviceUuid() == + QBluetoothUuid(QString("00001801-0000-1000-8000-00805f9b34fb"))) { + qDebug() << "Verifying GATT Service"; + QList chars = info->characteristics(); + QCOMPARE(chars.size(), 1); + + // Service Changed + QString temp("00002a05-0000-1000-8000-00805f9b34fb"); + //this should really be readable according to GATT Service spec + QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp)); + QCOMPARE(chars[0].properties(), QLowEnergyCharacteristic::Indicate); + QCOMPARE(chars[0].value(), QByteArray()); + QVERIFY(chars[0].isValid()); + QVERIFY(info->contains(chars[0])); + + QCOMPARE(chars[0].descriptors().size(), 1); + QCOMPARE(chars[0].descriptors().at(0).isValid(), true); + QCOMPARE(chars[0].descriptors().at(0).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration)); + QCOMPARE(chars[0].descriptors().at(0).type(), + QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration); + QVERIFY(verifyClientCharacteristicValue(chars[0].descriptors().at(0).value())); + QVERIFY(info->contains(chars[0].descriptors().at(0))); + } else if (info->serviceUuid() == + QBluetoothUuid(QString("0000180a-0000-1000-8000-00805f9b34fb"))) { + qDebug() << "Verifying Device Information"; + QList chars = info->characteristics(); + QCOMPARE(chars.size(), 9); + + // System ID + QString temp("00002a23-0000-1000-8000-00805f9b34fb"); + //this should really be readable according to GATT Service spec + QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp)); + QCOMPARE(chars[0].properties(), QLowEnergyCharacteristic::Read); +// Do not read the System ID as it is different for every device +// QEXPECT_FAIL("", "The value is different on different devices", Continue); +// QCOMPARE(chars[0].value(), QByteArray::fromHex("6e41ab0000296abc")); + QVERIFY(chars[0].isValid()); + QVERIFY(info->contains(chars[0])); + QCOMPARE(chars[0].descriptors().size(), 0); + + // Model Number + temp = QString("00002a24-0000-1000-8000-00805f9b34fb"); + QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp)); + QCOMPARE(chars[1].properties(), QLowEnergyCharacteristic::Read); + QCOMPARE(chars[1].value(), QByteArray::fromHex("4e2e412e00")); + QVERIFY(chars[1].isValid()); + QVERIFY(info->contains(chars[1])); + QCOMPARE(chars[1].descriptors().size(), 0); + + // Serial Number + temp = QString("00002a25-0000-1000-8000-00805f9b34fb"); + QCOMPARE(chars[2].uuid(), QBluetoothUuid(temp)); + QCOMPARE(chars[2].properties(), + (QLowEnergyCharacteristic::Read)); + QCOMPARE(chars[2].value(), QByteArray::fromHex("4e2e412e00")); + QVERIFY(chars[2].isValid()); + QVERIFY(info->contains(chars[2])); + QCOMPARE(chars[2].descriptors().size(), 0); + + // Firmware Revision + temp = QString("00002a26-0000-1000-8000-00805f9b34fb"); + QCOMPARE(chars[3].uuid(), QBluetoothUuid(temp)); + QCOMPARE(chars[3].properties(), + (QLowEnergyCharacteristic::Read)); + //FW rev. : 1.5 (Oct 23 2013) + // Other revisions will fail here + QCOMPARE(chars[3].value(), QByteArray::fromHex("312e3520284f637420323320323031332900")); + QVERIFY(chars[3].isValid()); + QVERIFY(info->contains(chars[3])); + QCOMPARE(chars[3].descriptors().size(), 0); + + // Hardware Revision + temp = QString("00002a27-0000-1000-8000-00805f9b34fb"); + QCOMPARE(chars[4].uuid(), QBluetoothUuid(temp)); + QCOMPARE(chars[4].properties(), + (QLowEnergyCharacteristic::Read)); + QCOMPARE(chars[4].value(), QByteArray::fromHex("4e2e412e00")); + QVERIFY(chars[4].isValid()); + QVERIFY(info->contains(chars[4])); + QCOMPARE(chars[4].descriptors().size(), 0); + + // Software Revision + temp = QString("00002a28-0000-1000-8000-00805f9b34fb"); + QCOMPARE(chars[5].uuid(), QBluetoothUuid(temp)); + QCOMPARE(chars[5].properties(), + (QLowEnergyCharacteristic::Read)); + QCOMPARE(chars[5].value(), QByteArray::fromHex("4e2e412e00")); + QVERIFY(chars[5].isValid()); + QVERIFY(info->contains(chars[5])); + QCOMPARE(chars[5].descriptors().size(), 0); + + // Manufacturer Name + temp = QString("00002a29-0000-1000-8000-00805f9b34fb"); + QCOMPARE(chars[6].uuid(), QBluetoothUuid(temp)); + QCOMPARE(chars[6].properties(), + (QLowEnergyCharacteristic::Read)); + QCOMPARE(chars[6].value(), QByteArray::fromHex("546578617320496e737472756d656e747300")); + QVERIFY(chars[6].isValid()); + QVERIFY(info->contains(chars[6])); + QCOMPARE(chars[6].descriptors().size(), 0); + + // IEEE + temp = QString("00002a2a-0000-1000-8000-00805f9b34fb"); + QCOMPARE(chars[7].uuid(), QBluetoothUuid(temp)); + QCOMPARE(chars[7].properties(), + (QLowEnergyCharacteristic::Read)); + QCOMPARE(chars[7].value(), QByteArray::fromHex("fe006578706572696d656e74616c")); + QVERIFY(chars[7].isValid()); + QVERIFY(info->contains(chars[7])); + QCOMPARE(chars[7].descriptors().size(), 0); + + // PnP ID + temp = QString("00002a50-0000-1000-8000-00805f9b34fb"); + QCOMPARE(chars[8].uuid(), QBluetoothUuid(temp)); + QCOMPARE(chars[8].properties(), + (QLowEnergyCharacteristic::Read)); + QCOMPARE(chars[8].value(), QByteArray::fromHex("010d0000001001")); + QVERIFY(chars[8].isValid()); + QVERIFY(info->contains(chars[8])); + QCOMPARE(chars[8].descriptors().size(), 0); + } else if (info->serviceUuid() == + QBluetoothUuid(QString("f000aa00-0451-4000-b000-000000000000"))) { + qDebug() << "Verifying Temperature"; + QList chars = info->characteristics(); + QVERIFY(chars.size() >= 2); + + // Temp Data + QString temp("f000aa01-0451-4000-b000-000000000000"); + QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp)); + QCOMPARE(chars[0].properties(), + (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Notify)); + QCOMPARE(chars[0].value(), QByteArray::fromHex("00000000")); + QVERIFY(chars[0].isValid()); + QVERIFY(info->contains(chars[0])); + + QCOMPARE(chars[0].descriptors().size(), 2); + //descriptor checks + QCOMPARE(chars[0].descriptors().at(0).isValid(), true); + QCOMPARE(chars[0].descriptors().at(0).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration)); + QCOMPARE(chars[0].descriptors().at(0).type(), + QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration); + QVERIFY(verifyClientCharacteristicValue(chars[0].descriptors().at(0).value())); + QVERIFY(info->contains(chars[0].descriptors().at(0))); + + QCOMPARE(chars[0].descriptors().at(1).isValid(), true); + QCOMPARE(chars[0].descriptors().at(1).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::CharacteristicUserDescription)); + QCOMPARE(chars[0].descriptors().at(1).type(), + QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + // value different in other revisions and test may fail + QCOMPARE(chars[0].descriptors().at(1).value(), + QByteArray::fromHex("54656d702e2044617461")); + QVERIFY(info->contains(chars[0].descriptors().at(1))); + + // Temp Config + temp = QString("f000aa02-0451-4000-b000-000000000000"); + QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp)); + QCOMPARE(chars[1].properties(), + (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write)); + QCOMPARE(chars[1].value(), QByteArray::fromHex("00")); + QVERIFY(chars[1].isValid()); + QVERIFY(info->contains(chars[1])); + + QCOMPARE(chars[1].descriptors().size(), 1); + //descriptor checks + QCOMPARE(chars[1].descriptors().at(0).isValid(), true); + QCOMPARE(chars[1].descriptors().at(0).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::CharacteristicUserDescription)); + QCOMPARE(chars[1].descriptors().at(0).type(), + QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + // value different in other revisions and test may fail + QCOMPARE(chars[1].descriptors().at(0).value(), + QByteArray::fromHex("54656d702e20436f6e662e")); + QVERIFY(info->contains(chars[1].descriptors().at(0))); + + + //Temp Period (introduced by later firmware versions) + if (chars.size() > 2) { + temp = QString("f000aa03-0451-4000-b000-000000000000"); + QCOMPARE(chars[2].uuid(), QBluetoothUuid(temp)); + QCOMPARE(chars[2].properties(), + (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write)); + QCOMPARE(chars[2].value(), QByteArray::fromHex("64")); + QVERIFY(chars[2].isValid()); + QVERIFY(info->contains(chars[2])); + + QCOMPARE(chars[2].descriptors().size(), 1); + //descriptor checks + QCOMPARE(chars[2].descriptors().at(0).isValid(), true); + QCOMPARE(chars[2].descriptors().at(0).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::CharacteristicUserDescription)); + QCOMPARE(chars[2].descriptors().at(0).type(), + QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + QCOMPARE(chars[2].descriptors().at(0).value(), + QByteArray::fromHex("54656d702e20506572696f64")); + QVERIFY(info->contains(chars[2].descriptors().at(0))); + } + } else if (info->serviceUuid() == + QBluetoothUuid(QString("0000ffe0-0000-1000-8000-00805f9b34fb"))) { + qDebug() << "Verifying Simple Keys"; + QList chars = info->characteristics(); + QCOMPARE(chars.size(), 1); + + // Temp Data + QString temp("0000ffe1-0000-1000-8000-00805f9b34fb"); + QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp)); + // value different in other revisions and test may fail + QCOMPARE(chars[0].properties(), + (QLowEnergyCharacteristic::Notify)); + QCOMPARE(chars[0].value(), QByteArray()); + QVERIFY(chars[0].isValid()); + QVERIFY(info->contains(chars[0])); + + QCOMPARE(chars[0].descriptors().size(), 2); + //descriptor checks + QCOMPARE(chars[0].descriptors().at(0).isValid(), true); + // value different in other revisions and test may fail + QCOMPARE(chars[0].descriptors().at(0).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration)); + QCOMPARE(chars[0].descriptors().at(0).type(), + QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration); + QVERIFY(verifyClientCharacteristicValue(chars[0].descriptors().at(0).value())); + QVERIFY(info->contains(chars[0].descriptors().at(0))); + + QCOMPARE(chars[0].descriptors().at(1).isValid(), true); + // value different in other revisions and test may fail + QCOMPARE(chars[0].descriptors().at(1).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::CharacteristicUserDescription)); + QCOMPARE(chars[0].descriptors().at(1).type(), + QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + QCOMPARE(chars[0].descriptors().at(1).value(), + QByteArray::fromHex("4b6579205072657373205374617465")); + QVERIFY(info->contains(chars[0].descriptors().at(1))); + + } else if (info->serviceUuid() == + QBluetoothUuid(QString("f000aa10-0451-4000-b000-000000000000"))) { + qDebug() << "Verifying Accelerometer"; + QList chars = info->characteristics(); + QCOMPARE(chars.size(), 3); + + // Accel Data + QString temp("f000aa11-0451-4000-b000-000000000000"); + QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp)); + // value different in other revisions and test may fail + QCOMPARE(chars[0].properties(), + (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Notify)); + QCOMPARE(chars[0].value(), QByteArray::fromHex("000000")); + QVERIFY(chars[0].isValid()); + QVERIFY(info->contains(chars[0])); + + QCOMPARE(chars[0].descriptors().size(), 2); + + QCOMPARE(chars[0].descriptors().at(0).isValid(), true); + // value different in other revisions and test may fail + QCOMPARE(chars[0].descriptors().at(0).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration)); + QCOMPARE(chars[0].descriptors().at(0).type(), + QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration); + QVERIFY(verifyClientCharacteristicValue(chars[0].descriptors().at(0).value())); + QVERIFY(info->contains(chars[0].descriptors().at(0))); + + QCOMPARE(chars[0].descriptors().at(1).isValid(), true); + // value different in other revisions and test may fail + QCOMPARE(chars[0].descriptors().at(1).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::CharacteristicUserDescription)); + QCOMPARE(chars[0].descriptors().at(1).type(), + QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + QCOMPARE(chars[0].descriptors().at(1).value(), + QByteArray::fromHex("416363656c2e2044617461")); + QVERIFY(info->contains(chars[0].descriptors().at(1))); + + // Accel Config + temp = QString("f000aa12-0451-4000-b000-000000000000"); + QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp)); + // value different in other revisions and test may fail + QCOMPARE(chars[1].properties(), + (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write)); + QCOMPARE(chars[1].value(), QByteArray::fromHex("00")); + QVERIFY(chars[1].isValid()); + QVERIFY(info->contains(chars[1])); + QCOMPARE(chars[1].descriptors().size(), 1); + + QCOMPARE(chars[1].descriptors().at(0).isValid(), true); + // value different in other revisions and test may fail + QCOMPARE(chars[1].descriptors().at(0).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::CharacteristicUserDescription)); + QCOMPARE(chars[1].descriptors().at(0).type(), + QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + QCOMPARE(chars[1].descriptors().at(0).value(), + QByteArray::fromHex("416363656c2e20436f6e662e")); + QVERIFY(info->contains(chars[1].descriptors().at(0))); + + // Accel Period + temp = QString("f000aa13-0451-4000-b000-000000000000"); + QCOMPARE(chars[2].uuid(), QBluetoothUuid(temp)); + // value different in other revisions and test may fail + QCOMPARE(chars[2].properties(), + (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write)); + QCOMPARE(chars[2].value(), QByteArray::fromHex("64")); // don't change it or set it to 0x64 + QVERIFY(chars[2].isValid()); + QVERIFY(info->contains(chars[2])); + + QCOMPARE(chars[2].descriptors().size(), 1); + //descriptor checks + QCOMPARE(chars[2].descriptors().at(0).isValid(), true); + // value different in other revisions and test may fail + QCOMPARE(chars[2].descriptors().at(0).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::CharacteristicUserDescription)); + QCOMPARE(chars[2].descriptors().at(0).type(), + QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + // value different in other revisions and test may fail + QCOMPARE(chars[2].descriptors().at(0).value(), + QByteArray::fromHex("416363656c2e20506572696f64")); + QVERIFY(info->contains(chars[2].descriptors().at(0))); + } else if (info->serviceUuid() == + QBluetoothUuid(QString("f000aa20-0451-4000-b000-000000000000"))) { + qDebug() << "Verifying Humidity"; + QList chars = info->characteristics(); + QVERIFY(chars.size() >= 2); //new firmware has more chars + + // Humidity Data + QString temp("f000aa21-0451-4000-b000-000000000000"); + QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp)); + // value different in other revisions and test may fail + QCOMPARE(chars[0].properties(), + (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Notify)); + QCOMPARE(chars[0].value(), QByteArray::fromHex("00000000")); + QVERIFY(chars[0].isValid()); + QVERIFY(info->contains(chars[0])); + + QCOMPARE(chars[0].descriptors().size(), 2); + //descriptor checks + QCOMPARE(chars[0].descriptors().at(0).isValid(), true); + // value different in other revisions and test may fail + QCOMPARE(chars[0].descriptors().at(0).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration)); + QCOMPARE(chars[0].descriptors().at(0).type(), + QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration); + QVERIFY(verifyClientCharacteristicValue(chars[0].descriptors().at(0).value())); + QVERIFY(info->contains(chars[0].descriptors().at(0))); + + QCOMPARE(chars[0].descriptors().at(1).isValid(), true); + // value different in other revisions and test may fail + QCOMPARE(chars[0].descriptors().at(1).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::CharacteristicUserDescription)); + QCOMPARE(chars[0].descriptors().at(1).type(), + QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + QCOMPARE(chars[0].descriptors().at(1).value(), + QByteArray::fromHex("48756d69642e2044617461")); + QVERIFY(info->contains(chars[0].descriptors().at(1))); + + // Humidity Config + temp = QString("f000aa22-0451-4000-b000-000000000000"); + QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp)); + // value different in other revisions and test may fail + QCOMPARE(chars[1].properties(), + (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write)); + QCOMPARE(chars[1].value(), QByteArray::fromHex("00")); + QVERIFY(chars[1].isValid()); + QVERIFY(info->contains(chars[1])); + + QCOMPARE(chars[1].descriptors().size(), 1); + //descriptor checks + QCOMPARE(chars[1].descriptors().at(0).isValid(), true); + // value different in other revisions and test may fail + QCOMPARE(chars[1].descriptors().at(0).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::CharacteristicUserDescription)); + QCOMPARE(chars[1].descriptors().at(0).type(), + QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + QCOMPARE(chars[1].descriptors().at(0).value(), + QByteArray::fromHex("48756d69642e20436f6e662e")); + QVERIFY(info->contains(chars[1].descriptors().at(0))); + + if (chars.size() >= 3) { + // New firmware new characteristic + // Humidity Period + temp = QString("f000aa23-0451-4000-b000-000000000000"); + QCOMPARE(chars[2].uuid(), QBluetoothUuid(temp)); + QCOMPARE(chars[2].properties(), + (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write)); + QCOMPARE(chars[2].value(), QByteArray::fromHex("64")); + QVERIFY(chars[2].isValid()); + QVERIFY(info->contains(chars[2])); + + QCOMPARE(chars[2].descriptors().size(), 1); + //descriptor checks + QCOMPARE(chars[2].descriptors().at(0).isValid(), true); + QCOMPARE(chars[2].descriptors().at(0).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::CharacteristicUserDescription)); + QCOMPARE(chars[2].descriptors().at(0).type(), + QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + QCOMPARE(chars[2].descriptors().at(0).value(), + QByteArray::fromHex("48756d69642e20506572696f64")); + QVERIFY(info->contains(chars[2].descriptors().at(0))); + } + } else if (info->serviceUuid() == + QBluetoothUuid(QString("f000aa30-0451-4000-b000-000000000000"))) { + qDebug() << "Verifying Magnetometer"; + QList chars = info->characteristics(); + QCOMPARE(chars.size(), 3); + + // Magnetometer Data + QString temp("f000aa31-0451-4000-b000-000000000000"); + QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp)); + // value different in other revisions and test may fail + QCOMPARE(chars[0].properties(), + (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Notify)); + QCOMPARE(chars[0].value(), QByteArray::fromHex("000000000000")); + QVERIFY(chars[0].isValid()); + QVERIFY(info->contains(chars[0])); + + QCOMPARE(chars[0].descriptors().size(), 2); + + QCOMPARE(chars[0].descriptors().at(0).isValid(), true); + // value different in other revisions and test may fail + QCOMPARE(chars[0].descriptors().at(0).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration)); + QCOMPARE(chars[0].descriptors().at(0).type(), + QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration); + QVERIFY(verifyClientCharacteristicValue(chars[0].descriptors().at(0).value())); + QVERIFY(info->contains(chars[0].descriptors().at(0))); + + QCOMPARE(chars[0].descriptors().at(1).isValid(), true); + // value different in other revisions and test may fail + QCOMPARE(chars[0].descriptors().at(1).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::CharacteristicUserDescription)); + QCOMPARE(chars[0].descriptors().at(1).type(), + QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + QCOMPARE(chars[0].descriptors().at(1).value(), + QByteArray::fromHex("4d61676e2e2044617461")); + QVERIFY(info->contains(chars[0].descriptors().at(1))); + + // Magnetometer Config + temp = QString("f000aa32-0451-4000-b000-000000000000"); + QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp)); + // value different in other revisions and test may fail + QCOMPARE(chars[1].properties(), + (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write)); + QCOMPARE(chars[1].value(), QByteArray::fromHex("00")); + QVERIFY(chars[1].isValid()); + QVERIFY(info->contains(chars[1])); + + QCOMPARE(chars[1].descriptors().size(), 1); + QCOMPARE(chars[1].descriptors().at(0).isValid(), true); + // value different in other revisions and test may fail + QCOMPARE(chars[1].descriptors().at(0).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::CharacteristicUserDescription)); + QCOMPARE(chars[1].descriptors().at(0).type(), + QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + // value different in other revisions and test may fail + QCOMPARE(chars[1].descriptors().at(0).value(), + QByteArray::fromHex("4d61676e2e20436f6e662e")); + QVERIFY(info->contains(chars[1].descriptors().at(0))); + + // Magnetometer Period + temp = QString("f000aa33-0451-4000-b000-000000000000"); + QCOMPARE(chars[2].uuid(), QBluetoothUuid(temp)); + // value different in other revisions and test may fail + QCOMPARE(chars[2].properties(), + (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write)); + QCOMPARE(chars[2].value(), QByteArray::fromHex("c8")); // don't change it or set it to 0xc8 + QVERIFY(chars[2].isValid()); + QVERIFY(info->contains(chars[2])); + + QCOMPARE(chars[2].descriptors().size(), 1); + QCOMPARE(chars[2].descriptors().at(0).isValid(), true); + // value different in other revisions and test may fail + QCOMPARE(chars[2].descriptors().at(0).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::CharacteristicUserDescription)); + QCOMPARE(chars[2].descriptors().at(0).type(), + QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + // value different in other revisions and test may fail + QCOMPARE(chars[2].descriptors().at(0).value(), + QByteArray::fromHex("4d61676e2e20506572696f64")); + QVERIFY(info->contains(chars[2].descriptors().at(0))); + } else if (info->serviceUuid() == + QBluetoothUuid(QString("f000aa40-0451-4000-b000-000000000000"))) { + qDebug() << "Verifying Pressure"; + const QList chars = info->characteristics(); + QVERIFY(chars.size() >= 3); + + // Pressure Data + QString temp("f000aa41-0451-4000-b000-000000000000"); + QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp)); + // value different in other revisions and test may fail + QCOMPARE(chars[0].properties(), + (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Notify)); + QCOMPARE(chars[0].value(), QByteArray::fromHex("00000000")); + QVERIFY(chars[0].isValid()); + QVERIFY(info->contains(chars[0])); + + QCOMPARE(chars[0].descriptors().size(), 2); + //descriptor checks + QCOMPARE(chars[0].descriptors().at(0).isValid(), true); + // value different in other revisions and test may fail + QCOMPARE(chars[0].descriptors().at(0).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration)); + QCOMPARE(chars[0].descriptors().at(0).type(), + QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration); + QVERIFY(verifyClientCharacteristicValue(chars[0].descriptors().at(0).value())); + QVERIFY(info->contains(chars[0].descriptors().at(0))); + + QCOMPARE(chars[0].descriptors().at(1).isValid(), true); + // value different in other revisions and test may fail + QCOMPARE(chars[0].descriptors().at(1).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::CharacteristicUserDescription)); + QCOMPARE(chars[0].descriptors().at(1).type(), + QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + // value different in other revisions and test may fail + QCOMPARE(chars[0].descriptors().at(1).value(), + QByteArray::fromHex("4261726f6d2e2044617461")); + QVERIFY(info->contains(chars[0].descriptors().at(1))); + + // Pressure Config + temp = QString("f000aa42-0451-4000-b000-000000000000"); + QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp)); + // value different in other revisions and test may fail + QCOMPARE(chars[1].properties(), + (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write)); + QCOMPARE(chars[1].value(), QByteArray::fromHex("00")); + QVERIFY(chars[1].isValid()); + QVERIFY(info->contains(chars[1])); + + QCOMPARE(chars[1].descriptors().size(), 1); + QCOMPARE(chars[1].descriptors().at(0).isValid(), true); + // value different in other revisions and test may fail + QCOMPARE(chars[1].descriptors().at(0).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::CharacteristicUserDescription)); + QCOMPARE(chars[1].descriptors().at(0).type(), + QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + QCOMPARE(chars[1].descriptors().at(0).value(), + QByteArray::fromHex("4261726f6d2e20436f6e662e")); + QVERIFY(info->contains(chars[1].descriptors().at(0))); + + //calibration and period characteristic are swapped, ensure we don't depend on their order + QLowEnergyCharacteristic calibration, period; + for (const QLowEnergyCharacteristic &ch : chars) { + //find calibration characteristic + if (ch.uuid() == QBluetoothUuid(QString("f000aa43-0451-4000-b000-000000000000"))) + calibration = ch; + else if (ch.uuid() == QBluetoothUuid(QString("f000aa44-0451-4000-b000-000000000000"))) + period = ch; + } + + if (calibration.isValid()) { + // Pressure Calibration + temp = QString("f000aa43-0451-4000-b000-000000000000"); + QCOMPARE(calibration.uuid(), QBluetoothUuid(temp)); + // value different in other revisions and test may fail + QCOMPARE(calibration.properties(), + (QLowEnergyCharacteristic::Read)); + QCOMPARE(calibration.value(), QByteArray::fromHex("00000000000000000000000000000000")); // don't change it + QVERIFY(calibration.isValid()); + QVERIFY(info->contains(calibration)); + + QCOMPARE(calibration.descriptors().size(), 2); + //descriptor checks + QCOMPARE(calibration.descriptors().at(0).isValid(), true); + // value different in other revisions and test may fail + QCOMPARE(calibration.descriptors().at(0).uuid(), + QBluetoothUuid( + QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration)); + QCOMPARE(calibration.descriptors().at(0).type(), + QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration); + QVERIFY(verifyClientCharacteristicValue(calibration.descriptors().at(0).value())); + QVERIFY(info->contains(calibration.descriptors().at(0))); + + QCOMPARE(calibration.descriptors().at(1).isValid(), true); + // value different in other revisions and test may fail + QCOMPARE(calibration.descriptors().at(1).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::CharacteristicUserDescription)); + QCOMPARE(calibration.descriptors().at(1).type(), + QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + QCOMPARE(calibration.descriptors().at(1).value(), + QByteArray::fromHex("4261726f6d2e2043616c6962722e")); + QVERIFY(info->contains(calibration.descriptors().at(1))); + } + + if (period.isValid()) { + // Period Calibration + temp = QString("f000aa44-0451-4000-b000-000000000000"); + QCOMPARE(period.uuid(), QBluetoothUuid(temp)); + // value different in other revisions and test may fail + QCOMPARE(period.properties(), + (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write)); + QCOMPARE(period.value(), QByteArray::fromHex("64")); + QVERIFY(period.isValid()); + QVERIFY(info->contains(period)); + + QCOMPARE(period.descriptors().size(), 1); + //descriptor checks + QCOMPARE(period.descriptors().at(0).isValid(), true); + // value different in other revisions and test may fail + QCOMPARE(period.descriptors().at(0).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::CharacteristicUserDescription)); + QCOMPARE(period.descriptors().at(0).type(), + QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + QCOMPARE(period.descriptors().at(0).value(), + QByteArray::fromHex("4261726f6d2e20506572696f64")); + QVERIFY(info->contains(period.descriptors().at(0))); + } + } else if (info->serviceUuid() == + QBluetoothUuid(QString("f000aa50-0451-4000-b000-000000000000"))) { + qDebug() << "Verifying Gyroscope"; + QList chars = info->characteristics(); + QVERIFY(chars.size() >= 2); + + // Gyroscope Data + QString temp("f000aa51-0451-4000-b000-000000000000"); + QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp)); + // value different in other revisions and test may fail + QCOMPARE(chars[0].properties(), + (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Notify)); + QCOMPARE(chars[0].value(), QByteArray::fromHex("000000000000")); + QVERIFY(chars[0].isValid()); + QVERIFY(info->contains(chars[0])); + + QCOMPARE(chars[0].descriptors().size(), 2); + //descriptor checks + QCOMPARE(chars[0].descriptors().at(0).isValid(), true); + // value different in other revisions and test may fail + QCOMPARE(chars[0].descriptors().at(0).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration)); + QCOMPARE(chars[0].descriptors().at(0).type(), + QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration); + QVERIFY(verifyClientCharacteristicValue(chars[0].descriptors().at(0).value())); + QVERIFY(info->contains(chars[0].descriptors().at(0))); + + QCOMPARE(chars[0].descriptors().at(1).isValid(), true); + // value different in other revisions and test may fail + QCOMPARE(chars[0].descriptors().at(1).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::CharacteristicUserDescription)); + QCOMPARE(chars[0].descriptors().at(1).type(), + QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + // value different in other revisions and test may fail + QCOMPARE(chars[0].descriptors().at(1).value(), + QByteArray::fromHex("4779726f2044617461")); + QVERIFY(info->contains(chars[0].descriptors().at(1))); + + // Gyroscope Config + temp = QString("f000aa52-0451-4000-b000-000000000000"); + QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp)); + // value different in other revisions and test may fail + QCOMPARE(chars[1].properties(), + (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write)); + QCOMPARE(chars[1].value(), QByteArray::fromHex("00")); + QVERIFY(chars[1].isValid()); + QVERIFY(info->contains(chars[1])); + + QCOMPARE(chars[1].descriptors().size(), 1); + //descriptor checks + QCOMPARE(chars[1].descriptors().at(0).isValid(), true); + // value different in other revisions and test may fail + QCOMPARE(chars[1].descriptors().at(0).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::CharacteristicUserDescription)); + QCOMPARE(chars[1].descriptors().at(0).type(), + QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + QCOMPARE(chars[1].descriptors().at(0).value(), + QByteArray::fromHex("4779726f20436f6e662e")); + QVERIFY(info->contains(chars[1].descriptors().at(0))); + + // Gyroscope Period + temp = QString("f000aa53-0451-4000-b000-000000000000"); + QCOMPARE(chars[2].uuid(), QBluetoothUuid(temp)); + // value different in other revisions and test may fail + QCOMPARE(chars[2].properties(), + (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write)); + QCOMPARE(chars[2].value(), QByteArray::fromHex("64")); + QVERIFY(chars[2].isValid()); + QVERIFY(info->contains(chars[2])); + + QCOMPARE(chars[2].descriptors().size(), 1); + //descriptor checks + QCOMPARE(chars[2].descriptors().at(0).isValid(), true); + QCOMPARE(chars[2].descriptors().at(0).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::CharacteristicUserDescription)); + QCOMPARE(chars[2].descriptors().at(0).type(), + QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + QCOMPARE(chars[2].descriptors().at(0).value(), + QByteArray::fromHex("4779726f20506572696f64")); + QVERIFY(info->contains(chars[2].descriptors().at(0))); + } else if (info->serviceUuid() == + QBluetoothUuid(QString("f000aa60-0451-4000-b000-000000000000"))) { + qDebug() << "Verifying Test Service"; + QList chars = info->characteristics(); + QCOMPARE(chars.size(), 2); + + // Test Data + QString temp("f000aa61-0451-4000-b000-000000000000"); + QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp)); + // value different in other revisions and test may fail + QCOMPARE(chars[0].properties(), + (QLowEnergyCharacteristic::Read)); + QCOMPARE(chars[0].value(), QByteArray::fromHex("3f00")); + QVERIFY(chars[0].isValid()); + QVERIFY(info->contains(chars[0])); + + QCOMPARE(chars[0].descriptors().size(), 1); + QCOMPARE(chars[0].descriptors().at(0).isValid(), true); + // value different in other revisions and test may fail + QCOMPARE(chars[0].descriptors().at(0).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::CharacteristicUserDescription)); + QCOMPARE(chars[0].descriptors().at(0).type(), + QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + QCOMPARE(chars[0].descriptors().at(0).value(), + QByteArray::fromHex("546573742044617461")); + QVERIFY(info->contains(chars[0].descriptors().at(0))); + + // Test Config + temp = QString("f000aa62-0451-4000-b000-000000000000"); + QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp)); + QCOMPARE(chars[1].properties(), + (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write)); + QCOMPARE(chars[1].value(), QByteArray::fromHex("00")); + QVERIFY(chars[1].isValid()); + QVERIFY(info->contains(chars[1])); + + QCOMPARE(chars[1].descriptors().size(), 1); + //descriptor checks + QCOMPARE(chars[1].descriptors().at(0).isValid(), true); + // value different in other revisions and test may fail + QCOMPARE(chars[1].descriptors().at(0).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::CharacteristicUserDescription)); + QCOMPARE(chars[1].descriptors().at(0).type(), + QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + QCOMPARE(chars[1].descriptors().at(0).value(), + QByteArray::fromHex("5465737420436f6e666967")); + QVERIFY(info->contains(chars[1].descriptors().at(0))); + } else if (info->serviceUuid() == + QBluetoothUuid(QString("f000ccc0-0451-4000-b000-000000000000"))) { + qDebug() << "Connection Control Service"; + QList chars = info->characteristics(); + QCOMPARE(chars.size(), 3); + + //first characteristic + QString temp("f000ccc1-0451-4000-b000-000000000000"); + QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp)); + QCOMPARE(chars[0].properties(), + (QLowEnergyCharacteristic::Notify|QLowEnergyCharacteristic::Read)); + // the connection control parameter change from platform to platform + // better not test them here + //QCOMPARE(chars[0].value(), QByteArray::fromHex("000000000000")); + QVERIFY(chars[0].isValid()); + QVERIFY(info->contains(chars[0])); + + QCOMPARE(chars[0].descriptors().size(), 2); + //descriptor checks + QCOMPARE(chars[0].descriptors().at(0).isValid(), true); + QCOMPARE(chars[0].descriptors().at(0).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration)); + QCOMPARE(chars[0].descriptors().at(0).type(), + QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration); + QVERIFY(verifyClientCharacteristicValue(chars[0].descriptors().at(0).value())); + QVERIFY(info->contains(chars[0].descriptors().at(0))); + + QCOMPARE(chars[0].descriptors().at(1).isValid(), true); + // value different in other revisions and test may fail + QCOMPARE(chars[0].descriptors().at(1).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::CharacteristicUserDescription)); + QCOMPARE(chars[0].descriptors().at(1).type(), + QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + QCOMPARE(chars[0].descriptors().at(1).value(), + QByteArray::fromHex("436f6e6e2e20506172616d73")); + QVERIFY(info->contains(chars[0].descriptors().at(1))); + + //second characteristic + temp = QString("f000ccc2-0451-4000-b000-000000000000"); + QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp)); + QCOMPARE(chars[1].properties(), QLowEnergyCharacteristic::Write); + QCOMPARE(chars[1].value(), QByteArray()); + QVERIFY(chars[1].isValid()); + QVERIFY(info->contains(chars[1])); + + QCOMPARE(chars[1].descriptors().size(), 1); + QCOMPARE(chars[1].descriptors().at(0).isValid(), true); + QCOMPARE(chars[1].descriptors().at(0).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::CharacteristicUserDescription)); + QCOMPARE(chars[1].descriptors().at(0).type(), + QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + QCOMPARE(chars[1].descriptors().at(0).value(), + QByteArray::fromHex("436f6e6e2e20506172616d7320526571")); + QVERIFY(info->contains(chars[1].descriptors().at(0))); + + //third characteristic + temp = QString("f000ccc3-0451-4000-b000-000000000000"); + QCOMPARE(chars[2].uuid(), QBluetoothUuid(temp)); + QCOMPARE(chars[2].properties(), QLowEnergyCharacteristic::Write); + QCOMPARE(chars[2].value(), QByteArray()); + QVERIFY(chars[2].isValid()); + QVERIFY(info->contains(chars[2])); + + QCOMPARE(chars[2].descriptors().size(), 1); + QCOMPARE(chars[2].descriptors().at(0).isValid(), true); + QCOMPARE(chars[2].descriptors().at(0).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::CharacteristicUserDescription)); + QCOMPARE(chars[2].descriptors().at(0).type(), + QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + QCOMPARE(chars[2].descriptors().at(0).value(), + QByteArray::fromHex("446973636f6e6e65637420526571")); + QVERIFY(info->contains(chars[2].descriptors().at(0))); + } else if (info->serviceUuid() == + QBluetoothUuid(QString("f000ffc0-0451-4000-b000-000000000000"))) { + qDebug() << "Verifying OID Service"; + QList chars = info->characteristics(); + QCOMPARE(chars.size(), 2); + + // first characteristic + QString temp("f000ffc1-0451-4000-b000-000000000000"); + QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp)); + // value different in other revisions and test may fail + QCOMPARE(chars[0].properties(), + (QLowEnergyCharacteristic::Notify|QLowEnergyCharacteristic::Write|QLowEnergyCharacteristic::WriteNoResponse)); + QCOMPARE(chars[0].value(), QByteArray()); + QVERIFY(chars[0].isValid()); + QVERIFY(info->contains(chars[0])); + + QCOMPARE(chars[0].descriptors().size(), 2); + //descriptor checks + QCOMPARE(chars[0].descriptors().at(0).isValid(), true); + QCOMPARE(chars[0].descriptors().at(0).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration)); + QCOMPARE(chars[0].descriptors().at(0).type(), + QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration); + QVERIFY(verifyClientCharacteristicValue(chars[0].descriptors().at(0).value())); + QVERIFY(info->contains(chars[0].descriptors().at(0))); + + QCOMPARE(chars[0].descriptors().at(1).isValid(), true); + // value different in other revisions and test may fail + QCOMPARE(chars[0].descriptors().at(1).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::CharacteristicUserDescription)); + QCOMPARE(chars[0].descriptors().at(1).type(), + QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + QCOMPARE(chars[0].descriptors().at(1).value(), + QByteArray::fromHex("496d67204964656e74696679")); + QVERIFY(info->contains(chars[0].descriptors().at(1))); + + // second characteristic + temp = QString("f000ffc2-0451-4000-b000-000000000000"); + QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp)); + // value different in other revisions and test may fail + QCOMPARE(chars[1].properties(), + (QLowEnergyCharacteristic::Notify|QLowEnergyCharacteristic::Write|QLowEnergyCharacteristic::WriteNoResponse)); + QCOMPARE(chars[1].value(), QByteArray()); + QVERIFY(chars[1].isValid()); + QVERIFY(info->contains(chars[1])); + + QCOMPARE(chars[1].descriptors().size(), 2); + //descriptor checks + QCOMPARE(chars[1].descriptors().at(0).isValid(), true); + // value different in other revisions and test may fail + QCOMPARE(chars[1].descriptors().at(0).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration)); + QCOMPARE(chars[1].descriptors().at(0).type(), + QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration); + QVERIFY(verifyClientCharacteristicValue(chars[0].descriptors().at(0).value())); + QVERIFY(info->contains(chars[1].descriptors().at(0))); + + QCOMPARE(chars[1].descriptors().at(1).isValid(), true); + // value different in other revisions and test may fail + QCOMPARE(chars[1].descriptors().at(1).uuid(), + QBluetoothUuid(QBluetoothUuid::DescriptorType::CharacteristicUserDescription)); + QCOMPARE(chars[1].descriptors().at(1).type(), + QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + QCOMPARE(chars[1].descriptors().at(1).value(), + QByteArray::fromHex("496d6720426c6f636b")); + QVERIFY(info->contains(chars[1].descriptors().at(1))); + } else { + QFAIL(QString("Service not found" + info->serviceUuid().toString()).toUtf8().constData()); + } +} + +/* + * CCC descriptors can have one of three distinct values: + * 0000 - notifications and indications are off + * 0100 - notifications enabled + * 0200 - indications enabled + * + * The exact value is managed by the BTLE peripheral for each central + * that connects. The value of this field is session based and may be retained + * during multiple connections. + * + * This function returns \c true if the CCC value has a valid range. + * */ +bool tst_QLowEnergyController::verifyClientCharacteristicValue(const QByteArray &value) +{ + if (value == QByteArray::fromHex("0000") + || value == QByteArray::fromHex("0100") + || value == QByteArray::fromHex("0200") ) + return true; + + qWarning() << "Found incorrect CC value" << value.toHex(); + return false; +} + +void tst_QLowEnergyController::tst_defaultBehavior() +{ + QList foundAddresses; + const QList infos = QBluetoothLocalDevice::allDevices(); + for (const QBluetoothHostInfo &info : infos) + foundAddresses.append(info.address()); + const QBluetoothAddress randomAddress("11:22:33:44:55:66"); + + // Test automatic detection of local adapter + QScopedPointer controlDefaultAdapter(QLowEnergyController::createCentral( + QBluetoothDeviceInfo(randomAddress, QString("random"), 1))); + + QCOMPARE(controlDefaultAdapter->remoteAddress(), randomAddress); + QCOMPARE(controlDefaultAdapter->state(), QLowEnergyController::UnconnectedState); + if (foundAddresses.isEmpty()) { + QVERIFY(controlDefaultAdapter->localAddress().isNull()); + } else { + QCOMPARE(controlDefaultAdapter->error(), QLowEnergyController::NoError); + QVERIFY(controlDefaultAdapter->errorString().isEmpty()); + QVERIFY(foundAddresses.contains(controlDefaultAdapter->localAddress())); + + // unrelated uuids don't return valid service object + // invalid service uuid + QVERIFY(!controlDefaultAdapter->createServiceObject( + QBluetoothUuid())); + // some random uuid + QVERIFY(!controlDefaultAdapter->createServiceObject( + QBluetoothUuid(QBluetoothUuid::CharacteristicType::DeviceName))); + } + + QCOMPARE(controlDefaultAdapter->services().size(), 0); + + // Test explicit local adapter + if (!foundAddresses.isEmpty()) { + + QScopedPointer controlExplicitAdapter( + QLowEnergyController::createCentral( + QBluetoothDeviceInfo(randomAddress, QString("random"), 1), + foundAddresses[0])); + + QCOMPARE(controlExplicitAdapter->remoteAddress(), randomAddress); + QCOMPARE(controlExplicitAdapter->localAddress(), foundAddresses[0]); + QCOMPARE(controlExplicitAdapter->state(), + QLowEnergyController::UnconnectedState); + QCOMPARE(controlExplicitAdapter->services().size(), 0); + + // unrelated uuids don't return valid service object + // invalid service uuid + QVERIFY(!controlExplicitAdapter->createServiceObject( + QBluetoothUuid())); + // some random uuid + QVERIFY(!controlExplicitAdapter->createServiceObject( + QBluetoothUuid(QBluetoothUuid::CharacteristicType::DeviceName))); + } +} + +void tst_QLowEnergyController::tst_writeCharacteristic() +{ +#if !defined(Q_OS_MACOS) && !QT_CONFIG(winrt_bt) + QList localAdapters = QBluetoothLocalDevice::allDevices(); + if (localAdapters.isEmpty()) + QSKIP("No local Bluetooth device found. Skipping test."); +#endif + + if (!remoteDeviceInfo.isValid()) + QSKIP("No remote BTLE device found. Skipping test."); + QScopedPointer control( + QLowEnergyController::createCentral(remoteDeviceInfo)); + + QCOMPARE(control->error(), QLowEnergyController::NoError); + + control->connectToDevice(); + { + QTRY_IMPL(control->state() != QLowEnergyController::ConnectingState, + 30000) + } + + if (control->state() == QLowEnergyController::ConnectingState + || control->error() != QLowEnergyController::NoError) { + // default BTLE backend forever hangs in ConnectingState + QSKIP("Cannot connect to remote device"); + } + + QTRY_VERIFY_WITH_TIMEOUT(control->state() == QLowEnergyController::ConnectedState, 20000); + QSignalSpy discoveryFinishedSpy(control.data(), SIGNAL(discoveryFinished())); + QSignalSpy stateSpy(control.data(), SIGNAL(stateChanged(QLowEnergyController::ControllerState))); + control->discoverServices(); + QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.size() == 1, 20000); + QCOMPARE(stateSpy.size(), 2); + QCOMPARE(stateSpy.at(0).at(0).value(), + QLowEnergyController::DiscoveringState); + QCOMPARE(stateSpy.at(1).at(0).value(), + QLowEnergyController::DiscoveredState); + + const QBluetoothUuid testService(QString("f000aa60-0451-4000-b000-000000000000")); + QList uuids = control->services(); + QVERIFY(uuids.contains(testService)); + + QLowEnergyService *service = control->createServiceObject(testService, this); + QVERIFY(service); + service->discoverDetails(); + QTRY_VERIFY_WITH_TIMEOUT( + service->state() == QLowEnergyService::RemoteServiceDiscovered, 30000); + + // test service described by + // http://processors.wiki.ti.com/index.php/CC2650_SensorTag_User%27s_Guide + const QList chars = service->characteristics(); + + QLowEnergyCharacteristic dataChar; + QLowEnergyCharacteristic configChar; + for (qsizetype i = 0; i < chars.size(); ++i) { + if (chars[i].uuid() == QBluetoothUuid(QString("f000aa61-0451-4000-b000-000000000000"))) + dataChar = chars[i]; + else if (chars[i].uuid() == QBluetoothUuid(QString("f000aa62-0451-4000-b000-000000000000"))) + configChar = chars[i]; + } + + QVERIFY(dataChar.isValid()); + QVERIFY(!(dataChar.properties() & ~QLowEnergyCharacteristic::Read)); // only a read char + QVERIFY(service->contains(dataChar)); + QVERIFY(configChar.isValid()); + QVERIFY(configChar.properties() & QLowEnergyCharacteristic::Write); + QVERIFY(configChar.properties() & QLowEnergyCharacteristic::Read); + QVERIFY(service->contains(configChar)); + + QCOMPARE(dataChar.value(), QByteArray::fromHex("3f00")); + QVERIFY(configChar.value() == QByteArray::fromHex("00") + || configChar.value() == QByteArray::fromHex("81")); + + QSignalSpy writeSpy(service, + SIGNAL(characteristicWritten(QLowEnergyCharacteristic,QByteArray))); + QSignalSpy readSpy(service, + SIGNAL(characteristicRead(QLowEnergyCharacteristic,QByteArray))); + + // ******************************************* + // test writing of characteristic + // enable Blinking LED if not already enabled + if (configChar.value() != QByteArray::fromHex("81")) { + service->writeCharacteristic(configChar, QByteArray::fromHex("81")); //0x81 blink LED D1 + QTRY_VERIFY_WITH_TIMEOUT(!writeSpy.isEmpty(), 10000); + QCOMPARE(configChar.value(), QByteArray::fromHex("81")); + QList firstSignalData = writeSpy.first(); + QLowEnergyCharacteristic signalChar = firstSignalData[0].value(); + QByteArray signalValue = firstSignalData[1].toByteArray(); + + QCOMPARE(signalValue, QByteArray::fromHex("81")); + QVERIFY(signalChar == configChar); + + writeSpy.clear(); + + } + + // test direct read of configChar + QVERIFY(readSpy.isEmpty()); + service->readCharacteristic(configChar); + QTRY_VERIFY_WITH_TIMEOUT(!readSpy.isEmpty(), 10000); + QCOMPARE(configChar.value(), QByteArray::fromHex("81")); + QCOMPARE(readSpy.size(), 1); //expect one characteristicRead signal + { + //verify the readCharacteristic() + QList firstSignalData = readSpy.first(); + QLowEnergyCharacteristic signalChar = firstSignalData[0].value(); + QByteArray signalValue = firstSignalData[1].toByteArray(); + + QCOMPARE(signalValue, QByteArray::fromHex("81")); + QCOMPARE(signalValue, configChar.value()); + QVERIFY(signalChar == configChar); + } + + service->writeCharacteristic(configChar, QByteArray::fromHex("00")); //turn LED D1 off + QTRY_VERIFY_WITH_TIMEOUT(!writeSpy.isEmpty(), 10000); + QCOMPARE(configChar.value(), QByteArray::fromHex("00")); + QList firstSignalData = writeSpy.first(); + QLowEnergyCharacteristic signalChar = firstSignalData[0].value(); + QByteArray signalValue = firstSignalData[1].toByteArray(); + + QCOMPARE(signalValue, QByteArray::fromHex("00")); + QVERIFY(signalChar == configChar); + + // ******************************************* + // write wrong value -> error response required + QSignalSpy errorSpy(service, SIGNAL(errorOccurred(QLowEnergyService::ServiceError))); + writeSpy.clear(); + QCOMPARE(errorSpy.size(), 0); + QCOMPARE(writeSpy.size(), 0); + + // write 2 byte value to 1 byte characteristic + service->writeCharacteristic(configChar, QByteArray::fromHex("1111")); + QTRY_VERIFY_WITH_TIMEOUT(!errorSpy.isEmpty(), 10000); + QCOMPARE(errorSpy[0].at(0).value(), + QLowEnergyService::CharacteristicWriteError); + QCOMPARE(service->error(), QLowEnergyService::CharacteristicWriteError); + QCOMPARE(writeSpy.size(), 0); + QCOMPARE(configChar.value(), QByteArray::fromHex("00")); + + // ******************************************* + // write to read-only characteristic -> error + errorSpy.clear(); + QCOMPARE(errorSpy.size(), 0); + service->writeCharacteristic(dataChar, QByteArray::fromHex("ffff")); + + QTRY_VERIFY_WITH_TIMEOUT(!errorSpy.isEmpty(), 10000); + QCOMPARE(errorSpy[0].at(0).value(), + QLowEnergyService::CharacteristicWriteError); + QCOMPARE(service->error(), QLowEnergyService::CharacteristicWriteError); + QCOMPARE(writeSpy.size(), 0); + QCOMPARE(dataChar.value(), QByteArray::fromHex("3f00")); + + + control->disconnectFromDevice(); + QTRY_COMPARE(control->state(), QLowEnergyController::UnconnectedState); + QCOMPARE(control->error(), QLowEnergyController::NoError); + // ******************************************* + // write value while disconnected -> error + errorSpy.clear(); + QCOMPARE(errorSpy.size(), 0); + service->writeCharacteristic(configChar, QByteArray::fromHex("ffff")); + QTRY_VERIFY_WITH_TIMEOUT(!errorSpy.isEmpty(), 2000); + QCOMPARE(errorSpy[0].at(0).value(), + QLowEnergyService::OperationError); + QCOMPARE(service->error(), QLowEnergyService::OperationError); + QCOMPARE(writeSpy.size(), 0); + QCOMPARE(configChar.value(), QByteArray::fromHex("00")); + + // invalid characteristics still belong to their respective service + QVERIFY(service->contains(configChar)); + QVERIFY(service->contains(dataChar)); + + QVERIFY(!service->contains(QLowEnergyCharacteristic())); + + delete service; +} + +void tst_QLowEnergyController::tst_readWriteDescriptor() +{ +#if !defined(Q_OS_MACOS) && !QT_CONFIG(winrt_bt) + QList localAdapters = QBluetoothLocalDevice::allDevices(); + if (localAdapters.isEmpty()) + QSKIP("No local Bluetooth device found. Skipping test."); +#endif + + if (!remoteDeviceInfo.isValid()) + QSKIP("No remote BTLE device found. Skipping test."); + QScopedPointer control(QLowEnergyController::createCentral(remoteDeviceInfo)); + + // quick setup - more elaborate test is done by connect() + control->connectToDevice(); + { + QTRY_IMPL(control->state() != QLowEnergyController::ConnectingState, + 30000) + } + + if (control->state() == QLowEnergyController::ConnectingState + || control->error() != QLowEnergyController::NoError) { + // default BTLE backend forever hangs in ConnectingState + QSKIP("Cannot connect to remote device"); + } + + QCOMPARE(control->state(), QLowEnergyController::ConnectedState); + QSignalSpy discoveryFinishedSpy(control.data(), SIGNAL(discoveryFinished())); + QSignalSpy stateSpy(control.data(), SIGNAL(stateChanged(QLowEnergyController::ControllerState))); + control->discoverServices(); + QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.size() == 1, 20000); + QCOMPARE(stateSpy.size(), 2); + QCOMPARE(stateSpy.at(0).at(0).value(), + QLowEnergyController::DiscoveringState); + QCOMPARE(stateSpy.at(1).at(0).value(), + QLowEnergyController::DiscoveredState); + + const QBluetoothUuid testService(QString("f000aa20-0451-4000-b000-000000000000")); + QList uuids = control->services(); + QVERIFY(uuids.contains(testService)); + + QLowEnergyService *service = control->createServiceObject(testService, this); + QVERIFY(service); + service->discoverDetails(); + QTRY_VERIFY_WITH_TIMEOUT( + service->state() == QLowEnergyService::RemoteServiceDiscovered, 30000); + + // Humidity service described by + // http://processors.wiki.ti.com/index.php/CC2650_SensorTag_User%27s_Guide + + // 1. Find humidity data characteristic + const QLowEnergyCharacteristic humidData = service->characteristic( + QBluetoothUuid(QStringLiteral("f000aa21-0451-4000-b000-000000000000"))); + const QLowEnergyCharacteristic humidConfig = service->characteristic( + QBluetoothUuid(QStringLiteral("f000aa22-0451-4000-b000-000000000000"))); + + if (!humidData.isValid()) { + delete service; + control->disconnectFromDevice(); + QTRY_COMPARE(control->state(), QLowEnergyController::UnconnectedState); + QCOMPARE(control->error(), QLowEnergyController::NoError); + QSKIP("Cannot find humidity data characteristic of TI Sensor"); + } + + // 2. Find humidity data notification descriptor + const QLowEnergyDescriptor notification = humidData.descriptor( + QBluetoothUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration)); + + if (!notification.isValid()) { + delete service; + control->disconnectFromDevice(); + QTRY_COMPARE(control->state(), QLowEnergyController::UnconnectedState); + QCOMPARE(control->error(), QLowEnergyController::NoError); + QSKIP("Cannot find humidity data notification of TI Sensor"); + } + + QCOMPARE(notification.value(), QByteArray::fromHex("0000")); + QVERIFY(service->contains(notification)); + QVERIFY(service->contains(humidData)); + if (humidConfig.isValid()) { + QVERIFY(service->contains(humidConfig)); + QCOMPARE(humidConfig.value(), QByteArray::fromHex("00")); + } + + // 3. Test reading and writing to descriptor -> activate notifications + QSignalSpy descWrittenSpy(service, + SIGNAL(descriptorWritten(QLowEnergyDescriptor,QByteArray))); + QSignalSpy descReadSpy(service, + SIGNAL(descriptorRead(QLowEnergyDescriptor,QByteArray))); + QSignalSpy charWrittenSpy(service, + SIGNAL(characteristicWritten(QLowEnergyCharacteristic,QByteArray))); + QSignalSpy charChangedSpy(service, + SIGNAL(characteristicChanged(QLowEnergyCharacteristic,QByteArray))); + + QLowEnergyDescriptor signalDesc; + QList firstSignalData; + QByteArray signalValue; + if (notification.value() != QByteArray::fromHex("0100")) { + // enable notifications if not already done + service->writeDescriptor(notification, QByteArray::fromHex("0100")); + + QTRY_VERIFY_WITH_TIMEOUT(!descWrittenSpy.isEmpty(), 3000); + QCOMPARE(notification.value(), QByteArray::fromHex("0100")); + firstSignalData = descWrittenSpy.first(); + signalDesc = firstSignalData[0].value(); + signalValue = firstSignalData[1].toByteArray(); + QCOMPARE(signalValue, QByteArray::fromHex("0100")); + QVERIFY(notification == signalDesc); + descWrittenSpy.clear(); + } + + // 4. Test reception of notifications + // activate the humidity sensor if available + if (humidConfig.isValid()) { + service->writeCharacteristic(humidConfig, QByteArray::fromHex("01")); + + // first signal is confirmation of humidConfig write + // subsequent signals are temp data updates + QTRY_VERIFY_WITH_TIMEOUT(charWrittenSpy.size() == 1, 10000); + QTRY_VERIFY_WITH_TIMEOUT(charChangedSpy.size() >= 4, 10000); + + QCOMPARE(charWrittenSpy.size(), 1); + QLowEnergyCharacteristic writtenChar = charWrittenSpy[0].at(0).value(); + QByteArray writtenValue = charWrittenSpy[0].at(1).toByteArray(); + QCOMPARE(humidConfig, writtenChar); + QCOMPARE(humidConfig.value(), writtenValue); + QCOMPARE(writtenChar.value(), writtenValue); + QCOMPARE(writtenValue, QByteArray::fromHex("01")); + + QList entry; + for (qsizetype i = 0; i < charChangedSpy.size(); ++i) { + entry = charChangedSpy[i]; + const QLowEnergyCharacteristic ch = entry[0].value(); + + QCOMPARE(humidData, ch); + + //check last characteristic changed value matches the characteristics current value + if (i == (charChangedSpy.size() - 1)) { + writtenValue = entry[1].toByteArray(); + QCOMPARE(ch.value(), writtenValue); + QCOMPARE(humidData.value(), writtenValue); + } + } + + service->writeCharacteristic(humidConfig, QByteArray::fromHex("00")); + } + + // 5. Test reading and writing of/to descriptor -> deactivate notifications + + service->readDescriptor(notification); + QTRY_VERIFY_WITH_TIMEOUT(!descReadSpy.isEmpty(), 3000); + QCOMPARE(descReadSpy.size(), 1); + firstSignalData = descReadSpy.first(); + signalDesc = firstSignalData[0].value(); + signalValue = firstSignalData[1].toByteArray(); + QCOMPARE(signalValue, notification.value()); + QCOMPARE(notification.value(), QByteArray::fromHex("0100")); + descReadSpy.clear(); + + + service->writeDescriptor(notification, QByteArray::fromHex("0000")); + // verify + QTRY_VERIFY_WITH_TIMEOUT(!descWrittenSpy.isEmpty(), 3000); + QCOMPARE(notification.value(), QByteArray::fromHex("0000")); + firstSignalData = descWrittenSpy.first(); + signalDesc = firstSignalData[0].value(); + signalValue = firstSignalData[1].toByteArray(); + QCOMPARE(signalValue, QByteArray::fromHex("0000")); + QVERIFY(notification == signalDesc); + descWrittenSpy.clear(); + + // The series of wait calls below is required because toggling CCC via the notifying + // property consistently crashes BlueZ 5.47. BlueZ 5.48 does not crash but + // an error is thrown. For details see QTBUG-65729 + if (isBluezDbusLE) + QTest::qWait(1000); + + // test concurrent writeRequests + // they need to be queued up + service->writeDescriptor(notification,QByteArray::fromHex("0100")); + if (isBluezDbusLE) + QTest::qWait(1000); + + service->writeDescriptor(notification, QByteArray::fromHex("0000")); + if (isBluezDbusLE) + QTest::qWait(1000); + + service->writeDescriptor(notification, QByteArray::fromHex("0100")); + if (isBluezDbusLE) + QTest::qWait(1000); + + service->writeDescriptor(notification, QByteArray::fromHex("0000")); + if (isBluezDbusLE) + QTest::qWait(1000); + + QTRY_VERIFY_WITH_TIMEOUT(descWrittenSpy.size() == 4, 10000); + + QCOMPARE(notification.value(), QByteArray::fromHex("0000")); + for (qsizetype i = 0; i < descWrittenSpy.size(); ++i) { + firstSignalData = descWrittenSpy.at(i); + signalDesc = firstSignalData[0].value(); + signalValue = firstSignalData[1].toByteArray(); + if (i & 0x1) // odd + QCOMPARE(signalValue, QByteArray::fromHex("0000")); + else // even + QCOMPARE(signalValue, QByteArray::fromHex("0100")); + QVERIFY(notification == signalDesc); + + } + + // 5. Test reading and writing of/to descriptor -> deactivate notifications + + service->readDescriptor(notification); + QTRY_VERIFY_WITH_TIMEOUT(!descReadSpy.isEmpty(), 3000); + QCOMPARE(descReadSpy.size(), 1); + firstSignalData = descReadSpy.first(); + signalDesc = firstSignalData[0].value(); + signalValue = firstSignalData[1].toByteArray(); + QCOMPARE(signalValue, notification.value()); + QCOMPARE(notification.value(), QByteArray::fromHex("0000")); + descReadSpy.clear(); + + descWrittenSpy.clear(); + + // ******************************************* + // write wrong value -> error response required + QSignalSpy errorSpy(service, SIGNAL(errorOccurred(QLowEnergyService::ServiceError))); + descWrittenSpy.clear(); + QCOMPARE(errorSpy.size(), 0); + QCOMPARE(descWrittenSpy.size(), 0); + + // write 4 byte value to 2 byte characteristic + service->writeDescriptor(notification, QByteArray::fromHex("11112222")); +#ifdef Q_OS_MAC + // On OS X/iOS we have a special method to set notify value, + // it accepts only false/true and not + // writing descriptors, there is only one way to find this error - + // immediately intercept in LE controller and set the error. + QVERIFY(!errorSpy.isEmpty()); +#else + QTRY_VERIFY_WITH_TIMEOUT(!errorSpy.isEmpty(), 30000); +#endif + QCOMPARE(errorSpy[0].at(0).value(), + QLowEnergyService::DescriptorWriteError); + QCOMPARE(service->error(), QLowEnergyService::DescriptorWriteError); + QCOMPARE(descWrittenSpy.size(), 0); + QCOMPARE(notification.value(), QByteArray::fromHex("0000")); + + control->disconnectFromDevice(); + QTRY_COMPARE(control->state(), QLowEnergyController::UnconnectedState); + QCOMPARE(control->error(), QLowEnergyController::NoError); + + // ******************************************* + // write value while disconnected -> error + errorSpy.clear(); + service->writeDescriptor(notification, QByteArray::fromHex("0100")); + QTRY_VERIFY_WITH_TIMEOUT(!errorSpy.isEmpty(), 2000); + QCOMPARE(errorSpy[0].at(0).value(), + QLowEnergyService::OperationError); + QCOMPARE(service->error(), QLowEnergyService::OperationError); + QCOMPARE(descWrittenSpy.size(), 0); + QCOMPARE(notification.value(), QByteArray::fromHex("0000")); + + delete service; +} + +/* + * By default this test is skipped. + * + * Following tests are performed: + * - encrypted read and discovery + * - readCharacteristic() of values longer than MTU + * - readCharacteristic() if values equal to MTU + * + * This test is semi manual as the test device environment is very specific. + * A programmable BTLE device is required. Currently, the test requires + * the CSR Dev Kit using the hr_sensor example. + * + * The following changes must be done to example to be able to fully + * utilise the test: + * 1.) gap_service_db.db -> UUID_DEVICE_NAME char - add FLAG_ENCR_R + * => tests encrypted read/discovery + * 2.) dev_info_service_db.db -> UUID_DEVICE_INFO_MANUFACTURER_NAME + * => The default name "Cambridge Silicon Radio" must be changed + * to "Cambridge Silicon Radi" (new length 22) + * 3.) revert change 1 above and redo test. This attempts to write a + * char that is readable w/o encryption but writeable with encryption + * => tests encryption code lines in writeCharacteristic() + * => otherwise the read encryption would have increased security level already + * => programmable CSR device must be reset before each run of this test + * (to undo the previous write) + */ +void tst_QLowEnergyController::tst_customProgrammableDevice() +{ + QSKIP("Skipping encryption"); + + //Adjust the uuids and device address as see fit to match + //values that match the current test environment + //The target characteristic must be readble and writable + //under encryption to test dynamic switching of security level + QBluetoothAddress encryptedDevice(QString("00:02:5B:00:15:10")); + QBluetoothUuid serviceUuid(QBluetoothUuid::ServiceClassUuid::GenericAccess); + QBluetoothUuid characterristicUuid(QBluetoothUuid::CharacteristicType::DeviceName); + + QScopedPointer control( + QLowEnergyController::createCentral(QBluetoothDeviceInfo(encryptedDevice, QString("DeviceFoo"), 1))); + QCOMPARE(control->error(), QLowEnergyController::NoError); + + control->connectToDevice(); + { + QTRY_IMPL(control->state() != QLowEnergyController::ConnectingState, + 30000) + } + + if (control->state() == QLowEnergyController::ConnectingState + || control->error() != QLowEnergyController::NoError) { + // default BTLE backend forever hangs in ConnectingState + QSKIP("Cannot connect to remote device"); + } + + QCOMPARE(control->state(), QLowEnergyController::ConnectedState); + QSignalSpy discoveryFinishedSpy(control.data(), SIGNAL(discoveryFinished())); + QSignalSpy stateSpy(control.data(), SIGNAL(stateChanged(QLowEnergyController::ControllerState))); + control->discoverServices(); + QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.size() == 1, 20000); + QCOMPARE(stateSpy.size(), 2); + QCOMPARE(stateSpy.at(0).at(0).value(), + QLowEnergyController::DiscoveringState); + QCOMPARE(stateSpy.at(1).at(0).value(), + QLowEnergyController::DiscoveredState); + + QList uuids = control->services(); + QVERIFY(uuids.contains(serviceUuid)); + + QLowEnergyService *service = control->createServiceObject(serviceUuid, this); + QVERIFY(service); + + // 1.) discovery triggers read of device name char which is encrypted + service->discoverDetails(); + QTRY_VERIFY_WITH_TIMEOUT( + service->state() == QLowEnergyService::RemoteServiceDiscovered, 30000); + + QLowEnergyCharacteristic encryptedChar = service->characteristic( + characterristicUuid); + const QByteArray encryptedReference("CSR HR Sensor"); + QVERIFY(encryptedChar.isValid()); + QCOMPARE(encryptedChar.value(), encryptedReference); + + // 2.) read of encrypted characteristic + // => the discovery of the encrypted char above will have switched to + // encryption already. + QSignalSpy encryptedReadSpy(service, + SIGNAL(characteristicRead(QLowEnergyCharacteristic,QByteArray))); + QSignalSpy encryptedErrorSpy(service, SIGNAL(errorOccurred(QLowEnergyService::ServiceError))); + service->readCharacteristic(encryptedChar); + QTRY_VERIFY_WITH_TIMEOUT(!encryptedReadSpy.isEmpty(), 10000); + QVERIFY(encryptedErrorSpy.isEmpty()); + QCOMPARE(encryptedReadSpy.size(), 1); + QList entry = encryptedReadSpy[0]; + QVERIFY(entry[0].value() == encryptedChar); + QCOMPARE(entry[1].toByteArray(), encryptedReference); + QCOMPARE(encryptedChar.value(), encryptedReference); + + // 3.) write to encrypted characteristic + QSignalSpy encryptedWriteSpy(service, + SIGNAL(characteristicWritten(QLowEnergyCharacteristic,QByteArray))); + encryptedReadSpy.clear(); + encryptedErrorSpy.clear(); + const QByteArray newValue("ZZZ HR Sensor"); + service->writeCharacteristic(encryptedChar, newValue); + QTRY_VERIFY_WITH_TIMEOUT(!encryptedWriteSpy.isEmpty(), 10000); + QVERIFY(encryptedErrorSpy.isEmpty()); + QVERIFY(encryptedReadSpy.isEmpty()); + QCOMPARE(encryptedWriteSpy.size(), 1); + entry = encryptedWriteSpy[0]; + QVERIFY(entry[0].value() == encryptedChar); + QCOMPARE(entry[1].toByteArray(), newValue); + QCOMPARE(encryptedChar.value(), newValue); + + delete service; + + //change to Device Information service + QVERIFY(uuids.contains(QBluetoothUuid::ServiceClassUuid::DeviceInformation)); + service = control->createServiceObject(QBluetoothUuid::ServiceClassUuid::DeviceInformation); + QVERIFY(service); + + service->discoverDetails(); + QTRY_VERIFY_WITH_TIMEOUT( + service->state() == QLowEnergyService::RemoteServiceDiscovered, 30000); + + // 4.) read of software revision string which is longer than mtu + // tests readCharacteristic() including blob reads + QSignalSpy readSpy(service, + SIGNAL(characteristicRead(QLowEnergyCharacteristic,QByteArray))); + QSignalSpy errorSpy(service, SIGNAL(errorOccurred(QLowEnergyService::ServiceError))); + + const QByteArray expectedSoftRev("Application version 2.3.0.0"); + QLowEnergyCharacteristic softwareRevChar = + service->characteristic(QBluetoothUuid::CharacteristicType::SoftwareRevisionString); + QVERIFY(softwareRevChar.isValid()); + QCOMPARE(softwareRevChar.value(), expectedSoftRev); + + service->readCharacteristic(softwareRevChar); + QTRY_VERIFY_WITH_TIMEOUT(!readSpy.isEmpty(), 10000); + QVERIFY(errorSpy.isEmpty()); + QCOMPARE(readSpy.size(), 1); + entry = readSpy[0]; + QVERIFY(entry[0].value() == softwareRevChar); + QCOMPARE(entry[1].toByteArray(), expectedSoftRev); + QCOMPARE(softwareRevChar.value(), expectedSoftRev); + + + // 5.) read of manufacturer string which is exactly as long as single + // MTU size (assuming negotiated MTU is 23) + // => blob read test without blob being required + // => the read blob answer will have zero length + + readSpy.clear(); + + // This assumes the manufacturer string was mondified via CSR SDK + // see function description above + const QByteArray expectedManufacturer("Cambridge Silicon Radi"); + QLowEnergyCharacteristic manufacturerChar = + service->characteristic(QBluetoothUuid::CharacteristicType::ManufacturerNameString); + QVERIFY(manufacturerChar.isValid()); + QCOMPARE(manufacturerChar.value(), expectedManufacturer); + + service->readCharacteristic(manufacturerChar); + QTRY_VERIFY_WITH_TIMEOUT(!readSpy.isEmpty(), 10000); + QVERIFY(errorSpy.isEmpty()); + QCOMPARE(readSpy.size(), 1); + entry = readSpy[0]; + QVERIFY(entry[0].value() == manufacturerChar); + QCOMPARE(entry[1].toByteArray(), expectedManufacturer); + QCOMPARE(manufacturerChar.value(), expectedManufacturer); + + delete service; + control->disconnectFromDevice(); + QTRY_COMPARE(control->state(), QLowEnergyController::UnconnectedState); + QCOMPARE(control->error(), QLowEnergyController::NoError); +} + + +/* 1.) Test with undiscovered devices + - read and write invalid char + 2.) Test with discovered devices + - read non-readable char + - write non-writable char + */ +void tst_QLowEnergyController::tst_errorCases() +{ +#if !defined(Q_OS_MACOS) && !QT_CONFIG(winrt_bt) + QList localAdapters = QBluetoothLocalDevice::allDevices(); + if (localAdapters.isEmpty()) + QSKIP("No local Bluetooth device found. Skipping test."); +#endif + + if (!remoteDeviceInfo.isValid()) + QSKIP("No remote BTLE device found. Skipping test."); + QScopedPointer control(QLowEnergyController::createCentral(remoteDeviceInfo)); + QCOMPARE(control->error(), QLowEnergyController::NoError); + + control->connectToDevice(); + { + QTRY_IMPL(control->state() != QLowEnergyController::ConnectingState, + 30000) + } + + if (control->state() == QLowEnergyController::ConnectingState + || control->error() != QLowEnergyController::NoError) { + // default BTLE backend forever hangs in ConnectingState + QSKIP("Cannot connect to remote device"); + } + + QCOMPARE(control->state(), QLowEnergyController::ConnectedState); + QSignalSpy discoveryFinishedSpy(control.data(), SIGNAL(discoveryFinished())); + QSignalSpy stateSpy(control.data(), SIGNAL(stateChanged(QLowEnergyController::ControllerState))); + control->discoverServices(); + QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.size() == 1, 20000); + QCOMPARE(stateSpy.size(), 2); + QCOMPARE(stateSpy.at(0).at(0).value(), + QLowEnergyController::DiscoveringState); + QCOMPARE(stateSpy.at(1).at(0).value(), + QLowEnergyController::DiscoveredState); + + + // Setup required uuids + const QBluetoothUuid irTemperaturServiceUuid(QStringLiteral("f000aa00-0451-4000-b000-000000000000")); + const QBluetoothUuid irCharUuid(QString("f000aa01-0451-4000-b000-000000000000")); + const QBluetoothUuid oadServiceUuid(QStringLiteral("f000ffc0-0451-4000-b000-000000000000")); + const QBluetoothUuid oadCharUuid(QString("f000ffc1-0451-4000-b000-000000000000")); + + QVERIFY(control->services().contains(irTemperaturServiceUuid)); + QVERIFY(control->services().contains(oadServiceUuid)); + + // Create service objects and basic tests + QLowEnergyService *irService = control->createServiceObject(irTemperaturServiceUuid); + QVERIFY(irService); + QCOMPARE(irService->state(), QLowEnergyService::RemoteService); + QVERIFY(irService->characteristics().isEmpty()); + QLowEnergyService *oadService = control->createServiceObject(oadServiceUuid); + QVERIFY(oadService); + QCOMPARE(oadService->state(), QLowEnergyService::RemoteService); + QVERIFY(oadService->characteristics().isEmpty()); + + QLowEnergyCharacteristic invalidChar; + QLowEnergyDescriptor invalidDesc; + + QVERIFY(!irService->contains(invalidChar)); + QVERIFY(!irService->contains(invalidDesc)); + + QSignalSpy irErrorSpy(irService, SIGNAL(errorOccurred(QLowEnergyService::ServiceError))); + QSignalSpy oadErrorSpy(oadService, SIGNAL(errorOccurred(QLowEnergyService::ServiceError))); + + QSignalSpy irReadSpy(irService, SIGNAL(characteristicRead(QLowEnergyCharacteristic,QByteArray))); + QSignalSpy irWrittenSpy(irService, SIGNAL(characteristicWritten(QLowEnergyCharacteristic,QByteArray))); + QSignalSpy irDescReadSpy(irService, SIGNAL(descriptorRead(QLowEnergyDescriptor,QByteArray))); + QSignalSpy irDescWrittenSpy(irService, SIGNAL(descriptorWritten(QLowEnergyDescriptor,QByteArray))); + + QSignalSpy oadCharReadSpy(oadService, SIGNAL(descriptorRead(QLowEnergyDescriptor,QByteArray))); + + // ******************************************************** + // Test read/write to discovered service + // with invalid characteristic & descriptor + + // discover IR Service + irService->discoverDetails(); + QTRY_VERIFY_WITH_TIMEOUT( + irService->state() == QLowEnergyService::RemoteServiceDiscovered, 30000); + QVERIFY(!irService->contains(invalidChar)); + QVERIFY(!irService->contains(invalidDesc)); + irErrorSpy.clear(); + + // read invalid characteristic + irService->readCharacteristic(invalidChar); + QTRY_VERIFY_WITH_TIMEOUT(!irErrorSpy.isEmpty(), 5000); + QCOMPARE(irErrorSpy.size(), 1); + QVERIFY(irWrittenSpy.isEmpty()); + QVERIFY(irReadSpy.isEmpty()); + QCOMPARE(irErrorSpy[0].at(0).value(), + QLowEnergyService::OperationError); + irErrorSpy.clear(); + + // read invalid descriptor + irService->readDescriptor(invalidDesc); + QTRY_VERIFY_WITH_TIMEOUT(!irErrorSpy.isEmpty(), 5000); + QCOMPARE(irErrorSpy.size(), 1); + QVERIFY(irDescWrittenSpy.isEmpty()); + QVERIFY(irDescReadSpy.isEmpty()); + QCOMPARE(irErrorSpy[0].at(0).value(), + QLowEnergyService::OperationError); + irErrorSpy.clear(); + + // write invalid characteristic + irService->writeCharacteristic(invalidChar, QByteArray("foo")); + QTRY_VERIFY_WITH_TIMEOUT(!irErrorSpy.isEmpty(), 5000); + QCOMPARE(irErrorSpy.size(), 1); + QVERIFY(irWrittenSpy.isEmpty()); + QVERIFY(irReadSpy.isEmpty()); + QCOMPARE(irErrorSpy[0].at(0).value(), + QLowEnergyService::OperationError); + irErrorSpy.clear(); + + // write invalid descriptor + irService->readDescriptor(invalidDesc); + QTRY_VERIFY_WITH_TIMEOUT(!irErrorSpy.isEmpty(), 5000); + QCOMPARE(irErrorSpy.size(), 1); + QVERIFY(irDescWrittenSpy.isEmpty()); + QVERIFY(irDescReadSpy.isEmpty()); + QCOMPARE(irErrorSpy[0].at(0).value(), + QLowEnergyService::OperationError); + irErrorSpy.clear(); + + // ******************************************************** + // Test read/write to undiscovered service + // with invalid characteristic & descriptor + + // read invalid characteristic + oadService->readCharacteristic(invalidChar); + QTRY_VERIFY_WITH_TIMEOUT(!oadErrorSpy.isEmpty(), 5000); + QCOMPARE(oadErrorSpy.size(), 1); + QCOMPARE(oadErrorSpy[0].at(0).value(), + QLowEnergyService::OperationError); + oadErrorSpy.clear(); + + // read invalid descriptor + oadService->readDescriptor(invalidDesc); + QTRY_VERIFY_WITH_TIMEOUT(!oadErrorSpy.isEmpty(), 5000); + QCOMPARE(oadErrorSpy.size(), 1); + QCOMPARE(oadErrorSpy[0].at(0).value(), + QLowEnergyService::OperationError); + oadErrorSpy.clear(); + + // write invalid characteristic + oadService->writeCharacteristic(invalidChar, QByteArray("foo")); + QTRY_VERIFY_WITH_TIMEOUT(!oadErrorSpy.isEmpty(), 5000); + QCOMPARE(oadErrorSpy.size(), 1); + QCOMPARE(oadErrorSpy[0].at(0).value(), + QLowEnergyService::OperationError); + oadErrorSpy.clear(); + + // write invalid descriptor + oadService->readDescriptor(invalidDesc); + QTRY_VERIFY_WITH_TIMEOUT(!oadErrorSpy.isEmpty(), 5000); + QCOMPARE(oadErrorSpy.size(), 1); + QCOMPARE(oadErrorSpy[0].at(0).value(), + QLowEnergyService::OperationError); + oadErrorSpy.clear(); + + // ******************************************************** + // Write to non-writable char + + QLowEnergyCharacteristic nonWritableChar = irService->characteristic(irCharUuid); + QVERIFY(nonWritableChar.isValid()); + // not writeable in any form + QVERIFY(!(nonWritableChar.properties() + & (QLowEnergyCharacteristic::Write|QLowEnergyCharacteristic::WriteNoResponse + |QLowEnergyCharacteristic::WriteSigned))); + irService->writeCharacteristic(nonWritableChar, QByteArray("ABCD")); + QTRY_VERIFY_WITH_TIMEOUT(!irErrorSpy.isEmpty(), 5000); + QVERIFY(irWrittenSpy.isEmpty()); + QVERIFY(irReadSpy.isEmpty()); + QCOMPARE(irErrorSpy[0].at(0).value(), + QLowEnergyService::CharacteristicWriteError); + irErrorSpy.clear(); + + // ******************************************************** + // Write to non-writable desc + // CharacteristicUserDescription is not writable + + QLowEnergyDescriptor nonWritableDesc = nonWritableChar.descriptor( + QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + QVERIFY(nonWritableDesc.isValid()); + irService->writeDescriptor(nonWritableDesc, QByteArray("ABCD")); + QTRY_VERIFY_WITH_TIMEOUT(!irErrorSpy.isEmpty(), 5000); + QVERIFY(irWrittenSpy.isEmpty()); + QVERIFY(irReadSpy.isEmpty()); + QCOMPARE(irErrorSpy[0].at(0).value(), + QLowEnergyService::DescriptorWriteError); + irErrorSpy.clear(); + + + // ******************************************************** + // Read non-readable char + + // discover OAD Service + oadService->discoverDetails(); + QTRY_VERIFY_WITH_TIMEOUT( + oadService->state() == QLowEnergyService::RemoteServiceDiscovered, 30000); + oadErrorSpy.clear(); + + // Test reading + QLowEnergyCharacteristic oadChar = oadService->characteristic(oadCharUuid); + QVERIFY(oadChar.isValid()); + oadService->readCharacteristic(oadChar); + QTRY_VERIFY_WITH_TIMEOUT(!oadErrorSpy.isEmpty(), 5000); + QCOMPARE(oadErrorSpy.size(), 1); + QVERIFY(oadCharReadSpy.isEmpty()); + QCOMPARE(oadErrorSpy[0].at(0).value(), + QLowEnergyService::CharacteristicReadError); + oadErrorSpy.clear(); + + delete irService; + delete oadService; + control->disconnectFromDevice(); + QTRY_COMPARE(control->state(), QLowEnergyController::UnconnectedState); + QCOMPARE(control->error(), QLowEnergyController::NoError); +} + +/* + Tests write without responses. We utilize the Over-The-Air image update + service of the SensorTag. + */ +void tst_QLowEnergyController::tst_writeCharacteristicNoResponse() +{ +#if !defined(Q_OS_MACOS) && !QT_CONFIG(winrt_bt) + QList localAdapters = QBluetoothLocalDevice::allDevices(); + if (localAdapters.isEmpty()) + QSKIP("No local Bluetooth device found. Skipping test."); +#endif + + if (!remoteDeviceInfo.isValid()) + QSKIP("No remote BTLE device found. Skipping test."); + QScopedPointer control(QLowEnergyController::createCentral(remoteDeviceInfo)); + + QCOMPARE(control->error(), QLowEnergyController::NoError); + + control->connectToDevice(); + { + QTRY_IMPL(control->state() != QLowEnergyController::ConnectingState, + 30000) + } + + if (control->state() == QLowEnergyController::ConnectingState + || control->error() != QLowEnergyController::NoError) { + // default BTLE backend forever hangs in ConnectingState + QSKIP("Cannot connect to remote device"); + } + + QTRY_VERIFY_WITH_TIMEOUT(control->state() == QLowEnergyController::ConnectedState, 20000); + QSignalSpy discoveryFinishedSpy(control.data(), SIGNAL(discoveryFinished())); + QSignalSpy stateSpy(control.data(), SIGNAL(stateChanged(QLowEnergyController::ControllerState))); + control->discoverServices(); + QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.size() == 1, 20000); + QCOMPARE(stateSpy.size(), 2); + QCOMPARE(stateSpy.at(0).at(0).value(), + QLowEnergyController::DiscoveringState); + QCOMPARE(stateSpy.at(1).at(0).value(), + QLowEnergyController::DiscoveredState); + + // The Over-The-Air update service uuid + const QBluetoothUuid testService(QString("f000ffc0-0451-4000-b000-000000000000")); + QList uuids = control->services(); + QVERIFY(uuids.contains(testService)); + + QLowEnergyService *service = control->createServiceObject(testService, this); + QVERIFY(service); + service->discoverDetails(); + QTRY_VERIFY_WITH_TIMEOUT( + service->state() == QLowEnergyService::RemoteServiceDiscovered, 30000); + + // 1. Get "Image Identity" and "Image Block" characteristic + const QLowEnergyCharacteristic imageIdentityChar = service->characteristic( + QBluetoothUuid(QString("f000ffc1-0451-4000-b000-000000000000"))); + const QLowEnergyCharacteristic imageBlockChar = service->characteristic( + QBluetoothUuid(QString("f000ffc2-0451-4000-b000-000000000000"))); + QVERIFY(imageIdentityChar.isValid()); + QVERIFY(imageIdentityChar.properties() & QLowEnergyCharacteristic::Write); + QVERIFY(imageIdentityChar.properties() & QLowEnergyCharacteristic::WriteNoResponse); + QVERIFY(!(imageIdentityChar.properties() & QLowEnergyCharacteristic::Read)); //not readable + QVERIFY(imageBlockChar.isValid()); + + // 2. Get "Image Identity" notification descriptor + const QLowEnergyDescriptor identityNotification = imageIdentityChar.descriptor( + QBluetoothUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration)); + const QLowEnergyDescriptor blockNotification = imageBlockChar.descriptor( + QBluetoothUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration)); + + if (!identityNotification.isValid() + || !blockNotification.isValid() + || !imageIdentityChar.isValid()) { + delete service; + control->disconnectFromDevice(); + QTRY_COMPARE(control->state(), QLowEnergyController::UnconnectedState); + QCOMPARE(control->error(), QLowEnergyController::NoError); + QSKIP("Cannot find OAD char/notification"); + } + + // 3. Enable notifications + QSignalSpy descWrittenSpy(service, + SIGNAL(descriptorWritten(QLowEnergyDescriptor,QByteArray))); + QSignalSpy charChangedSpy(service, + SIGNAL(characteristicChanged(QLowEnergyCharacteristic,QByteArray))); + QSignalSpy charWrittenSpy(service, + SIGNAL(characteristicWritten(QLowEnergyCharacteristic,QByteArray))); + QSignalSpy charReadSpy(service, + SIGNAL(characteristicRead(QLowEnergyCharacteristic,QByteArray))); + QSignalSpy errorSpy(service, SIGNAL(errorOccurred(QLowEnergyService::ServiceError))); + + //enable notifications on both characteristics + if (identityNotification.value() != QByteArray::fromHex("0100")) { + service->writeDescriptor(identityNotification, QByteArray::fromHex("0100")); + QTRY_VERIFY_WITH_TIMEOUT(!descWrittenSpy.isEmpty(), 3000); + QCOMPARE(identityNotification.value(), QByteArray::fromHex("0100")); + QList firstSignalData = descWrittenSpy.first(); + QLowEnergyDescriptor signalDesc = firstSignalData[0].value(); + QByteArray signalValue = firstSignalData[1].toByteArray(); + QCOMPARE(signalValue, QByteArray::fromHex("0100")); + QVERIFY(identityNotification == signalDesc); + descWrittenSpy.clear(); + } + + if (blockNotification.value() != QByteArray::fromHex("0100")) { + service->writeDescriptor(blockNotification, QByteArray::fromHex("0100")); + QTRY_VERIFY_WITH_TIMEOUT(!descWrittenSpy.isEmpty(), 3000); + QCOMPARE(blockNotification.value(), QByteArray::fromHex("0100")); + QList firstSignalData = descWrittenSpy.first(); + QLowEnergyDescriptor signalDesc = firstSignalData[0].value(); + QByteArray signalValue = firstSignalData[1].toByteArray(); + QCOMPARE(signalValue, QByteArray::fromHex("0100")); + QVERIFY(blockNotification == signalDesc); + descWrittenSpy.clear(); + } + + QList entry; + + // Test direct read of non-readable characteristic + QVERIFY(errorSpy.isEmpty()); + QVERIFY(charReadSpy.isEmpty()); + service->readCharacteristic(imageIdentityChar); + QTRY_VERIFY_WITH_TIMEOUT(!errorSpy.isEmpty(), 10000); + QCOMPARE(errorSpy.size(), 1); // should throw CharacteristicReadError + QVERIFY(charReadSpy.isEmpty()); + entry = errorSpy[0]; + QCOMPARE(entry[0].value(), + QLowEnergyService::CharacteristicReadError); + + // 4. Trigger image identity announcement (using traditional write) + bool foundOneImage = false; + + // Image A + // Write triggers a notification and write confirmation + service->writeCharacteristic(imageIdentityChar, QByteArray::fromHex("0")); + QTest::qWait(1000); + QTRY_COMPARE_WITH_TIMEOUT(charChangedSpy.size(), 1, 5000); + QTRY_COMPARE_WITH_TIMEOUT(charWrittenSpy.size(), 1, 5000); + + // This is very SensorTag specific logic. + // If the image block is empty the current firmware + // does not even send a notification for imageIdentityChar + // but for imageBlockChar + + entry = charChangedSpy[0]; + QLowEnergyCharacteristic first = entry[0].value(); + QByteArray val1 = entry[1].toByteArray(); + if (val1.size() == 8) { + QCOMPARE(imageIdentityChar, first); + foundOneImage = true; + } else { + // we received a notification for imageBlockChar + QCOMPARE(imageBlockChar, first); + qWarning() << "Invalid image A ident info"; + } + + entry = charWrittenSpy[0]; + QLowEnergyCharacteristic second = entry[0].value(); + QByteArray val2 = entry[1].toByteArray(); + QCOMPARE(imageIdentityChar, second); + QVERIFY(val2 == QByteArray::fromHex("0") || val2 == val1); + + // notifications on non-readable characteristics do not update cache + QVERIFY(imageIdentityChar.value().isEmpty()); + QVERIFY(imageBlockChar.value().isEmpty()); + + charChangedSpy.clear(); + charWrittenSpy.clear(); + + // Image B + service->writeCharacteristic(imageIdentityChar, QByteArray::fromHex("1")); + QTest::qWait(1000); + QTRY_COMPARE_WITH_TIMEOUT(charChangedSpy.size(), 1, 5000); + QTRY_COMPARE_WITH_TIMEOUT(charWrittenSpy.size(), 1, 5000);; + + entry = charChangedSpy[0]; + first = entry[0].value(); + val1 = entry[1].toByteArray(); + if (val1.size() == 8) { + QCOMPARE(imageIdentityChar, first); + foundOneImage = true; + } else { + // we received a notification for imageBlockChar without explicitly + // enabling them. This is caused by the device's default settings. + QCOMPARE(imageBlockChar, first); + qWarning() << "Invalid image B ident info"; + } + + entry = charWrittenSpy[0]; + second = entry[0].value(); + val2 = entry[1].toByteArray(); + QCOMPARE(imageIdentityChar, second); + + // notifications on non-readable characteristics do not update cache + QVERIFY(imageIdentityChar.value().isEmpty()); + QVERIFY(imageBlockChar.value().isEmpty()); + + /* Bluez resends the last confirmed write value, other platforms + * send the value received by the change notification value. + */ + qDebug() << "Image B(1):" << val1.toHex() << val2.toHex(); + QVERIFY(val2 == QByteArray::fromHex("1") || val2 == val1); + + QVERIFY2(foundOneImage, "The SensorTag doesn't have a valid image? (1)"); + + // 5. Trigger image identity announcement (without response) + charChangedSpy.clear(); + charWrittenSpy.clear(); + foundOneImage = false; + + // Image A + service->writeCharacteristic(imageIdentityChar, + QByteArray::fromHex("0"), + QLowEnergyService::WriteWithoutResponse); + + // we only expect one signal (the notification but not the write confirmation) + // Wait at least a second for a potential second signals + QTest::qWait(1000); + QTRY_COMPARE_WITH_TIMEOUT(charChangedSpy.size(), 1, 10000); + QTRY_COMPARE_WITH_TIMEOUT(charWrittenSpy.size(), 0, 10000); + + entry = charChangedSpy[0]; + first = entry[0].value(); + val1 = entry[1].toByteArray(); + +#ifdef Q_OS_ANDROID + QEXPECT_FAIL("", "Android sends write confirmation when using WriteWithoutResponse", + Continue); +#endif + QVERIFY(charWrittenSpy.isEmpty()); + if (val1.size() == 8) { + QCOMPARE(first, imageIdentityChar); + foundOneImage = true; + } else { + // we received a notification for imageBlockChar without explicitly + // enabling them. This is caused by the device's default settings. + QCOMPARE(imageBlockChar, first); + qWarning() << "Image A not set?"; + } + + // notifications on non-readable characteristics do not update cache + QVERIFY(imageIdentityChar.value().isEmpty()); + QVERIFY(imageBlockChar.value().isEmpty()); + + charChangedSpy.clear(); + + // Image B + service->writeCharacteristic(imageIdentityChar, + QByteArray::fromHex("1"), + QLowEnergyService::WriteWithoutResponse); + + // we only expect one signal (the notification but not the write confirmation) + // Wait at least a second for a potential second signals + QTest::qWait(1000); + QTRY_COMPARE_WITH_TIMEOUT(charWrittenSpy.size(), 0, 10000); + QTRY_COMPARE_WITH_TIMEOUT(charChangedSpy.size(), 1, 10000); + + entry = charChangedSpy[0]; + first = entry[0].value(); + val1 = entry[1].toByteArray(); + +#ifdef Q_OS_ANDROID + QEXPECT_FAIL("", "Android sends write confirmation when using WriteWithoutResponse", + Continue); +#endif + QVERIFY(charWrittenSpy.isEmpty()); + if (val1.size() == 8) { + QCOMPARE(first, imageIdentityChar); + foundOneImage = true; + } else { + // we received a notification for imageBlockChar without explicitly + // enabling them. This is caused by the device's default settings. + QCOMPARE(imageBlockChar, first); + qWarning() << "Image B not set?"; + } + + // notifications on non-readable characteristics do not update cache + QVERIFY(imageIdentityChar.value().isEmpty()); + QVERIFY(imageBlockChar.value().isEmpty()); + + + QVERIFY2(foundOneImage, "The SensorTag doesn't have a valid image? (2)"); + + delete service; + control->disconnectFromDevice(); + QTRY_COMPARE(control->state(), QLowEnergyController::UnconnectedState); + QCOMPARE(control->error(), QLowEnergyController::NoError); +} + +using namespace Qt::Literals::StringLiterals; + +void tst_QLowEnergyController::tst_rssiError() +{ + // Create unconnected/invalid controller instances and verify that + // reading RSSI value triggers error signal. For the actual + // RSSI read testing see tst_qlowenergycontroller_device + + // Peripheral + std::unique_ptr peripheral{QLowEnergyController::createPeripheral()}; + QSignalSpy peripheralErrorSpy(peripheral.get(), &QLowEnergyController::errorOccurred); + peripheral->readRssi(); + QTRY_VERIFY(!peripheralErrorSpy.isEmpty()); + QCOMPARE(peripheralErrorSpy.takeFirst().at(0).value(), + QLowEnergyController::Error::RssiReadError); + QCOMPARE(peripheral->error(), QLowEnergyController::Error::RssiReadError); + + // Central + QBluetoothDeviceInfo info(QBluetoothAddress{u"11:22:33:44:55:66"_s}, u"invalid"_s, 1); + std::unique_ptr central{QLowEnergyController::createCentral(info)}; + QSignalSpy centralErrorSpy(central.get(), &QLowEnergyController::errorOccurred); + central->readRssi(); + QTRY_VERIFY(!centralErrorSpy.isEmpty()); + QCOMPARE(centralErrorSpy.takeFirst().at(0).value(), + QLowEnergyController::Error::RssiReadError); + QCOMPARE(central->error(), QLowEnergyController::Error::RssiReadError); +} + +QTEST_MAIN(tst_QLowEnergyController) + +#include "tst_qlowenergycontroller.moc" diff --git a/tests/auto/qlowenergydescriptor/CMakeLists.txt b/tests/auto/qlowenergydescriptor/CMakeLists.txt new file mode 100644 index 0000000..81b814e --- /dev/null +++ b/tests/auto/qlowenergydescriptor/CMakeLists.txt @@ -0,0 +1,31 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## tst_qlowenergydescriptor Test: +##################################################################### + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qlowenergydescriptor LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qlowenergydescriptor + SOURCES + tst_qlowenergydescriptor.cpp + LIBRARIES + Qt::Bluetooth +) + +set_target_properties(tst_qlowenergydescriptor PROPERTIES + MACOSX_BUNDLE TRUE +) + +if (APPLE AND NOT IOS) + # Ninja has trouble with relative paths, convert to absolute as a workaround + get_filename_component(SHARED_PLIST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../shared ABSOLUTE) + set_target_properties(tst_qlowenergydescriptor PROPERTIES + MACOSX_BUNDLE_INFO_PLIST "${SHARED_PLIST_DIR}/Info.macos.plist" + ) +endif() diff --git a/tests/auto/qlowenergydescriptor/tst_qlowenergydescriptor.cpp b/tests/auto/qlowenergydescriptor/tst_qlowenergydescriptor.cpp new file mode 100644 index 0000000..8d9b04b --- /dev/null +++ b/tests/auto/qlowenergydescriptor/tst_qlowenergydescriptor.cpp @@ -0,0 +1,338 @@ +// Copyright (C) 2016 BlackBerry Limited all rights reserved +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include +#include + +#include + +#include +#include +#include +#include + +#if QT_CONFIG(permissions) +#include +#include +#include +#endif + +QT_USE_NAMESPACE + +class tst_QLowEnergyDescriptor : public QObject +{ + Q_OBJECT + +public: + tst_QLowEnergyDescriptor(); + ~tst_QLowEnergyDescriptor(); + +protected slots: + void deviceDiscovered(const QBluetoothDeviceInfo &info); + +private slots: + void initTestCase(); + void cleanupTestCase(); + void tst_constructionDefault(); + void tst_assignCompare(); + +private: + QList remoteLeDeviceInfos; + QLowEnergyController *globalControl; + QLowEnergyService *globalService; +#if QT_CONFIG(permissions) + Qt::PermissionStatus permissionStatus = Qt::PermissionStatus::Undetermined; +#endif +}; + +tst_QLowEnergyDescriptor::tst_QLowEnergyDescriptor() : + globalControl(nullptr), globalService(nullptr) +{ + QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true")); +#if QT_CONFIG(permissions) + permissionStatus = qApp->checkPermission(QBluetoothPermission{}); + const bool ciRun = qEnvironmentVariable("QTEST_ENVIRONMENT").split(' ').contains("ci"); + if (!ciRun && permissionStatus == Qt::PermissionStatus::Undetermined) { + QTestEventLoop loop; + qApp->requestPermission(QBluetoothPermission{}, [this, &loop](const QPermission &permission){ + permissionStatus = permission.status(); + loop.exitLoop(); + }); + if (permissionStatus == Qt::PermissionStatus::Undetermined) + loop.enterLoopMSecs(30000); + } +#endif // QT_CONFIG(permissions) +} + +tst_QLowEnergyDescriptor::~tst_QLowEnergyDescriptor() +{ +} + +void tst_QLowEnergyDescriptor::initTestCase() +{ + if (QBluetoothLocalDevice::allDevices().isEmpty()) { + qWarning("No local adapter, not discovering remote devices"); + return; + } + + QBluetoothLocalDevice device; + if (device.hostMode() == QBluetoothLocalDevice::HostPoweredOff) { + // Attempt to switch Bluetooth ON + device.powerOn(); + QTest::qWait(1000); + if (device.hostMode() == QBluetoothLocalDevice::HostPoweredOff) { + qWarning("Bluetooth couldn't be switched ON, not discovering remote devices"); + return; + } + } + +#if QT_CONFIG(permissions) + if (permissionStatus != Qt::PermissionStatus::Granted) { + qWarning("Use of BLuetooth LE requires the Bluetooth permission granted"); + return; + } +#endif + + // find an arbitrary low energy device in vicinity + // find an arbitrary service with descriptor + + QBluetoothDeviceDiscoveryAgent *devAgent = new QBluetoothDeviceDiscoveryAgent(this); + connect(devAgent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)), + this, SLOT(deviceDiscovered(QBluetoothDeviceInfo))); + + QSignalSpy errorSpy(devAgent, SIGNAL(errorOccurred(QBluetoothDeviceDiscoveryAgent::Error))); + QVERIFY(errorSpy.isValid()); + QVERIFY(errorSpy.isEmpty()); + + QSignalSpy spy(devAgent, SIGNAL(finished())); + // there should be no changes yet + QVERIFY(spy.isValid()); + QVERIFY(spy.isEmpty()); + + devAgent->start(); + QTRY_VERIFY_WITH_TIMEOUT(spy.size() > 0, 100000); + + // find first service with descriptor + QLowEnergyController *controller = nullptr; + for (const QBluetoothDeviceInfo& remoteDeviceInfo : std::as_const(remoteLeDeviceInfos)) { + controller = QLowEnergyController::createCentral(remoteDeviceInfo, this); + qDebug() << "Connecting to" << remoteDeviceInfo.address(); + controller->connectToDevice(); + QTRY_IMPL(controller->state() != QLowEnergyController::ConnectingState, + 50000) + if (controller->state() != QLowEnergyController::ConnectedState) { + // any error and we skip + delete controller; + qDebug() << "Skipping device"; + continue; + } + + QSignalSpy discoveryFinishedSpy(controller, SIGNAL(discoveryFinished())); + QSignalSpy stateSpy(controller, SIGNAL(stateChanged(QLowEnergyController::ControllerState))); + controller->discoverServices(); + QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.size() == 1, 10000); + QCOMPARE(stateSpy.size(), 2); + QCOMPARE(stateSpy.at(0).at(0).value(), + QLowEnergyController::DiscoveringState); + QCOMPARE(stateSpy.at(1).at(0).value(), + QLowEnergyController::DiscoveredState); + + const QList leServiceUuids = controller->services(); + for (const QBluetoothUuid &leServiceUuid : leServiceUuids) { + QLowEnergyService *leService = controller->createServiceObject(leServiceUuid, this); + if (!leService) + continue; + + leService->discoverDetails(); + QTRY_VERIFY_WITH_TIMEOUT( + leService->state() == QLowEnergyService::RemoteServiceDiscovered, 10000); + + const QList chars = leService->characteristics(); + for (const QLowEnergyCharacteristic &ch : chars) { + const QList descriptors = ch.descriptors(); + for (const QLowEnergyDescriptor &d : descriptors) { + if (!d.value().isEmpty()) { + globalService = leService; + globalControl = controller; + qWarning() << "Found service with descriptor" << remoteDeviceInfo.address() + << globalService->serviceName() << globalService->serviceUuid(); + break; + } + } + if (globalControl) + break; + } + + if (globalControl) + break; + else + delete leService; + } + + if (globalControl) + break; + + delete controller; + } + + if (!globalControl) { + qWarning() << "Test limited due to missing remote QLowEnergyDescriptor." + << "Please ensure the Bluetooth Low Energy device is advertising its services."; + } +} + +void tst_QLowEnergyDescriptor::cleanupTestCase() +{ + if (globalControl) + globalControl->disconnectFromDevice(); +} + +void tst_QLowEnergyDescriptor::deviceDiscovered(const QBluetoothDeviceInfo &info) +{ + if (info.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration) + remoteLeDeviceInfos.append(info); +} + +void tst_QLowEnergyDescriptor::tst_constructionDefault() +{ + QLowEnergyDescriptor descriptor; + QVERIFY(!descriptor.isValid()); + QCOMPARE(descriptor.value(), QByteArray()); + QVERIFY(descriptor.uuid().isNull()); + QCOMPARE(descriptor.name(), QString()); + QCOMPARE(descriptor.type(), QBluetoothUuid::DescriptorType::UnknownDescriptorType); + + QLowEnergyDescriptor copyConstructed(descriptor); + QVERIFY(!copyConstructed.isValid()); + QCOMPARE(copyConstructed.value(), QByteArray()); + QVERIFY(copyConstructed.uuid().isNull()); + QCOMPARE(copyConstructed.name(), QString()); + QCOMPARE(copyConstructed.type(), QBluetoothUuid::DescriptorType::UnknownDescriptorType); + + QVERIFY(copyConstructed == descriptor); + QVERIFY(descriptor == copyConstructed); + QVERIFY(!(copyConstructed != descriptor)); + QVERIFY(!(descriptor != copyConstructed)); + + QLowEnergyDescriptor assigned; + + QVERIFY(assigned == descriptor); + QVERIFY(descriptor == assigned); + QVERIFY(!(assigned != descriptor)); + QVERIFY(!(descriptor != assigned)); + + assigned = descriptor; + QVERIFY(!assigned.isValid()); + QCOMPARE(assigned.value(), QByteArray()); + QVERIFY(assigned.uuid().isNull()); + QCOMPARE(assigned.name(), QString()); + QCOMPARE(assigned.type(), QBluetoothUuid::DescriptorType::UnknownDescriptorType); + + QVERIFY(assigned == descriptor); + QVERIFY(descriptor == assigned); + QVERIFY(!(assigned != descriptor)); + QVERIFY(!(descriptor != assigned)); +} + + +void tst_QLowEnergyDescriptor::tst_assignCompare() +{ + //find the descriptor + if (!globalService) + QSKIP("No descriptor found."); + + QLowEnergyDescriptor target; + QVERIFY(!target.isValid()); + QCOMPARE(target.type(), QBluetoothUuid::DescriptorType::UnknownDescriptorType); + QCOMPARE(target.name(), QString()); + QCOMPARE(target.uuid(), QBluetoothUuid()); + QCOMPARE(target.value(), QByteArray()); + + qsizetype index = 0; + bool valueFound = false; + QList targets; + const QList chars = globalService->characteristics(); + for (const QLowEnergyCharacteristic &ch : chars) { + if (!ch.descriptors().isEmpty()) { + targets = ch.descriptors(); + for (qsizetype i = 0; i < targets.size(); ++i) { + // try to get a descriptor we can read + if (targets[i].type() == QBluetoothUuid::DescriptorType::CharacteristicUserDescription) { + index = i; + valueFound = true; + break; + } + } + break; + } + } + + if (targets.isEmpty()) + QSKIP("No descriptor found despite prior indication."); + + // test assignment operator + target = targets[index]; + QVERIFY(target.isValid()); + QVERIFY(target.type() != QBluetoothUuid::DescriptorType::UnknownDescriptorType); + QVERIFY(!target.name().isEmpty()); + QVERIFY(!target.uuid().isNull()); + QVERIFY(!valueFound || !target.value().isEmpty()); + + QVERIFY(target == targets[index]); + QVERIFY(targets[index] == target); + QVERIFY(!(target != targets[index])); + QVERIFY(!(targets[index] != target)); + + QCOMPARE(target.isValid(), targets[index].isValid()); + QCOMPARE(target.type(), targets[index].type()); + QCOMPARE(target.name(), targets[index].name()); + QCOMPARE(target.uuid(), targets[index].uuid()); + QCOMPARE(target.value(), targets[index].value()); + + // test copy constructor + QLowEnergyDescriptor copyConstructed(target); + QCOMPARE(copyConstructed.isValid(), targets[index].isValid()); + QCOMPARE(copyConstructed.type(), targets[index].type()); + QCOMPARE(copyConstructed.name(), targets[index].name()); + QCOMPARE(copyConstructed.uuid(), targets[index].uuid()); + QCOMPARE(copyConstructed.value(), targets[index].value()); + + QVERIFY(copyConstructed == target); + QVERIFY(target == copyConstructed); + QVERIFY(!(copyConstructed != target)); + QVERIFY(!(target != copyConstructed)); + + // test invalidation + QLowEnergyDescriptor invalid; + target = invalid; + QVERIFY(!target.isValid()); + QCOMPARE(target.value(), QByteArray()); + QVERIFY(target.uuid().isNull()); + QCOMPARE(target.name(), QString()); + QCOMPARE(target.type(), QBluetoothUuid::DescriptorType::UnknownDescriptorType); + + QVERIFY(invalid == target); + QVERIFY(target == invalid); + QVERIFY(!(invalid != target)); + QVERIFY(!(target != invalid)); + + QVERIFY(!(targets[index] == target)); + QVERIFY(!(target == targets[index])); + QVERIFY(targets[index] != target); + QVERIFY(target != targets[index]); + + if (targets.size() >= 2) { + QLowEnergyDescriptor second = targets[(index+1)%2]; + // at least two descriptors + QVERIFY(!(targets[index] == second)); + QVERIFY(!(second == targets[index])); + QVERIFY(targets[index] != second); + QVERIFY(second != targets[index]); + } +} + +QTEST_MAIN(tst_QLowEnergyDescriptor) + +#include "tst_qlowenergydescriptor.moc" + diff --git a/tests/auto/qlowenergyservice/CMakeLists.txt b/tests/auto/qlowenergyservice/CMakeLists.txt new file mode 100644 index 0000000..eba5db0 --- /dev/null +++ b/tests/auto/qlowenergyservice/CMakeLists.txt @@ -0,0 +1,19 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## tst_qlowenergyservice Test: +##################################################################### + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qlowenergyservice LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qlowenergyservice + SOURCES + tst_qlowenergyservice.cpp + LIBRARIES + Qt::Bluetooth +) diff --git a/tests/auto/qlowenergyservice/tst_qlowenergyservice.cpp b/tests/auto/qlowenergyservice/tst_qlowenergyservice.cpp new file mode 100644 index 0000000..670a592 --- /dev/null +++ b/tests/auto/qlowenergyservice/tst_qlowenergyservice.cpp @@ -0,0 +1,48 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include + +#include + + +/* + * This is a very simple test despite the complexity of QLowEnergyService. + * It mostly aims to test the static API behaviors of the class. The connection + * orientated elements are test by the test for QLowEnergyController as it + * is impossible to test the two classes separately from each other. + */ + +class tst_QLowEnergyService : public QObject +{ + Q_OBJECT + +private slots: + void tst_flags(); +}; + +void tst_QLowEnergyService::tst_flags() +{ + QLowEnergyService::ServiceTypes flag1(QLowEnergyService::PrimaryService); + QLowEnergyService::ServiceTypes flag2(QLowEnergyService::IncludedService); + QLowEnergyService::ServiceTypes result; + + // test QFlags &operator|=(QFlags f) + result = flag1 | flag2; + QVERIFY(result.testFlag(QLowEnergyService::PrimaryService)); + QVERIFY(result.testFlag(QLowEnergyService::IncludedService)); + + // test QFlags &operator|=(Enum f) + result = flag1 | QLowEnergyService::IncludedService; + QVERIFY(result.testFlag(QLowEnergyService::PrimaryService)); + QVERIFY(result.testFlag(QLowEnergyService::IncludedService)); + + // test Q_DECLARE_OPERATORS_FOR_FLAGS(QLowEnergyService::ServiceTypes) + result = QLowEnergyService::IncludedService | flag1; + QVERIFY(result.testFlag(QLowEnergyService::PrimaryService)); + QVERIFY(result.testFlag(QLowEnergyService::IncludedService)); +} + +QTEST_MAIN(tst_QLowEnergyService) + +#include "tst_qlowenergyservice.moc" diff --git a/tests/auto/qndeffilter/CMakeLists.txt b/tests/auto/qndeffilter/CMakeLists.txt new file mode 100644 index 0000000..e7fb1e5 --- /dev/null +++ b/tests/auto/qndeffilter/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qndeffilter LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qndeffilter + SOURCES + tst_qndeffilter.cpp + LIBRARIES + Qt::Nfc +) diff --git a/tests/auto/qndeffilter/tst_qndeffilter.cpp b/tests/auto/qndeffilter/tst_qndeffilter.cpp new file mode 100644 index 0000000..90493e4 --- /dev/null +++ b/tests/auto/qndeffilter/tst_qndeffilter.cpp @@ -0,0 +1,485 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include + +#include +#include +#include +#include +#include + +QT_USE_NAMESPACE + +class tst_QNdefFilter : public QObject +{ + Q_OBJECT +private slots: + void construct(); + void copyConstruct(); + void assingmentOperator(); + + void clearFilter(); + + void orderMatch(); + + void appendRecord(); + void appendRecord_data(); + + void appendRecordParameters(); + void appendRecordParameters_data(); + + void appendRecordTemplate(); + void appendRecordTemplate_data(); + + void match(); + void match_data(); +}; + +void tst_QNdefFilter::construct() +{ + QNdefFilter filter; + QCOMPARE(filter.recordCount(), 0); + QCOMPARE(filter.orderMatch(), false); +} + +void tst_QNdefFilter::copyConstruct() +{ + QNdefFilter filter; + filter.setOrderMatch(true); + filter.appendRecord(1, 2); + filter.appendRecord(QNdefRecord::Empty, "", 0, 1); + + QNdefFilter filterCopy(filter); + QCOMPARE(filterCopy.orderMatch(), true); + QCOMPARE(filterCopy.recordCount(), 2); + QNdefFilter::Record rec = filterCopy.recordAt(1); + QCOMPARE(rec.typeNameFormat, QNdefRecord::Empty); + QCOMPARE(rec.type, QByteArray()); + QCOMPARE(rec.minimum, 0U); + QCOMPARE(rec.maximum, 1U); +} + +void tst_QNdefFilter::assingmentOperator() +{ + QNdefFilter filter; + filter.setOrderMatch(true); + filter.appendRecord(1, 2); + filter.appendRecord(QNdefRecord::Empty, "", 0, 1); + + QNdefFilter filterCopy; + filterCopy = filter; + + QCOMPARE(filterCopy.orderMatch(), true); + QCOMPARE(filterCopy.recordCount(), 2); + QNdefFilter::Record rec = filterCopy.recordAt(1); + QCOMPARE(rec.typeNameFormat, QNdefRecord::Empty); + QCOMPARE(rec.type, QByteArray()); + QCOMPARE(rec.minimum, 0U); + QCOMPARE(rec.maximum, 1U); +} + +void tst_QNdefFilter::clearFilter() +{ + QNdefFilter filter; + filter.setOrderMatch(true); + filter.appendRecord(1, 2); + filter.appendRecord(QNdefRecord::Empty, "", 0, 1); + + filter.clear(); + + QCOMPARE(filter.orderMatch(), false); + QCOMPARE(filter.recordCount(), 0); +} + +void tst_QNdefFilter::orderMatch() +{ + QNdefFilter filter; + QCOMPARE(filter.orderMatch(), false); + + filter.setOrderMatch(true); + QCOMPARE(filter.orderMatch(), true); + + filter.setOrderMatch(false); + QCOMPARE(filter.orderMatch(), false); +} + +void tst_QNdefFilter::appendRecord() +{ + QFETCH(QNdefRecord::TypeNameFormat, typeNameFormat); + QFETCH(QByteArray, type); + QFETCH(unsigned int, minimum); + QFETCH(unsigned int, maximum); + QFETCH(bool, result); + + QNdefFilter filter; + + const QNdefFilter::Record record { typeNameFormat, type, minimum, maximum }; + QVERIFY(filter.appendRecord(record) == result); + const int desiredRecordCount = result ? 1 : 0; + QCOMPARE(filter.recordCount(), desiredRecordCount); +} + +void tst_QNdefFilter::appendRecord_data() +{ + QTest::addColumn("typeNameFormat"); + QTest::addColumn("type"); + QTest::addColumn("minimum"); + QTest::addColumn("maximum"); + QTest::addColumn("result"); + + constexpr struct { + const char *type; + QNdefRecord::TypeNameFormat format; + } inputs[] = { + { "Empty", QNdefRecord::Empty }, + { "NfcRtd", QNdefRecord::NfcRtd }, + { "Mime", QNdefRecord::Mime }, + { "Uri", QNdefRecord::Uri}, + { "ExternalRtd", QNdefRecord::ExternalRtd }, + { "Unknown", QNdefRecord::Unknown } + }; + + for (auto [typeC, format] : inputs) { + const auto type = QByteArray::fromRawData(typeC, strlen(typeC)); + QTest::addRow("%s; min < max", typeC) << format << type << 1u << 2u << true; + QTest::addRow("%s; min == max", typeC) << format << type << 2u << 2u << true; + QTest::addRow("%s; min > max", typeC) << format << type << 2u << 1u << false; + } +} + +void tst_QNdefFilter::appendRecordParameters() +{ + QFETCH(QNdefRecord::TypeNameFormat, typeNameFormat); + QFETCH(QByteArray, type); + QFETCH(unsigned int, minimum); + QFETCH(unsigned int, maximum); + QFETCH(bool, result); + + QNdefFilter filter; + + QVERIFY(filter.appendRecord(typeNameFormat, type, minimum, maximum) == result); + const int desiredRecordCount = result ? 1 : 0; + QCOMPARE(filter.recordCount(), desiredRecordCount); +} + +void tst_QNdefFilter::appendRecordParameters_data() +{ + appendRecord_data(); +} + +void tst_QNdefFilter::appendRecordTemplate() +{ + QFETCH(QByteArray, type); + QFETCH(unsigned int, minimum); + QFETCH(unsigned int, maximum); + QFETCH(bool, result); + + QNdefFilter filter; + if (type == QByteArray("SmartPoster")) + QVERIFY(filter.appendRecord(minimum, maximum) == result); + else if (type == QByteArray("Text")) + QVERIFY(filter.appendRecord(minimum, maximum) == result); + else if (type == QByteArray("Uri")) + QVERIFY(filter.appendRecord(minimum, maximum) == result); + + const int desiredRecordCount = result ? 1 : 0; + QCOMPARE(filter.recordCount(), desiredRecordCount); +} + +void tst_QNdefFilter::appendRecordTemplate_data() +{ + QTest::addColumn("type"); + QTest::addColumn("minimum"); + QTest::addColumn("maximum"); + QTest::addColumn("result"); + + const QList types {"SmartPoster", "Text", "Uri"}; + for (const auto &type : types) { + QTest::newRow(type + "; min < max") << type << 1u << 2u << true; + QTest::newRow(type + "; min == max") << type << 2u << 2u << true; + QTest::newRow(type + "; min > max") << type << 2u << 1u << false; + } +} + +void tst_QNdefFilter::match() +{ + QFETCH(QNdefFilter, filter); + QFETCH(QNdefMessage, message); + QFETCH(bool, result); + + QCOMPARE(filter.match(message), result); +} + +void tst_QNdefFilter::match_data() +{ + QTest::addColumn("filter"); + QTest::addColumn("message"); + QTest::addColumn("result"); + + QNdefFilter filter; + filter.appendRecord(1, 2); + filter.appendRecord(QNdefRecord::Mime, "image/png", 1, 1); + filter.appendRecord(QNdefRecord::Empty, "", 0, 100); + + QNdefNfcTextRecord textRec; + textRec.setPayload("text"); + + QNdefRecord mimeRec; + mimeRec.setTypeNameFormat(QNdefRecord::Mime); + mimeRec.setType("image/png"); + mimeRec.setPayload("some image should be here"); + + QNdefRecord emptyRec; + emptyRec.setTypeNameFormat(QNdefRecord::Empty); + + { + QTest::addRow("empty filter, empty message, match") + << QNdefFilter() << QNdefMessage() << true; + + QNdefMessage message; + message.push_back(emptyRec); + + QTest::addRow("empty filter, non-empty message, no match") + << QNdefFilter() << message << false; + + QTest::addRow("non-empty filter, empty message, no match") + << filter << QNdefMessage() << false; + + QNdefFilter f; + f.appendRecord(0, 1); + + QTest::addRow("filter with 0 or 1 rec, empty message, match") + << f << QNdefMessage() << true; + + QNdefMessage uriMsg; + uriMsg.push_back(QNdefNfcUriRecord()); + + QTest::addRow("filter with 0 or 1 rec, one record, match") << f << uriMsg << true; + + uriMsg.push_back(QNdefNfcUriRecord()); + + QTest::addRow("filter with 0 or 1 rec, too many records, no match") << f << uriMsg << false; + } + + { + filter.setOrderMatch(false); + + QNdefMessage message; + message.push_back(textRec); + message.push_back(mimeRec); + + QTest::addRow("No optional records, no ordering, match") << filter << message << true; + + message.push_back(emptyRec); + message.push_back(emptyRec); + + QTest::addRow("Multiple records with optional, no ordering, match") + << filter << message << true; + + filter.setOrderMatch(true); + + QTest::addRow("Multiple records with optional, with ordering, match") + << filter << message << true; + } + + { + filter.setOrderMatch(false); + + QNdefMessage message; + message.push_back(mimeRec); + message.push_back(emptyRec); + message.push_back(textRec); + message.push_back(emptyRec); + message.push_back(textRec); + + QTest::addRow("Random order, no ordering, match") << filter << message << true; + + filter.setOrderMatch(true); + QTest::addRow("Random order, with ordering, no match") << filter << message << false; + } + + { + filter.setOrderMatch(false); + + QNdefRecord rec; + rec.setTypeNameFormat(QNdefRecord::NfcRtd); + rec.setType("image/png"); + rec.setPayload("borken image with invalid format"); + + QNdefMessage message; + message.push_back(textRec); + message.push_back(rec); + + QTest::addRow("TypeNameFormat mismatch, no ordering, no match") + << filter << message << false; + + filter.setOrderMatch(true); + QTest::addRow("TypeNameFormat mismatch, with ordering, no match") + << filter << message << false; + } + + { + filter.setOrderMatch(false); + + QNdefRecord rec; + rec.setTypeNameFormat(QNdefRecord::Mime); + rec.setType("image/jpeg"); + rec.setPayload("Good image with invalid type"); + + QNdefMessage message; + message.push_back(textRec); + message.push_back(rec); + + QTest::addRow("Type mismatch, no ordering, no match") << filter << message << false; + + filter.setOrderMatch(true); + QTest::addRow("Type mismatch, with ordering, no match") << filter << message << false; + } + + { + filter.setOrderMatch(false); + + QNdefMessage message; + message.push_back(QNdefNfcUriRecord()); + message.push_back(textRec); + message.push_back(textRec); + message.push_back(mimeRec); + message.push_back(emptyRec); + message.push_back(emptyRec); + + QTest::addRow("Type not from filter in the beginning, no ordering, no match") + << filter << message << false; + + filter.setOrderMatch(true); + + QTest::addRow("Type not from filter in the beginning, with ordering, no match") + << filter << message << false; + } + + { + filter.setOrderMatch(false); + + QNdefMessage message; + message.push_back(textRec); + message.push_back(textRec); + message.push_back(mimeRec); + message.push_back(emptyRec); + message.push_back(QNdefNfcUriRecord()); + message.push_back(emptyRec); + + QTest::addRow("Type not from filter in the middle, no ordering, no match") + << filter << message << false; + + filter.setOrderMatch(true); + + QTest::addRow("Type not from filter in the middle, with ordering, no match") + << filter << message << false; + } + + { + filter.setOrderMatch(false); + + QNdefMessage message; + message.push_back(textRec); + message.push_back(textRec); + message.push_back(mimeRec); + message.push_back(emptyRec); + message.push_back(emptyRec); + message.push_back(QNdefNfcUriRecord()); + + QTest::addRow("Type not from filter in the end, no ordering, no match") + << filter << message << false; + + filter.setOrderMatch(true); + + QTest::addRow("Type not from filter in the end, with ordering, no match") + << filter << message << false; + } + + QNdefFilter repeatedFilter; + // These 2 consecutive QNdefNfcTextRecord's are the same as + // repeatedFilter.appendRecord(0, 2); + repeatedFilter.appendRecord(0, 1); + repeatedFilter.appendRecord(0, 1); + repeatedFilter.appendRecord(QNdefRecord::Mime, "", 1, 1); + repeatedFilter.appendRecord(1, 1); + + { + repeatedFilter.setOrderMatch(false); + + QNdefMessage message; + message.push_back(textRec); + message.push_back(textRec); + message.push_back(mimeRec); + + QTest::addRow("Filter with repeated type format, no ordering, match") + << repeatedFilter << message << true; + + repeatedFilter.setOrderMatch(true); + + QTest::addRow("Filter with repeated type format, with ordering, no match") + << repeatedFilter << message << false; + } + + { + repeatedFilter.setOrderMatch(false); + + QNdefMessage message; + message.push_back(textRec); + message.push_back(mimeRec); + message.push_back(textRec); + + QTest::addRow("Filter with repeated type format 2, no ordering, match") + << repeatedFilter << message << true; + + repeatedFilter.setOrderMatch(true); + + QTest::addRow("Filter with repeated type format 2, with ordering, match") + << repeatedFilter << message << true; + } + + QNdefFilter repeatedFilter2; + repeatedFilter2.appendRecord(0, 2); + repeatedFilter2.appendRecord(1, 1); + repeatedFilter2.appendRecord(QNdefRecord::Mime, "", 1, 1); + + { + repeatedFilter2.setOrderMatch(false); + + QNdefMessage message; + message.push_back(textRec); + message.push_back(mimeRec); + + QTest::addRow("Filter with repeated type format 3, no ordering, match") + << repeatedFilter2 << message << true; + + repeatedFilter2.setOrderMatch(true); + + QTest::addRow("Filter with repeated type format 3, with ordering, match") + << repeatedFilter2 << message << true; + } + + { + repeatedFilter2.setOrderMatch(false); + + QNdefMessage message; + message.push_back(textRec); + message.push_back(textRec); + message.push_back(textRec); + message.push_back(textRec); + message.push_back(mimeRec); + + QTest::addRow("Filter with repeated type format 4, no ordering, no match") + << repeatedFilter2 << message << false; + + repeatedFilter2.setOrderMatch(true); + + QTest::addRow("Filter with repeated type format 4, with ordering, no match") + << repeatedFilter2 << message << false; + } +} + +QTEST_MAIN(tst_QNdefFilter) + +#include "tst_qndeffilter.moc" diff --git a/tests/auto/qndefmessage/CMakeLists.txt b/tests/auto/qndefmessage/CMakeLists.txt new file mode 100644 index 0000000..6ed6fc2 --- /dev/null +++ b/tests/auto/qndefmessage/CMakeLists.txt @@ -0,0 +1,19 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## tst_qndefmessage Test: +##################################################################### + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qndefmessage LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qndefmessage + SOURCES + tst_qndefmessage.cpp + LIBRARIES + Qt::Nfc +) diff --git a/tests/auto/qndefmessage/tst_qndefmessage.cpp b/tests/auto/qndefmessage/tst_qndefmessage.cpp new file mode 100644 index 0000000..d31f3b6 --- /dev/null +++ b/tests/auto/qndefmessage/tst_qndefmessage.cpp @@ -0,0 +1,739 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include + +#include +#include +#include +#include + +QT_USE_NAMESPACE + +Q_DECLARE_METATYPE(QNdefRecord) + +class tst_QNdefMessage : public QObject +{ + Q_OBJECT + +public: + tst_QNdefMessage(); + ~tst_QNdefMessage(); + +private slots: + void equality(); + void equality_data(); + void parseSingleRecordMessage_data(); + void parseSingleRecordMessage(); + void parseCorruptedMessage(); + void parseCorruptedMessage_data(); + void parseComplexMessage(); +}; + +tst_QNdefMessage::tst_QNdefMessage() +{ +} + +tst_QNdefMessage::~tst_QNdefMessage() +{ +} + +void tst_QNdefMessage::equality() +{ + QFETCH(QNdefMessage, lhs); + QFETCH(QNdefMessage, rhs); + QFETCH(bool, result); + + QCOMPARE(lhs == rhs, result); + QCOMPARE(rhs == lhs, result); +} + +void tst_QNdefMessage::equality_data() +{ + QTest::addColumn("lhs"); + QTest::addColumn("rhs"); + QTest::addColumn("result"); + + QTest::newRow("empty vs empty") << QNdefMessage() << QNdefMessage() << true; + { + QNdefRecord rec; + rec.setTypeNameFormat(QNdefRecord::Empty); + + QNdefMessage message; + message.push_back(rec); + + QTest::newRow("empty vs empty record") << QNdefMessage() << message << true; + } + { + QNdefMessage message; + message.push_back(QNdefNfcTextRecord()); + + QTest::newRow("empty vs non-empty record") << QNdefMessage() << message << false; + } + { + QNdefMessage lhs; + lhs.push_back(QNdefNfcTextRecord()); + + QNdefMessage rhs; + rhs.push_back(QNdefNfcUriRecord()); + + QTest::newRow("different records") << lhs << rhs << false; + } + { + QNdefMessage lhs; + lhs.push_back(QNdefNfcTextRecord()); + lhs.push_back(QNdefNfcUriRecord()); + + QNdefMessage rhs; + rhs.push_back(QNdefNfcUriRecord()); + + QTest::newRow("different amount of records") << lhs << rhs << false; + } + { + QNdefMessage lhs; + lhs.push_back(QNdefNfcTextRecord()); + lhs.push_back(QNdefNfcUriRecord()); + + QNdefMessage rhs; + rhs.push_back(QNdefNfcUriRecord()); + rhs.push_back(QNdefNfcTextRecord()); + + QTest::newRow("same records, different order") << lhs << rhs << false; + } + { + QNdefMessage lhs; + lhs.push_back(QNdefNfcTextRecord()); + lhs.push_back(QNdefNfcUriRecord()); + + QNdefMessage rhs; + rhs.push_back(QNdefNfcTextRecord()); + rhs.push_back(QNdefNfcUriRecord()); + + QTest::newRow("same records, same order") << lhs << rhs << true; + } +} + +void tst_QNdefMessage::parseSingleRecordMessage_data() +{ + QTest::addColumn("data"); + QTest::addColumn("message"); + QTest::addColumn("expectedData"); + + // empty message + { + QByteArray data; + data.append(char(0xc0)); // MB=1, ME=1 + data.append(char(0)); // TYPE LENGTH + data.append(char(0)); // PAYLOAD LENGTH 3 + data.append(char(0)); // PAYLOAD LENGTH 2 + data.append(char(0)); // PAYLOAD LENGTH 1 + data.append(char(0)); // PAYLOAD LENGTH 0 + QTest::newRow("empty") << data << QNdefMessage() << QVariantList(); + + QNdefRecord record; + record.setTypeNameFormat(QNdefRecord::Empty); + QTest::newRow("empty record") << data + << QNdefMessage(record) + << QVariantList(); + } + + // empty short message + { + QByteArray data; + data.append(char(0xd0)); // MB=1, ME=1, SR=1 + data.append(char(0)); // TYPE LENGTH + data.append(char(0)); // PAYLOAD LENGTH + QTest::newRow("empty") << data << QNdefMessage() << QVariantList(); + + QNdefRecord record; + record.setTypeNameFormat(QNdefRecord::Empty); + QTest::newRow("empty record") << data + << QNdefMessage(record) + << QVariantList(); + } + + // unknown message + { + QByteArray type("type"); + QByteArray id("id"); + QByteArray payload("payload"); + + QByteArray data; + data.append(char(0xcd)); // MB=1, ME=1, IL=1, TNF=5 + data.append(char(type.size())); // TYPE LENGTH + data.append(char((payload.size() >> 24) & 0xff)); // PAYLOAD LENGTH 3 + data.append(char((payload.size() >> 16) & 0xff)); // PAYLOAD LENGTH 2 + data.append(char((payload.size() >> 8) & 0xff)); // PAYLOAD LENGTH 1 + data.append(char((payload.size() >> 0) & 0xff)); // PAYLOAD LENGTH 0 + data.append(char(id.size())); // ID LENGTH + data.append(type); + data.append(id); + data.append(payload); + + QNdefRecord record; + record.setTypeNameFormat(QNdefRecord::Unknown); + record.setType(type); + record.setId(id); + record.setPayload(payload); + QList recordList; + recordList.append(record); + QTest::newRow("unknown") << data << QNdefMessage(recordList) << QVariantList(); + } + + // chunked message + { + QByteArray type("type"); + QByteArray id("id"); + QByteArray payload("payload"); + + QByteArray data; + data.append(char(0xbd)); // MB=1, CF=1, SR=1, IL=1, TNF=5 + data.append(char(type.size())); // TYPE LENGTH + data.append(char(1)); // PAYLOAD LENGTH + data.append(char(id.size())); // ID LENGTH + data.append(type); // TYPE + data.append(id); // ID + data.append(payload.at(0)); // PAYLOAD[0] + + for (int i = 1; i < payload.size() - 1; ++i) { + data.append(char(0x36)); // CF=1, SR=1, TNF=6 + data.append(char(0)); // TYPE LENGTH + data.append(char(1)); // PAYLOAD LENGTH + data.append(payload.at(i)); // PAYLOAD[i] + } + + data.append(char(0x56)); // ME=1, SR=1, TNF=6 + data.append(char(0)); // TYPE LENGTH + data.append(char(1)); // PAYLOAD LENGTH + data.append(payload.at(payload.size() - 1)); // PAYLOAD[length - 1] + + QNdefRecord record; + record.setTypeNameFormat(QNdefRecord::Unknown); + record.setType(type); + record.setId(id); + record.setPayload(payload); + QList recordList; + recordList.append(record); + QTest::newRow("chunked") << data << QNdefMessage(recordList) << QVariantList(); + + const QByteArray recordContent = record.type() + record.id() + + record.payload(); + QCOMPARE(recordContent, QByteArray::fromHex(QByteArray("7479706569647061796c6f6164"))); + } + + // NFC-RTD Text + { + QByteArray type("T"); + QByteArray payload; + payload.append(char(0x02)); // UTF-8, 2 byte language code + payload.append("en"); + payload.append("Test String"); + + QByteArray data; + data.append(char(0xc1)); // MB=1, ME=1, IL=0, TNF=1 + data.append(char(type.size())); // TYPE LENGTH + data.append(char((payload.size() >> 24) & 0xff)); // PAYLOAD LENGTH 3 + data.append(char((payload.size() >> 16) & 0xff)); // PAYLOAD LENGTH 2 + data.append(char((payload.size() >> 8) & 0xff)); // PAYLOAD LENGTH 1 + data.append(char((payload.size() >> 0) & 0xff)); // PAYLOAD LENGTH 0 + data.append(type); + data.append(payload); + + QNdefRecord record; + record.setTypeNameFormat(QNdefRecord::NfcRtd); + record.setType("T"); + record.setPayload("\002enTest String"); + QList recordList; + recordList.append(record); + QTest::newRow("nfc-rtd text") << data << QNdefMessage(recordList) + << (QVariantList() << QStringLiteral("Test String") + << QStringLiteral("en")); + + const QByteArray recordContent = record.type() + record.id() + + record.payload(); + QCOMPARE(recordContent, + QByteArray::fromHex(QByteArray("5402656e5465737420537472696e67"))); + } + + // NFC-RTD Text + { + QByteArray type("T"); + QByteArray payload; + payload.append(char(0x02)); // UTF-8, 2 byte language code + payload.append("ja"); + payload.append(QByteArray::fromHex("e38386e382b9e38388e69687e5ad97e58897")); + + QByteArray data; + data.append(char(0xc1)); // MB=1, ME=1, IL=0, TNF=1 + data.append(char(type.size())); // TYPE LENGTH + data.append(char((payload.size() >> 24) & 0xff)); // PAYLOAD LENGTH 3 + data.append(char((payload.size() >> 16) & 0xff)); // PAYLOAD LENGTH 2 + data.append(char((payload.size() >> 8) & 0xff)); // PAYLOAD LENGTH 1 + data.append(char((payload.size() >> 0) & 0xff)); // PAYLOAD LENGTH 0 + data.append(type); + data.append(payload); + + QNdefRecord record; + record.setTypeNameFormat(QNdefRecord::NfcRtd); + record.setType("T"); + record.setPayload("\002ja" + QByteArray::fromHex("e38386e382b9e38388e69687e5ad97e58897")); + QList recordList; + recordList.append(record); + QTest::newRow("nfc-rtd text ja") + << data << QNdefMessage(recordList) + << (QVariantList() << QString::fromUtf8("\343\203\206\343\202\271\343\203\210\346\226" + "\207\345\255\227\345\210\227") + << QStringLiteral("ja")); + + const QByteArray recordContent = record.type() + record.id() + + record.payload(); + QCOMPARE(recordContent, + QByteArray::fromHex(QByteArray("54026a61e38386e382b9e38388e69687e5ad97e58897"))); + } + + // NFC-RTD URI + { + QByteArray type("U"); + QByteArray payload; + payload.append(char(0x00)); + payload.append("http://qt-project.org/"); + + QByteArray data; + data.append(char(0xc1)); + data.append(char(type.size())); + data.append(char((payload.size() >> 24) & 0xff)); // PAYLOAD LENGTH 3 + data.append(char((payload.size() >> 16) & 0xff)); // PAYLOAD LENGTH 2 + data.append(char((payload.size() >> 8) & 0xff)); // PAYLOAD LENGTH 1 + data.append(char((payload.size() >> 0) & 0xff)); // PAYLOAD LENGTH 0 + data.append(type); + data.append(payload); + + QNdefRecord record; + record.setTypeNameFormat(QNdefRecord::NfcRtd); + record.setType("U"); + record.setPayload(QByteArray("\000http://qt-project.org/", 23)); + QList recordList; + recordList.append(record); + QTest::newRow("nfc-rtd uri http://qt-project.org/") + << data << QNdefMessage(recordList) + << (QVariantList() << QUrl(QStringLiteral("http://qt-project.org/"))); + + const QByteArray recordContent = record.type() + record.id() + + record.payload(); + QCOMPARE(recordContent, + QByteArray::fromHex(QByteArray("5500687474703a2f2f71742d70726f6a6563742e6f72672f"))); + } + + // NFC-RTD URI + { + QByteArray type("U"); + QByteArray payload; + payload.append(char(0x03)); + payload.append("qt-project.org/"); + + QByteArray data; + data.append(char(0xc1)); + data.append(char(type.size())); + data.append(char((payload.size() >> 24) & 0xff)); // PAYLOAD LENGTH 3 + data.append(char((payload.size() >> 16) & 0xff)); // PAYLOAD LENGTH 2 + data.append(char((payload.size() >> 8) & 0xff)); // PAYLOAD LENGTH 1 + data.append(char((payload.size() >> 0) & 0xff)); // PAYLOAD LENGTH 0 + data.append(type); + data.append(payload); + + QNdefRecord record; + record.setTypeNameFormat(QNdefRecord::NfcRtd); + record.setType("U"); + record.setPayload(QByteArray("\003qt-project.org/", 16)); + QList recordList; + recordList.append(record); + QTest::newRow("nfc-rtd uri abbrev http://qt-project.org/") + << data << QNdefMessage(recordList) + << (QVariantList() << QUrl(QStringLiteral("http://qt-project.org/"))); + + const QByteArray recordContent = record.type() + record.id() + + record.payload(); + QCOMPARE(recordContent, + QByteArray::fromHex(QByteArray("550371742d70726f6a6563742e6f72672f"))); + } + + // NFC-RTD URI + { + QByteArray type("U"); + QByteArray payload; + payload.append(char(0x05)); + payload.append("+1234567890"); + + QByteArray data; + data.append(char(0xc1)); + data.append(char(type.size())); + data.append(char((payload.size() >> 24) & 0xff)); // PAYLOAD LENGTH 3 + data.append(char((payload.size() >> 16) & 0xff)); // PAYLOAD LENGTH 2 + data.append(char((payload.size() >> 8) & 0xff)); // PAYLOAD LENGTH 1 + data.append(char((payload.size() >> 0) & 0xff)); // PAYLOAD LENGTH 0 + data.append(type); + data.append(payload); + + QNdefRecord record; + record.setTypeNameFormat(QNdefRecord::NfcRtd); + record.setType("U"); + record.setPayload(QByteArray("\005+1234567890", 12)); + QList recordList; + recordList.append(record); + QTest::newRow("nfc-rtd uri tel:+1234567890") + << data << QNdefMessage(recordList) + << (QVariantList() << QUrl(QStringLiteral("tel:+1234567890"))); + + const QByteArray recordContent = record.type() + record.id() + + record.payload(); + QCOMPARE(recordContent, + QByteArray::fromHex(QByteArray("55052b31323334353637383930"))); + } + + // Chunk payload - the NFC-RTD URI split into 3 chunks + { + const QByteArray type("U"); + const QByteArray id("test"); + QByteArray payload1; + payload1.append(char(0x05)); + payload1.append("+123"); + + const QByteArray payload2("456"); + const QByteArray payload3("7890"); + + QByteArray data; + data.append(char(0xB9)); // MB=1, ME=0, CF=1, SR=1, IL=1, TNF=1 (NFC-RTD) + data.append(type.size()); + data.append(payload1.size() & 0xff); // length fits into 1 byte + data.append(id.size()); + data.append(type); + data.append(id); + data.append(payload1); + data.append(char(0x36)); // MB=0, ME=0, CF=1, SR=1, IL=0, TNF=6 (Unchanged) + data.append(char(0x00)); + data.append(payload2.size()); + data.append(payload2); + data.append(char(0x56)); // MB=0, ME=1, CF=0, SR=1, IL=0, TNF=6 (Unchanged) + data.append(char(0x00)); + data.append(payload3.size()); + data.append(payload3); + + QNdefRecord record; + record.setTypeNameFormat(QNdefRecord::NfcRtd); + record.setType(type); + record.setId(id); + record.setPayload(QByteArray("\005+1234567890", 12)); + QList recordList; + recordList.append(record); + QTest::newRow("chunk payloads nfc-rtd uri tel:+1234567890") + << data << QNdefMessage(recordList) + << (QVariantList() << QUrl(QStringLiteral("tel:+1234567890"))); + } + + // Truncated message + { + QByteArray type("U"); + QByteArray id("Test ID"); + QByteArray payload; + payload.append(char(0x00)); + payload.append("http://qt-project.org/"); + QByteArray data; + data.append(char(0xc9)); // MB=1, ME=1, IL=1 + + QTest::newRow("truncated 1") << data << QNdefMessage() << QVariantList(); + + data.append(char(type.size())); // TYPE LENGTH + QTest::newRow("truncated 2") << data << QNdefMessage() << QVariantList(); + + data.append(char((payload.size() >> 24) & 0xff)); // PAYLOAD LENGTH 3 + QTest::newRow("truncated 3") << data << QNdefMessage() << QVariantList(); + + data.append(char((payload.size() >> 16) & 0xff)); // PAYLOAD LENGTH 2 + QTest::newRow("truncated 4") << data << QNdefMessage() << QVariantList(); + + data.append(char((payload.size() >> 8) & 0xff)); // PAYLOAD LENGTH 1 + QTest::newRow("truncated 5") << data << QNdefMessage() << QVariantList(); + + data.append(char((payload.size() >> 0) & 0xff)); // PAYLOAD LENGTH 0 + QTest::newRow("truncated 6") << data << QNdefMessage() << QVariantList(); + + data.append(char(id.size())); // ID LENGTH + QTest::newRow("truncated 7") << data << QNdefMessage() << QVariantList(); + + data.append(type); + QTest::newRow("truncated 8") << data << QNdefMessage() << QVariantList(); + + data.append(id); + QTest::newRow("truncated 9") << data << QNdefMessage() << QVariantList(); + + payload.chop(1); + data.append(payload); + QTest::newRow("truncated 10") << data << QNdefMessage() << QVariantList(); + } +} + +void tst_QNdefMessage::parseSingleRecordMessage() +{ + QFETCH(QByteArray, data); + QFETCH(QNdefMessage, message); + QFETCH(QVariantList, expectedData); + + if (QByteArray(QTest::currentDataTag()).startsWith("truncated ")) + QTest::ignoreMessage(QtWarningMsg, "Unexpected end of message"); + + QNdefMessage parsedMessage = QNdefMessage::fromByteArray(data); + + QVERIFY(parsedMessage == message); + QVERIFY(message == parsedMessage); + + QNdefMessage reparsedMessage = QNdefMessage::fromByteArray(message.toByteArray()); + + QVERIFY(message == reparsedMessage); + QVERIFY(reparsedMessage == message); + + for (qsizetype i = 0; i < message.size(); ++i) { + const QNdefRecord &record = message.at(i); + const QNdefRecord &parsedRecord = parsedMessage.at(i); + + QCOMPARE(record.typeNameFormat(), parsedRecord.typeNameFormat()); + QCOMPARE(record.type(), parsedRecord.type()); + QCOMPARE(record.id(), parsedRecord.id()); + QCOMPARE(record.payload(), parsedRecord.payload()); + QCOMPARE(record.isEmpty(), parsedRecord.isEmpty()); + + if (record.isRecordType()) { + QNdefNfcTextRecord textRecord(record); + QNdefNfcTextRecord parsedTextRecord(parsedRecord); + + QCOMPARE(textRecord.text(), parsedTextRecord.text()); + QCOMPARE(textRecord.locale(), parsedTextRecord.locale()); + + if (expectedData.size() == 2) { + QCOMPARE(parsedTextRecord.text(), expectedData.at(0).toString()); + QCOMPARE(parsedTextRecord.locale(), expectedData.at(1).toString()); + } + } else if (record.isRecordType()) { + QNdefNfcUriRecord uriRecord(record); + QNdefNfcUriRecord parsedUriRecord(parsedRecord); + + QCOMPARE(uriRecord.uri(), parsedUriRecord.uri()); + + if (expectedData.size() == 1) + QCOMPARE(parsedUriRecord.uri(), expectedData.at(0).toUrl()); + } else if (record.isRecordType()) { + QVERIFY(record.isEmpty()); + } + } +} + +void tst_QNdefMessage::parseCorruptedMessage() +{ + // This test is needed to check that all the potential errors in the + // input data are handled correctly. + + QFETCH(QByteArray, data); + QFETCH(QByteArray, warningMessage); + + if (!warningMessage.isEmpty()) + QTest::ignoreMessage(QtWarningMsg, warningMessage.constData()); + + QNdefMessage parsedMessage = QNdefMessage::fromByteArray(data); + // corrupted data always results in an empty message + QVERIFY(parsedMessage.isEmpty()); +} + +void tst_QNdefMessage::parseCorruptedMessage_data() +{ + QTest::addColumn("data"); + QTest::addColumn("warningMessage"); + + { + QByteArray data; + data.append(char(0x50)); // MB=0, ME=1, SR=1 + data.append(char(0)); // TYPE LENGTH + data.append(char(0)); // PAYLOAD LENGTH + + const QByteArray warningMsg = "Haven't got message begin yet"; + + QTest::newRow("No message begin") << data << warningMsg; + } + { + QByteArray data; + data.append(char(0x90)); // MB=1, ME=0, SR=1 + data.append(char(0)); // TYPE LENGTH + data.append(char(0)); // PAYLOAD LENGTH + + const QByteArray warningMsg = "Malformed NDEF Message, missing begin or end"; + + QTest::newRow("No message end") << data << warningMsg; + } + { + QByteArray data; + data.append(char(0x90)); // MB=1, ME=0, SR=1 + data.append(char(0)); // TYPE LENGTH + data.append(char(0)); // PAYLOAD LENGTH + data.append(char(0xd0)); // MB=1, ME=1, SR=1 + data.append(char(0)); // TYPE LENGTH + data.append(char(0)); // PAYLOAD LENGTH + + const QByteArray warningMsg = "Got message begin but already parsed some records"; + + QTest::newRow("Multiple message begin") << data << warningMsg; + } + { + QByteArray data; + data.append(char(0xB1)); // MB=1, ME=0, CF=1, SR=1, IL=0, TNF=1 (NFC-RTD) + data.append(char(0x01)); // type length + data.append(char(0x01)); // payload length + data.append('U'); // type + data.append('a'); // payload + data.append(char(0x76)); // MB=0, ME=1 (incorrect), CF=1, SR=1, IL=0, TNF=6 (Unchanged) + data.append(char(0x00)); // type length + data.append(char(0x01)); // payload length + data.append('b'); // payload + data.append(char(0x56)); // MB=0, ME=1, CF=0, SR=1, IL=0, TNF=6 (Unchanged) + data.append(char(0x00)); // type length + data.append(char(0x01)); // payload length + data.append('c'); // payload + + const QByteArray warningMsg = "Got message end but already parsed final record"; + + QTest::newRow("Multiple message end") << data << warningMsg; + } + { + QByteArray data; + data.append(char(0xB1)); // MB=1, ME=0, CF=1, SR=1, IL=0, TNF=1 (NFC-RTD) + data.append(char(0x01)); // type length + data.append(char(0x01)); // payload length + data.append('U'); // type + data.append('a'); // payload + data.append(char(0x36)); // MB=0, ME=0, CF=1, SR=1, IL=0, TNF=6 (Unchanged) + data.append(char(0x00)); // type length + data.append(char(0x01)); // payload length + data.append('b'); // payload + data.append(char(0x51)); // MB=0, ME=1, CF=0, SR=1, IL=0, TNF=1 (NFC-RTD - incorrect) + data.append(char(0x00)); // type length + data.append(char(0x01)); // payload length + data.append('c'); // payload + + const QByteArray warningMsg = "Partial chunk not empty, but TNF not 0x06 as expected"; + + QTest::newRow("Incorrect TNF in chunk") << data << warningMsg; + } + { + QByteArray data; + data.append(char(0xB1)); // MB=1, ME=0, CF=1, SR=1, IL=0, TNF=1 (NFC-RTD) + data.append(char(0x01)); // type length + data.append(char(0x01)); // payload length + data.append('U'); // type + data.append('a'); // payload + data.append(char(0x36)); // MB=0, ME=0, CF=1, SR=1, IL=0, TNF=6 (Unchanged) + data.append(char(0x01)); // type length (incorrect) + data.append(char(0x01)); // payload length + data.append('U'); // type (incorrect) + data.append('b'); // payload + data.append(char(0x56)); // MB=0, ME=1, CF=0, SR=1, IL=0, TNF=6 (Unchanged) + data.append(char(0x00)); // type length + data.append(char(0x01)); // payload length + data.append('c'); // payload + + const QByteArray warningMsg = "Invalid chunked data, TYPE_LENGTH != 0"; + + QTest::newRow("Incorrect TYPE_LENGTH in chunk") << data << warningMsg; + } + { + QByteArray data; + data.append(char(0xB1)); // MB=1, ME=0, CF=1, SR=1, IL=0, TNF=1 (NFC-RTD) + data.append(char(0x01)); // type length + data.append(char(0x01)); // payload length + data.append('U'); // type + data.append('a'); // payload + data.append(char(0x3E)); // MB=0, ME=0, CF=1, SR=1, IL=1 (incorrect), TNF=6 (Unchanged) + data.append(char(0x00)); // type length + data.append(char(0x01)); // payload length + data.append(char(0x01)); // id length (incorrect) + data.append('i'); // id (incorrect) + data.append('b'); // payload + data.append(char(0x56)); // MB=0, ME=1, CF=0, SR=1, IL=0, TNF=6 (Unchanged) + data.append(char(0x00)); // type length + data.append(char(0x01)); // payload length + data.append('c'); // payload + + const QByteArray warningMsg = "Invalid chunked data, IL != 0"; + + QTest::newRow("Incorrect IL in chunk") << data << warningMsg; + } + { + QByteArray data; + data.append(char(0xC8)); // MB=1, ME=1, CF=0, SR=0, IL=1, TNF=0 + data.append(char(0)); // type legnth + data.append(char(0)); // payload length (incorrect, 4 bytes expected) + + const QByteArray warningMsg = "Unexpected end of message"; + + QTest::newRow("Invalid header length") << data << warningMsg; + } + { + QByteArray data; + data.append(char(0xC1)); // MB=1, ME=1, CF=0, SR=0, IL=0, TNF=1 + data.append(char(0x01)); // type legnth + data.append(char(0xFF)); // payload length 3 + data.append(char(0xFF)); // payload length 2 + data.append(char(0xFF)); // payload length 1 + data.append(char(0xFF)); // payload length 0 + data.append('U'); // type + data.append('a'); // payload + + // In case of 32 bit the code path will be different from 64 bit, so + // the warning message is also different. + const QByteArray warningMsg = (sizeof(qsizetype) <= sizeof(quint32)) + ? "Payload can't fit into QByteArray" + : "Unexpected end of message"; + + QTest::newRow("Max payload length") << data << warningMsg; + } +} + +void tst_QNdefMessage::parseComplexMessage() +{ + const QByteArray reference("1234567890"); + QNdefMessage message; + QNdefRecord first; + QVERIFY(first.isEmpty()); + first.setTypeNameFormat(QNdefRecord::Uri); + QVERIFY(first.isEmpty()); + first.setPayload(reference); + QCOMPARE(first.payload(), reference); + QVERIFY(!first.isEmpty()); + QCOMPARE(first.typeNameFormat(), QNdefRecord::Uri); + + message.append(first); + + QNdefRecord second; + + QCOMPARE(second.payload(), QByteArray()); + QVERIFY(second.isEmpty()); + QCOMPARE(second.typeNameFormat(), QNdefRecord::Empty); + + message.append(second); + + QByteArray result = message.toByteArray(); + QNdefMessage messageCopy = QNdefMessage::fromByteArray(result); + QCOMPARE(messageCopy.size(), 2); + + first = messageCopy.at(0); + second = messageCopy.at(1); + + QCOMPARE(first.payload(), reference); + QVERIFY(!first.isEmpty()); + QCOMPARE(first.typeNameFormat(), QNdefRecord::Uri); + QCOMPARE(second.payload(), QByteArray()); + QVERIFY(second.isEmpty()); + QCOMPARE(second.typeNameFormat(), QNdefRecord::Empty); + +} + +QTEST_MAIN(tst_QNdefMessage) + +#include "tst_qndefmessage.moc" + diff --git a/tests/auto/qndefnfcsmartposterrecord/CMakeLists.txt b/tests/auto/qndefnfcsmartposterrecord/CMakeLists.txt new file mode 100644 index 0000000..6776fa3 --- /dev/null +++ b/tests/auto/qndefnfcsmartposterrecord/CMakeLists.txt @@ -0,0 +1,19 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## tst_qndefnfcsmartposterrecord Test: +##################################################################### + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qndefnfcsmartposterrecord LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qndefnfcsmartposterrecord + SOURCES + tst_qndefnfcsmartposterrecord.cpp + LIBRARIES + Qt::Nfc +) diff --git a/tests/auto/qndefnfcsmartposterrecord/tst_qndefnfcsmartposterrecord.cpp b/tests/auto/qndefnfcsmartposterrecord/tst_qndefnfcsmartposterrecord.cpp new file mode 100644 index 0000000..c5c5d88 --- /dev/null +++ b/tests/auto/qndefnfcsmartposterrecord/tst_qndefnfcsmartposterrecord.cpp @@ -0,0 +1,543 @@ +// Copyright (C) 2016 Research In Motion +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include + +#include +#include +#include +#include +#include + +QT_USE_NAMESPACE + +static const quint8 payload[] = { + 0xC1, 0x02, 0x00, 0x00, 0x03, 0x0D, 0x53, 0x70, 0x91, 0x01, 0x08, 0x55, 0x01, 0x72, 0x69, 0x6D, 0x2E, 0x63, 0x6F, 0x6D, + 0x11, 0x01, 0x0D, 0x54, 0x02, 0x65, 0x6E, 0x49, 0x63, 0x6F, 0x6E, 0x20, 0x54, 0x69, 0x74, 0x6C, 0x65, 0x11, 0x01, 0x09, + 0x74, 0x74, 0x65, 0x78, 0x74, 0x2F, 0x68, 0x74, 0x6D, 0x6C, 0x11, 0x01, 0x04, 0x73, 0x00, 0x00, 0x04, 0x00, 0x11, 0x03, + 0x01, 0x61, 0x63, 0x74, 0x01, 0x42, 0x09, 0x00, 0x00, 0x02, 0xC5, 0x69, 0x6D, 0x61, 0x67, 0x65, 0x2F, 0x70, 0x6E, 0x67, + 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x1E, + 0x00, 0x00, 0x00, 0x1E, 0x08, 0x02, 0x00, 0x00, 0x00, 0xB4, 0x52, 0x39, 0xF5, 0x00, 0x00, 0x02, 0x8C, 0x49, 0x44, 0x41, + 0x54, 0x78, 0x9C, 0x62, 0x60, 0x68, 0x60, 0xA0, 0x11, 0x02, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xA2, 0x99, 0xB9, 0x0D, 0x0C, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xA2, 0xA1, 0xD1, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xA2, 0xA1, 0xD1, 0x00, 0x00, + 0x00, 0x00, 0xFF, 0xFF, 0xA2, 0xA1, 0xD1, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x62, 0x60, 0x60, 0xE8, 0xA6, 0x11, 0x02, + 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xA2, 0xA1, 0xD1, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xA2, 0xA1, 0xD1, 0x00, 0x00, 0x00, + 0x00, 0xFF, 0xFF, 0xA2, 0xA1, 0xD1, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x82, 0x1A, 0x1D, 0x1B, 0xBB, 0x75, 0xE6, 0xCC, + 0x8B, 0x10, 0x34, 0x7F, 0xFE, 0xE5, 0xF2, 0xF2, 0x83, 0x82, 0x82, 0x93, 0x81, 0xE2, 0xF9, 0xF9, 0x7B, 0x81, 0x22, 0x1D, + 0x1D, 0x27, 0xE1, 0x1A, 0x3A, 0x3B, 0x4F, 0x02, 0x45, 0x94, 0x94, 0x66, 0x41, 0xB8, 0x69, 0x69, 0x3B, 0xF7, 0xEF, 0x7F, + 0x74, 0xF7, 0xEE, 0x87, 0xD5, 0xAB, 0x6F, 0x1A, 0x1B, 0x2F, 0x42, 0x36, 0x1A, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x82, 0x1A, + 0x0D, 0x34, 0xEE, 0x3F, 0x06, 0x00, 0x2A, 0x05, 0x6A, 0x83, 0xB3, 0x21, 0x2A, 0xDF, 0xBF, 0xFF, 0x01, 0xE4, 0xBA, 0xB8, + 0xAC, 0x02, 0xB2, 0xD7, 0xAF, 0xBF, 0x8D, 0xA9, 0x05, 0x6E, 0x34, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC2, 0x67, 0x34, 0xD0, + 0x2D, 0x70, 0xA3, 0xE1, 0x0E, 0x87, 0x1B, 0x1D, 0x1A, 0xBA, 0x09, 0xAE, 0xF2, 0xDD, 0xBB, 0xEF, 0x10, 0x06, 0xC4, 0x4A, + 0x08, 0x02, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x42, 0x31, 0x1A, 0xA8, 0x02, 0xE8, 0x53, 0x7B, 0xFB, 0x15, 0x67, 0xCE, 0xBC, + 0x80, 0x28, 0x85, 0x33, 0x80, 0xD6, 0xA0, 0x19, 0x0D, 0x91, 0x82, 0x68, 0x01, 0x8A, 0x4B, 0x4B, 0x4F, 0x5F, 0xB5, 0xEA, + 0x06, 0xB2, 0xD1, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x42, 0x37, 0x1A, 0xC2, 0x05, 0xAA, 0x80, 0x98, 0x78, 0xE5, 0xCA, + 0x1B, 0xB8, 0xD3, 0x20, 0x46, 0x40, 0x8C, 0x8E, 0x8E, 0xDE, 0x02, 0x11, 0x04, 0xBA, 0x1D, 0x57, 0x34, 0x02, 0x00, 0x00, + 0x00, 0xFF, 0xFF, 0xC2, 0x6E, 0x34, 0x30, 0xC8, 0x90, 0x8D, 0xBE, 0x7F, 0xFF, 0x03, 0x3C, 0x4C, 0x20, 0x46, 0xD7, 0xD5, + 0x1D, 0x81, 0x28, 0xC0, 0x93, 0x42, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC2, 0x6E, 0x34, 0xD0, 0x14, 0x88, 0xCE, 0x0B, + 0x17, 0x5E, 0x01, 0xC9, 0xFE, 0xFE, 0x33, 0xF0, 0x30, 0x81, 0x18, 0xDD, 0xD5, 0x75, 0x0A, 0x59, 0x3D, 0x30, 0x39, 0x41, + 0x10, 0xB2, 0xD1, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x42, 0x8F, 0x46, 0x60, 0x08, 0x42, 0xDC, 0x08, 0x01, 0x90, 0x68, + 0xAC, 0xAF, 0x3F, 0xBA, 0x7B, 0xF7, 0x03, 0x48, 0x98, 0x40, 0x8C, 0x9E, 0x3A, 0xF5, 0x3C, 0x72, 0x04, 0xC0, 0xA3, 0x04, + 0x98, 0x2E, 0xE1, 0x46, 0x03, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC2, 0x97, 0x42, 0x80, 0x6E, 0x87, 0x18, 0x0D, 0x4C, 0xE6, + 0xC0, 0xF4, 0x0B, 0x61, 0x10, 0x6F, 0x34, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC2, 0x62, 0x34, 0x50, 0x33, 0x50, 0x0F, 0xD0, + 0x2C, 0xA0, 0x38, 0xDC, 0x68, 0xA0, 0x67, 0x21, 0x7E, 0x42, 0x0E, 0x10, 0x78, 0x58, 0x03, 0x23, 0x13, 0xA2, 0x12, 0xD9, + 0x68, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC2, 0x1E, 0xD6, 0x70, 0x04, 0x37, 0x1A, 0xCE, 0x86, 0x80, 0xB4, 0xB4, 0x5D, + 0xC8, 0xC9, 0x06, 0x88, 0x80, 0x81, 0x86, 0x66, 0x34, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x22, 0xC1, 0x68, 0x60, 0xA6, 0x87, + 0x1B, 0x0D, 0x4C, 0x9D, 0x90, 0x6C, 0x02, 0x4C, 0xCB, 0xB8, 0x8C, 0x06, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x22, 0xC1, 0x68, + 0x79, 0xF9, 0x99, 0xC8, 0x46, 0xC3, 0x53, 0x11, 0x30, 0xBB, 0x03, 0x15, 0x9C, 0x3F, 0xFF, 0x12, 0xCD, 0x68, 0x00, 0x00, + 0x00, 0x00, 0xFF, 0xFF, 0x22, 0xC1, 0x68, 0xE4, 0xE8, 0x02, 0x1A, 0x0D, 0x0C, 0x7D, 0x48, 0xB8, 0x23, 0x03, 0x64, 0xA3, + 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x22, 0xCD, 0x68, 0x20, 0x03, 0x6E, 0x34, 0x90, 0x0B, 0x2C, 0x12, 0x80, 0x11, 0x0E, + 0x37, 0x17, 0x18, 0x38, 0xC8, 0x49, 0x1B, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xA2, 0x42, 0x79, 0x0D, 0xCC, 0xBA, 0x40, 0x84, + 0x91, 0x5F, 0xBA, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xA2, 0x61, 0xB5, 0x0B, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xA2, 0xA1, + 0xD1, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xA2, 0xA1, 0xD1, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xA2, 0xA1, 0xD1, 0x00, + 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xA3, 0xA1, 0xD1, 0x00, 0x27, 0x58, 0x04, 0x5A, 0x28, 0x87, 0x48, 0xD1, 0x00, 0x00, 0x00, + 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82 +}; + +class tst_QNdefNfcSmartPosterRecord : public QObject +{ + Q_OBJECT + +public: + tst_QNdefNfcSmartPosterRecord(); + ~tst_QNdefNfcSmartPosterRecord(); + +private: + QNdefNfcTextRecord getTextRecord(const QString& locale); + QString getTitle(const QString& locale); + void checkLocale(const QNdefNfcSmartPosterRecord& record, const QStringList& localeList); + + QMap _textRecords; + +private slots: + void tst_emptyRecord(); + void tst_titles(); + void tst_uri(); + void tst_action(); + void tst_icon(); + void tst_size(); + void tst_typeInfo(); + void tst_construct(); + void tst_downcast(); +}; + +tst_QNdefNfcSmartPosterRecord::tst_QNdefNfcSmartPosterRecord() +{ + _textRecords["en"] = "test"; + _textRecords["fr"] = "essai"; + _textRecords["es"] = "prueba"; + _textRecords["de"] = "pruefung"; + _textRecords["nl"] = "proef"; + _textRecords["en-US"] = "trial"; +} + +tst_QNdefNfcSmartPosterRecord::~tst_QNdefNfcSmartPosterRecord() +{ +} + +QNdefNfcTextRecord tst_QNdefNfcSmartPosterRecord::getTextRecord(const QString& locale) +{ + QNdefNfcTextRecord record; + record.setLocale(locale); + record.setEncoding(QNdefNfcTextRecord::Utf8); + record.setText(_textRecords[locale]); + return record; +} + +QString tst_QNdefNfcSmartPosterRecord::getTitle(const QString& locale) +{ + return _textRecords[locale]; +} + +void tst_QNdefNfcSmartPosterRecord::checkLocale(const QNdefNfcSmartPosterRecord& record, const QStringList& localeList) +{ + for (auto it = _textRecords.cbegin(), end = _textRecords.cend(); it != end; ++it) { + const QString &locale = it.key(); + if (localeList.contains(locale)) + QVERIFY(record.hasTitle(locale)); + else + QVERIFY(!record.hasTitle(locale)); + } + + if (localeList.empty()) { + QVERIFY(record.hasTitle()); + } +} + +void tst_QNdefNfcSmartPosterRecord::tst_emptyRecord() +{ + QNdefNfcSmartPosterRecord record; + + QCOMPARE(record.typeNameFormat(), QNdefRecord::NfcRtd); + QCOMPARE(record.type(), QByteArray("Sp")); + QVERIFY(record.id().isEmpty()); + QVERIFY(record.payload().isEmpty()); + + QVERIFY(!record.hasTitle()); + QVERIFY(!record.hasAction()); + QVERIFY(!record.hasIcon()); + QVERIFY(!record.hasSize()); + QVERIFY(!record.hasTypeInfo()); + + QCOMPARE(record.titleCount(), 0); + QCOMPARE(record.titleRecord(0), QNdefNfcTextRecord()); + QCOMPARE(record.title(), QString()); + + QList emptyTitleList; + QCOMPARE(record.titleRecords(), emptyTitleList); + + QCOMPARE(record.uri(), QUrl()); + QCOMPARE(record.uriRecord(), QNdefNfcUriRecord()); + QCOMPARE(record.action(), QNdefNfcSmartPosterRecord::UnspecifiedAction); + QCOMPARE(record.iconCount(), 0); + QCOMPARE(record.iconRecord(0), QNdefNfcIconRecord()); + QCOMPARE(record.icon(), QByteArray()); + + QList emptyIconList; + QCOMPARE(record.iconRecords(), emptyIconList); + + quint32 size = 0; + QCOMPARE(record.size(), size); + QCOMPARE(record.typeInfo(), QString()); + + QVERIFY(record.isRecordType()); + QVERIFY(!record.isRecordType()); + QVERIFY(!record.isRecordType()); + + QCOMPARE(record, QNdefNfcSmartPosterRecord()); + QVERIFY(!(record != QNdefNfcSmartPosterRecord())); +} + +void tst_QNdefNfcSmartPosterRecord::tst_titles() +{ + QNdefNfcSmartPosterRecord record; + + // Set "en" locale + QNdefNfcTextRecord enRecord = getTextRecord("en"); + QVERIFY(record.addTitle(enRecord)); + + QCOMPARE(record.titleCount(), 1); + { + QStringList locales; + locales << "en"; + checkLocale(record, locales); + } + + // Get "en" locale + QCOMPARE(record.titleRecord(0), enRecord); + QCOMPARE(record.title(), getTitle("en")); + QCOMPARE(record.title("fr"), QString()); + + QList titleRecords = record.titleRecords(); + QCOMPARE(titleRecords.size(), 1); + QCOMPARE(titleRecords[0], enRecord); + + QVERIFY(!record.addTitle(enRecord)); + QCOMPARE(record.titleCount(), 1); + + // Add "de" locale + QNdefNfcTextRecord deRecord = getTextRecord("de"); + QVERIFY(record.addTitle(deRecord)); + + QCOMPARE(record.titleCount(), 2); + QCOMPARE(record.titleRecord(1), deRecord); + { + QStringList locales; + locales << "en" << "de"; + checkLocale(record, locales); + } + + // Add "fr" locale + QNdefNfcTextRecord frRecord = getTextRecord("fr"); + QVERIFY(record.addTitle(frRecord)); + + QCOMPARE(record.titleCount(), 3); + QCOMPARE(record.titleRecord(2), frRecord); + { + QStringList locales; + locales << "en" << "de" << "fr"; + checkLocale(record, locales); + } + + QVERIFY(record.removeTitle(frRecord)); + + QCOMPARE(record.titleCount(), 2); + { + QStringList locales; + locales << "en" << "de"; + checkLocale(record, locales); + } + + QVERIFY(!record.removeTitle(frRecord)); + QCOMPARE(record.titleCount(), 2); + + QVERIFY(record.removeTitle("en")); + QCOMPARE(record.titleCount(), 1); + { + QStringList locales; + locales << "de"; + checkLocale(record, locales); + } + + titleRecords = record.titleRecords(); + QCOMPARE(titleRecords.size(), 1); + QCOMPARE(titleRecords[0], deRecord); + + QCOMPARE(record.title(), getTitle("de")); + + QVERIFY(record.removeTitle(deRecord)); + QCOMPARE(record.titleCount(), 0); + + // Test setTitles + QNdefNfcTextRecord nlRecord = getTextRecord("nl"); + QNdefNfcTextRecord esRecord = getTextRecord("es"); + + QVERIFY(record.addTitle(enRecord)); + QVERIFY(record.addTitle(deRecord)); + QVERIFY(record.addTitle(frRecord)); + QCOMPARE(record.titleCount(), 3); + + QList titles; + titles << nlRecord << esRecord; + record.setTitles(titles); + + QCOMPARE(record.titleCount(), 2); + QCOMPARE(record.title("en"), QString()); + QCOMPARE(record.title("de"), QString()); + QCOMPARE(record.title("fr"), QString()); + + QCOMPARE(record.title("nl"), getTitle("nl")); + QCOMPARE(record.title("es"), getTitle("es")); +} + +void tst_QNdefNfcSmartPosterRecord::tst_uri() +{ + QNdefNfcSmartPosterRecord record; + QString qtString = "http://www.qt-project.org"; + QString bbString = "http://www.blackberry.com"; + + QCOMPARE(record.uri(), QUrl()); + QCOMPARE(record.uriRecord(), QNdefNfcUriRecord()); + + QUrl qtUrl(qtString); + record.setUri(qtUrl); + QCOMPARE(record.uri(), qtUrl); + + QNdefNfcUriRecord qtRecord; + qtRecord.setUri(qtString); + QCOMPARE(record.uriRecord(), qtRecord); + + QNdefNfcUriRecord bbRecord; + bbRecord.setUri(bbString); + record.setUri(bbRecord); + QCOMPARE(record.uri(), QUrl(bbString)); + QCOMPARE(record.uriRecord(), bbRecord); +} + +void tst_QNdefNfcSmartPosterRecord::tst_action() +{ + QNdefNfcSmartPosterRecord record; + QVERIFY(!record.hasAction()); + + record.setAction(QNdefNfcSmartPosterRecord::DoAction); + QVERIFY(record.hasAction()); + QCOMPARE(record.action(), QNdefNfcSmartPosterRecord::DoAction); + + record.setAction(QNdefNfcSmartPosterRecord::SaveAction); + QVERIFY(record.hasAction()); + QCOMPARE(record.action(), QNdefNfcSmartPosterRecord::SaveAction); + + record.setAction(QNdefNfcSmartPosterRecord::EditAction); + QVERIFY(record.hasAction()); + QCOMPARE(record.action(), QNdefNfcSmartPosterRecord::EditAction); + + record.setAction(QNdefNfcSmartPosterRecord::UnspecifiedAction); + QVERIFY(record.hasAction()); + QCOMPARE(record.action(), QNdefNfcSmartPosterRecord::UnspecifiedAction); +} + +void tst_QNdefNfcSmartPosterRecord::tst_icon() +{ + QNdefNfcSmartPosterRecord record; + QVERIFY(!record.hasIcon()); + + QNdefNfcIconRecord icon; + record.addIcon(icon); + QVERIFY(record.hasIcon()); + QCOMPARE(record.iconCount(), 1); + QCOMPARE(record.iconRecord(0), icon); + QCOMPARE(record.icon(), QByteArray()); + + QList iconRecords = record.iconRecords(); + QCOMPARE(iconRecords.size(), 1); + QCOMPARE(iconRecords[0], icon); + + QVERIFY(record.removeIcon(QByteArray())); + QVERIFY(!record.hasIcon()); + QCOMPARE(record.iconCount(), 0); + + QByteArray mimeType = "test/data"; + record.addIcon(mimeType, "icondata"); + QVERIFY(record.hasIcon()); + QVERIFY(record.hasIcon(mimeType)); + QVERIFY(!record.hasIcon(QByteArray("mime"))); + + QCOMPARE(record.iconCount(), 1); + QCOMPARE(record.icon(), QByteArray("icondata")); + QCOMPARE(record.icon(mimeType), QByteArray("icondata")); + // invalid type => empty data + QCOMPARE(record.icon(QByteArray("mime")), QByteArray()); + + QNdefNfcIconRecord icon2; + icon2.setData("iconrecorddata"); + icon2.setType("test/icon"); + record.addIcon(icon2); + QVERIFY(record.hasIcon(QByteArray("test/icon"))); + + QCOMPARE(record.iconCount(), 2); + QCOMPARE(record.icon("test/icon"), QByteArray("iconrecorddata")); + + iconRecords = record.iconRecords(); + QCOMPARE(iconRecords.size(), 2); + + QNdefNfcIconRecord icon3; + icon3.setData("icondata"); + icon3.setType("test/data"); + + QCOMPARE(iconRecords[0], icon3); + QCOMPARE(iconRecords[1], icon2); + + QVERIFY(record.removeIcon(mimeType)); + QVERIFY(!record.removeIcon(QByteArray("mime"))); + QCOMPARE(record.iconCount(), 1); + iconRecords = record.iconRecords(); + QCOMPARE(iconRecords.size(), 1); + QCOMPARE(iconRecords[0], icon2); + + QVERIFY(record.removeIcon(icon2)); + QVERIFY(!record.removeIcon(icon3)); // already removed + QCOMPARE(record.iconCount(), 0); + + QList iconList; + + QNdefNfcIconRecord testIcon; + testIcon.setData("testicondata"); + testIcon.setType("test/data"); + + iconList << testIcon << icon2; + record.setIcons(iconList); + + QCOMPARE(record.iconCount(), 2); + iconRecords = record.iconRecords(); + QCOMPARE(iconRecords.size(), 2); + + QCOMPARE(iconRecords[0], testIcon); + QCOMPARE(iconRecords[1], icon2); +} + +void tst_QNdefNfcSmartPosterRecord::tst_size() +{ + QNdefNfcSmartPosterRecord record; + QVERIFY(!record.hasSize()); + QCOMPARE(record.size(), 0U); + + quint32 size = 1024; + record.setSize(size); + QCOMPARE(record.size(), size); + QVERIFY(record.hasSize()); + + size = 0x12345678; // check that all bytes are stored correctly + record.setSize(size); + QCOMPARE(record.size(), size); + QVERIFY(record.hasSize()); + + size = 0; + record.setSize(size); + QCOMPARE(record.size(), size); + QVERIFY(record.hasSize()); +} + +void tst_QNdefNfcSmartPosterRecord::tst_typeInfo() +{ + QNdefNfcSmartPosterRecord record; + QVERIFY(!record.hasTypeInfo()); + QVERIFY(record.typeInfo().isEmpty()); + + QString typeInfo("typeinfo"); + record.setTypeInfo(typeInfo); + QCOMPARE(record.typeInfo(), typeInfo); + QVERIFY(record.hasTypeInfo()); + + typeInfo = "moreinfo"; + record.setTypeInfo(typeInfo); + QCOMPARE(record.typeInfo(), typeInfo); + QVERIFY(record.hasTypeInfo()); + + typeInfo = QString(); + record.setTypeInfo(typeInfo); + QCOMPARE(record.typeInfo(), typeInfo); + QVERIFY(record.hasTypeInfo()); +} + +void tst_QNdefNfcSmartPosterRecord::tst_construct() +{ + QByteArray data((char *)payload, sizeof(payload)); + QNdefMessage ndefMessage = QNdefMessage::fromByteArray(data); + QCOMPARE(ndefMessage.size(), 1); + QNdefRecord record = ndefMessage[0]; + + QVERIFY(record.isRecordType()); + + // Construct a SP record from a standard QNdefRecord + QNdefNfcSmartPosterRecord sprecord(record); + + QCOMPARE(sprecord.typeNameFormat(), record.typeNameFormat()); + QCOMPARE(sprecord.type(), record.type()); + QCOMPARE(sprecord.payload(), record.payload()); + + QVERIFY(sprecord.hasTitle("en")); + QCOMPARE(sprecord.title("en"), QString("Icon Title")); + + QCOMPARE(sprecord.titleCount(), 1); + QList titleRecords = sprecord.titleRecords(); + + QCOMPARE(titleRecords[0].text(), QString("Icon Title")); + QCOMPARE(titleRecords[0].locale(), QString("en")); + QCOMPARE(sprecord.uri(), QUrl("http://www.rim.com")); + + QVERIFY(sprecord.hasAction()); + QCOMPARE(sprecord.action(), QNdefNfcSmartPosterRecord::SaveAction); + + QByteArray mimeType = "image/png"; + QVERIFY(sprecord.hasIcon()); + QVERIFY(sprecord.hasIcon(mimeType)); + QCOMPARE(sprecord.iconCount(), 1); + + QList iconRecords = sprecord.iconRecords(); + QCOMPARE(iconRecords.size(), 1); + QCOMPARE(iconRecords[0].type(), mimeType); + QVERIFY(!iconRecords[0].data().isEmpty()); + QVERIFY(iconRecords.value(1).type().isEmpty()); + QVERIFY(iconRecords.value(1).data().isEmpty()); + + QVERIFY(sprecord.hasSize()); + const quint32 size = 1024; + QCOMPARE(sprecord.size(), size); + + QVERIFY(sprecord.hasTypeInfo()); + QCOMPARE(sprecord.typeInfo(), QString("text/html")); + + QVERIFY(record == sprecord); + QVERIFY(!(record != sprecord)); +} + +void tst_QNdefNfcSmartPosterRecord::tst_downcast() +{ + QByteArray data((char *)payload, sizeof(payload)); + QNdefMessage ndefMessage = QNdefMessage::fromByteArray(data); + QCOMPARE(ndefMessage.size(), 1); + QNdefRecord record = ndefMessage[0]; + + QVERIFY(record.isRecordType()); + + // Trying to downcast a QNdefRecord to a QNdefNfcSmartPosterRecord causes + // an exception because a QNdefRecord does not contain the shared private data. + // So first need to create a real QNdefNfcSmartPosterRecord and refer to it via its base + QNdefNfcSmartPosterRecord sprecord(record); + QNdefRecord *pRecord = (QNdefRecord *)&sprecord; + + QVERIFY(pRecord->isRecordType()); + + QCOMPARE(pRecord->typeNameFormat(), sprecord.typeNameFormat()); + QCOMPARE(pRecord->type(), sprecord.type()); + QCOMPARE(pRecord->payload(), sprecord.payload()); + + QCOMPARE(pRecord->typeNameFormat(), record.typeNameFormat()); + QCOMPARE(pRecord->type(), record.type()); + QCOMPARE(pRecord->payload(), record.payload()); + + // Add another title + QNdefNfcTextRecord esRecord = getTextRecord("es"); + QVERIFY(sprecord.addTitle(esRecord)); + + QCOMPARE(sprecord.titleCount(), 2); + { + QStringList locales; + locales << "en" << "es"; + checkLocale(sprecord, locales); + } + + // Now make sure the base and SP record's payloads are the same + QByteArray basePayload = pRecord->payload(); + QByteArray spPayload = sprecord.payload(); + + // Check length is longer on the base + QVERIFY(basePayload.size() > record.payload().size()); + + // Check the payloads are the same + QCOMPARE(basePayload, spPayload); +} + +QTEST_MAIN(tst_QNdefNfcSmartPosterRecord) + +#include "tst_qndefnfcsmartposterrecord.moc" diff --git a/tests/auto/qndefrecord/CMakeLists.txt b/tests/auto/qndefrecord/CMakeLists.txt new file mode 100644 index 0000000..74b5bed --- /dev/null +++ b/tests/auto/qndefrecord/CMakeLists.txt @@ -0,0 +1,19 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## tst_qndefrecord Test: +##################################################################### + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qndefrecord LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qndefrecord + SOURCES + tst_qndefrecord.cpp + LIBRARIES + Qt::Nfc +) diff --git a/tests/auto/qndefrecord/tst_qndefrecord.cpp b/tests/auto/qndefrecord/tst_qndefrecord.cpp new file mode 100644 index 0000000..d667129 --- /dev/null +++ b/tests/auto/qndefrecord/tst_qndefrecord.cpp @@ -0,0 +1,437 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include + +#include +#include +#include + +QT_USE_NAMESPACE + +Q_DECLARE_METATYPE(QNdefRecord::TypeNameFormat) + +class tst_QNdefRecord : public QObject +{ + Q_OBJECT + +public: + tst_QNdefRecord(); + ~tst_QNdefRecord(); + +private slots: + void tst_record(); + void tst_comparison(); + void tst_comparison_data(); + void tst_isRecordType(); + + void tst_textRecord_data(); + void tst_textRecord(); + + void tst_uriRecord_data(); + void tst_uriRecord(); + + void tst_ndefRecord_data(); + void tst_ndefRecord(); +}; + +tst_QNdefRecord::tst_QNdefRecord() +{ +} + +tst_QNdefRecord::~tst_QNdefRecord() +{ +} + +void tst_QNdefRecord::tst_record() +{ + // test empty record + { + QNdefRecord record; + + QVERIFY(record.isEmpty()); + QCOMPARE(record.typeNameFormat(), QNdefRecord::Empty); + QVERIFY(record.type().isEmpty()); + QVERIFY(record.id().isEmpty()); + QVERIFY(record.payload().isEmpty()); + + QVERIFY(!record.isRecordType()); + QVERIFY(!record.isRecordType()); + + QCOMPARE(record, QNdefRecord()); + QVERIFY(!(record != QNdefRecord())); + } + + // test type name format + { + QNdefRecord record; + + record.setTypeNameFormat(QNdefRecord::Empty); + QCOMPARE(record.typeNameFormat(), QNdefRecord::Empty); + + record.setTypeNameFormat(QNdefRecord::NfcRtd); + QCOMPARE(record.typeNameFormat(), QNdefRecord::NfcRtd); + + record.setTypeNameFormat(QNdefRecord::Mime); + QCOMPARE(record.typeNameFormat(), QNdefRecord::Mime); + + record.setTypeNameFormat(QNdefRecord::Uri); + QCOMPARE(record.typeNameFormat(), QNdefRecord::Uri); + + record.setTypeNameFormat(QNdefRecord::ExternalRtd); + QCOMPARE(record.typeNameFormat(), QNdefRecord::ExternalRtd); + + record.setTypeNameFormat(QNdefRecord::Unknown); + QCOMPARE(record.typeNameFormat(), QNdefRecord::Unknown); + + record.setTypeNameFormat(QNdefRecord::TypeNameFormat(6)); + QCOMPARE(record.typeNameFormat(), QNdefRecord::Unknown); + + record.setTypeNameFormat(QNdefRecord::TypeNameFormat(7)); + QCOMPARE(record.typeNameFormat(), QNdefRecord::Unknown); + } + + // test type + { + QNdefRecord record; + + record.setType("test type"); + QCOMPARE(record.type(), QByteArray("test type")); + } + + // test id + { + QNdefRecord record; + + record.setId("test id"); + QCOMPARE(record.id(), QByteArray("test id")); + } + + // test payload + { + QNdefRecord record; + + record.setPayload("test payload"); + QVERIFY(!record.isEmpty()); + QVERIFY(!record.payload().isEmpty()); + QCOMPARE(record.payload(), QByteArray("test payload")); + } + + // test copy + { + QNdefRecord record; + record.setTypeNameFormat(QNdefRecord::ExternalRtd); + record.setType("qt-project.org:test-rtd"); + record.setId("test id"); + record.setPayload("test payload"); + + QNdefRecord ccopy(record); + + QCOMPARE(record.typeNameFormat(), ccopy.typeNameFormat()); + QCOMPARE(record.type(), ccopy.type()); + QCOMPARE(record.id(), ccopy.id()); + QCOMPARE(record.payload(), ccopy.payload()); + + QVERIFY(record == ccopy); + QVERIFY(!(record != ccopy)); + + QNdefRecord acopy; + acopy = record; + + QCOMPARE(record.typeNameFormat(), acopy.typeNameFormat()); + QCOMPARE(record.type(), acopy.type()); + QCOMPARE(record.id(), acopy.id()); + QCOMPARE(record.payload(), acopy.payload()); + + QVERIFY(record == acopy); + QVERIFY(!(record != acopy)); + + QVERIFY(record != QNdefRecord()); + } + + // test clear + { + QNdefRecord record; + record.setTypeNameFormat(QNdefRecord::NfcRtd); + record.setId("id"); + record.setType("type"); + record.setPayload("Some random data"); + + record.clear(); + QCOMPARE(record.typeNameFormat(), QNdefRecord::Empty); + QVERIFY(record.id().isEmpty()); + QVERIFY(record.type().isEmpty()); + QVERIFY(record.payload().isEmpty()); + QVERIFY(record.isEmpty()); + } +} + +void tst_QNdefRecord::tst_comparison() +{ + QFETCH(QNdefRecord, lhs); + QFETCH(QNdefRecord, rhs); + QFETCH(bool, result); + + QCOMPARE(lhs == rhs, result); + QCOMPARE(lhs != rhs, !result); + + QCOMPARE(rhs == lhs, result); + QCOMPARE(rhs != lhs, !result); +} + +void tst_QNdefRecord::tst_comparison_data() +{ + QTest::addColumn("lhs"); + QTest::addColumn("rhs"); + QTest::addColumn("result"); + + QTest::newRow("default-constructed records") << QNdefRecord() << QNdefRecord() << true; + { + QNdefRecord rec; + rec.setTypeNameFormat(QNdefRecord::Empty); + + QTest::newRow("default-constructed vs empty") << QNdefRecord() << rec << false; + } + + QNdefRecord record; + record.setTypeNameFormat(QNdefRecord::NfcRtd); + record.setType("T"); + record.setId("text-record"); + record.setPayload("Some random text"); + + { + QNdefRecord lhs = record; + QNdefRecord rhs = record; + rhs.setTypeNameFormat(QNdefRecord::ExternalRtd); + + QTest::newRow("typeNameFormat mismatch") << lhs << rhs << false; + } + { + QNdefRecord lhs = record; + QNdefRecord rhs = record; + rhs.setType("t"); + + QTest::newRow("type mismatch") << lhs << rhs << false; + } + { + QNdefRecord lhs = record; + QNdefRecord rhs = record; + rhs.setId("random id"); + + QTest::newRow("id mismatch") << lhs << rhs << false; + } + { + QNdefRecord lhs = record; + QNdefRecord rhs = record; + rhs.setPayload("another random text"); + + QTest::newRow("payload mismatch") << lhs << rhs << false; + } + { + QNdefRecord lhs = record; + QNdefRecord rhs = record; + + QTest::newRow("same records") << lhs << rhs << true; + } +} + +class PngNdefRecord : public QNdefRecord +{ +public: + PngNdefRecord() : QNdefRecord(QNdefRecord::Mime, "image/png") { } +}; + +class JpegNdefRecord : public QNdefRecord +{ +public: + JpegNdefRecord() : QNdefRecord(QNdefRecord::Mime, "image/jpeg") { } +}; + +void tst_QNdefRecord::tst_isRecordType() +{ + QNdefRecord rec; + rec.setTypeNameFormat(QNdefRecord::Mime); + rec.setType("image/png"); + + QVERIFY(!rec.isRecordType()); + QVERIFY(!rec.isRecordType()); + QVERIFY(rec.isRecordType()); +} + +void tst_QNdefRecord::tst_textRecord_data() +{ + QTest::addColumn("locale"); + QTest::addColumn("text"); + QTest::addColumn("utf8"); + QTest::addColumn("payload"); + + + QTest::newRow("en_US utf8") << QString::fromLatin1("en_US") + << QString::fromLatin1("Test String") + << true + << QByteArray::fromHex("05656E5F55535465737420537472696E67"); + QTest::newRow("en_US utf16") << QString::fromLatin1("en_US") + << QString::fromLatin1("Test String") + << false + << QByteArray::fromHex("85656E5F5553FEFF005400650073007400200053007400720069006E0067"); + QTest::newRow("ja_JP utf8") << QString::fromLatin1("ja_JP") + << QString::fromUtf8("\343\203\206\343\202\271\343\203\210\346" + "\226\207\345\255\227\345\210\227") + << true + << QByteArray::fromHex("056A615F4A50E38386E382B9E38388E69687E5AD97E58897"); + QTest::newRow("ja_JP utf16") << QString::fromLatin1("ja_JP") + << QString::fromUtf8("\343\203\206\343\202\271\343\203\210\346" + "\226\207\345\255\227\345\210\227") + << false + << QByteArray::fromHex("856A615F4A50FEFF30C630B930C865875B575217"); +} + +void tst_QNdefRecord::tst_textRecord() +{ + QFETCH(QString, locale); + QFETCH(QString, text); + QFETCH(bool, utf8); + QFETCH(QByteArray, payload); + + // test setters + { + QNdefNfcTextRecord record; + record.setLocale(locale); + record.setText(text); + record.setEncoding(utf8 ? QNdefNfcTextRecord::Utf8 : QNdefNfcTextRecord::Utf16); + + QCOMPARE(record.typeNameFormat(), QNdefRecord::NfcRtd); + QCOMPARE(record.type(), QByteArray("T")); + QCOMPARE(record.payload(), payload); + + QVERIFY(record != QNdefRecord()); + } + + // test getters + { + QNdefNfcTextRecord record; + record.setPayload(payload); + + QCOMPARE(record.locale(), locale); + QCOMPARE(record.text(), text); + QCOMPARE(record.encoding() == QNdefNfcTextRecord::Utf8, utf8); + } + + // test copy + { + QNdefRecord record; + record.setTypeNameFormat(QNdefRecord::NfcRtd); + record.setType("T"); + record.setPayload(payload); + + QVERIFY(!record.isRecordType()); + QVERIFY(record.isRecordType()); + QVERIFY(!record.isRecordType()); + + QNdefNfcTextRecord textRecord(record); + + QVERIFY(!textRecord.isEmpty()); + + QVERIFY(record == textRecord); + + QCOMPARE(textRecord.locale(), locale); + QCOMPARE(textRecord.text(), text); + QCOMPARE(textRecord.encoding() == QNdefNfcTextRecord::Utf8, utf8); + } +} + +void tst_QNdefRecord::tst_uriRecord_data() +{ + QTest::addColumn("url"); + QTest::addColumn("payload"); + + + QTest::newRow("http") << QString::fromLatin1("http://qt-project.org/") + << QByteArray::fromHex("0371742d70726f6a6563742e6f72672f"); + QTest::newRow("tel") << QString::fromLatin1("tel:+1234567890") + << QByteArray::fromHex("052B31323334353637383930"); + QTest::newRow("mailto") << QString::fromLatin1("mailto:test@example.com") + << QByteArray::fromHex("0674657374406578616D706C652E636F6D"); + QTest::newRow("urn") << QString::fromLatin1("urn:nfc:ext:qt-project.org:test") + << QByteArray::fromHex("136E66633A6578743A71742D70726F6A6563742E6F72673A74657374"); +} + +void tst_QNdefRecord::tst_uriRecord() +{ + QFETCH(QString, url); + QFETCH(QByteArray, payload); + + // test setters + { + QNdefNfcUriRecord record; + record.setUri(QUrl(url)); + + QCOMPARE(record.typeNameFormat(), QNdefRecord::NfcRtd); + QCOMPARE(record.type(), QByteArray("U")); + QCOMPARE(record.payload(), payload); + + QVERIFY(record != QNdefRecord()); + } + + // test getters + { + QNdefNfcUriRecord record; + record.setPayload(payload); + + QCOMPARE(record.uri(), QUrl(url)); + } + + // test copy + { + QNdefRecord record; + record.setTypeNameFormat(QNdefRecord::NfcRtd); + record.setType("U"); + record.setPayload(payload); + + QVERIFY(!record.isRecordType()); + QVERIFY(!record.isRecordType()); + QVERIFY(record.isRecordType()); + + QNdefNfcUriRecord uriRecord(record); + + QVERIFY(!uriRecord.isEmpty()); + + QVERIFY(record == uriRecord); + + QCOMPARE(uriRecord.uri(), QUrl(url)); + } +} + +void tst_QNdefRecord::tst_ndefRecord_data() +{ + QTest::addColumn("typeNameFormat"); + QTest::addColumn("type"); + + QTest::newRow("NfcRtd:U") << QNdefRecord::NfcRtd << QByteArray("U"); + QTest::newRow("NfcRtd:T") << QNdefRecord::NfcRtd << QByteArray("T"); + QTest::newRow("Empty:BLAH") << QNdefRecord::Empty << QByteArray("BLAH"); + QTest::newRow("Empty") << QNdefRecord::Empty << QByteArray(""); + QTest::newRow("Unknown") << QNdefRecord::Unknown << QByteArray("BLAHfoo"); + QTest::newRow("Mime") << QNdefRecord::Mime << QByteArray("foobar"); + QTest::newRow("ExternalRtd") << QNdefRecord::ExternalRtd << QByteArray(""); + QTest::newRow("Uri") << QNdefRecord::Uri << QByteArray("example.com/uri"); +} + +void tst_QNdefRecord::tst_ndefRecord() +{ + QFETCH(QNdefRecord::TypeNameFormat, typeNameFormat); + QFETCH(QByteArray, type); + + { + QNdefRecord record; + record.setTypeNameFormat(typeNameFormat); + record.setType(type); + QCOMPARE(record.typeNameFormat(), typeNameFormat); + QCOMPARE(record.type(), type); + } +} + +QTEST_MAIN(tst_QNdefRecord) + +#include "tst_qndefrecord.moc" + diff --git a/tests/auto/qnearfieldmanager/CMakeLists.txt b/tests/auto/qnearfieldmanager/CMakeLists.txt new file mode 100644 index 0000000..9fa7403 --- /dev/null +++ b/tests/auto/qnearfieldmanager/CMakeLists.txt @@ -0,0 +1,49 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qnearfieldmanager LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +if (NOT QT_FEATURE_private_tests) + return() +endif() + +##################################################################### +## tst_qnearfieldmanager Test: +##################################################################### + +# Collect test data +list(APPEND test_data "../nfcdata/Qt Labs Website Tag Type1.nfc") +list(APPEND test_data "../nfcdata/Qt Website Tag Type1.nfc") + +qt_internal_add_test(tst_qnearfieldmanager + SOURCES + ../nfccommons/qnearfieldmanager_emulator.cpp ../nfccommons/qnearfieldmanager_emulator_p.h + ../nfccommons/qnearfieldtarget_emulator.cpp ../nfccommons/qnearfieldtarget_emulator_p.h + ../nfccommons/targetemulator.cpp ../nfccommons/targetemulator_p.h + ../nfccommons/qnearfieldtagtype1.cpp ../nfccommons/qnearfieldtagtype1_p.h + ../nfccommons/qnearfieldtagtype2.cpp ../nfccommons/qnearfieldtagtype2_p.h + ../nfccommons/qtlv.cpp ../nfccommons/qtlv_p.h + tst_qnearfieldmanager.cpp + DEFINES + SRCDIR="${CMAKE_CURRENT_SOURCE_DIR}/../nfcdata" + INCLUDE_DIRECTORIES + ../nfccommons + LIBRARIES + Qt::NfcPrivate + TESTDATA ${test_data} +) + +#### Keys ignored in scope 1:.:.:qnearfieldmanager.pro:: +# _REQUIREMENTS = "contains(QT_CONFIG, private_tests)" + +## Scopes: +##################################################################### + +qt_internal_extend_target(tst_qnearfieldmanager CONDITION builtin_testdata + DEFINES + BUILTIN_TESTDATA +) diff --git a/tests/auto/qnearfieldmanager/tst_qnearfieldmanager.cpp b/tests/auto/qnearfieldmanager/tst_qnearfieldmanager.cpp new file mode 100644 index 0000000..a902ac5 --- /dev/null +++ b/tests/auto/qnearfieldmanager/tst_qnearfieldmanager.cpp @@ -0,0 +1,164 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include + +#include +#include +#include +#include +#include +#include + +QT_USE_NAMESPACE + +Q_DECLARE_METATYPE(QNearFieldTarget*) +Q_DECLARE_METATYPE(QNearFieldTarget::Type) +Q_DECLARE_METATYPE(QNdefFilter) +Q_DECLARE_METATYPE(QNdefRecord::TypeNameFormat) + +class tst_QNearFieldManager : public QObject +{ + Q_OBJECT + +public: + tst_QNearFieldManager(); + +private slots: + void initTestCase(); + + void isSupported(); + void isSupported_data(); + + void userInformation(); + + void targetDetected_data(); + void targetDetected(); +}; + +tst_QNearFieldManager::tst_QNearFieldManager() +{ + QDir::setCurrent(QLatin1String(SRCDIR)); + + qRegisterMetaType(); + qRegisterMetaType(); +} + +void tst_QNearFieldManager::initTestCase() +{ + QNearFieldManagerPrivateImpl *emulatorBackend = new QNearFieldManagerPrivateImpl; + QNearFieldManager manager(emulatorBackend, 0); + + QVERIFY(manager.isEnabled()); +} + +void tst_QNearFieldManager::isSupported() +{ + QFETCH(QNearFieldTarget::AccessMethod, accessMethod); + QFETCH(bool, supported); + + QNearFieldManagerPrivateImpl *emulatorBackend = new QNearFieldManagerPrivateImpl; + QNearFieldManager manager(emulatorBackend, nullptr); + + QCOMPARE(manager.isSupported(accessMethod), supported); +} + +void tst_QNearFieldManager::isSupported_data() +{ + QTest::addColumn("accessMethod"); + QTest::addColumn("supported"); + + QTest::newRow("UnknownAccess") << QNearFieldTarget::UnknownAccess << false; + QTest::newRow("NdefAccess") << QNearFieldTarget::NdefAccess << true; + QTest::newRow("TagTypeSpecificAccess") << QNearFieldTarget::TagTypeSpecificAccess << false; + QTest::newRow("AnyAccess") << QNearFieldTarget::AnyAccess << true; +} + +void tst_QNearFieldManager::userInformation() +{ + QNearFieldManagerPrivateImpl *emulatorBackend = new QNearFieldManagerPrivateImpl; + QNearFieldManager manager(emulatorBackend, nullptr); + + QSignalSpy spy(emulatorBackend, &QNearFieldManagerPrivateImpl::userInformationChanged); + + manager.startTargetDetection(QNearFieldTarget::AnyAccess); + + const QString progressString("NFC target detection in progress"); + manager.setUserInformation(progressString); + + const QString errorString("Failed to detect NFC targets"); + manager.stopTargetDetection(errorString); + + QCOMPARE(spy.size(), 2); + QCOMPARE(spy.at(0).at(0).toString(), progressString); + QCOMPARE(spy.at(1).at(0).toString(), errorString); +} + +void tst_QNearFieldManager::targetDetected_data() +{ + QTest::addColumn("accessMethod"); + QTest::addColumn("deleteTarget"); + + QTest::newRow("UnknownAccess") << QNearFieldTarget::UnknownAccess << false; + QTest::newRow("NdefAccess, no delete") << QNearFieldTarget::NdefAccess << false; + QTest::newRow("AnyAccess, delete") << QNearFieldTarget::AnyAccess << true; +} + +void tst_QNearFieldManager::targetDetected() +{ + QFETCH(QNearFieldTarget::AccessMethod, accessMethod); + QFETCH(bool, deleteTarget); + + QNearFieldManagerPrivateImpl *emulatorBackend = new QNearFieldManagerPrivateImpl; + QNearFieldManager manager(emulatorBackend, nullptr); + + QSignalSpy targetDetectedSpy(&manager, &QNearFieldManager::targetDetected); + QSignalSpy targetLostSpy(&manager, &QNearFieldManager::targetLost); + QSignalSpy detectionStoppedSpy(&manager, &QNearFieldManager::targetDetectionStopped); + + const bool started = manager.startTargetDetection(accessMethod); + + if (started) { + QTRY_VERIFY(!targetDetectedSpy.isEmpty()); + + QNearFieldTarget *target = targetDetectedSpy.first().at(0).value(); + + QSignalSpy disconnectedSpy(target, SIGNAL(disconnected())); + + QVERIFY(target); + + QVERIFY(!target->uid().isEmpty()); + + if (!deleteTarget) { + QTRY_VERIFY(!targetLostSpy.isEmpty()); + + QNearFieldTarget *lostTarget = targetLostSpy.first().at(0).value(); + + QCOMPARE(target, lostTarget); + + QVERIFY(!disconnectedSpy.isEmpty()); + } else { + delete target; + + // wait for another targetDetected() without a targetLost() signal in between. + targetDetectedSpy.clear(); + targetLostSpy.clear(); + + QTRY_VERIFY(targetLostSpy.isEmpty() && !targetDetectedSpy.isEmpty()); + } + } + + manager.stopTargetDetection(); + + QCOMPARE(detectionStoppedSpy.size(), 1); +} + +QTEST_MAIN(tst_QNearFieldManager) + +// Unset the moc namespace which is not required for the following include. +#undef QT_BEGIN_MOC_NAMESPACE +#define QT_BEGIN_MOC_NAMESPACE +#undef QT_END_MOC_NAMESPACE +#define QT_END_MOC_NAMESPACE + +#include "tst_qnearfieldmanager.moc" diff --git a/tests/auto/qnearfieldtagtype1/CMakeLists.txt b/tests/auto/qnearfieldtagtype1/CMakeLists.txt new file mode 100644 index 0000000..03189bf --- /dev/null +++ b/tests/auto/qnearfieldtagtype1/CMakeLists.txt @@ -0,0 +1,48 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qnearfieldtagtype1 LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +if (NOT QT_FEATURE_private_tests) + return() +endif() + +##################################################################### +## tst_qnearfieldtagtype1 Test: +##################################################################### + +# Collect test data +list(APPEND test_data "../nfcdata/Qt Labs Website Tag Type1.nfc") +list(APPEND test_data "../nfcdata/Qt Website Tag Type1.nfc") + +qt_internal_add_test(tst_qnearfieldtagtype1 + SOURCES + ../nfccommons/qnearfieldtarget_emulator.cpp ../nfccommons/qnearfieldtarget_emulator_p.h + ../nfccommons/targetemulator.cpp ../nfccommons/targetemulator_p.h + ../nfccommons/qnearfieldtagtype1.cpp ../nfccommons/qnearfieldtagtype1_p.h + ../nfccommons/qnearfieldtagtype2.cpp ../nfccommons/qnearfieldtagtype2_p.h + ../nfccommons/qtlv.cpp ../nfccommons/qtlv_p.h + tst_qnearfieldtagtype1.cpp + DEFINES + SRCDIR="${CMAKE_CURRENT_SOURCE_DIR}/../nfcdata" + INCLUDE_DIRECTORIES + ../nfccommons + LIBRARIES + Qt::NfcPrivate + TESTDATA ${test_data} +) + +#### Keys ignored in scope 1:.:.:qnearfieldtagtype1.pro:: +# _REQUIREMENTS = "contains(QT_CONFIG, private_tests)" + +## Scopes: +##################################################################### + +qt_internal_extend_target(tst_qnearfieldtagtype1 CONDITION builtin_testdata + DEFINES + BUILTIN_TESTDATA +) diff --git a/tests/auto/qnearfieldtagtype1/tst_qnearfieldtagtype1.cpp b/tests/auto/qnearfieldtagtype1/tst_qnearfieldtagtype1.cpp new file mode 100644 index 0000000..8f54058 --- /dev/null +++ b/tests/auto/qnearfieldtagtype1/tst_qnearfieldtagtype1.cpp @@ -0,0 +1,458 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include + +#include +#include + +#include +#include + +QT_USE_NAMESPACE + +Q_DECLARE_METATYPE(QNearFieldTarget*) + +class tst_QNearFieldTagType1 : public QObject +{ + Q_OBJECT + +public: + tst_QNearFieldTagType1(); + +private slots: + void init(); + void cleanup(); + + void staticMemoryModel(); + void dynamicMemoryModel(); + + void ndefMessages(); + +private: + void waitForMatchingTarget(); + + QObject *targetParent; + QNearFieldTagType1 *target; +}; + +tst_QNearFieldTagType1::tst_QNearFieldTagType1() +: targetParent(0), target(0) +{ + QDir::setCurrent(QLatin1String(SRCDIR)); + + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); +} + +void tst_QNearFieldTagType1::init() +{ + targetParent = new QObject(); + + TagActivator::instance()->initialize(); + TagActivator::instance()->start(); +} + +void tst_QNearFieldTagType1::cleanup() +{ + TagActivator::instance()->reset(); + + delete targetParent; + targetParent = 0; + target = 0; +} + +void tst_QNearFieldTagType1::waitForMatchingTarget() +{ + TagActivator *activator = TagActivator::instance(); + QSignalSpy targetDetectedSpy(activator, SIGNAL(tagActivated(TagBase*))); + + QTRY_VERIFY(!targetDetectedSpy.isEmpty()); + + target = new TagType1(targetDetectedSpy.first().at(0).value(), targetParent); + + QVERIFY(target); + + QCOMPARE(target->type(), QNearFieldTarget::NfcTagType1); +} + +void tst_QNearFieldTagType1::staticMemoryModel() +{ + waitForMatchingTarget(); + if (QTest::currentTestFailed()) + return; + + QVERIFY(target->accessMethods() & QNearFieldTarget::TagTypeSpecificAccess); + + QCOMPARE(target->version(), quint8(0x10)); + + // readIdentification() + { + QNearFieldTarget::RequestId id = target->readIdentification(); + QVERIFY(target->waitForRequestCompleted(id)); + + const QByteArray data = target->requestResponse(id).toByteArray(); + + QCOMPARE(data.size(), 6); + + quint8 hr0 = data.at(0); + //quint8 hr1 = data.at(1); + const QByteArray uid4 = data.mid(2, 4); + + // verify NfcTagType1 + QVERIFY(hr0 & 0x10); + + QCOMPARE(uid4, target->uid().left(4)); + } + + // readAll() + { + // read all reads the first 120 bytes, prepended with HR0 and HR1. + QNearFieldTarget::RequestId id = target->readAll(); + QVERIFY(target->waitForRequestCompleted(id)); + + const QByteArray data = target->requestResponse(id).toByteArray(); + QCOMPARE(data.size(), 122); + + // verify NfcTagType1. + QVERIFY(data.at(0) & 0x10); + + // NFC Magic Number means NDEF message present. + QCOMPARE(quint8(data.at(10)) == 0xe1, target->hasNdefMessage()); + } + + // readByte() + { + QNearFieldTarget::RequestId id = target->readAll(); + QVERIFY(target->waitForRequestCompleted(id)); + + const QByteArray data = target->requestResponse(id).toByteArray(); + + for (int i = 0; i < 120; ++i) { + id = target->readByte(i); + QVERIFY(target->waitForRequestCompleted(id)); + + quint8 byte = target->requestResponse(id).toUInt(); + + QCOMPARE(byte, quint8(data.at(i + 2))); + } + } + + // writeByte() + { + for (int i = 0; i < 8; ++i) { + QNearFieldTarget::RequestId id = target->readByte(i); + QVERIFY(target->waitForRequestCompleted(id)); + + quint8 byte = target->requestResponse(id).toUInt(); + + id = target->writeByte(i, 0x55); + QVERIFY(target->waitForRequestCompleted(id)); + QVERIFY(!target->requestResponse(id).isValid()); + + id = target->readByte(i); + QVERIFY(target->waitForRequestCompleted(id)); + + quint8 readByte = target->requestResponse(id).toUInt(); + QCOMPARE(readByte, byte); + } + + for (int i = 8; i < 104; ++i) { + // Write 0x55 + QNearFieldTarget::RequestId id = target->writeByte(i, 0x55); + QVERIFY(target->waitForRequestCompleted(id)); + QVERIFY(target->requestResponse(id).toBool()); + + id = target->readByte(i); + QVERIFY(target->waitForRequestCompleted(id)); + quint8 readByte = target->requestResponse(id).toUInt(); + QCOMPARE(readByte, quint8(0x55)); + + // Write 0xaa + id = target->writeByte(i, 0xaa); + QVERIFY(target->waitForRequestCompleted(id)); + QVERIFY(target->requestResponse(id).toBool()); + + id = target->readByte(i); + QVERIFY(target->waitForRequestCompleted(id)); + readByte = target->requestResponse(id).toUInt(); + QCOMPARE(readByte, quint8(0xaa)); + + // Write 0x55 without erase, result should be 0xff + id = target->writeByte(i, 0x55, QNearFieldTagType1::WriteOnly); + QVERIFY(target->waitForRequestCompleted(id)); + QVERIFY(target->requestResponse(id).toBool()); + + id = target->readByte(i); + QVERIFY(target->waitForRequestCompleted(id)); + readByte = target->requestResponse(id).toUInt(); + QCOMPARE(readByte, quint8(0xff)); + } + + for (int i = 104; i < 120; ++i) { + QNearFieldTarget::RequestId id = target->readByte(i); + QVERIFY(target->waitForRequestCompleted(id)); + + quint8 byte = target->requestResponse(id).toUInt(); + + id = target->writeByte(i, 0x55); + QVERIFY(target->waitForRequestCompleted(id)); + QVERIFY(!target->requestResponse(id).isValid()); + + id = target->readByte(i); + QVERIFY(target->waitForRequestCompleted(id)); + + quint8 readByte = target->requestResponse(id).toUInt(); + QCOMPARE(readByte, byte); + } + } +} + +void tst_QNearFieldTagType1::dynamicMemoryModel() +{ + bool testedStatic = false; + bool testedDynamic = false; + + QList seenIds; + forever { + waitForMatchingTarget(); + if (QTest::currentTestFailed()) + return; + + QNearFieldTarget::RequestId id = target->readIdentification(); + QVERIFY(target->waitForRequestCompleted(id)); + + const QByteArray data = target->requestResponse(id).toByteArray(); + if (seenIds.contains(data)) + break; + else + seenIds.append(data); + + quint8 hr0 = data.at(0); + bool dynamic = (((hr0 & 0xf0) == 0x10) && ((hr0 & 0x0f) != 0x01)); + + if (dynamic) { + testedDynamic = true; + + // block 0, UID is locked + { + QNearFieldTarget::RequestId id = target->readBlock(0x00); + QVERIFY(target->waitForRequestCompleted(id)); + + const QByteArray block = target->requestResponse(id).toByteArray(); + + QCOMPARE(target->uid(), block.left(7)); + QCOMPARE(quint8(block.at(7)), quint8(0x00)); + + id = target->writeBlock(0x00, QByteArray(8, quint8(0x55))); + QVERIFY(target->waitForRequestCompleted(id)); + QVERIFY(!target->requestResponse(id).isValid()); + + QCOMPARE(target->uid(), block.left(7)); + QCOMPARE(quint8(block.at(7)), quint8(0x00)); + } + + // static data area + QNearFieldTarget::RequestId id = target->readSegment(0); + QVERIFY(target->waitForRequestCompleted(id)); + QByteArray segment = target->requestResponse(id).toByteArray(); + for (int i = 1; i < 0x0d; ++i) { + // Write 0x55 + id = target->writeBlock(i, QByteArray(8, quint8(0x55))); + QVERIFY(target->waitForRequestCompleted(id)); + QVERIFY(target->requestResponse(id).toBool()); + + id = target->readBlock(i); + QVERIFY(target->waitForRequestCompleted(id)); + QCOMPARE(target->requestResponse(id).toByteArray(), QByteArray(8, quint8(0x55))); + + segment.replace(i * 8, 8, QByteArray(8, quint8(0x55))); + + id = target->readSegment(0); + QVERIFY(target->waitForRequestCompleted(id)); + QCOMPARE(target->requestResponse(id).toByteArray(), segment); + + // Write 0xaa + id = target->writeBlock(i, QByteArray(8, quint8(0xaa))); + QVERIFY(target->waitForRequestCompleted(id)); + QVERIFY(target->requestResponse(id).toBool()); + + id = target->readBlock(i); + QVERIFY(target->waitForRequestCompleted(id)); + QCOMPARE(target->requestResponse(id).toByteArray(), QByteArray(8, quint8(0xaa))); + + segment.replace(i * 8, 8, QByteArray(8, quint8(0xaa))); + + id = target->readSegment(0); + QVERIFY(target->waitForRequestCompleted(id)); + QCOMPARE(target->requestResponse(id).toByteArray(), segment); + + // Write 0x55 without erase, result should be 0xff + id = target->writeBlock(i, QByteArray(8, quint8(0x55)), + QNearFieldTagType1::WriteOnly); + QVERIFY(target->waitForRequestCompleted(id)); + QVERIFY(target->requestResponse(id).toBool()); + + id = target->readBlock(i); + QVERIFY(target->waitForRequestCompleted(id)); + QCOMPARE(target->requestResponse(id).toByteArray(), QByteArray(8, quint8(0xff))); + + segment.replace(i * 8, 8, QByteArray(8, quint8(0xff))); + + id = target->readSegment(0); + QVERIFY(target->waitForRequestCompleted(id)); + QCOMPARE(target->requestResponse(id).toByteArray(), segment); + } + + // static / dynamic reserved lock area + for (int i = 0x0d; i < 0x10; ++i) { + id = target->readBlock(i); + QVERIFY(target->waitForRequestCompleted(id)); + QByteArray block = target->requestResponse(id).toByteArray(); + + id = target->writeBlock(i, QByteArray(8, quint8(0x55))); + QVERIFY(target->waitForRequestCompleted(id)); + QVERIFY(!target->requestResponse(id).isValid()); + + id = target->readBlock(i); + QVERIFY(target->waitForRequestCompleted(id)); + QCOMPARE(target->requestResponse(id).toByteArray(), block); + } + } else { + testedStatic = true; + + for (int i = 0; i < 256; ++i) { + QNearFieldTarget::RequestId id = target->readBlock(i); + QVERIFY(target->waitForRequestCompleted(id)); + QVERIFY(!target->requestResponse(id).isValid()); + + id = target->writeBlock(i, QByteArray(8, quint8(0x55))); + QVERIFY(target->waitForRequestCompleted(id)); + QVERIFY(!target->requestResponse(id).isValid()); + } + for (int i = 0; i < 16; ++i) { + QNearFieldTarget::RequestId id = target->readSegment(i); + QVERIFY(target->waitForRequestCompleted(id)); + QVERIFY(!target->requestResponse(id).isValid()); + } + } + } + + QVERIFY(testedStatic); + QVERIFY(testedDynamic); +} + +void tst_QNearFieldTagType1::ndefMessages() +{ + QByteArray firstId; + forever { + waitForMatchingTarget(); + if (QTest::currentTestFailed()) + return; + + QNearFieldTarget::RequestId id = target->readIdentification(); + QVERIFY(target->waitForRequestCompleted(id)); + + const QByteArray uid = target->requestResponse(id).toByteArray(); + if (firstId.isEmpty()) + firstId = uid; + else if (firstId == uid) + break; + + QVERIFY(target->hasNdefMessage()); + + QSignalSpy ndefMessageReadSpy(target, SIGNAL(ndefMessageRead(QNdefMessage))); + QSignalSpy requestCompletedSpy(target, + SIGNAL(requestCompleted(QNearFieldTarget::RequestId))); + QSignalSpy errorSpy(target, + SIGNAL(error(QNearFieldTarget::Error,QNearFieldTarget::RequestId))); + + QNearFieldTarget::RequestId readId = target->readNdefMessages(); + + QVERIFY(readId.isValid()); + + QNearFieldTarget::RequestId completedId; + + while (completedId != readId) { + QTRY_VERIFY(!requestCompletedSpy.isEmpty() && errorSpy.isEmpty()); + + completedId = + requestCompletedSpy.takeFirst().first().value(); + } + + QList ndefMessages; + for (qsizetype i = 0; i < ndefMessageReadSpy.size(); ++i) + ndefMessages.append(ndefMessageReadSpy.at(i).first().value()); + + QList messages; + QNdefNfcTextRecord textRecord; + textRecord.setText(QStringLiteral("tst_QNearFieldTagType1::ndefMessages")); + + QNdefMessage message; + message.append(textRecord); + + if (target->memorySize() > 120) { + QNdefRecord record; + record.setTypeNameFormat(QNdefRecord::ExternalRtd); + record.setType("org.qt-project:ndefMessagesTest"); + record.setPayload(QByteArray(120, quint8(0x55))); + message.append(record); + } + + messages.append(message); + + requestCompletedSpy.clear(); + errorSpy.clear(); + + QNearFieldTarget::RequestId writeId = target->writeNdefMessages(messages); + + QVERIFY(writeId.isValid()); + + completedId = QNearFieldTarget::RequestId(); + + while (completedId != writeId) { + QTRY_VERIFY(!requestCompletedSpy.isEmpty() && errorSpy.isEmpty()); + + completedId = + requestCompletedSpy.takeFirst().first().value(); + } + + QVERIFY(target->hasNdefMessage()); + + ndefMessageReadSpy.clear(); + requestCompletedSpy.clear(); + errorSpy.clear(); + + readId = target->readNdefMessages(); + + QVERIFY(readId.isValid()); + + completedId = QNearFieldTarget::RequestId(); + + while (completedId != readId) { + QTRY_VERIFY(!requestCompletedSpy.isEmpty() && errorSpy.isEmpty()); + + completedId = + requestCompletedSpy.takeFirst().first().value(); + } + + QList storedMessages; + for (qsizetype i = 0; i < ndefMessageReadSpy.size(); ++i) + storedMessages.append(ndefMessageReadSpy.at(i).first().value()); + + QVERIFY(ndefMessages != storedMessages); + + QCOMPARE(messages, storedMessages); + } +} + +QTEST_MAIN(tst_QNearFieldTagType1) + +// Unset the moc namespace which is not required for the following include. +#undef QT_BEGIN_MOC_NAMESPACE +#define QT_BEGIN_MOC_NAMESPACE +#undef QT_END_MOC_NAMESPACE +#define QT_END_MOC_NAMESPACE + +#include "tst_qnearfieldtagtype1.moc" diff --git a/tests/auto/qnearfieldtagtype2/CMakeLists.txt b/tests/auto/qnearfieldtagtype2/CMakeLists.txt new file mode 100644 index 0000000..cc6d6f3 --- /dev/null +++ b/tests/auto/qnearfieldtagtype2/CMakeLists.txt @@ -0,0 +1,48 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qnearfieldtagtype2 LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +if (NOT QT_FEATURE_private_tests) + return() +endif() + +##################################################################### +## tst_qnearfieldtagtype2 Test: +##################################################################### + +# Collect test data +list(APPEND test_data "nfcdata/Dynamic Empty Tag.nfc") +list(APPEND test_data "nfcdata/Empty Tag.nfc") + +qt_internal_add_test(tst_qnearfieldtagtype2 + SOURCES + ../nfccommons/qnearfieldtarget_emulator.cpp ../nfccommons/qnearfieldtarget_emulator_p.h + ../nfccommons/targetemulator.cpp ../nfccommons/targetemulator_p.h + ../nfccommons/qnearfieldtagtype1.cpp ../nfccommons/qnearfieldtagtype1_p.h + ../nfccommons/qnearfieldtagtype2.cpp ../nfccommons/qnearfieldtagtype2_p.h + ../nfccommons/qtlv.cpp ../nfccommons/qtlv_p.h + tst_qnearfieldtagtype2.cpp + DEFINES + SRCDIR="${CMAKE_CURRENT_SOURCE_DIR}/nfcdata" + INCLUDE_DIRECTORIES + ../nfccommons + LIBRARIES + Qt::NfcPrivate + TESTDATA ${test_data} +) + +#### Keys ignored in scope 1:.:.:qnearfieldtagtype2.pro:: +# _REQUIREMENTS = "contains(QT_CONFIG, private_tests)" + +## Scopes: +##################################################################### + +qt_internal_extend_target(tst_qnearfieldtagtype2 CONDITION builtin_testdata + DEFINES + BUILTIN_TESTDATA +) diff --git a/tests/auto/qnearfieldtagtype2/nfcdata/Dynamic Empty Tag.nfc b/tests/auto/qnearfieldtagtype2/nfcdata/Dynamic Empty Tag.nfc new file mode 100644 index 0000000..30cf6b2 --- /dev/null +++ b/tests/auto/qnearfieldtagtype2/nfcdata/Dynamic Empty Tag.nfc @@ -0,0 +1,6 @@ +[Target] +Name=Dynamic Empty Tag +Type=TagType2 + +[TagType2] +Data=@ByteArray(333\0\x33\x33\x33\x33\0\0\0\0\0\x10\xff\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0) diff --git a/tests/auto/qnearfieldtagtype2/nfcdata/Empty Tag.nfc b/tests/auto/qnearfieldtagtype2/nfcdata/Empty Tag.nfc new file mode 100644 index 0000000..22b31b4 --- /dev/null +++ b/tests/auto/qnearfieldtagtype2/nfcdata/Empty Tag.nfc @@ -0,0 +1,6 @@ +[Target] +Name=Empty Tag +Type=TagType2 + +[TagType2] +Data=@ByteArray(\x11\x11\x11\0\x11\x11\x11\x11\0\0\0\0\xe1\x10\x6\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0) diff --git a/tests/auto/qnearfieldtagtype2/tst_qnearfieldtagtype2.cpp b/tests/auto/qnearfieldtagtype2/tst_qnearfieldtagtype2.cpp new file mode 100644 index 0000000..59b1dd2 --- /dev/null +++ b/tests/auto/qnearfieldtagtype2/tst_qnearfieldtagtype2.cpp @@ -0,0 +1,330 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include + +#include +#include +#include +#include + +QT_USE_NAMESPACE + +Q_DECLARE_METATYPE(QNearFieldTarget*) + +static const char * const deadbeef = "\xde\xad\xbe\xef"; + +class tst_QNearFieldTagType2 : public QObject +{ + Q_OBJECT + +public: + tst_QNearFieldTagType2(); + +private slots: + void init(); + void cleanup(); + + void staticMemoryModel(); + void dynamicMemoryModel(); + + void ndefMessages(); + +private: + void waitForMatchingTarget(); + + QObject *targetParent; + QNearFieldTagType2 *target; +}; + +tst_QNearFieldTagType2::tst_QNearFieldTagType2() +: targetParent(0), target(0) +{ + QDir::setCurrent(QLatin1String(SRCDIR)); + + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); +} + +void tst_QNearFieldTagType2::init() +{ + targetParent = new QObject(); + + TagActivator::instance()->initialize(); + TagActivator::instance()->start(); +} + +void tst_QNearFieldTagType2::cleanup() +{ + TagActivator::instance()->reset(); + + delete targetParent; + targetParent = 0; + target = 0; +} + +void tst_QNearFieldTagType2::waitForMatchingTarget() +{ + TagActivator *activator = TagActivator::instance(); + QSignalSpy targetDetectedSpy(activator, SIGNAL(tagActivated(TagBase*))); + + QTRY_VERIFY(!targetDetectedSpy.isEmpty()); + + target = new TagType2(targetDetectedSpy.first().at(0).value(), targetParent); + + QVERIFY(target); + + QCOMPARE(target->type(), QNearFieldTarget::NfcTagType2); +} + +void tst_QNearFieldTagType2::staticMemoryModel() +{ + waitForMatchingTarget(); + if (QTest::currentTestFailed()) + return; + + QVERIFY(target->accessMethods() & QNearFieldTarget::TagTypeSpecificAccess); + + QCOMPARE(target->version(), quint8(0x10)); + + // readBlock(), writeBlock() + { + for (int i = 0; i < 2; ++i) { + QNearFieldTarget::RequestId id = target->readBlock(i); + QVERIFY(target->waitForRequestCompleted(id)); + + const QByteArray block = target->requestResponse(id).toByteArray(); + + id = target->writeBlock(i, QByteArray(4, 0x55)); + QVERIFY(target->waitForRequestCompleted(id)); + QVERIFY(!target->requestResponse(id).toBool()); + + id = target->readBlock(i); + QVERIFY(target->waitForRequestCompleted(id)); + + const QByteArray readBlock = target->requestResponse(id).toByteArray(); + QCOMPARE(readBlock, block); + } + + for (int i = 3; i < 16; ++i) { + // Read initial data + QNearFieldTarget::RequestId id = target->readBlock(i); + QVERIFY(target->waitForRequestCompleted(id)); + QByteArray initialBlock = target->requestResponse(id).toByteArray(); + + // Write 0x55 + id = target->writeBlock(i, QByteArray(4, 0x55)); + QVERIFY(target->waitForRequestCompleted(id)); + QVERIFY(target->requestResponse(id).toBool()); + + id = target->readBlock(i); + QVERIFY(target->waitForRequestCompleted(id)); + QByteArray readBlock = target->requestResponse(id).toByteArray(); + QCOMPARE(readBlock, QByteArray(4, 0x55) + initialBlock.mid(4)); + + // Write 0xaa + id = target->writeBlock(i, QByteArray(4, char(0xaa))); + QVERIFY(target->waitForRequestCompleted(id)); + QVERIFY(target->requestResponse(id).toBool()); + + id = target->readBlock(i); + QVERIFY(target->waitForRequestCompleted(id)); + readBlock = target->requestResponse(id).toByteArray(); + QCOMPARE(readBlock, QByteArray(4, char(0xaa)) + initialBlock.mid(4)); + } + } +} + +void tst_QNearFieldTagType2::dynamicMemoryModel() +{ + bool testedStatic = false; + bool testedDynamic = false; + + QList seenIds; + forever { + waitForMatchingTarget(); + if (QTest::currentTestFailed()) + return; + + QVERIFY(target->accessMethods() & QNearFieldTarget::TagTypeSpecificAccess); + + QNearFieldTarget::RequestId id = target->readBlock(0); + QVERIFY(target->waitForRequestCompleted(id)); + + const QByteArray data = target->requestResponse(id).toByteArray(); + const QByteArray uid = data.left(3) + data.mid(4, 4); + + if (seenIds.contains(uid)) + break; + else + seenIds.append(uid); + + QCOMPARE(target->version(), quint8(0x10)); + + bool dynamic = target->memorySize() > 1024; + + if (dynamic) { + testedDynamic = true; + + int totalBlocks = target->memorySize() / 4; + int sector1Blocks = qMin(totalBlocks - 256, 256); + + // default sector is sector 0 + for (int i = 3; i < 256; ++i) { + // Write 0x55 + QNearFieldTarget::RequestId id = target->writeBlock(i, deadbeef); + QVERIFY(target->waitForRequestCompleted(id)); + QVERIFY(target->requestResponse(id).toBool()); + } + + // change to sector 1 + { + QNearFieldTarget::RequestId id = target->selectSector(1); + QVERIFY(target->waitForRequestCompleted(id)); + QVERIFY(target->requestResponse(id).toBool()); + } + + for (int i = 0; i < sector1Blocks; ++i) { + QNearFieldTarget::RequestId id = target->readBlock(i); + QVERIFY(target->waitForRequestCompleted(id)); + QByteArray initialBlock = target->requestResponse(id).toByteArray(); + + QVERIFY(initialBlock.left(4) != deadbeef); + + // Write 0x55 + id = target->writeBlock(i, QByteArray(4, 0x55)); + QVERIFY(target->waitForRequestCompleted(id)); + QVERIFY(target->requestResponse(id).toBool()); + + id = target->readBlock(i); + QVERIFY(target->waitForRequestCompleted(id)); + QByteArray readBlock = target->requestResponse(id).toByteArray(); + QCOMPARE(readBlock, QByteArray(4, 0x55) + initialBlock.mid(4)); + + // Write 0xaa + id = target->writeBlock(i, QByteArray(4, char(0xaa))); + QVERIFY(target->waitForRequestCompleted(id)); + QVERIFY(target->requestResponse(id).toBool()); + + id = target->readBlock(i); + QVERIFY(target->waitForRequestCompleted(id)); + readBlock = target->requestResponse(id).toByteArray(); + QCOMPARE(readBlock, QByteArray(4, char(0xaa)) + initialBlock.mid(4)); + } + + // change to sector 0 + { + QNearFieldTarget::RequestId id = target->selectSector(0); + QVERIFY(target->waitForRequestCompleted(id)); + QVERIFY(target->requestResponse(id).toBool()); + } + + for (int i = 3; i < 256; ++i) { + QNearFieldTarget::RequestId id = target->readBlock(i); + QVERIFY(target->waitForRequestCompleted(id)); + QByteArray readBlock = target->requestResponse(id).toByteArray(); + + QVERIFY(readBlock.left(4) == deadbeef); + } + } else { + testedStatic = true; + + QNearFieldTarget::RequestId id = target->selectSector(1); + QVERIFY(target->waitForRequestCompleted(id)); + QVERIFY(!target->requestResponse(id).toBool()); + } + } + + QVERIFY(testedStatic); + QVERIFY(testedDynamic); +} + +void tst_QNearFieldTagType2::ndefMessages() +{ + QSKIP("Not implemented"); + + QByteArray firstId; + forever { + waitForMatchingTarget(); + if (QTest::currentTestFailed()) + return; + + QNearFieldTarget::RequestId id = target->readBlock(0); + QVERIFY(target->waitForRequestCompleted(id)); + + QByteArray uid = target->requestResponse(id).toByteArray().left(3); + + id = target->readBlock(1); + QVERIFY(target->waitForRequestCompleted(id)); + uid.append(target->requestResponse(id).toByteArray()); + + if (firstId.isEmpty()) + firstId = uid; + else if (firstId == uid) + break; + + QVERIFY(target->hasNdefMessage()); + + QSignalSpy ndefMessageReadSpy(target, SIGNAL(ndefMessageRead(QNdefMessage))); + + target->readNdefMessages(); + + QTRY_VERIFY(!ndefMessageReadSpy.isEmpty()); + + QList ndefMessages; + for (qsizetype i = 0; i < ndefMessageReadSpy.size(); ++i) + ndefMessages.append(ndefMessageReadSpy.at(i).first().value()); + + QList messages; + QNdefNfcTextRecord textRecord; + textRecord.setText(QStringLiteral("tst_QNearFieldTagType2::ndefMessages")); + + QNdefMessage message; + message.append(textRecord); + + if (target->memorySize() > 120) { + QNdefRecord record; + record.setTypeNameFormat(QNdefRecord::ExternalRtd); + record.setType("org.qt-project:ndefMessagesTest"); + record.setPayload(QByteArray(120, quint8(0x55))); + message.append(record); + } + + messages.append(message); + + QSignalSpy requestCompleteSpy(target, &QNearFieldTagType2::requestCompleted); + id = target->writeNdefMessages(messages); + + QTRY_VERIFY(!requestCompleteSpy.isEmpty()); + const auto completedId = + requestCompleteSpy.takeFirst().first().value(); + QCOMPARE(completedId, id); + + QVERIFY(target->hasNdefMessage()); + + ndefMessageReadSpy.clear(); + + target->readNdefMessages(); + + QTRY_VERIFY(!ndefMessageReadSpy.isEmpty()); + + QList storedMessages; + for (qsizetype i = 0; i < ndefMessageReadSpy.size(); ++i) + storedMessages.append(ndefMessageReadSpy.at(i).first().value()); + + QVERIFY(ndefMessages != storedMessages); + + QVERIFY(messages == storedMessages); + } +} + +QTEST_MAIN(tst_QNearFieldTagType2) + +// Unset the moc namespace which is not required for the following include. +#undef QT_BEGIN_MOC_NAMESPACE +#define QT_BEGIN_MOC_NAMESPACE +#undef QT_END_MOC_NAMESPACE +#define QT_END_MOC_NAMESPACE + +#include "tst_qnearfieldtagtype2.moc" diff --git a/tests/bluetoothtestdevice/CMakeLists.txt b/tests/bluetoothtestdevice/CMakeLists.txt new file mode 100644 index 0000000..e017eed --- /dev/null +++ b/tests/bluetoothtestdevice/CMakeLists.txt @@ -0,0 +1,74 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## bluetoothtestdevice Tool: +##################################################################### + +cmake_minimum_required(VERSION 3.16...3.21) + +if(NOT TARGET Qt::Bluetooth) + # for standalone build + project(bluetoothtestdevice LANGUAGES CXX) + + set(CMAKE_AUTOMOC ON) + + find_package(Qt6 REQUIRED COMPONENTS Bluetooth Core) + if(ANDROID OR APPLE) + find_package(Qt6 REQUIRED COMPONENTS Gui) + endif() + + qt_add_executable( + bluetoothtestdevice + bluetoothtestdevice.cpp + ) + +else() + + qt_internal_add_executable(bluetoothtestdevice + SOURCES + bluetoothtestdevice.cpp + ) + + if(MACOS) + # Explicitly link against the static permission plugin because tests + # currently don't have finalizers run for them except for iOS. + # TODO: Remove this when qtbase automatically runs finalizers for tests: QTBUG-112212 + target_link_libraries(bluetoothtestdevice PRIVATE Qt6::QDarwinBluetoothPermissionPlugin) + endif() + +endif() + +set_target_properties(bluetoothtestdevice PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +if(APPLE) + # Ninja has trouble with relative paths, convert to absolute as a workaround + get_filename_component(SHARED_PLIST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../shared ABSOLUTE) + if(IOS) + set_target_properties(bluetoothtestdevice PROPERTIES + MACOSX_BUNDLE_INFO_PLIST "${SHARED_PLIST_DIR}/Info.ios.plist" + ) + else() + set_target_properties(bluetoothtestdevice PROPERTIES + MACOSX_BUNDLE_INFO_PLIST "${SHARED_PLIST_DIR}/Info.macos.plist" + ) + endif() +endif() + +target_link_libraries( + bluetoothtestdevice + PUBLIC + Qt::Core + Qt::Bluetooth +) + +if(ANDROID OR APPLE) + target_link_libraries( + bluetoothtestdevice + PUBLIC + Qt::Gui + ) +endif() diff --git a/tests/bluetoothtestdevice/bluetoothtestdevice.cpp b/tests/bluetoothtestdevice/bluetoothtestdevice.cpp new file mode 100644 index 0000000..b5c32ee --- /dev/null +++ b/tests/bluetoothtestdevice/bluetoothtestdevice.cpp @@ -0,0 +1,474 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(Q_OS_ANDROID) || defined(Q_OS_DARWIN) +#include +#else +#include +#endif // Q_OS_ANDROID || Q_OS_IOS + +#if QT_CONFIG(permissions) +#include +#endif + +#include + +static const QLatin1String largeAttributeServiceUuid("1f85e37c-ac16-11eb-ae5c-93d3a763feed"); +static const QLatin1String largeAttributeCharUuid("40e4f68e-ac16-11eb-9956-cfe55a8c370c"); +static const QLatin1String largeAttributeDescUuid("44e4f68e-ac16-11eb-9956-cfe55a8c370c"); +static constexpr qsizetype largeAttributeSize{508}; // Size for char and desc values + +static const QLatin1String platformIdentifierServiceUuid("4a92cb7f-5031-4a09-8304-3e89413f458d"); +static const QLatin1String platformIdentifierCharUuid("6b0ecf7c-5f09-4c87-aaab-bb49d5d383aa"); + +static const QLatin1String + notificationIndicationTestServiceUuid("bb137ac5-5716-4b80-873b-e2d11d29efe2"); +static const QLatin1String + notificationIndicationTestChar1Uuid("6da4d652-0248-478a-a5a8-1e2f076158cc"); +static const QLatin1String + notificationIndicationTestChar2Uuid("990930f0-b9cc-4c27-8c1b-ebc2bcae5c95"); +static const QLatin1String + notificationIndicationTestChar3Uuid("9a60486b-de5b-4e03-b914-4e158c0bd388"); +static const QLatin1String + notificationIndicationTestChar4Uuid("d92435d4-6c2e-43f8-a6be-bbb66b5a3e28"); + +static const QLatin1String connectionCountServiceUuid("78c61a07-a0f9-4b92-be2d-2570d8dbf010"); +static const QLatin1String connectionCountCharUuid("9414ec2d-792f-46a2-a19e-186d0fb38a08"); + +static const QLatin1String mtuServiceUuid("9a9483eb-cf4f-4c32-9a6b-794238d5b483"); +static const QLatin1String mtuCharUuid("960d7e2a-a850-4a70-8064-cd74e9ccb6ff"); + +static const QLatin1String repeatedWriteServiceUuid("72b12a31-98ea-406d-a89d-2c932d11ff67"); +static const QLatin1String repeatedWriteTargetCharUuid("2192ee43-6d17-4e78-b286-db2c3b696833"); +static const QLatin1String repeatedWriteNotifyCharUuid("b3f9d1a2-3d55-49c9-8b29-e09cec77ff86"); + +static void establishNotifyOnWriteConnection(QLowEnergyService *svc) +{ + // Make sure that the value from the repeatedWriteTargetCharUuid + // characteristic is writted to the repeatedWriteNotifyCharUuid + // characteristic + Q_ASSERT(svc->serviceUuid() == QBluetoothUuid(repeatedWriteServiceUuid)); + QObject::connect(svc, &QLowEnergyService::characteristicChanged, svc, + [svc](const QLowEnergyCharacteristic &characteristic, + const QByteArray &newValue) + { + if (characteristic.uuid() == QBluetoothUuid(repeatedWriteTargetCharUuid)) { + auto notifyChar = svc->characteristic(QBluetoothUuid(repeatedWriteNotifyCharUuid)); + svc->writeCharacteristic(notifyChar, newValue); + } + }); +} + +int main(int argc, char *argv[]) +{ + qDebug() << "build:" << __DATE__ << __TIME__; + QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true")); +#if defined(Q_OS_ANDROID) || defined(Q_OS_DARWIN) + QGuiApplication app(argc, argv); +#else + QCoreApplication app(argc, argv); +#endif // Q_OS_ANDROID || Q_OS_IOS + +#if QT_CONFIG(permissions) + // Check Bluetooth permission and request it if the app doesn't have it + auto permissionStatus = app.checkPermission(QBluetoothPermission{}); + if (permissionStatus == Qt::PermissionStatus::Undetermined) { + app.requestPermission(QBluetoothPermission{}, + [&permissionStatus](const QPermission &permission) { + qApp->exit(); // Exit the permission request processing started below + permissionStatus = permission.status(); + }); + // Process permission request + app.exec(); + } + if (permissionStatus == Qt::PermissionStatus::Denied) { + qWarning("Bluetooth permission denied, exiting"); + return -1; + } +#endif + + // prepare list of services + QList serviceDefinitions; + + int connectioncount = 0; + { + // connection count service + QLowEnergyServiceData serviceData; + serviceData.setType(QLowEnergyServiceData::ServiceTypePrimary); + serviceData.setUuid(QBluetoothUuid(connectionCountServiceUuid)); + + QLowEnergyCharacteristicData charData; + charData.setUuid(QBluetoothUuid(connectionCountCharUuid)); + size_t size = sizeof(int); + QByteArray initialValue(size, 0); + charData.setValue(initialValue); + charData.setValueLength(size, size); + charData.setProperties(QLowEnergyCharacteristic::PropertyType::Read); + + serviceData.addCharacteristic(charData); + + serviceDefinitions << serviceData; + } + + { + // mtu size service + QLowEnergyServiceData serviceData; + serviceData.setType(QLowEnergyServiceData::ServiceTypePrimary); + serviceData.setUuid(QBluetoothUuid(mtuServiceUuid)); + + QLowEnergyCharacteristicData charData; + charData.setUuid(QBluetoothUuid(mtuCharUuid)); + size_t size = sizeof(int); + int mtu = 23; + QByteArray initialValue((const char *)&mtu, sizeof(int)); + charData.setValue(initialValue); + charData.setValueLength(size, size); + charData.setProperties(QLowEnergyCharacteristic::PropertyType::Read + | QLowEnergyCharacteristic::PropertyType::Notify); + + serviceData.addCharacteristic(charData); + + serviceDefinitions << serviceData; + } + { + // large attribute service + // + // This is a service offering a large characteristic and descriptor which can + // be read and written to + QLowEnergyServiceData serviceData; + serviceData.setType(QLowEnergyServiceData::ServiceTypePrimary); + serviceData.setUuid(QBluetoothUuid(largeAttributeServiceUuid)); + + QLowEnergyCharacteristicData charData; + charData.setUuid(QBluetoothUuid(largeAttributeCharUuid)); + QByteArray initialValue(largeAttributeSize, 0); + initialValue[0] = 0x0b; + charData.setValue(initialValue); + charData.setValueLength(largeAttributeSize, largeAttributeSize); + charData.setProperties(QLowEnergyCharacteristic::PropertyType::Read + | QLowEnergyCharacteristic::PropertyType::Write); + + + QByteArray descInitialValue(largeAttributeSize, 0); + descInitialValue[0] = 0xdd; + QLowEnergyDescriptorData descData( + QBluetoothUuid{largeAttributeDescUuid}, + descInitialValue + ); + descData.setWritePermissions(true); + descData.setReadPermissions(true); + + charData.addDescriptor(descData); + + serviceData.addCharacteristic(charData); + serviceDefinitions << serviceData; + } + + { + + // notification service + // + // This is a service which offers: + // - one characteristic which does not support notification or indication + // - one characteristic which does only support notification + // - one characteristic which does only support indication + // - one characteristic which supports both notification or indication + // to test their discovery + QLowEnergyServiceData serviceData; + + serviceData.setType(QLowEnergyServiceData::ServiceTypePrimary); + serviceData.setUuid(QBluetoothUuid(notificationIndicationTestServiceUuid)); + + { + QLowEnergyCharacteristicData charData; + charData.setUuid(QBluetoothUuid(notificationIndicationTestChar1Uuid)); + QByteArray initialValue(8, 0); + initialValue[0] = 0x0b; + charData.setValue(initialValue); + charData.setValueLength(8, 8); + charData.setProperties(QLowEnergyCharacteristic::PropertyType::Read); + + serviceData.addCharacteristic(charData); + } + { + QLowEnergyCharacteristicData charData; + charData.setUuid(QBluetoothUuid(notificationIndicationTestChar2Uuid)); + QByteArray initialValue(8, 0); + initialValue[0] = 0x0b; + charData.setValue(initialValue); + charData.setValueLength(8, 8); + charData.setProperties(QLowEnergyCharacteristic::PropertyType::Read + | QLowEnergyCharacteristic::PropertyType::Notify); + + const QLowEnergyDescriptorData clientConfig( + QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration, + QLowEnergyCharacteristic::CCCDDisable); + charData.addDescriptor(clientConfig); + + serviceData.addCharacteristic(charData); + } + { + QLowEnergyCharacteristicData charData; + charData.setUuid(QBluetoothUuid(notificationIndicationTestChar3Uuid)); + QByteArray initialValue(8, 0); + initialValue[0] = 0x0b; + charData.setValue(initialValue); + charData.setValueLength(8, 8); + charData.setProperties(QLowEnergyCharacteristic::PropertyType::Read + | QLowEnergyCharacteristic::PropertyType::Indicate); + + const QLowEnergyDescriptorData clientConfig( + QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration, + QLowEnergyCharacteristic::CCCDDisable); + charData.addDescriptor(clientConfig); + + serviceData.addCharacteristic(charData); + } + { + QLowEnergyCharacteristicData charData; + charData.setUuid(QBluetoothUuid(notificationIndicationTestChar4Uuid)); + QByteArray initialValue(8, 0); + initialValue[0] = 0x0b; + charData.setValue(initialValue); + charData.setValueLength(8, 8); + charData.setProperties(QLowEnergyCharacteristic::PropertyType::Read + | QLowEnergyCharacteristic::PropertyType::Notify + | QLowEnergyCharacteristic::PropertyType::Indicate); + + const QLowEnergyDescriptorData clientConfig( + QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration, + QLowEnergyCharacteristic::CCCDDisable); + charData.addDescriptor(clientConfig); + + serviceData.addCharacteristic(charData); + } + + serviceDefinitions << serviceData; + } + + { + // server's platform identifier service + QLowEnergyServiceData serviceData; + serviceData.setType(QLowEnergyServiceData::ServiceTypePrimary); + serviceData.setUuid(QBluetoothUuid(platformIdentifierServiceUuid)); + + QLowEnergyCharacteristicData charData; + charData.setUuid(QBluetoothUuid(platformIdentifierCharUuid)); +#if defined(Q_OS_ANDROID) + QByteArray platformIdentifier("android"); +#elif defined(QT_OS_WIN) + QByteArray platformIdentifier("windows"); +#elif defined(Q_OS_DARWIN) + QByteArray platformIdentifier("darwin"); +#elif defined(Q_OS_LINUX) + QByteArray platformIdentifier("linux"); +#else + QByteArray platformIdentifier("unspecified"); +#endif + qDebug() << "Server will report it is running on: " << platformIdentifier; + charData.setValue(platformIdentifier); + charData.setProperties(QLowEnergyCharacteristic::PropertyType::Read); + + serviceData.addCharacteristic(charData); + + serviceDefinitions << serviceData; + } + + { + // repeated characteristic write service + // + // This service offers an 8 bytes large characteristic which can + // be read and written. Once the value is updated, it writes the + // same value to the other characteristic, which notifies the client + // about its change. This way we can make sure that all write were + // successful and happened in the right order. + // We can't use one characteristics for writing and notification, + // because on most backends when the characteristics was written + // by the client, there will be no notification about it. + QLowEnergyServiceData serviceData; + serviceData.setType(QLowEnergyServiceData::ServiceTypePrimary); + serviceData.setUuid(QBluetoothUuid(repeatedWriteServiceUuid)); + + { + // The characteristics to be written by the client. + QLowEnergyCharacteristicData charData; + charData.setUuid(QBluetoothUuid(repeatedWriteTargetCharUuid)); + QByteArray initialValue(8, 0); + charData.setValue(initialValue); + charData.setValueLength(8, 8); + charData.setProperties(QLowEnergyCharacteristic::PropertyType::Read + | QLowEnergyCharacteristic::PropertyType::Write); + + serviceData.addCharacteristic(charData); + } + { + // The characteristics written by the server, + // it will send notifications to the client. + QLowEnergyCharacteristicData charData; + charData.setUuid(QBluetoothUuid(repeatedWriteNotifyCharUuid)); + QByteArray initialValue(8, 0); + charData.setValue(initialValue); + charData.setValueLength(8, 8); + charData.setProperties(QLowEnergyCharacteristic::PropertyType::Read + | QLowEnergyCharacteristic::PropertyType::Write + | QLowEnergyCharacteristic::PropertyType::Notify); + + const QLowEnergyDescriptorData clientConfig( + QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration, + QLowEnergyCharacteristic::CCCDDisable); + charData.addDescriptor(clientConfig); + + serviceData.addCharacteristic(charData); + } + + serviceDefinitions << serviceData; + } + +#ifndef Q_OS_IOS + auto localAdapters = QBluetoothLocalDevice::allDevices(); + if (localAdapters.isEmpty()) { + qWarning() << "Bluetoothtestdevice did not find a local adapter"; + return EXIT_FAILURE; + } + QBluetoothLocalDevice adapter(localAdapters.back().address()); + adapter.setHostMode(QBluetoothLocalDevice::HostDiscoverable); +#endif // Q_OS_IOS + + // Advertising data + QLowEnergyAdvertisingData advertisingData; + advertisingData.setDiscoverability(QLowEnergyAdvertisingData::DiscoverabilityGeneral); + advertisingData.setIncludePowerLevel(true); + advertisingData.setLocalName("BluetoothTestDevice"); + QList serviceUuids; + for (const auto &serviceData : serviceDefinitions) { + serviceUuids << serviceData.uuid(); + } + // leads to too large advertising data + // advertisingData.setServices(serviceUuids); + + // start advertising +#ifndef Q_OS_IOS + auto devices = QBluetoothLocalDevice::allDevices(); + qDebug() << "advertising on" << devices.back().address(); + const QScopedPointer leController( + QLowEnergyController::createPeripheral(devices.back().address())); +#else + const QScopedPointer leController( + QLowEnergyController::createPeripheral()); +#endif // Q_OS_IOS + + QObject::connect(leController.data(), &QLowEnergyController::errorOccurred, + [](QLowEnergyController::Error error) { + qDebug() << "Bluetoothtestdevice QLowEnergyController errorOccurred:" << error; + }); + + QObject::connect(leController.data(), &QLowEnergyController::stateChanged, + [](QLowEnergyController::ControllerState state) { + qDebug() << "Bluetoothtestdevice QLowEnergyController stateChanged:" << state; + }); + + + QList> services; + + for (const auto &serviceData : serviceDefinitions) { + services.emplaceBack(leController->addService(serviceData)); + } + + establishNotifyOnWriteConnection(services[5].get()); + + leController->startAdvertising(QLowEnergyAdvertisingParameters(), advertisingData, + advertisingData); + + + auto reconnect = [&connectioncount, &leController, advertisingData, &services, serviceDefinitions]() { + connectioncount++; + for (qsizetype i = 0; i < services.size(); ++i) { + services[i].reset(leController->addService(serviceDefinitions[i])); + } + + establishNotifyOnWriteConnection(services[5].get()); + + { + // set connection counter + Q_ASSERT(services[0]->serviceUuid() + == QBluetoothUuid(connectionCountServiceUuid)); + QByteArray value((const char *)&connectioncount, sizeof(int)); + QLowEnergyCharacteristic characteristic = services[0]->characteristic( + QBluetoothUuid(connectionCountCharUuid)); + Q_ASSERT(characteristic.isValid()); + services[0]->writeCharacteristic(characteristic, value); + } + + bool allValid = true; + for (const auto &service : services) { + allValid = allValid & !service.isNull(); + } + + if (allValid){ + leController->startAdvertising(QLowEnergyAdvertisingParameters(), advertisingData, + advertisingData); + qDebug() << "starting advertising for " << connectioncount << "th time."; + } + else + qDebug() << "Cannot start advertising: Service not valid."; + }; + QObject::connect(leController.data(), &QLowEnergyController::disconnected, reconnect); + + QObject::connect(leController.data(), &QLowEnergyController::mtuChanged, [&services](int mtu) { + qDebug() << "MTU changed, callback called."; + Q_ASSERT(services[1]->serviceUuid() == QBluetoothUuid(mtuServiceUuid)); + QByteArray value((const char *)&mtu, sizeof(int)); + QLowEnergyCharacteristic characteristic = + services[1]->characteristic(QBluetoothUuid(mtuCharUuid)); + Q_ASSERT(characteristic.isValid()); + services[1]->writeCharacteristic(characteristic, value); + }); + + QTimer notificationTestTimer; + quint64 currentCharacteristicValue = 0; + const auto characteristicChanger = [&services, ¤tCharacteristicValue]() { + QByteArray value((const char *)¤tCharacteristicValue, 8); + + Q_ASSERT(services[3]->serviceUuid() + == QBluetoothUuid(notificationIndicationTestServiceUuid)); + { + QLowEnergyCharacteristic characteristic = services[3]->characteristic( + QBluetoothUuid(notificationIndicationTestChar2Uuid)); + Q_ASSERT(characteristic.isValid()); + services[3]->writeCharacteristic(characteristic, + value); // Potentially causes notification. + } + { + QLowEnergyCharacteristic characteristic = services[3]->characteristic( + QBluetoothUuid(notificationIndicationTestChar3Uuid)); + Q_ASSERT(characteristic.isValid()); + services[3]->writeCharacteristic(characteristic, + value); // Potentially causes notification. + } + { + QLowEnergyCharacteristic characteristic = services[3]->characteristic( + QBluetoothUuid(notificationIndicationTestChar4Uuid)); + Q_ASSERT(characteristic.isValid()); + services[3]->writeCharacteristic(characteristic, + value); // Potentially causes notification. + } + + ++currentCharacteristicValue; + }; + QObject::connect(¬ificationTestTimer, &QTimer::timeout, characteristicChanger); + notificationTestTimer.start(100); + + return app.exec(); +} diff --git a/tests/bttestui/Button.qml b/tests/bttestui/Button.qml new file mode 100644 index 0000000..004aca7 --- /dev/null +++ b/tests/bttestui/Button.qml @@ -0,0 +1,28 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick + +Rectangle +{ + id: button + signal clicked() + property string buttonText + width: powerOn.width + 10 + height: powerOn.height + 10 + border.color: "black" + border.width: 2 + radius: 4 + + + Text { + id: powerOn + text: buttonText + font.pointSize: 16 + anchors.centerIn: parent + } + MouseArea { + anchors.fill: parent + onClicked: button.clicked() + } +} diff --git a/tests/bttestui/CMakeLists.txt b/tests/bttestui/CMakeLists.txt new file mode 100644 index 0000000..4daee3d --- /dev/null +++ b/tests/bttestui/CMakeLists.txt @@ -0,0 +1,89 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## bttestui Binary: +##################################################################### + +cmake_minimum_required(VERSION 3.16...3.21) + +# Resources: +set(bttest_resource_files + "Button.qml" + "main.qml" +) + +if(NOT TARGET Qt::Bluetooth) + # for standalone build + project(bttestui LANGUAGES CXX) + + set(CMAKE_AUTOMOC ON) + + find_package(Qt6 REQUIRED COMPONENTS Bluetooth Core Gui Quick) + + qt_add_executable(bttestui + btlocaldevice.cpp btlocaldevice.h + main.cpp + ) + + target_link_libraries(bttestui PUBLIC + Qt::Bluetooth + Qt::Gui + Qt::Quick + ) + + qt_add_resources(bttestui "bttest" + PREFIX + "/" + FILES + ${bttest_resource_files} + ) +else() + # in-tree build + qt_internal_add_executable(bttestui + GUI + SOURCES + btlocaldevice.cpp btlocaldevice.h + main.cpp + LIBRARIES + Qt::Bluetooth + Qt::Gui + Qt::Quick + ) + + qt_internal_add_resource(bttestui "bttest" + PREFIX + "/" + FILES + ${bttest_resource_files} + ) + + if(MACOS) + # Explicitly link against the static permission plugin because tests + # currently don't have finalizers run for them except for iOS. + # TODO: Remove this when qtbase automatically runs finalizers for tests: QTBUG-112212 + target_link_libraries(bttestui PRIVATE Qt6::QDarwinBluetoothPermissionPlugin) + endif() + +endif() + +set_target_properties(bttestui PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +if(APPLE) + # Ninja has trouble with relative paths, convert to absolute as a workaround + get_filename_component(SHARED_PLIST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../shared ABSOLUTE) + if(IOS) + set_target_properties(bttestui PROPERTIES + MACOSX_BUNDLE_INFO_PLIST "${SHARED_PLIST_DIR}/Info.ios.plist" + ) + else() + set_target_properties(bttestui PROPERTIES + MACOSX_BUNDLE_INFO_PLIST "${SHARED_PLIST_DIR}/Info.macos.plist" + ) + endif() +endif() + + diff --git a/tests/bttestui/README b/tests/bttestui/README new file mode 100644 index 0000000..e76ea90 --- /dev/null +++ b/tests/bttestui/README @@ -0,0 +1,21 @@ +This application is a graphical test application for Bluetooth. +It is able to invoke close to all API features offered by the QtBluetooth API. +It includes features like: + +1.) Turning Bluetooth on/off +2.) Pairing with remote devices +3.) Discovery of services and devices +4.) Connecting to a remote SPP profile using RFCOMM +5.) Start of a SPP Bluetooth server + +Some features require interaction with remote devices. In particular this involves +pairing and the direct connecting to remote SPP servers. The remote test device address +is hardcoded via BTCHAT_DEVICE_ADDR. + +Also, the test application reuses the service uuid employed by the btchat example +(see examples/bluetooth/btchat). It can either directly connect to the remote +btchat app server or create its own btchat server. + +Note that the application is purposely very liberal with regards to the amount of its +debug output. This is done to be able to confirm proper working of the tested +APIs. diff --git a/tests/bttestui/btlocaldevice.cpp b/tests/bttestui/btlocaldevice.cpp new file mode 100644 index 0000000..19e78bb --- /dev/null +++ b/tests/bttestui/btlocaldevice.cpp @@ -0,0 +1,1594 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "btlocaldevice.h" +#include +#include +#include +#include +#include +#include +#include + +#define BTCHAT_DEVICE_ADDR "00:15:83:38:17:C3" + +//same uuid as examples/bluetooth/btchat +//the reverse UUID is only used on Android to counter +//https://issuetracker.google.com/issues/37076498 (tracked via QTBUG-61392) +#define TEST_SERVICE_UUID "e8e10f95-1a70-4b27-9ccf-02010264e9c8" +#define TEST_REVERSE_SERVICE_UUID "c8e96402-0102-cf9c-274b-701a950fe1e8" + +#define SOCKET_PROTOCOL QBluetoothServiceInfo::RfcommProtocol +//#define SOCKET_PROTOCOL QBluetoothServiceInfo::L2capProtocol + +using namespace Qt::Literals::StringLiterals; +// Main service used for testing read/write/notify +static constexpr auto leServiceUuid{"10f5e37c-ac16-11eb-ae5c-93d3a763feed"_L1}; +static constexpr auto leCharUuid1{"11f4f68e-ac16-11eb-9956-cfe55a8ccafe"_L1}; +static constexpr auto leCharUuid2{"12f4f68e-ac16-11eb-9956-cfe55a8ccafe"_L1}; +// Service for testing the included services +static constexpr auto leSecondServiceUuid{"20f5e37c-ac16-11eb-ae5c-93d3a763feed"_L1}; +static constexpr auto leSecondServiceCharUuid1{"21f4f68e-ac16-11eb-9956-cfe55a8ccafe"_L1}; +// Service for testing the secondary service and other miscellaneous +static constexpr auto leThirdServiceUuid{"30f5e37c-ac16-11eb-ae5c-93d3a763feed"_L1}; +static constexpr auto leThirdServiceCharUuid1{"31f4f68e-ac16-11eb-9956-cfe55a8ccafe"_L1}; + +// Used for finding a matching LE peripheral device. Typically the default BtTestUi is ok +// when running against macOS/iOS/Linux peripheral, but with Android this needs to be adjusted +// to device's name. We can't use bluetooth address for matching as the public address of the +// peripheral may change +static const auto leRemotePeriphreralDeviceName = "BtTestUi"_L1; +static const qsizetype leCharacteristicSize = 4; // Set to 1...512 bytes +static QByteArray leCharacteristicValue = QByteArray{leCharacteristicSize, 1}; +static QByteArray leDescriptorValue = "a descriptor value"_ba; +static auto leSecondCharacteristicValue = QByteArray{leCharacteristicSize, 2}; +static quint8 leCharacteristicValueUpdate = 1; +static char leDescriptorValueUpdate = 'b'; + +// String tables to shorten the enum strings to fit the screen estate. +// The values in the tables must be in same order as the corresponding enums +static constexpr const char* controllerStateString[] = { + "Unconnected", + "Connecting", + "Connected", + "Discovering", + "Discovered", + "Closing", + "Advertising", +}; + +static constexpr const char* controllerErrorString[] = { + "None", + "UnknownError", + "UnknownRemDev", + "NetworkError", + "InvAdapter", + "ConnectionErr", + "AdvertisingErr", + "RemHostClosed", + "AuthError", + "MissingPerm", + "RssiError" +}; + +static constexpr const char* serviceStateString[] = { + "InvalidService", + "RemoteService", + "RemDiscovering", + "RemDiscovered", + "LocalService", +}; + +static constexpr const char* serviceErrorString[] = { + "None", + "Operation", + "CharWrite", + "DescWrite", + "Unknown", + "CharRead", + "DescRead", +}; + +BtLocalDevice::BtLocalDevice(QObject *parent) + : QObject(parent), securityFlags(QBluetooth::Security::NoSecurity) +{ + localDevice = new QBluetoothLocalDevice(this); + connect(localDevice, &QBluetoothLocalDevice::errorOccurred, this, + &BtLocalDevice::errorOccurred); + connect(localDevice, &QBluetoothLocalDevice::hostModeStateChanged, + this, &BtLocalDevice::hostModeStateChanged); + connect(localDevice, &QBluetoothLocalDevice::pairingFinished, + this, &BtLocalDevice::pairingFinished); + connect(localDevice, &QBluetoothLocalDevice::deviceConnected, + this, &BtLocalDevice::connected); + connect(localDevice, &QBluetoothLocalDevice::deviceDisconnected, + this, &BtLocalDevice::disconnected); + + if (localDevice->isValid()) { + deviceAgent = new QBluetoothDeviceDiscoveryAgent(this); + connect(deviceAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, + this, &BtLocalDevice::deviceDiscovered); + connect(deviceAgent, &QBluetoothDeviceDiscoveryAgent::deviceUpdated, + this, &BtLocalDevice::deviceUpdated); + connect(deviceAgent, &QBluetoothDeviceDiscoveryAgent::finished, + this, &BtLocalDevice::discoveryFinished); + connect(deviceAgent, &QBluetoothDeviceDiscoveryAgent::errorOccurred, this, + &BtLocalDevice::discoveryError); + connect(deviceAgent, &QBluetoothDeviceDiscoveryAgent::canceled, + this, &BtLocalDevice::discoveryCanceled); + + serviceAgent = new QBluetoothServiceDiscoveryAgent(this); + connect(serviceAgent, &QBluetoothServiceDiscoveryAgent::serviceDiscovered, + this, &BtLocalDevice::serviceDiscovered); + connect(serviceAgent, &QBluetoothServiceDiscoveryAgent::finished, + this, &BtLocalDevice::serviceDiscoveryFinished); + connect(serviceAgent, &QBluetoothServiceDiscoveryAgent::canceled, + this, &BtLocalDevice::serviceDiscoveryCanceled); + connect(serviceAgent, &QBluetoothServiceDiscoveryAgent::errorOccurred, this, + &BtLocalDevice::serviceDiscoveryError); + + socket = new QBluetoothSocket(SOCKET_PROTOCOL, this); + connect(socket, &QBluetoothSocket::stateChanged, + this, &BtLocalDevice::socketStateChanged); + connect(socket, &QBluetoothSocket::errorOccurred, this, &BtLocalDevice::socketError); + connect(socket, &QBluetoothSocket::connected, this, &BtLocalDevice::socketConnected); + connect(socket, &QBluetoothSocket::disconnected, this, &BtLocalDevice::socketDisconnected); + connect(socket, &QIODevice::readyRead, this, &BtLocalDevice::readData); + connect(socket, &QBluetoothSocket::bytesWritten, this, [](qint64 bytesWritten){ + qDebug() << "Bytes Written to Client socket:" << bytesWritten; + }); + setSecFlags(static_cast(socket->preferredSecurityFlags())); + + server = new QBluetoothServer(SOCKET_PROTOCOL, this); + connect(server, &QBluetoothServer::newConnection, this, &BtLocalDevice::serverNewConnection); + connect(server, &QBluetoothServer::errorOccurred, this, &BtLocalDevice::serverError); + } +} + +BtLocalDevice::~BtLocalDevice() +{ + while (!serverSockets.isEmpty()) + { + QBluetoothSocket* s = serverSockets.takeFirst(); + s->abort(); + s->deleteLater(); + } +} + +QBluetooth::SecurityFlags BtLocalDevice::secFlags() const +{ + return securityFlags; +} + +void BtLocalDevice::setSecFlags(int newFlags) +{ + QBluetooth::SecurityFlags fl(newFlags); + + if (securityFlags != fl) { + securityFlags = fl; + emit secFlagsChanged(); + } +} + +QString BtLocalDevice::hostMode() const +{ + if (localDevice) { + switch (localDevice->hostMode()) { + case QBluetoothLocalDevice::HostDiscoverable: + return QStringLiteral("HostMode: Discoverable"); + case QBluetoothLocalDevice::HostConnectable: + return QStringLiteral("HostMode: Connectable"); + case QBluetoothLocalDevice::HostDiscoverableLimitedInquiry: + return QStringLiteral("HostMode: DiscoverableLimit"); + case QBluetoothLocalDevice::HostPoweredOff: + return QStringLiteral("HostMode: Powered Off"); + } + } + + return QStringLiteral("HostMode: "); +} + +void BtLocalDevice::setHostMode(int newMode) +{ + if (localDevice) + localDevice->setHostMode(static_cast(newMode)); +} + +void BtLocalDevice::requestPairingUpdate(bool isPairing) +{ + QBluetoothAddress baddr(BTCHAT_DEVICE_ADDR); + if (!localDevice || baddr.isNull()) + return; + + if (isPairing) { + //toggle between authorized and non-authorized pairing to achieve better + //level of testing + static short pairing = 0; + if ((pairing%2) == 1) + localDevice->requestPairing(baddr, QBluetoothLocalDevice::Paired); + else + localDevice->requestPairing(baddr, QBluetoothLocalDevice::AuthorizedPaired); + pairing++; + } else { + localDevice->requestPairing(baddr, QBluetoothLocalDevice::Unpaired); + } + + for (qsizetype i = 0; i < foundTestServers.size(); ++i) { + if (isPairing) + localDevice->requestPairing(foundTestServers.at(i).device().address(), + QBluetoothLocalDevice::Paired); + else + localDevice->requestPairing(foundTestServers.at(i).device().address(), + QBluetoothLocalDevice::Unpaired); + } +} + +void BtLocalDevice::pairingFinished(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing) +{ + qDebug() << "(Un)Pairing finished" << address.toString() << pairing; +} + +void BtLocalDevice::connected(const QBluetoothAddress &addr) +{ + qDebug() << "Newly connected device" << addr.toString(); +} + +void BtLocalDevice::disconnected(const QBluetoothAddress &addr) +{ + qDebug() << "Newly disconnected device" << addr.toString(); +} + +void BtLocalDevice::cycleSecurityFlags() +{ + if (securityFlags.testFlag(QBluetooth::Security::Secure)) + setSecFlags(QBluetooth::SecurityFlags(QBluetooth::Security::NoSecurity)); + else if (securityFlags.testFlag(QBluetooth::Security::Encryption)) + setSecFlags(secFlags() | QBluetooth::Security::Secure); + else if (securityFlags.testFlag(QBluetooth::Security::Authentication)) + setSecFlags(secFlags() | QBluetooth::Security::Encryption); + else if (securityFlags.testFlag(QBluetooth::Security::Authorization)) + setSecFlags(secFlags() | QBluetooth::Security::Authentication); + else + setSecFlags(secFlags() | QBluetooth::Security::Authorization); +} + +void BtLocalDevice::deviceDiscovered(const QBluetoothDeviceInfo &info) +{ + QString services; + if (info.serviceClasses() & QBluetoothDeviceInfo::PositioningService) + services += "Position|"; + if (info.serviceClasses() & QBluetoothDeviceInfo::NetworkingService) + services += "Network|"; + if (info.serviceClasses() & QBluetoothDeviceInfo::RenderingService) + services += "Rendering|"; + if (info.serviceClasses() & QBluetoothDeviceInfo::CapturingService) + services += "Capturing|"; + if (info.serviceClasses() & QBluetoothDeviceInfo::ObjectTransferService) + services += "ObjectTra|"; + if (info.serviceClasses() & QBluetoothDeviceInfo::AudioService) + services += "Audio|"; + if (info.serviceClasses() & QBluetoothDeviceInfo::TelephonyService) + services += "Telephony|"; + if (info.serviceClasses() & QBluetoothDeviceInfo::InformationService) + services += "Information|"; + + services.truncate(services.size()-1); //cut last '/' + + qDebug() << "Found new device: " << info.name() << info.isValid() << info.address().toString() + << info.rssi() << info.majorDeviceClass() + << info.minorDeviceClass() << services; + // With LE we match the device by its name as the public bluetooth address can change + if (info.name() == leRemotePeriphreralDeviceName) { + qDebug() << "#### Matching LE peripheral device found"; + leRemotePeripheralDevice = info; + latestRSSI = QByteArray::number(info.rssi()); + emit leChanged(); + } +} + +void BtLocalDevice::deviceUpdated(const QBluetoothDeviceInfo &info, + QBluetoothDeviceInfo::Fields updateFields) +{ + if (info.name() == leRemotePeriphreralDeviceName + && updateFields & QBluetoothDeviceInfo::Field::RSSI) { + qDebug() << "#### LE peripheral RSSI updated during scan"; + latestRSSI = QByteArray::number(info.rssi()); + emit leChanged(); + } +} + +void BtLocalDevice::discoveryFinished() +{ + qDebug() << "###### Device Discovery Finished"; +} + +void BtLocalDevice::discoveryCanceled() +{ + qDebug() << "###### Device Discovery Canceled"; +} + +void BtLocalDevice::discoveryError(QBluetoothDeviceDiscoveryAgent::Error error) +{ + auto *client = qobject_cast(sender()); + if (!client) + return; + qDebug() << "###### Device Discovery Error:" << error << (client ? client->errorString() : QString()); +} + +void BtLocalDevice::startDiscovery() +{ + if (deviceAgent) { + qDebug() << "###### Starting device discovery process"; + deviceAgent->start(QBluetoothDeviceDiscoveryAgent::ClassicMethod); + } +} + +void BtLocalDevice::stopDiscovery() +{ + if (deviceAgent) { + qDebug() << "Stopping device discovery process"; + deviceAgent->stop(); + } +} + +void BtLocalDevice::startServiceDiscovery(bool isMinimalDiscovery) +{ + if (serviceAgent) { + serviceAgent->setRemoteAddress(QBluetoothAddress()); + + qDebug() << "###### Starting service discovery process"; + serviceAgent->start(isMinimalDiscovery + ? QBluetoothServiceDiscoveryAgent::MinimalDiscovery + : QBluetoothServiceDiscoveryAgent::FullDiscovery); + } +} + +void BtLocalDevice::startTargettedServiceDiscovery() +{ + if (serviceAgent) { + const QBluetoothAddress baddr(BTCHAT_DEVICE_ADDR); + qDebug() << "###### Starting service discovery on" + << baddr.toString(); + if (baddr.isNull()) + return; + + if (!serviceAgent->setRemoteAddress(baddr)) { + qWarning() << "###### Cannot set remote address. Aborting"; + return; + } + + serviceAgent->start(); + } +} + +void BtLocalDevice::stopServiceDiscovery() +{ + if (serviceAgent) { + qDebug() << "Stopping service discovery process"; + serviceAgent->stop(); + } +} + +void BtLocalDevice::serviceDiscovered(const QBluetoothServiceInfo &info) +{ + QStringList classIds; + const QList uuids = info.serviceClassUuids(); + for (const QBluetoothUuid &uuid : uuids) + classIds.append(uuid.toString()); + qDebug() << "$$ Found new service" << info.device().address().toString() + << info.serviceUuid() << info.serviceName() << info.serviceDescription() << classIds; + + bool matchingService = + (info.serviceUuid() == QBluetoothUuid(QString(TEST_SERVICE_UUID))); +#ifdef Q_OS_ANDROID + // QTBUG-61392 + matchingService = matchingService + || (info.serviceUuid() == QBluetoothUuid(QString(TEST_REVERSE_SERVICE_UUID))); +#endif + + if (matchingService + || info.serviceClassUuids().contains(QBluetoothUuid(QString(TEST_SERVICE_UUID)))) + { + //This is here to detect the test server for SPP testing later on + bool alreadyKnown = false; + for (const QBluetoothServiceInfo& found : std::as_const(foundTestServers)) { + if (found.device().address() == info.device().address()) { + alreadyKnown = true; + break; + } + } + + if (!alreadyKnown) { + foundTestServers.append(info); + qDebug() << "@@@@@@@@ Adding:" << info.device().address().toString(); + } + } +} + +void BtLocalDevice::serviceDiscoveryFinished() +{ + qDebug() << "###### Service Discovery Finished"; +} + +void BtLocalDevice::serviceDiscoveryCanceled() +{ + qDebug() << "###### Service Discovery Canceled"; +} + +void BtLocalDevice::serviceDiscoveryError(QBluetoothServiceDiscoveryAgent::Error error) +{ + auto *client = qobject_cast(sender()); + if (!client) + return; + qDebug() << "###### Service Discovery Error:" << error << (client ? client->errorString() : QString()); +} + +void BtLocalDevice::dumpServiceDiscovery() +{ + if (deviceAgent) { + qDebug() << "Device Discovery active:" << deviceAgent->isActive(); + qDebug() << "Error:" << deviceAgent->error() << deviceAgent->errorString(); + const QList list = deviceAgent->discoveredDevices(); + qDebug() << "Discovered Devices:" << list.size(); + + for (const QBluetoothDeviceInfo &info : list) + qDebug() << info.name() << info.address().toString() << info.rssi(); + } + if (serviceAgent) { + qDebug() << "Service Discovery active:" << serviceAgent->isActive(); + qDebug() << "Error:" << serviceAgent->error() << serviceAgent->errorString(); + const QList list = serviceAgent->discoveredServices(); + qDebug() << "Discovered Services:" << list.size(); + + for (const QBluetoothServiceInfo &i : list) { + qDebug() << i.device().address().toString() << i.device().name() << i.serviceName(); + } + + qDebug() << "###### TestServer offered by:"; + for (const QBluetoothServiceInfo& found : std::as_const(foundTestServers)) { + qDebug() << found.device().name() << found.device().address().toString(); + } + } +} + +void BtLocalDevice::connectToService() +{ + if (socket) { + if (socket->preferredSecurityFlags() != securityFlags) + socket->setPreferredSecurityFlags(securityFlags); + socket->connectToService(QBluetoothAddress(BTCHAT_DEVICE_ADDR),QBluetoothUuid(QString(TEST_SERVICE_UUID))); + } +} + +void BtLocalDevice::connectToServiceViaSearch() +{ + if (socket) { + qDebug() << "###### Connecting to service socket"; + if (!foundTestServers.isEmpty()) { + if (socket->preferredSecurityFlags() != securityFlags) + socket->setPreferredSecurityFlags(securityFlags); + + QBluetoothServiceInfo info = foundTestServers.at(0); + socket->connectToService(info); + } else { + qWarning() << "Perform search for test service before triggering this function"; + } + } +} + +void BtLocalDevice::disconnectToService() +{ + if (socket) { + qDebug() << "###### Disconnecting socket"; + socket->disconnectFromService(); + } +} + +void BtLocalDevice::closeSocket() +{ + if (socket) { + qDebug() << "###### Closing socket"; + socket->close(); + } + + if (!serverSockets.isEmpty()) { + qDebug() << "###### Closing server sockets"; + for (QBluetoothSocket *s : serverSockets) + s->close(); + } +} + +void BtLocalDevice::abortSocket() +{ + if (socket) { + qDebug() << "###### Disconnecting socket"; + socket->abort(); + } + + if (!serverSockets.isEmpty()) { + qDebug() << "###### Closing server sockets"; + for (QBluetoothSocket *s : serverSockets) + s->abort(); + } +} + +void BtLocalDevice::socketConnected() +{ + qDebug() << "###### Socket connected"; +} + +void BtLocalDevice::socketDisconnected() +{ + qDebug() << "###### Socket disconnected"; +} + +void BtLocalDevice::socketError(QBluetoothSocket::SocketError error) +{ + auto *client = qobject_cast(sender()); + + qDebug() << "###### Socket error" << error << (client ? client->errorString() : QString()); +} + +void BtLocalDevice::socketStateChanged(QBluetoothSocket::SocketState state) +{ + qDebug() << "###### Socket state" << state; + emit socketStateUpdate(static_cast(state)); +} + +void BtLocalDevice::dumpSocketInformation() +{ + if (socket) { + qDebug() << "*******************************"; + qDebug() << "Local info (addr, name, port):" << socket->localAddress().toString() + << socket->localName() << socket->localPort(); + qDebug() << "Peer Info (adr, name, port):" << socket->peerAddress().toString() + << socket->peerName() << socket->peerPort(); + qDebug() << "socket type:" << socket->socketType(); + qDebug() << "socket state:" << socket->state(); + qDebug() << "socket bytesAvailable()" << socket->bytesAvailable(); + QString tmp; + switch (socket->error()) { + case QBluetoothSocket::SocketError::NoSocketError: tmp += "NoSocketError"; break; + case QBluetoothSocket::SocketError::UnknownSocketError: tmp += "UnknownSocketError"; break; + case QBluetoothSocket::SocketError::HostNotFoundError: tmp += "HostNotFoundError"; break; + case QBluetoothSocket::SocketError::ServiceNotFoundError: tmp += "ServiceNotFound"; break; + case QBluetoothSocket::SocketError::NetworkError: tmp += "NetworkError"; break; + //case QBluetoothSocket::SocketError::OperationError: tmp+= "OperationError"; break; + case QBluetoothSocket::SocketError::UnsupportedProtocolError: tmp += "UnsupportedProtocolError"; break; + case QBluetoothSocket::SocketError::MissingPermissionsError: tmp += "MissingPermissionsError"; break; + default: tmp+= "Undefined"; break; + } + + qDebug() << "socket error:" << tmp << socket->errorString(); + } else { + qDebug() << "No valid socket existing"; + } +} + +void BtLocalDevice::writeData() +{ + const char * testData = "ABCABC\n"; + if (socket && socket->state() == QBluetoothSocket::SocketState::ConnectedState) { + socket->write(testData); + } + for (QBluetoothSocket* client : serverSockets) { + client->write(testData); + } +} + +void BtLocalDevice::readData() +{ + if (socket) { + while (socket->canReadLine()) { + QByteArray line = socket->readLine().trimmed(); + qDebug() << ">> peer(" << socket->peerName() << socket->peerAddress() + << socket->peerPort() << ") local(" + << socket->localName() << socket->localAddress() << socket->localPort() + << ")>>" << QString::fromUtf8(line.constData(), line.size()); + } + } +} + +void BtLocalDevice::serverError(QBluetoothServer::Error error) +{ + qDebug() << "###### Server socket error" << error; +} + +void BtLocalDevice::serverListenPort() +{ + if (server && localDevice) { + if (server->isListening() || serviceInfo.isRegistered()) { + qDebug() << "###### Already listening" << serviceInfo.isRegistered(); + return; + } + + if (server->securityFlags() != securityFlags) { + qDebug() << "###### Setting security policy on server socket" << securityFlags; + server->setSecurityFlags(securityFlags); + } + + qDebug() << "###### Start listening via port"; + bool ret = server->listen(localDevice->address()); + qDebug() << "###### Listening(Expecting TRUE):" << ret; + + if (!ret) + return; + + QBluetoothServiceInfo::Sequence profileSequence; + QBluetoothServiceInfo::Sequence classId; + classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ServiceClassUuid::SerialPort)); + classId << QVariant::fromValue(quint16(0x100)); + profileSequence.append(QVariant::fromValue(classId)); + serviceInfo.setAttribute(QBluetoothServiceInfo::BluetoothProfileDescriptorList, + profileSequence); + + classId.clear(); + classId << QVariant::fromValue(QBluetoothUuid(QString(TEST_SERVICE_UUID))); + classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ServiceClassUuid::SerialPort)); + serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classId); + + // Service name, description and provider + serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceName, tr("Bt Chat Server")); + serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceDescription, + tr("Example bluetooth chat server")); + serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceProvider, tr("qt-project.org")); + + // Service UUID set + serviceInfo.setServiceUuid(QBluetoothUuid(QString(TEST_SERVICE_UUID))); + + + // Service Discoverability + QBluetoothServiceInfo::Sequence browseSequence; + browseSequence << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ServiceClassUuid::PublicBrowseGroup)); + serviceInfo.setAttribute(QBluetoothServiceInfo::BrowseGroupList, browseSequence); + + // Protocol descriptor list + QBluetoothServiceInfo::Sequence protocolDescriptorList; + QBluetoothServiceInfo::Sequence protocol; + protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ProtocolUuid::L2cap)); + if (server->serverType() == QBluetoothServiceInfo::L2capProtocol) + protocol << QVariant::fromValue(server->serverPort()); + protocolDescriptorList.append(QVariant::fromValue(protocol)); + + if (server->serverType() == QBluetoothServiceInfo::RfcommProtocol) { + protocol.clear(); + protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::ProtocolUuid::Rfcomm)) + << QVariant::fromValue(quint8(server->serverPort())); + protocolDescriptorList.append(QVariant::fromValue(protocol)); + } + serviceInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, + protocolDescriptorList); + + //Register service + qDebug() << "###### Registering service on" << localDevice->address().toString() << server->serverPort(); + bool result = serviceInfo.registerService(localDevice->address()); + if (!result) { + server->close(); + qDebug() << "###### Reverting registration due to SDP failure."; + } + } + +} + +void BtLocalDevice::serverListenUuid() +{ + if (server) { + if (server->isListening() || serviceInfo.isRegistered()) { + qDebug() << "###### Already listening" << serviceInfo.isRegistered(); + return; + } + + if (server->securityFlags() != securityFlags) { + qDebug() << "###### Setting security policy on server socket" << securityFlags; + server->setSecurityFlags(securityFlags); + } + + qDebug() << "###### Start listening via UUID"; + serviceInfo = server->listen(QBluetoothUuid(QString(TEST_SERVICE_UUID)), tr("Bt Chat Server")); + qDebug() << "###### Listening(Expecting TRUE, TRUE):" << serviceInfo.isRegistered() << serviceInfo.isValid(); + } +} + +void BtLocalDevice::serverClose() +{ + if (server) { + qDebug() << "###### Closing Server socket"; + if (serviceInfo.isRegistered()) + serviceInfo.unregisterService(); + server->close(); + } +} + +void BtLocalDevice::serverNewConnection() +{ + qDebug() << "###### New incoming server connection, pending:" << server->hasPendingConnections(); + if (!server->hasPendingConnections()) { + qDebug() << "FAIL: expected pending server connection"; + return; + } + QBluetoothSocket *client = server->nextPendingConnection(); + if (!client) { + qDebug() << "FAIL: Cannot obtain pending server connection"; + return; + } + + client->setParent(this); + connect(client, &QBluetoothSocket::disconnected, this, &BtLocalDevice::clientSocketDisconnected); + connect(client, &QIODevice::readyRead, this, &BtLocalDevice::clientSocketReadyRead); + connect(client, &QBluetoothSocket::stateChanged, + this, &BtLocalDevice::socketStateChanged); + connect(client, &QBluetoothSocket::errorOccurred, this, &BtLocalDevice::socketError); + connect(client, &QBluetoothSocket::connected, this, &BtLocalDevice::socketConnected); + connect(client, &QBluetoothSocket::bytesWritten, this, [](qint64 bytesWritten){ + qDebug() << "Bytes Written to Server socket:" << bytesWritten; + }); + serverSockets.append(client); +} + +void BtLocalDevice::clientSocketDisconnected() +{ + auto *client = qobject_cast(sender()); + if (!client) + return; + + qDebug() << "######" << "Removing server socket connection"; + + serverSockets.removeOne(client); + client->deleteLater(); +} + + +void BtLocalDevice::clientSocketReadyRead() +{ + auto *socket = qobject_cast(sender()); + if (!socket) + return; + + while (socket->canReadLine()) { + const QByteArray line = socket->readLine().trimmed(); + QString lineString = QString::fromUtf8(line.constData(), line.size()); + qDebug() << ">>(" << server->serverAddress() << server->serverPort() <<")>>" + << lineString; + + //when using the tst_QBluetoothSocket we echo received text back + //Any line starting with "Echo:" will be echoed + if (lineString.startsWith(QStringLiteral("Echo:"))) { + qDebug() << "Assuming tst_qbluetoothsocket as client. Echoing back."; + lineString += QLatin1Char('\n'); + socket->write(lineString.toUtf8()); + } + } +} + + +void BtLocalDevice::dumpServerInformation() +{ + static QBluetooth::SecurityFlags secFlag = QBluetooth::Security::Authentication; + if (server) { + qDebug() << "*******************************"; + qDebug() << "server port:" <serverPort() + << "type:" << server->serverType() + << "address:" << server->serverAddress().toString(); + qDebug() << "error:" << server->error(); + qDebug() << "listening:" << server->isListening() + << "hasPending:" << server->hasPendingConnections() + << "maxPending:" << server->maxPendingConnections(); + qDebug() << "security:" << server->securityFlags() << "Togling security flag"; + if (secFlag == QBluetooth::SecurityFlags(QBluetooth::Security::Authentication)) + secFlag = QBluetooth::Security::Encryption; + else + secFlag = QBluetooth::Security::Authentication; + + //server->setSecurityFlags(secFlag); + + for (const QBluetoothSocket *client : std::as_const(serverSockets)) { + qDebug() << "##" << client->localAddress().toString() + << client->localName() << client->localPort(); + qDebug() << "##" << client->peerAddress().toString() + << client->peerName() << client->peerPort(); + qDebug() << client->socketType() << client->state(); + qDebug() << "Pending bytes: " << client->bytesAvailable(); + QString tmp; + switch (client->error()) { + case QBluetoothSocket::SocketError::NoSocketError: tmp += "NoSocketError"; break; + case QBluetoothSocket::SocketError::UnknownSocketError: tmp += "UnknownSocketError"; break; + case QBluetoothSocket::SocketError::HostNotFoundError: tmp += "HostNotFoundError"; break; + case QBluetoothSocket::SocketError::ServiceNotFoundError: tmp += "ServiceNotFound"; break; + case QBluetoothSocket::SocketError::NetworkError: tmp += "NetworkError"; break; + case QBluetoothSocket::SocketError::UnsupportedProtocolError: tmp += "UnsupportedProtocolError"; break; + //case QBluetoothSocket::SocketError::OperationError: tmp+= "OperationError"; break; + case QBluetoothSocket::SocketError::MissingPermissionsError: tmp += "MissingPermissionsError"; break; + default: tmp += QString::number(static_cast(client->error())); break; + } + + qDebug() << "socket error:" << tmp << client->errorString(); + } + } +} + +template +void printError(const QLatin1StringView name, T* ptr) +{ + if (!ptr) + return; + qDebug() << name << "error:" << ptr->error(); +} + +void BtLocalDevice::dumpErrors() +{ + qDebug() << "###### Errors"; + printError("Device agent"_L1, deviceAgent); + printError("Service agent"_L1, serviceAgent); + printError("LE Central"_L1, leCentralController.get()); + printError("LE Central Service"_L1, leCentralService.get()); + printError("LE Peripheral"_L1, lePeripheralController.get()); + if (!lePeripheralServices.isEmpty()) + printError("LE Peripheral Service"_L1, lePeripheralServices[0].get()); + printError("Socket"_L1, socket); + printError("Server"_L1, server); +} + +void BtLocalDevice::dumpInformation() +{ + if (!localDevice) + return; + qDebug() << "###### default local device"; + dumpLocalDevice(localDevice); + const QList list = QBluetoothLocalDevice::allDevices(); + qDebug() << "Found local devices: " << list.size(); + for (const QBluetoothHostInfo &info : list) { + qDebug() << " " << info.address().toString() << " " <pairingStatus(BB); + qDebug() << "###### Bonding state with" << address2.toString() << ": " << localDevice->pairingStatus(address2); + qDebug() << "###### Bonding state with" << address.toString() << ": " << localDevice->pairingStatus(address); + + qDebug() << "###### Connected Devices"; + const QList connectedDevices = localDevice->connectedDevices(); + for (const QBluetoothAddress &addr : connectedDevices) + qDebug() << " " << addr.toString(); + + qDebug() << "###### Discovered Devices"; + if (deviceAgent) { + const QList devices = deviceAgent->discoveredDevices(); + for (const QBluetoothDeviceInfo &info : devices) { + deviceDiscovered(info); + } + } + + QBluetoothDeviceDiscoveryAgent invalidAgent(QBluetoothAddress("11:22:33:44:55:66")); + invalidAgent.start(); + qDebug() << "######" << "Testing device discovery agent constructor with invalid address"; + qDebug() << "######" << (invalidAgent.error() == QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError) + << "(Expected: true)"; + QBluetoothDeviceDiscoveryAgent validAgent(localDevice->address()); + validAgent.start(); + qDebug() << "######" << (validAgent.error() == QBluetoothDeviceDiscoveryAgent::NoError) << "(Expected: true)"; + + QBluetoothServiceDiscoveryAgent invalidSAgent(QBluetoothAddress("11:22:33:44:55:66")); + invalidSAgent.start(); + qDebug() << "######" << "Testing service discovery agent constructor with invalid address"; + qDebug() << "######" << (invalidSAgent.error() == QBluetoothServiceDiscoveryAgent::InvalidBluetoothAdapterError) + << "(Expected: true)"; + QBluetoothServiceDiscoveryAgent validSAgent(localDevice->address()); + validSAgent.start(); + qDebug() << "######" << (validSAgent.error() == QBluetoothServiceDiscoveryAgent::NoError) << "(Expected: true)"; + + dumpLeInfo(); +} + +void BtLocalDevice::powerOn() +{ + if (!localDevice) + return; + qDebug() << "Powering on"; + localDevice->powerOn(); +} + +void BtLocalDevice::reset() +{ + emit errorOccurred(static_cast(1000)); + if (serviceAgent) { + serviceAgent->clear(); + } + foundTestServers.clear(); +} + +void BtLocalDevice::dumpLocalDevice(QBluetoothLocalDevice *dev) +{ + qDebug() << " Valid: " << dev->isValid(); + qDebug() << " Name" << dev->name(); + qDebug() << " Address" << dev->address().toString(); + qDebug() << " HostMode" << dev->hostMode(); +} + +void BtLocalDevice::peripheralCreate() +{ + qDebug() << "######" << "LE create peripheral"; + if (lePeripheralController) { + qDebug() << "Peripheral already existed"; + return; + } + + lePeripheralController.reset(QLowEnergyController::createPeripheral()); + emit leChanged(); + + QObject::connect(lePeripheralController.get(), &QLowEnergyController::errorOccurred, + [this](QLowEnergyController::Error error) { + qDebug() << "QLowEnergyController peripheral errorOccurred:" << error; + emit leChanged(); + }); + QObject::connect(lePeripheralController.get(), &QLowEnergyController::stateChanged, + [this](QLowEnergyController::ControllerState state) { + qDebug() << "QLowEnergyController peripheral stateChanged:" << state; + emit leChanged(); + }); +} + +void BtLocalDevice::peripheralAddServices() +{ + qDebug() << "######" << "LE add services"; + if (!lePeripheralController) { + qDebug() << "Create peripheral first"; + return; + } + if (lePeripheralServiceData.isEmpty()) { + // Create service data + { + QLowEnergyServiceData sd; + sd.setType(QLowEnergyServiceData::ServiceTypePrimary); + sd.setUuid(QBluetoothUuid(leServiceUuid)); + + QLowEnergyCharacteristicData charData; + charData.setUuid(QBluetoothUuid(leCharUuid1)); + charData.setValue(leCharacteristicValue); + charData.setValueLength(leCharacteristicSize, leCharacteristicSize); + charData.setProperties(QLowEnergyCharacteristic::PropertyType::Read + | QLowEnergyCharacteristic::PropertyType::Write + | QLowEnergyCharacteristic::PropertyType::Notify + | QLowEnergyCharacteristic::ExtendedProperty); + + const QLowEnergyDescriptorData clientConfig( + QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration, + QLowEnergyCharacteristic::CCCDDisable); + charData.addDescriptor(clientConfig); + + const QLowEnergyDescriptorData userDescription( + QBluetoothUuid::DescriptorType::CharacteristicUserDescription, + leDescriptorValue); + charData.addDescriptor(userDescription); + + const QLowEnergyDescriptorData extendedProperties( + QBluetoothUuid::DescriptorType::CharacteristicExtendedProperties, + // From bluetooth specs: length 2 bytes + // bit 0: reliable write, bit 1: writable auxiliaries + QByteArray::fromHex("0300")); + charData.addDescriptor(extendedProperties); + + sd.addCharacteristic(charData); + + // Set another characteristic without notifications + QLowEnergyCharacteristicData secondCharData; + secondCharData.setUuid(QBluetoothUuid(leCharUuid2)); + secondCharData.setValue(leSecondCharacteristicValue); + secondCharData.setValueLength(leCharacteristicSize, leCharacteristicSize); + secondCharData.setProperties(QLowEnergyCharacteristic::PropertyType::Read + | QLowEnergyCharacteristic::PropertyType::Write); + sd.addCharacteristic(secondCharData); + lePeripheralServiceData << sd; + } + { + QLowEnergyServiceData sd; + sd.setType(QLowEnergyServiceData::ServiceTypePrimary); + sd.setUuid(QBluetoothUuid(leSecondServiceUuid)); + + QLowEnergyCharacteristicData charData; + charData.setUuid(QBluetoothUuid(leSecondServiceCharUuid1)); + charData.setValue("second service char"_ba); + charData.setProperties(QLowEnergyCharacteristic::PropertyType::Read); + sd.addCharacteristic(charData); + lePeripheralServiceData << sd; + } + { + QLowEnergyServiceData sd; + sd.setType(QLowEnergyServiceData::ServiceTypeSecondary); + sd.setUuid(QBluetoothUuid(leThirdServiceUuid)); + + QLowEnergyCharacteristicData charData; + charData.setUuid(QBluetoothUuid(leThirdServiceCharUuid1)); + charData.setValue("third service char"_ba); + charData.setProperties(QLowEnergyCharacteristic::PropertyType::Read); + sd.addCharacteristic(charData); + lePeripheralServiceData << sd; + } + } + + Q_ASSERT(lePeripheralServiceData.size() == 3); + // Free previous services if any + lePeripheralServices.clear(); + // Add first service, and then set the first service as the included service for the second + auto service = lePeripheralController->addService(lePeripheralServiceData[0]); + if (service) { + lePeripheralServiceData[1].setIncludedServices({service}); + // Then add the services to controller + lePeripheralServices.emplaceBack(service); + lePeripheralServices.emplaceBack( + lePeripheralController->addService(lePeripheralServiceData[1])); + lePeripheralServices.emplaceBack( + lePeripheralController->addService(lePeripheralServiceData[2])); + } + + emit leChanged(); + + if (lePeripheralServices.isEmpty()) { + qDebug() << "Peripheral service creation failed"; + return; + } + + QObject::connect(lePeripheralServices[0].get(), &QLowEnergyService::characteristicWritten, + [](const QLowEnergyCharacteristic&, const QByteArray& value){ + qDebug() << "LE peripheral service characteristic value written" << value; + }); + QObject::connect(lePeripheralServices[0].get(), &QLowEnergyService::characteristicRead, + [](const QLowEnergyCharacteristic&, const QByteArray& value){ + qDebug() << "LE peripheral service characteristic value read" << value; + }); + QObject::connect(lePeripheralServices[0].get(), &QLowEnergyService::characteristicChanged, + [](const QLowEnergyCharacteristic&, const QByteArray& value){ + qDebug() << "LE peripheral service characteristic value changed" << value; + }); + QObject::connect(lePeripheralServices[0].get(), &QLowEnergyService::descriptorRead, + [](const QLowEnergyDescriptor&, const QByteArray& value){ + qDebug() << "LE peripheral service descriptor value read" << value; + }); + QObject::connect(lePeripheralServices[0].get(), &QLowEnergyService::descriptorWritten, + [](const QLowEnergyDescriptor&, const QByteArray& value){ + qDebug() << "LE peripheral service descriptor value written" << value; + }); + QObject::connect(lePeripheralServices[0].get(), &QLowEnergyService::errorOccurred, + [this](QLowEnergyService::ServiceError error){ + qDebug() << "LE peripheral service errorOccurred:" << error; + emit leChanged(); + }); + QObject::connect(lePeripheralServices[0].get(), &QLowEnergyService::stateChanged, + [this](QLowEnergyService::ServiceState state){ + qDebug() << "LE peripheral service state changed:" << state; + emit leChanged(); + }); +} + +void BtLocalDevice::peripheralStartAdvertising() +{ + qDebug() << "######" << "LE start advertising"; + if (!lePeripheralController) { + qDebug() << "Create peripheral first"; + return; + } + + if (leAdvertisingData.localName().isEmpty()) { + // Create advertisement data + leAdvertisingData.setDiscoverability(QLowEnergyAdvertisingData::DiscoverabilityGeneral); + leAdvertisingData.setIncludePowerLevel(true); + leAdvertisingData.setLocalName(leRemotePeriphreralDeviceName); + + leAdvertisingData.setManufacturerData(0xCAFE, "maker"); + // Here we use short unrelated UUID so we can fit both service UUID and manufacturer data + // into the advertisement. This is for testing purposes + leAdvertisingData.setServices( + {QBluetoothUuid(QBluetoothUuid::ServiceClassUuid::AlertNotificationService)}); + // May result in too big advertisement data, can be useful for testing such scenario + // leAdvertisingData.setServices({QBluetoothUuid(leServiceUuid)}); + } + // Start advertising. For testing the advertising can be started without valid services + qDebug() << "Starting advertising, services are valid:" << !lePeripheralServiceData.isEmpty(); + lePeripheralController->startAdvertising(QLowEnergyAdvertisingParameters{}, + leAdvertisingData, leAdvertisingData); +} + +void BtLocalDevice::peripheralStopAdvertising() +{ + qDebug() << "######" << "LE stop advertising"; + if (!lePeripheralController) { + qDebug() << "Peripheral does not exist"; + return; + } + lePeripheralController->stopAdvertising(); +} + +void BtLocalDevice::centralCharacteristicWrite() +{ + qDebug() << "######" << "LE central write characteristic"; + if (!leCentralController || !leCentralService) { + qDebug() << "Central or central service does not exist"; + return; + } + auto characteristic = leCentralService->characteristic(QBluetoothUuid(leCharUuid1)); + if (characteristic.isValid()) { + // Update value at the beginning and end so we can check whole data is sent in large writes + // Value is offset'd with 100 to easily see which end did the write when testing + leCharacteristicValueUpdate += 1; + leCharacteristicValue[0] = leCharacteristicValueUpdate + 100; + leCharacteristicValue[leCharacteristicSize - 1] = leCharacteristicValueUpdate + 100; + qDebug() << " Central writes value:" << leCharacteristicValue; + leCentralService->writeCharacteristic(characteristic, leCharacteristicValue); + } else { + qDebug() << "Characteristic was invalid"; + } +} + +void BtLocalDevice::centralCharacteristicRead() +{ + qDebug() << "######" << "LE central read characteristic"; + if (!leCentralController || !leCentralService) { + qDebug() << "Central or central service does not exist"; + return; + } + auto characteristic = leCentralService->characteristic(QBluetoothUuid(leCharUuid1)); + if (characteristic.isValid()) { + qDebug() << " Value before issuing read():" << characteristic.value(); + leCentralService->readCharacteristic(characteristic); + } else { + qDebug() << "Characteristic was invalid"; + } +} + +void BtLocalDevice::centralDescriptorWrite() +{ + qDebug() << "######" << "LE central write descriptor"; + if (!leCentralController || !leCentralService) { + qDebug() << "Central or central service does not exist"; + return; + } + auto descriptor = leCentralService->characteristic(QBluetoothUuid(leCharUuid1)) + .descriptor(QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + + if (descriptor.isValid()) { + leDescriptorValue[0] = leDescriptorValueUpdate++; + qDebug() << " Central writes value: " << leDescriptorValue; + leCentralService->writeDescriptor(descriptor, leDescriptorValue); + } else { + qDebug() << "Descriptor was invalid"; + } +} + +void BtLocalDevice::centralDescriptorRead() +{ + qDebug() << "######" << "LE central read descriptor"; + if (!leCentralController || !leCentralService) { + qDebug() << "Central or central service does not exist"; + return; + } + auto descriptor = leCentralService->characteristic(QBluetoothUuid(leCharUuid1)) + .descriptor(QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + if (descriptor.isValid()) { + qDebug() << " Value before issuing read():" << descriptor.value(); + leCentralService->readDescriptor(descriptor); + } else { + qDebug() << "Descriptor was invalid"; + } +} + + +void BtLocalDevice::peripheralCharacteristicWrite() +{ + qDebug() << "######" << "LE peripheral write characteristic"; + if (!lePeripheralController || lePeripheralServices.isEmpty()) { + qDebug() << "Peripheral or peripheral service does not exist"; + return; + } + + auto characteristic = lePeripheralServices[0]->characteristic(QBluetoothUuid(leCharUuid1)); + if (characteristic.isValid()) { + // Update value at the beginning and end so we can check whole data is sent in large writes + leCharacteristicValue[0] = ++leCharacteristicValueUpdate; + leCharacteristicValue[leCharacteristicSize - 1] = leCharacteristicValueUpdate; + qDebug() << " Peripheral writes value:" << leCharacteristicValue; + lePeripheralServices[0]->writeCharacteristic(characteristic, leCharacteristicValue); + } else { + qDebug() << "Characteristic was invalid"; + } +} + +void BtLocalDevice::peripheralCharacteristicRead() +{ + qDebug() << "######" << "LE peripheral read characteristic"; + if (!lePeripheralController || lePeripheralServices.isEmpty()) { + qDebug() << "Peripheral or peripheral service does not exist"; + return; + } + auto characteristic = lePeripheralServices[0]->characteristic(QBluetoothUuid(leCharUuid1)); + if (characteristic.isValid()) + qDebug() << " Value:" << characteristic.value(); + else + qDebug() << "Characteristic was invalid"; +} + +void BtLocalDevice::peripheralDescriptorWrite() +{ + qDebug() << "######" << "LE peripheral write descriptor"; + if (!lePeripheralController || lePeripheralServices.isEmpty()) { + qDebug() << "Peripheral or peripheral service does not exist"; + return; + } + auto descriptor = lePeripheralServices[0]->characteristic(QBluetoothUuid(leCharUuid1)) + .descriptor(QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + + if (descriptor.isValid()) { + leDescriptorValue[0] = leDescriptorValueUpdate++; + qDebug() << " Peripheral writes value: " << leDescriptorValue; + lePeripheralServices[0]->writeDescriptor(descriptor, leDescriptorValue); + } else { + qDebug() << "Descriptor was invalid"; + } +} + +void BtLocalDevice::peripheralDescriptorRead() +{ + qDebug() << "######" << "LE peripheral read descriptor"; + if (!lePeripheralController || lePeripheralServices.isEmpty()) { + qDebug() << "Peripheral or peripheral service does not exist"; + return; + } + auto descriptor = lePeripheralServices[0]->characteristic(QBluetoothUuid(leCharUuid1)) + .descriptor(QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + if (descriptor.isValid()) + qDebug() << " Value:" << descriptor.value(); + else + qDebug() << "Descriptor was invalid"; +} + +void BtLocalDevice::startLeDeviceDiscovery() +{ + qDebug() << "######" << "LE device discovery start for:" << leRemotePeriphreralDeviceName; + if (deviceAgent) + deviceAgent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod); +} + +void BtLocalDevice::centralStartServiceDiscovery() +{ + qDebug() << "######" << "LE service discovery start"; + if (!leCentralController) { + qDebug() << "Create and connect central first"; + return; + } + leCentralController->discoverServices(); +} + +void BtLocalDevice::centralCreate() +{ + qDebug() << "######" << "Central create"; + if (leCentralController) { + qDebug() << "Central already existed"; + return; + } + + if (!leRemotePeripheralDevice.isValid()) { + qDebug() << "Creation failed, needs successful LE device discovery first"; + return; + } + + if (deviceAgent && deviceAgent->isActive()) { + qDebug() << "###### Stopping device discovery agent"; + deviceAgent->stop(); + } + + leCentralController.reset(QLowEnergyController::createCentral(leRemotePeripheralDevice)); + emit leChanged(); + + if (!leCentralController) { + qDebug() << "LE Central creation failed"; + return; + } + + QObject::connect(leCentralController.get(), &QLowEnergyController::errorOccurred, + [](QLowEnergyController::Error error) { + qDebug() << "QLowEnergyController central errorOccurred:" << error; + }); + QObject::connect(leCentralController.get(), &QLowEnergyController::discoveryFinished, []() { + qDebug() << "QLowEnergyController central service discovery finished"; + }); + QObject::connect(leCentralController.get(), &QLowEnergyController::serviceDiscovered, + [](const QBluetoothUuid &newService){ + qDebug() << "QLowEnergyController central service discovered:" << newService; + }); + QObject::connect(leCentralController.get(), &QLowEnergyController::stateChanged, + [this](QLowEnergyController::ControllerState state) { + qDebug() << "QLowEnergyController central stateChanged:" << state; + if (state == QLowEnergyController::UnconnectedState) + latestRSSI = "N/A"_ba; + emit leChanged(); + }); + QObject::connect(leCentralController.get(), &QLowEnergyController::rssiRead, + [this](qint16 rssi) { + qDebug() << "QLowEnergyController central RSSI updated:" << rssi; + latestRSSI = QByteArray::number(rssi); + emit leChanged(); + }); +} + +void BtLocalDevice::centralDiscoverServiceDetails() +{ + qDebug() << "###### Discover Service details"; + if (!leCentralController) { + qDebug() << "Central does not exist"; + return; + } + leCentralService.reset( + leCentralController->createServiceObject(QBluetoothUuid(leServiceUuid))); + emit leChanged(); + if (!leCentralService) { + qDebug() << "Service creation failed, cannot discover details"; + return; + } + QObject::connect(leCentralService.get(), &QLowEnergyService::stateChanged, + [this](QLowEnergyService::ServiceState state){ + qDebug() << "LE central service state changed:" << state; + emit leChanged(); + }); + QObject::connect(leCentralService.get(), &QLowEnergyService::characteristicWritten, + [](const QLowEnergyCharacteristic&, const QByteArray& value){ + qDebug() << "LE central service characteristic value written" << value; + }); + QObject::connect(leCentralService.get(), &QLowEnergyService::characteristicRead, + [](const QLowEnergyCharacteristic&, const QByteArray& value){ + qDebug() << "LE central service characteristic value read" << value; + }); + QObject::connect(leCentralService.get(), &QLowEnergyService::characteristicChanged, + [](const QLowEnergyCharacteristic&, const QByteArray& value){ + qDebug() << "LE central service characteristic value changed" << value; + }); + QObject::connect(leCentralService.get(), &QLowEnergyService::descriptorRead, + [](const QLowEnergyDescriptor&, const QByteArray& value){ + qDebug() << "LE central service descriptor value read" << value; + }); + QObject::connect(leCentralService.get(), &QLowEnergyService::descriptorWritten, + [this](const QLowEnergyDescriptor&, const QByteArray& value){ + qDebug() << "LE central service descriptor value written" << value; + emit leChanged(); + }); + QObject::connect(leCentralService.get(), &QLowEnergyService::errorOccurred, + [](QLowEnergyService::ServiceError error){ + qDebug() << "LE central service error occurred:" << error; + }); + leCentralService->discoverDetails(QLowEnergyService::FullDiscovery); +} + +void BtLocalDevice::centralConnect() +{ + qDebug() << "######" << "Central connect"; + if (!leCentralController) { + qDebug() << "Create central first"; + return; + } + leCentralController->connectToDevice(); +} + +void BtLocalDevice::dumpLeInfo() +{ + const auto controllerDump = [](QLowEnergyController* controller) { + qDebug() << " State:" << controller->state(); + qDebug() << " Role:" << controller->role(); + qDebug() << " Error:" << controller->error(); + qDebug() << " ErrorString:" << controller->errorString(); + qDebug() << " MTU:" << controller->mtu(); + qDebug() << " Local Address:" << controller->localAddress(); + qDebug() << " RemoteAddress:" << controller->remoteAddress(); + qDebug() << " RemoteName:" << controller->remoteName(); + qDebug() << " Services count:" << controller->services().size(); + }; + qDebug() << "######" << "LE Peripheral controller"; + if (lePeripheralController) + controllerDump(lePeripheralController.get()); + + qDebug() << "######" << "LE Central controller"; + if (leCentralController) + controllerDump(leCentralController.get()); + + qDebug() << "######" << "LE Found peripheral device"; + if (leRemotePeripheralDevice.isValid()) { + qDebug() << " Name:" << leRemotePeripheralDevice.name(); + qDebug() << " UUID:" << leRemotePeripheralDevice.deviceUuid(); + qDebug() << " Address:" << leRemotePeripheralDevice.address(); + } + + const auto serviceDump = [](QLowEnergyService* service){ + qDebug() << " Name:" << service->serviceName(); + qDebug() << " Uuid:" << service->serviceUuid(); + qDebug() << " Error:" << service->error(); + auto characteristics = service->characteristics(); + for (const auto& characteristic : characteristics) { + qDebug() << " Characteristic"; + qDebug() << " Uuid" << characteristic.uuid(); + qDebug() << " Value" << characteristic.value(); + + } + }; + + qDebug() << "######" << "LE Central-side service"; + if (leCentralService) + serviceDump(leCentralService.get()); + + qDebug() << "######" << "LE Peripheral-side service"; + if (!lePeripheralServices.isEmpty()) + serviceDump(lePeripheralServices[0].get()); +} + +void BtLocalDevice::centralSubscribeUnsubscribe() +{ + qDebug() << "######" << "LE Central (Un)Subscribe"; + if (!leCentralService) { + qDebug() << "Service object does not exist"; + return; + } + auto characteristic = leCentralService->characteristic(QBluetoothUuid(leCharUuid1)); + if (!characteristic.isValid()) { + qDebug() << "Characteristic is not valid"; + return; + } + + auto descriptor = characteristic.descriptor( + QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration); + if (!descriptor.isValid()) { + qDebug() << "Descriptor is not valid"; + return; + } + if (descriptor.value() == QByteArray::fromHex("0000")) { + qDebug() << " Subscribing notifications"; + leCentralService->writeDescriptor(descriptor, QByteArray::fromHex("0100")); + } else { + qDebug() << " Unsubscribing notifications"; + leCentralService->writeDescriptor(descriptor, QByteArray::fromHex("0000")); + } + emit leChanged(); +} + +void BtLocalDevice::centralDelete() +{ + qDebug() << "######" << "Delete central" << leCentralController.get(); + leCentralController.reset(nullptr); + latestRSSI = "(N/A)"_ba; + emit leChanged(); +} + +void BtLocalDevice::centralDisconnect() +{ + qDebug() << "######" << "LE central disconnect"; + if (!leCentralController) { + qDebug() << "Create central first"; + return; + } + leCentralController->disconnectFromDevice(); +} + +void BtLocalDevice::peripheralDelete() +{ + qDebug() << "######" << "Delete peripheral" << lePeripheralController.get(); + lePeripheralController.reset(nullptr); + emit leChanged(); +} + +void BtLocalDevice::peripheralDisconnect() +{ + qDebug() << "######" << "LE peripheral disconnect"; + if (!lePeripheralController) { + qDebug() << "Create peripheral first"; + return; + } + lePeripheralController->disconnectFromDevice(); +} + +bool BtLocalDevice::centralExists() const +{ + return leCentralController.get(); +} + +bool BtLocalDevice::centralSubscribed() const +{ + if (!leCentralService) + return false; + + auto characteristic = leCentralService->characteristic(QBluetoothUuid(leCharUuid1)); + if (!characteristic.isValid()) + return false; + + auto descriptor = characteristic.descriptor( + QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration); + if (!descriptor.isValid()) + return false; + + return (descriptor.value() != QByteArray::fromHex("0000")); +} + +QByteArray BtLocalDevice::centralState() const +{ + if (!leCentralController) + return "(N/A)"_ba; + + return controllerStateString[leCentralController->state()]; +} + +QByteArray BtLocalDevice::centralServiceState() const +{ + if (!leCentralService) + return "(N/A)"_ba; + + return serviceStateString[leCentralService->state()]; +} + +QByteArray BtLocalDevice::centralError() const +{ + if (!leCentralController) + return "(N/A)"_ba; + + return controllerErrorString[leCentralController->error()]; +} + +QByteArray BtLocalDevice::centralServiceError() const +{ + if (!leCentralService) + return "(N/A)"_ba; + + return serviceErrorString[leCentralService->error()]; +} + +void BtLocalDevice::centralReadRSSI() const +{ + qDebug() << "######" << "LE central readRSSI"; + if (!leCentralController) + return; + leCentralController->readRssi(); +} + +QByteArray BtLocalDevice::centralRSSI() const +{ + return latestRSSI; +} + +QByteArray BtLocalDevice::peripheralState() const +{ + if (!lePeripheralController) + return "(N/A)"_ba; + + return controllerStateString[lePeripheralController->state()]; +} + +QByteArray BtLocalDevice::peripheralServiceState() const +{ + if (lePeripheralServices.isEmpty()) + return "(N/A)"_ba; + + return serviceStateString[lePeripheralServices[0]->state()]; +} + +QByteArray BtLocalDevice::peripheralError() const +{ + if (!lePeripheralController) + return "(N/A)"_ba; + + return controllerErrorString[lePeripheralController->error()]; +} + +QByteArray BtLocalDevice::peripheralServiceError() const +{ + if (lePeripheralServices.isEmpty()) + return "(N/A)"_ba; + + return serviceErrorString[lePeripheralServices[0]->error()]; +} + +bool BtLocalDevice::peripheralExists() const +{ + return lePeripheralController.get(); +} diff --git a/tests/bttestui/btlocaldevice.h b/tests/bttestui/btlocaldevice.h new file mode 100644 index 0000000..4e7a822 --- /dev/null +++ b/tests/bttestui/btlocaldevice.h @@ -0,0 +1,172 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef BTLOCALDEVICE_H +#define BTLOCALDEVICE_H + +#include +#include +#include +#include +#include +#include +#include +#include + +class BtLocalDevice : public QObject +{ + Q_OBJECT +public: + explicit BtLocalDevice(QObject *parent = 0); + ~BtLocalDevice(); + Q_PROPERTY(QString hostMode READ hostMode NOTIFY hostModeStateChanged) + Q_PROPERTY(int secFlags READ secFlags WRITE setSecFlags NOTIFY secFlagsChanged) + + Q_PROPERTY(bool centralExists READ centralExists NOTIFY leChanged); + Q_PROPERTY(bool centralSubscribed READ centralSubscribed NOTIFY leChanged); + Q_PROPERTY(QByteArray centralState READ centralState NOTIFY leChanged); + Q_PROPERTY(QByteArray centralError READ centralError NOTIFY leChanged); + Q_PROPERTY(QByteArray centralServiceState READ centralServiceState NOTIFY leChanged); + Q_PROPERTY(QByteArray centralServiceError READ centralServiceError NOTIFY leChanged); + Q_PROPERTY(QByteArray centralRSSI READ centralRSSI NOTIFY leChanged); + + Q_PROPERTY(QByteArray peripheralState READ peripheralState NOTIFY leChanged); + Q_PROPERTY(QByteArray peripheralError READ peripheralError NOTIFY leChanged); + Q_PROPERTY(QByteArray peripheralServiceState READ peripheralServiceState NOTIFY leChanged); + Q_PROPERTY(QByteArray peripheralServiceError READ peripheralServiceError NOTIFY leChanged); + Q_PROPERTY(bool peripheralExists READ peripheralExists NOTIFY leChanged); + + QBluetooth::SecurityFlags secFlags() const; + void setSecFlags(int); + QString hostMode() const; + +signals: + void errorOccurred(QBluetoothLocalDevice::Error error); + void hostModeStateChanged(); + void socketStateUpdate(int foobar); + void secFlagsChanged(); + bool leChanged(); // Same signal used for LE changes for simplicity + +public slots: + //QBluetoothLocalDevice + void dumpInformation(); + void dumpErrors(); + void powerOn(); + void reset(); + void setHostMode(int newMode); + void requestPairingUpdate(bool isPairing); + void pairingFinished(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing); + void connected(const QBluetoothAddress &addr); + void disconnected(const QBluetoothAddress &addr); + void cycleSecurityFlags(); + + //QBluetoothDeviceDiscoveryAgent + void deviceDiscovered(const QBluetoothDeviceInfo &info); + void deviceUpdated(const QBluetoothDeviceInfo &info, + QBluetoothDeviceInfo::Fields updateFields); + void discoveryFinished(); + void discoveryCanceled(); + void discoveryError(QBluetoothDeviceDiscoveryAgent::Error error); + void startDiscovery(); + void stopDiscovery(); + + //QBluetoothServiceDiscoveryAgent + void startServiceDiscovery(bool isMinimalDiscovery); + void startTargettedServiceDiscovery(); + void stopServiceDiscovery(); + void serviceDiscovered(const QBluetoothServiceInfo &info); + void serviceDiscoveryFinished(); + void serviceDiscoveryCanceled(); + void serviceDiscoveryError(QBluetoothServiceDiscoveryAgent::Error error); + void dumpServiceDiscovery(); + + //QBluetoothSocket + void connectToService(); + void connectToServiceViaSearch(); + void disconnectToService(); + void closeSocket(); + void abortSocket(); + void socketConnected(); + void socketDisconnected(); + void socketError(QBluetoothSocket::SocketError error); + void socketStateChanged(QBluetoothSocket::SocketState); + void dumpSocketInformation(); + void writeData(); + void readData(); + + //QBluetoothServer + void serverError(QBluetoothServer::Error error); + void serverListenPort(); + void serverListenUuid(); + void serverClose(); + void serverNewConnection(); + void clientSocketDisconnected(); + void clientSocketReadyRead(); + void dumpServerInformation(); + + //QLowEnergyController central + void centralCreate(); + void centralConnect(); + void centralStartServiceDiscovery(); + void centralDiscoverServiceDetails(); + void centralCharacteristicWrite(); + void centralCharacteristicRead(); + void centralDescriptorWrite(); + void centralDescriptorRead(); + void centralSubscribeUnsubscribe(); + void centralDelete(); + void centralDisconnect(); + bool centralExists() const; + bool centralSubscribed() const; + QByteArray centralState() const; + QByteArray centralServiceState() const; + QByteArray centralError() const; + QByteArray centralServiceError() const; + void centralReadRSSI() const; + QByteArray centralRSSI() const; + + //QLowEnergyController peripheral + void peripheralCreate(); + void peripheralAddServices(); + void peripheralStartAdvertising(); + void peripheralStopAdvertising(); + void peripheralCharacteristicRead(); + void peripheralCharacteristicWrite(); + void peripheralDescriptorRead(); + void peripheralDescriptorWrite(); + void peripheralDelete(); + void peripheralDisconnect(); + bool peripheralExists() const; + QByteArray peripheralState() const; + QByteArray peripheralServiceState() const; + QByteArray peripheralError() const; + QByteArray peripheralServiceError() const; + + // QLowEnergyController misc + void startLeDeviceDiscovery(); + void dumpLeInfo(); + +private: + void dumpLocalDevice(QBluetoothLocalDevice *dev); + + QBluetoothLocalDevice *localDevice = nullptr; + QBluetoothDeviceDiscoveryAgent *deviceAgent = nullptr; + QBluetoothServiceDiscoveryAgent *serviceAgent = nullptr; + QBluetoothSocket *socket = nullptr; + QBluetoothServer *server = nullptr; + QList serverSockets; + QBluetoothServiceInfo serviceInfo; + QList foundTestServers; + QBluetooth::SecurityFlags securityFlags; + + std::unique_ptr leCentralController; + std::unique_ptr lePeripheralController; + std::unique_ptr leCentralService; + QLowEnergyAdvertisingData leAdvertisingData; + QList lePeripheralServiceData; + QList> lePeripheralServices; + QBluetoothDeviceInfo leRemotePeripheralDevice; + QByteArray latestRSSI = "N/A"; +}; + +#endif // BTLOCALDEVICE_H diff --git a/tests/bttestui/main.cpp b/tests/bttestui/main.cpp new file mode 100644 index 0000000..50d5784 --- /dev/null +++ b/tests/bttestui/main.cpp @@ -0,0 +1,50 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include +#include +#include +#include + +#include + +#if QT_CONFIG(permissions) +#include +#endif + +#include "btlocaldevice.h" + +int main(int argc, char *argv[]) +{ + QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true")); + QGuiApplication app(argc, argv); + +#if QT_CONFIG(permissions) + // Check Bluetooth permission and request it if the app doesn't have it + auto permissionStatus = app.checkPermission(QBluetoothPermission{}); + if (permissionStatus == Qt::PermissionStatus::Undetermined) { + app.requestPermission(QBluetoothPermission{}, + [&permissionStatus](const QPermission &permission) { + qApp->exit(); // Exit the permission request processing started below + permissionStatus = permission.status(); + }); + // Process permission request + app.exec(); + } + if (permissionStatus == Qt::PermissionStatus::Denied) { + qWarning("Bluetooth permission denied, exiting"); + return -1; + } +#endif + + qmlRegisterType("Local", 6, 5, "BluetoothDevice"); + + QQuickView view; + view.setSource(QStringLiteral("qrc:///main.qml")); + view.setResizeMode(QQuickView::SizeRootObjectToView); + + QObject::connect(view.engine(), SIGNAL(quit()), qApp, SLOT(quit())); + view.show(); + + return QGuiApplication::exec(); +} diff --git a/tests/bttestui/main.qml b/tests/bttestui/main.qml new file mode 100644 index 0000000..82688ae --- /dev/null +++ b/tests/bttestui/main.qml @@ -0,0 +1,387 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick +import Local + +Flickable { + width: content.width + height: content.height + contentWidth: content.width + contentHeight: content.height + + Rectangle { + id: content + width: mainRow.implicitWidth + height: mainRow.implicitHeight + + BluetoothDevice { + id: device + function evaluateError(error) + { + switch (error) { + case 0: return "Last Error: NoError" + case 1: return "Last Error: Pairing Error" + case 100: return "Last Error: Unknown Error" + case 1000: return "Last Error: " + } + } + + function evaluateSocketState(s) { + switch (s) { + case 0: return "Socket: Unconnected"; + case 1: return "Socket: HostLookup"; + case 2: return "Socket: Connecting"; + case 3: return "Socket: Connected"; + case 4: return "Socket: Bound"; + case 5: return "Socket: Listening"; + case 6: return "Socket: Closing"; + } + return "Socket: "; + } + + + onErrorOccurred: (error) => errorText.text = evaluateError(error) + onHostModeStateChanged: hostModeText.text = device.hostMode; + onSocketStateUpdate: (foobar) => socketStateText.text = evaluateSocketState(foobar); + } + + Row { + id: mainRow + anchors.top: parent.top + anchors.left: parent.left + anchors.margins: 4 + + spacing: 8 + Column { + spacing: 8 + Text{ + width: connectBtn.width + horizontalAlignment: Text.AlignLeft + font.pointSize: 12 + wrapMode: Text.WordWrap + text: "Device Management" + } + Button { + + buttonText: "PowerOn" + onClicked: device.powerOn() + } + Button { + buttonText: "PowerOff" + onClicked: device.setHostMode(0) + } + Button { + id: connectBtn + buttonText: "Connectable" + onClicked: device.setHostMode(1) + } + Button { + buttonText: "Discover" + onClicked: device.setHostMode(2) + } + Button { + buttonText: "Pair" + onClicked: device.requestPairingUpdate(true) + } + Button { + buttonText: "Unpair" + onClicked: device.requestPairingUpdate(false) + } + Button { + buttonText: "Cycle SecFlag" + onClicked: device.cycleSecurityFlags() + } + Text { + id: errorText + text: "Last Error: " + } + Text { + id: hostModeText + text: device.hostMode + } + Text { + id: socketStateText + text: device.evaluateSocketState(0) + } + Text { + id: secFlagLabel; + text: "SecFlags: " + device.secFlags + } + } + Column { + spacing: 8 + Text{ + width: startFullSDiscBtn.width + horizontalAlignment: Text.AlignLeft + font.pointSize: 12 + wrapMode: Text.WordWrap + text: "Device & Service Discovery" + } + Button { + buttonText: "StartDDisc" + onClicked: device.startDiscovery() + } + Button { + buttonText: "StopDDisc" + onClicked: device.stopDiscovery() + } + Button { + buttonText: "StartMinSDisc" + onClicked: device.startServiceDiscovery(true) + } + Button { + id: startFullSDiscBtn + buttonText: "StartFullSDisc" + onClicked: device.startServiceDiscovery(false) + } + Button { + id: startRemoteSDiscBtn + buttonText: "StartRemSDisc" + onClicked: device.startTargettedServiceDiscovery() + } + Button { + buttonText: "StopSDisc" + onClicked: device.stopServiceDiscovery(); + } + Button { + buttonText: "DumpSDisc" + onClicked: device.dumpServiceDiscovery(); + } + + } + + Column { + spacing: 8 + Text{ + width: connectSearchBtn.width + horizontalAlignment: Text.AlignLeft + font.pointSize: 12 + wrapMode: Text.WordWrap + text: "Client & Server Socket" + } + Button { + buttonText: "SocketDump" + onClicked: device.dumpSocketInformation() + } + Button { + buttonText: "CConnect" + onClicked: device.connectToService() + } + Button { + id: connectSearchBtn + buttonText: "ConnectSearch" + onClicked: device.connectToServiceViaSearch() + } + Button { + buttonText: "CDisconnect" + onClicked: device.disconnectToService() + } + + Button { + buttonText: "CClose" + onClicked: device.closeSocket() + } + + Button { + buttonText: "CAbort" + onClicked: device.abortSocket() + } + Button { + //Write to all open sockets ABCABC\n + buttonText: "CSWrite" + onClicked: device.writeData() + } + Button { + buttonText: "ServerDump" + onClicked: device.dumpServerInformation() + } + Button { + //Listen on server via port + buttonText: "SListenPort" + onClicked: device.serverListenPort() + } + Button { + //Listen on server via uuid + buttonText: "SListenUuid" + onClicked: device.serverListenUuid() + } + Button { + //Close Bluetooth server + buttonText: "SClose" + onClicked: device.serverClose() + } + } + Column { + spacing: 8 + Text{ + width: centralBtn.width + horizontalAlignment: Text.AlignLeft + color: device.centralExists ? "blue" : "black" + font.bold: device.centralExists + font.pointSize: 12 + wrapMode: Text.WordWrap + text: "Low Energy Central Controller" + } + Rectangle { + color: "lightsteelblue" + width: parent.width + height: centralInfo.height + clip: true + Column { + id: centralInfo + Text { text: "CState:" + device.centralState } + Text { text: "CError:" + device.centralError } + Text { text: "SState:" + device.centralServiceState } + Text { text: "SError:" + device.centralServiceError } + Text { text: "Subscribed: " + device.centralSubscribed } + Text { text: "RSSI: " + device.centralRSSI } + } + } + // The ordinal numbers below indicate the typical sequence + Button { + id: centralBtn + buttonText: "1 DeviceDiscovery" + onClicked: device.startLeDeviceDiscovery() + } + Button { + buttonText: "2 CreateCentral" + onClicked: device.centralCreate() + } + Button { + buttonText: "3 ConnectCentral" + onClicked: device.centralConnect() + } + Button { + buttonText: "4 ServiceDiscovery" + onClicked: device.centralStartServiceDiscovery() + } + Button { + buttonText: "5 ServiceDetails" + onClicked: device.centralDiscoverServiceDetails(); + } + Button { + buttonText: "CharacteristicRead" + onClicked: device.centralCharacteristicRead() + } + Button { + buttonText: "CharacteristicWrite" + onClicked: device.centralCharacteristicWrite() + } + Button { + buttonText: "DescriptorRead" + onClicked: device.centralDescriptorRead() + } + Button { + buttonText: "DescriptorWrite" + onClicked: device.centralDescriptorWrite() + } + Button { + buttonText: "Sub/Unsubscribe" + onClicked: device.centralSubscribeUnsubscribe(); + } + Button { + buttonText: "DeleteController" + onClicked: device.centralDelete() + } + Button { + buttonText: "Disconnect" + onClicked: device.centralDisconnect() + } + Button { + buttonText: "ReadRSSI" + onClicked: device.centralReadRSSI() + } + } + Column { + spacing: 8 + Text{ + width: centralBtn.width + horizontalAlignment: Text.AlignLeft + color: device.peripheralExists ? "blue" : "black" + font.bold: device.peripheralExists + font.pointSize: 12 + wrapMode: Text.WordWrap + text: "Low Energy Peripheral Controller" + } + Rectangle { + color: "lightsteelblue" + width: parent.width + height: peripheralInfo.height + clip: true + Column { + id: peripheralInfo + Text { text: "CState: " + device.peripheralState } + Text { text: "CError: " + device.peripheralError } + Text { text: "SState: " + device.peripheralServiceState } + Text { text: "SError: " + device.peripheralServiceError } + } + } + Button { + buttonText: "1 CreatePeripheral" + onClicked: device.peripheralCreate() + } + Button { + buttonText: "2 AddServices" + onClicked: device.peripheralAddServices() + } + Button { + buttonText: "3 StartAdvertise" + onClicked: device.peripheralStartAdvertising() + } + Button { + buttonText: "StopAdvertise" + onClicked: device.peripheralStopAdvertising() + } + Button { + buttonText: "CharacteristicRead" + onClicked: device.peripheralCharacteristicRead() + } + Button { + buttonText: "CharacteristicWrite" + onClicked: device.peripheralCharacteristicWrite() + } + Button { + buttonText: "DescriptorRead" + onClicked: device.peripheralDescriptorRead() + } + Button { + buttonText: "DescriptorWrite" + onClicked: device.peripheralDescriptorWrite() + } + Button { + buttonText: "DeleteController" + onClicked: device.peripheralDelete() + } + Button { + buttonText: "Disconnect" + onClicked: device.peripheralDisconnect() + } + } + Column { + spacing: 8 + Text{ + width: resetBtn.width + horizontalAlignment: Text.AlignLeft + font.pointSize: 12 + wrapMode: Text.WordWrap + text: "Misc Controls" + } + Button { + buttonText: "Dump" + onClicked: device.dumpInformation() + } + Button { + id: resetBtn + buttonText: "Reset" + onClicked: device.reset() + } + Button { + id: errorButton + buttonText: "Errors" + onClicked: device.dumpErrors() + } + } + } + } +} diff --git a/tests/global/global.cfg b/tests/global/global.cfg new file mode 100644 index 0000000..ab3b751 --- /dev/null +++ b/tests/global/global.cfg @@ -0,0 +1,6 @@ + + + + + + diff --git a/tests/manual/CMakeLists.txt b/tests/manual/CMakeLists.txt new file mode 100644 index 0000000..47fdbfb --- /dev/null +++ b/tests/manual/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +if(TARGET Qt::Bluetooth) + add_subdirectory(qlowenergycontroller) + add_subdirectory(qlowenergycontroller_peripheral) + add_subdirectory(examples/btscanner) +endif() + diff --git a/tests/manual/examples/btscanner/CMakeLists.txt b/tests/manual/examples/btscanner/CMakeLists.txt new file mode 100644 index 0000000..08bac2d --- /dev/null +++ b/tests/manual/examples/btscanner/CMakeLists.txt @@ -0,0 +1,48 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(btscanner LANGUAGES CXX) + find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) + endif() + +qt_internal_add_manual_test(btscanner + GUI + SOURCES + device.cpp device.h device.ui + main.cpp + service.cpp service.h service.ui + LIBRARIES + Qt::Bluetooth + Qt::Core + Qt::Widgets + ENABLE_AUTOGEN_TOOLS + uic +) + +if(MACOS) + # Explicitly link against the static permission plugin because tests + # currently don't have finalizers run for them except for iOS. + # TODO: Remove this when qtbase automatically runs finalizers for tests: QTBUG-112212 + target_link_libraries(btscanner PRIVATE Qt6::QDarwinBluetoothPermissionPlugin) +endif() + +set_target_properties(btscanner PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +if(APPLE) + if (IOS) + set_target_properties(btscanner PROPERTIES + MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist" + ) + else() + # Using absolute path for shared plist files is a Ninja bug workaround + get_filename_component(SHARED_PLIST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../../examples/bluetooth/shared ABSOLUTE) + set_target_properties(btscanner PROPERTIES + MACOSX_BUNDLE_INFO_PLIST "${SHARED_PLIST_DIR}/Info.cmake.macos.plist" + ) + endif() +endif() diff --git a/tests/manual/examples/btscanner/Info.plist b/tests/manual/examples/btscanner/Info.plist new file mode 100644 index 0000000..49fd219 --- /dev/null +++ b/tests/manual/examples/btscanner/Info.plist @@ -0,0 +1,41 @@ + + + + + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + ${ASSETCATALOG_COMPILER_APPICON_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + ${QMAKE_SHORT_VERSION} + CFBundleSignature + ${QMAKE_PKGINFO_TYPEINFO} + CFBundleVersion + ${QMAKE_FULL_VERSION} + LSRequiresIPhoneOS + + MinimumOSVersion + ${IPHONEOS_DEPLOYMENT_TARGET} + NSBluetoothAlwaysUsageDescription + Qt's BT scanner wants to access your Bluetooth adapter! + UILaunchStoryboardName + LaunchScreen + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/tests/manual/examples/btscanner/btscanner.pro b/tests/manual/examples/btscanner/btscanner.pro new file mode 100644 index 0000000..3ef4996 --- /dev/null +++ b/tests/manual/examples/btscanner/btscanner.pro @@ -0,0 +1,24 @@ +TARGET = btscanner + +QT = core bluetooth widgets +requires(qtConfig(listwidget)) +TEMPLATE = app + +SOURCES = \ + main.cpp \ + device.cpp \ + service.cpp + +ios: QMAKE_INFO_PLIST = Info.plist +macos: QMAKE_INFO_PLIST = ../../../../examples/bluetooth/shared/Info.qmake.macos.plist + +HEADERS = \ + device.h \ + service.h + +FORMS = \ + device.ui \ + service.ui + +target.path = $$[QT_INSTALL_EXAMPLES]/bluetooth/btscanner +INSTALLS += target diff --git a/tests/manual/examples/btscanner/device.cpp b/tests/manual/examples/btscanner/device.cpp new file mode 100644 index 0000000..6d1f775 --- /dev/null +++ b/tests/manual/examples/btscanner/device.cpp @@ -0,0 +1,182 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "device.h" +#include "service.h" +#include "ui_device.h" + +#include +#include +#include + +#include + +#if QT_CONFIG(permissions) +#include +#include +#include +#endif // QT_CONFIG(permissions) + +static QColor colorForPairing(QBluetoothLocalDevice::Pairing pairing) +{ + return pairing == QBluetoothLocalDevice::Paired + || pairing == QBluetoothLocalDevice::AuthorizedPaired + ? QColor(Qt::green) : QColor(Qt::red); +} + +DeviceDiscoveryDialog::DeviceDiscoveryDialog(QWidget *parent) : + QDialog(parent), + localDevice(new QBluetoothLocalDevice(this)), + ui(new Ui::DeviceDiscovery) +{ +#ifdef Q_OS_ANDROID + this->setWindowState(Qt::WindowMaximized); +#endif + ui->setupUi(this); + ui->stopScan->setVisible(false); + + // In case of multiple Bluetooth adapters it is possible to set the adapter + // to be used. Example code: + // + // QBluetoothAddress address("XX:XX:XX:XX:XX:XX"); + // discoveryAgent = new QBluetoothDeviceDiscoveryAgent(address, this); + + discoveryAgent = new QBluetoothDeviceDiscoveryAgent(this); + + connect(ui->scan, &QAbstractButton::clicked, this, &DeviceDiscoveryDialog::startScan); + connect(ui->stopScan, &QAbstractButton::clicked, this, &DeviceDiscoveryDialog::stopScan); + + connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, + this, &DeviceDiscoveryDialog::addDevice); + connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, + this, &DeviceDiscoveryDialog::scanFinished); + + connect(ui->list, &QListWidget::itemActivated, + this, &DeviceDiscoveryDialog::itemActivated); + + connect(localDevice, &QBluetoothLocalDevice::hostModeStateChanged, + this, &DeviceDiscoveryDialog::hostModeStateChanged); + + hostModeStateChanged(localDevice->hostMode()); + // add context menu for devices to be able to pair device + ui->list->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->list, &QWidget::customContextMenuRequested, + this, &DeviceDiscoveryDialog::displayPairingMenu); + connect(localDevice, &QBluetoothLocalDevice::pairingFinished, + this, &DeviceDiscoveryDialog::pairingDone); +} + +DeviceDiscoveryDialog::~DeviceDiscoveryDialog() +{ + delete ui; +} + +void DeviceDiscoveryDialog::addDevice(const QBluetoothDeviceInfo &info) +{ + const QString label = info.address().toString() + u' ' + info.name(); + const auto items = ui->list->findItems(label, Qt::MatchExactly); + if (items.isEmpty()) { + QListWidgetItem *item = new QListWidgetItem(label); + QBluetoothLocalDevice::Pairing pairingStatus = localDevice->pairingStatus(info.address()); + item->setForeground(colorForPairing(pairingStatus)); + ui->list->addItem(item); + } +} + +void DeviceDiscoveryDialog::startScan() +{ +#if QT_CONFIG(permissions) + if (qApp->checkPermission(QBluetoothPermission{}) != Qt::PermissionStatus::Granted) { + QMessageBox::warning(this, tr("Missing permission"), + tr("Permission is needed to use Bluetooth. "\ + "Please grant the permission to this "\ + "application in the system settings.")); + return; + } +#endif // QT_CONFIG(permissions) + discoveryAgent->start(); + ui->scan->setVisible(false); + ui->stopScan->setVisible(true); +} + +void DeviceDiscoveryDialog::stopScan() +{ + discoveryAgent->stop(); + scanFinished(); +} + +void DeviceDiscoveryDialog::scanFinished() +{ + ui->scan->setVisible(true); + ui->stopScan->setVisible(false); +} + +void DeviceDiscoveryDialog::itemActivated(QListWidgetItem *item) +{ + const QString text = item->text(); + const auto index = text.indexOf(' '); + if (index == -1) + return; + + QBluetoothAddress address(text.left(index)); + QString name(text.mid(index + 1)); + + ServiceDiscoveryDialog d(name, address); + d.exec(); +} + +void DeviceDiscoveryDialog::on_discoverable_clicked(bool clicked) +{ + if (clicked) + localDevice->setHostMode(QBluetoothLocalDevice::HostDiscoverable); + else + localDevice->setHostMode(QBluetoothLocalDevice::HostConnectable); +} + +void DeviceDiscoveryDialog::on_power_clicked(bool clicked) +{ + if (clicked) + localDevice->powerOn(); + else + localDevice->setHostMode(QBluetoothLocalDevice::HostPoweredOff); +} + +void DeviceDiscoveryDialog::hostModeStateChanged(QBluetoothLocalDevice::HostMode mode) +{ + ui->power->setChecked(mode != QBluetoothLocalDevice::HostPoweredOff); + ui->discoverable->setChecked(mode == QBluetoothLocalDevice::HostDiscoverable); + + const bool on = mode != QBluetoothLocalDevice::HostPoweredOff; + ui->scan->setEnabled(on); + ui->discoverable->setEnabled(on); +} +void DeviceDiscoveryDialog::displayPairingMenu(const QPoint &pos) +{ + if (ui->list->count() == 0) + return; + QMenu menu(this); + QAction *pairAction = menu.addAction("Pair"); + QAction *removePairAction = menu.addAction("Remove Pairing"); + QAction *chosenAction = menu.exec(ui->list->viewport()->mapToGlobal(pos)); + QListWidgetItem *currentItem = ui->list->currentItem(); + + QString text = currentItem->text(); + const auto index = text.indexOf(' '); + if (index == -1) + return; + + QBluetoothAddress address (text.left(index)); + if (chosenAction == pairAction) { + localDevice->requestPairing(address, QBluetoothLocalDevice::Paired); + } else if (chosenAction == removePairAction) { + localDevice->requestPairing(address, QBluetoothLocalDevice::Unpaired); + } +} +void DeviceDiscoveryDialog::pairingDone(const QBluetoothAddress &address, + QBluetoothLocalDevice::Pairing pairing) +{ + const auto items = ui->list->findItems(address.toString(), Qt::MatchContains); + const QColor color = colorForPairing(pairing); + for (auto *item : items) + item->setForeground(color); +} diff --git a/tests/manual/examples/btscanner/device.h b/tests/manual/examples/btscanner/device.h new file mode 100644 index 0000000..389062b --- /dev/null +++ b/tests/manual/examples/btscanner/device.h @@ -0,0 +1,49 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef DEVICE_H +#define DEVICE_H + +#include + +#include + +QT_BEGIN_NAMESPACE +class QBluetoothAddress; +class QBluetoothDeviceDiscoveryAgent; +class QBluetoothDeviceInfo; +class QListWidgetItem; + +namespace Ui { + class DeviceDiscovery; +} +QT_END_NAMESPACE + +class DeviceDiscoveryDialog : public QDialog +{ + Q_OBJECT + +public: + DeviceDiscoveryDialog(QWidget *parent = nullptr); + ~DeviceDiscoveryDialog(); + +public slots: + void addDevice(const QBluetoothDeviceInfo &info); + void on_power_clicked(bool clicked); + void on_discoverable_clicked(bool clicked); + void displayPairingMenu(const QPoint &pos); + void pairingDone(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing); +private slots: + void startScan(); + void stopScan(); + void scanFinished(); + void itemActivated(QListWidgetItem *item); + void hostModeStateChanged(QBluetoothLocalDevice::HostMode mode); + +private: + QBluetoothDeviceDiscoveryAgent *discoveryAgent; + QBluetoothLocalDevice *localDevice; + Ui::DeviceDiscovery *ui; +}; + +#endif diff --git a/tests/manual/examples/btscanner/device.ui b/tests/manual/examples/btscanner/device.ui new file mode 100644 index 0000000..fd86a35 --- /dev/null +++ b/tests/manual/examples/btscanner/device.ui @@ -0,0 +1,118 @@ + + + DeviceDiscovery + + + + 0 + 0 + 400 + 411 + + + + Bluetooth Scanner + + + + + + + + + Local Device + + + + + + Bluetooth Powered On + + + true + + + + + + + Discoverable + + + true + + + + + + + + + + + + Scan + + + + + + + Stop scan + + + + + + + Clear + + + + + + + Quit + + + + + + + + + + + quit + clicked() + DeviceDiscovery + accept() + + + 323 + 275 + + + 396 + 268 + + + + + clear + clicked() + list + clear() + + + 188 + 276 + + + 209 + 172 + + + + + diff --git a/tests/manual/examples/btscanner/main.cpp b/tests/manual/examples/btscanner/main.cpp new file mode 100644 index 0000000..8ed2e65 --- /dev/null +++ b/tests/manual/examples/btscanner/main.cpp @@ -0,0 +1,33 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "device.h" + +#include +#include + +#if QT_CONFIG(permissions) +#include +#endif + +int main(int argc, char *argv[]) +{ + // QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true")); + QApplication app(argc, argv); + DeviceDiscoveryDialog d; + + d.show(); + + // Check, and if needed, request a permission to use Bluetooth. +#if QT_CONFIG(permissions) + const auto permissionStatus = app.checkPermission(QBluetoothPermission{}); + if (permissionStatus == Qt::PermissionStatus::Undetermined) { + app.requestPermission(QBluetoothPermission{}, [](const QPermission &){ + }); + } + // Else means either 'Granted' or 'Denied' and both normally must be + // changed using the system's settings application. +#endif // QT_CONFIG(permissions) + + return app.exec(); +} diff --git a/tests/manual/examples/btscanner/service.cpp b/tests/manual/examples/btscanner/service.cpp new file mode 100644 index 0000000..aa6fe43 --- /dev/null +++ b/tests/manual/examples/btscanner/service.cpp @@ -0,0 +1,62 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// Copyright (C) 2013 BlackBerry Limited. All rights reserved. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "service.h" +#include "ui_service.h" + +#include +#include +#include +#include +#include + + +ServiceDiscoveryDialog::ServiceDiscoveryDialog(const QString &name, + const QBluetoothAddress &address, QWidget *parent) + : QDialog(parent), ui(new Ui::ServiceDiscovery) +{ + ui->setupUi(this); + + //Using default Bluetooth adapter + QBluetoothLocalDevice localDevice; + QBluetoothAddress adapterAddress = localDevice.address(); + + // In case of multiple Bluetooth adapters it is possible to + // set which adapter will be used by providing MAC Address. + // Example code: + // + // QBluetoothAddress adapterAddress("XX:XX:XX:XX:XX:XX"); + // discoveryAgent = new QBluetoothServiceDiscoveryAgent(adapterAddress, this); + + discoveryAgent = new QBluetoothServiceDiscoveryAgent(adapterAddress, this); + discoveryAgent->setRemoteAddress(address); + + setWindowTitle(name); + + connect(discoveryAgent, &QBluetoothServiceDiscoveryAgent::serviceDiscovered, + this, &ServiceDiscoveryDialog::addService); + connect(discoveryAgent, &QBluetoothServiceDiscoveryAgent::finished, + ui->status, &QWidget::hide); + + discoveryAgent->start(); +} + +ServiceDiscoveryDialog::~ServiceDiscoveryDialog() +{ + delete ui; +} + +void ServiceDiscoveryDialog::addService(const QBluetoothServiceInfo &info) +{ + if (info.serviceName().isEmpty()) + return; + + QString line = info.serviceName(); + if (!info.serviceDescription().isEmpty()) + line.append("\n\t" + info.serviceDescription()); + if (!info.serviceProvider().isEmpty()) + line.append("\n\t" + info.serviceProvider()); + + ui->list->addItem(line); +} diff --git a/tests/manual/examples/btscanner/service.h b/tests/manual/examples/btscanner/service.h new file mode 100644 index 0000000..1c84f38 --- /dev/null +++ b/tests/manual/examples/btscanner/service.h @@ -0,0 +1,36 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef SERVICE_H +#define SERVICE_H + +#include + +QT_BEGIN_NAMESPACE +class QBluetoothAddress; +class QBluetoothServiceDiscoveryAgent; +class QBluetoothServiceInfo; + +namespace Ui { + class ServiceDiscovery; +} +QT_END_NAMESPACE + +class ServiceDiscoveryDialog : public QDialog +{ + Q_OBJECT + +public: + ServiceDiscoveryDialog(const QString &name, const QBluetoothAddress &address, + QWidget *parent = nullptr); + ~ServiceDiscoveryDialog(); + +public slots: + void addService(const QBluetoothServiceInfo &info); + +private: + QBluetoothServiceDiscoveryAgent *discoveryAgent; + Ui::ServiceDiscovery *ui; +}; + +#endif diff --git a/tests/manual/examples/btscanner/service.ui b/tests/manual/examples/btscanner/service.ui new file mode 100644 index 0000000..4ca12ee --- /dev/null +++ b/tests/manual/examples/btscanner/service.ui @@ -0,0 +1,71 @@ + + + ServiceDiscovery + + + + 0 + 0 + 539 + 486 + + + + Available Services + + + + + + + + + Querying... + + + + + + + QDialogButtonBox::Close + + + + + + + + + buttonBox + accepted() + ServiceDiscovery + accept() + + + 396 + 457 + + + 535 + 443 + + + + + buttonBox + rejected() + ServiceDiscovery + reject() + + + 339 + 464 + + + 535 + 368 + + + + + diff --git a/tests/manual/qlowenergycontroller/CMakeLists.txt b/tests/manual/qlowenergycontroller/CMakeLists.txt new file mode 100644 index 0000000..a1039a5 --- /dev/null +++ b/tests/manual/qlowenergycontroller/CMakeLists.txt @@ -0,0 +1,68 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.16...3.21) + +if(NOT TARGET Qt::Bluetooth) + # for standalone build (and the only way for iOS) + project(tst_qlowenergycontroller_device LANGUAGES CXX) + + set(CMAKE_AUTOMOC ON) + + find_package(Qt6 REQUIRED COMPONENTS Bluetooth Core Test Gui) + + qt_add_executable( + tst_qlowenergycontroller_device + tst_qlowenergycontroller_device.cpp + ) + target_link_libraries( + tst_qlowenergycontroller_device + PUBLIC + Qt::Core + Qt::Bluetooth + Qt::Test + Qt::Gui + ) + +else() + +qt_internal_add_test(tst_qlowenergycontroller_device + SOURCES + tst_qlowenergycontroller_device.cpp + LIBRARIES + Qt::Bluetooth +) + +qt_internal_extend_target(tst_qlowenergycontroller_device + CONDITION ANDROID AND NOT ANDROID_EMBEDDED + DEFINES + QT_ANDROID_BLUETOOTH +) + +if(MACOS) + # Explicitly link against the static permission plugin because tests + # currently don't have finalizers run for them except for iOS. + # TODO: Remove this when qtbase automatically runs finalizers for tests: QTBUG-112212 + target_link_libraries(tst_qlowenergycontroller_device PRIVATE Qt6::QDarwinBluetoothPermissionPlugin) +endif() + +endif() + +set_target_properties(tst_qlowenergycontroller_device PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +if(APPLE) + # Ninja has trouble with relative paths, convert to absolute as a workaround + get_filename_component(SHARED_PLIST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../shared ABSOLUTE) + if(IOS) + set_target_properties(tst_qlowenergycontroller_device PROPERTIES + MACOSX_BUNDLE_INFO_PLIST "${SHARED_PLIST_DIR}/Info.ios.plist" + ) + else() + set_target_properties(tst_qlowenergycontroller_device PROPERTIES + MACOSX_BUNDLE_INFO_PLIST "${SHARED_PLIST_DIR}/Info.macos.plist" + ) + endif() +endif() diff --git a/tests/manual/qlowenergycontroller/tst_qlowenergycontroller_device.cpp b/tests/manual/qlowenergycontroller/tst_qlowenergycontroller_device.cpp new file mode 100644 index 0000000..e492363 --- /dev/null +++ b/tests/manual/qlowenergycontroller/tst_qlowenergycontroller_device.cpp @@ -0,0 +1,945 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if QT_CONFIG(permissions) +#include +#include +#include +#endif + +static const QLatin1String largeAttributeServiceUuid("1f85e37c-ac16-11eb-ae5c-93d3a763feed"); +static const QLatin1String largeAttributeCharUuid("40e4f68e-ac16-11eb-9956-cfe55a8c370c"); +static const QLatin1String largeAttributeDescUuid("44e4f68e-ac16-11eb-9956-cfe55a8c370c"); +static constexpr qsizetype largeAttributeSize{508}; // Size for char and desc values + +static const QLatin1String platformIdentifierServiceUuid("4a92cb7f-5031-4a09-8304-3e89413f458d"); +static const QLatin1String platformIdentifierCharUuid("6b0ecf7c-5f09-4c87-aaab-bb49d5d383aa"); + +static const QLatin1String + notificationIndicationTestServiceUuid("bb137ac5-5716-4b80-873b-e2d11d29efe2"); +static const QLatin1String + notificationIndicationTestChar1Uuid("6da4d652-0248-478a-a5a8-1e2f076158cc"); +static const QLatin1String + notificationIndicationTestChar2Uuid("990930f0-b9cc-4c27-8c1b-ebc2bcae5c95"); +static const QLatin1String + notificationIndicationTestChar3Uuid("9a60486b-de5b-4e03-b914-4e158c0bd388"); +static const QLatin1String + notificationIndicationTestChar4Uuid("d92435d4-6c2e-43f8-a6be-bbb66b5a3e28"); + +static const QLatin1String connectionCountServiceUuid("78c61a07-a0f9-4b92-be2d-2570d8dbf010"); +static const QLatin1String connectionCountCharUuid("9414ec2d-792f-46a2-a19e-186d0fb38a08"); + +static const QLatin1String repeatedWriteServiceUuid("72b12a31-98ea-406d-a89d-2c932d11ff67"); +static const QLatin1String repeatedWriteTargetCharUuid("2192ee43-6d17-4e78-b286-db2c3b696833"); +static const QLatin1String repeatedWriteNotifyCharUuid("b3f9d1a2-3d55-49c9-8b29-e09cec77ff86"); + + +// With the defines below some test cases are picked on at compile-time as opposed to runtime skips +// to avoid the lengthy init() and clean() executions +#if defined(QT_ANDROID_BLUETOOTH) || defined(QT_WINRT_BLUETOOTH) || defined(Q_OS_DARWIN) +#define QT_BLUETOOTH_MTU_SUPPORTED +#endif + +#if defined(QT_ANDROID_BLUETOOTH) || defined(Q_OS_DARWIN) +#define QT_BLUETOOTH_RSSI_SUPPORTED +#endif + +#if defined(QT_BLUETOOTH_MTU_SUPPORTED) +static const QLatin1String mtuServiceUuid("9a9483eb-cf4f-4c32-9a6b-794238d5b483"); +static const QLatin1String mtuCharUuid("960d7e2a-a850-4a70-8064-cd74e9ccb6ff"); +#endif + +/* + * This class contains all unit tests for QLowEnergyController + * which require a remote device and can thus not run completely automated. + * + * This testcase acts as a bluetooth LE *client*. + * The counterpart *server* device is the "bluetoothtestdevice" in the same + * repository and it needs to be ran when this testcase is ran. + * + * The name of the server device needs to be adjusted in this code so that + * this LE client can find it. For example on macOS and Linux it is a generic + * "BluetoothTestDevice" where as on Android it is the device's bluetooth name + * set by the user. Please see the BTLE_SERVER_DEVICE_NAME below. + */ +class tst_qlowenergycontroller_device : public QObject +{ + Q_OBJECT + +public: + tst_qlowenergycontroller_device(); + ~tst_qlowenergycontroller_device(); +private slots: + void initTestCase(); + void init(); + void cleanup(); + void cleanupTestCase(); + + // Keep readServerPlatform as the first test, later tests + // may depend on its results. + void readServerPlatform(); + +#if defined(QT_BLUETOOTH_MTU_SUPPORTED) + void checkMtuNegotiation(); +#endif +#if defined(QT_BLUETOOTH_RSSI_SUPPORTED) + void rssiRead(); +#endif + void readWriteLargeCharacteristic(); + void readWriteLargeDescriptor(); + void readDuringServiceDiscovery(); + void readNotificationAndIndicationProperty(); + void testNotificationAndIndication(); + void testRepeatedCharacteristicsWrite(); + +public: + void checkconnectionCounter(std::unique_ptr &control); + static int connectionCounter; + +private: + void discoverTestServer(); + + std::unique_ptr mDevAgent; + std::unique_ptr mController; + QBluetoothDeviceInfo mRemoteDeviceInfo; + QString mServerDeviceName; + QByteArray mServerPlatform; +#if QT_CONFIG(permissions) + Qt::PermissionStatus permissionStatus = Qt::PermissionStatus::Undetermined; +#endif +}; + +// connectionCounter is used to check that the server-side connect events +// occur as expected. On the first time when the value is the initial "-1" +// we read the current connection count from a service/characteristic providing it. +// This way we don't need to always restart the server-side for testing +int tst_qlowenergycontroller_device::connectionCounter = -1; + +tst_qlowenergycontroller_device::tst_qlowenergycontroller_device() +{ + QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true")); +#if QT_CONFIG(permissions) + // FIXME: Android has more specific BT permissions, fix when appropriate + // change is done in qtbase + permissionStatus = qApp->checkPermission(QBluetoothPermission{}); + if (qApp->checkPermission(QBluetoothPermission{}) == Qt::PermissionStatus::Undetermined) { + QTestEventLoop loop; + qApp->requestPermission(QBluetoothPermission{}, [this, &loop](const QPermission &permission){ + permissionStatus = permission.status(); + loop.exitLoop(); + }); + if (permissionStatus == Qt::PermissionStatus::Undetermined) + loop.enterLoopMSecs(30000); + } +#endif +} + +tst_qlowenergycontroller_device::~tst_qlowenergycontroller_device() { } + +void tst_qlowenergycontroller_device::initTestCase() +{ +#if QT_CONFIG(permissions) + if (permissionStatus != Qt::PermissionStatus::Granted) + QSKIP("This manual test requires Blutooth permissions granted."); +#endif + qDebug() << "Testcase build time: " << __TIME__; + mDevAgent.reset(new QBluetoothDeviceDiscoveryAgent(this)); + mDevAgent->setLowEnergyDiscoveryTimeout(75000); + mServerDeviceName = qEnvironmentVariable("BTLE_SERVER_DEVICE_NAME"); + if (mServerDeviceName.isEmpty()) + mServerDeviceName = QStringLiteral("BluetoothTestDevice"); + qDebug() << "Using server device name for testing: " << mServerDeviceName; + qDebug() << "To change this set BTLE_SERVER_DEVICE_NAME environment variable"; +} + +void tst_qlowenergycontroller_device::discoverTestServer() +{ + mRemoteDeviceInfo = QBluetoothDeviceInfo(); // Invalidate whatever we had before + QSignalSpy finishedSpy(mDevAgent.get(), SIGNAL(finished())); + QSignalSpy canceledSpy(mDevAgent.get(), SIGNAL(canceled())); + // there should be no changes yet + QVERIFY(finishedSpy.isValid() && finishedSpy.isEmpty()); + QVERIFY(canceledSpy.isValid() && canceledSpy.isEmpty()); + + QObject forLifeTime; + QObject::connect(mDevAgent.get(), &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, + &forLifeTime, [&](const QBluetoothDeviceInfo& info) { + if (info.name() == mServerDeviceName) { + qDebug() << "Matching server device discovered, stopping device discovery agent"; + mDevAgent->stop(); + } + }); + + // Start device discovery + mDevAgent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod); + QTRY_VERIFY_WITH_TIMEOUT(!finishedSpy.isEmpty() || !canceledSpy.isEmpty(), 80000); + + // Verify that we have found a matching server device + bool deviceFound = false; + const QList infos = mDevAgent->discoveredDevices(); + for (const QBluetoothDeviceInfo &info : infos) { + if (info.name() == mServerDeviceName) { + mRemoteDeviceInfo = info; + deviceFound = true; + qDebug() << "Found a matching server device" << info.name() << info.address(); + break; + } + qDebug() << "Ignoring a non-matching device:" << info.name() << info.address(); + } + QVERIFY2(deviceFound, "Cannot find remote device."); +} + + +void tst_qlowenergycontroller_device::init() +{ + // Connect to the test server. If unsuccessful, rediscover and retry. + // Rediscovery may be needed as the address of the remote can change and + // also at least Bluez backend recovers from its own internal errors + // more likely making the test less flaky + while (!mController || mController->state() != QLowEnergyController::ConnectedState) { + discoverTestServer(); + QVERIFY(mRemoteDeviceInfo.isValid()); + mController.reset(QLowEnergyController::createCentral(mRemoteDeviceInfo)); + mController->connectToDevice(); + QTRY_VERIFY_WITH_TIMEOUT(mController->state() != QLowEnergyController::ConnectingState, 45000); + if (mController->state() != QLowEnergyController::ConnectedState) { + mController.reset(); + qDebug() << "Retrying connecting to the server in 5 seconds"; + QTest::qWait(5000); + } + } + QCOMPARE(mController->state(), QLowEnergyController::ConnectedState); + QCOMPARE(mController->error(), QLowEnergyController::NoError); +} + +void tst_qlowenergycontroller_device::cleanup() +{ + mController->disconnectFromDevice(); + + // Attempt a graceful close. If the test has already failed, the QTRY would exit immediately + if (!QTest::currentTestFailed()) + QTRY_VERIFY_WITH_TIMEOUT(mController->state() == + QLowEnergyController::UnconnectedState, 30000); + else + QTest::qWait(2000); + + QCOMPARE(mController->state(), QLowEnergyController::UnconnectedState); + qDebug() << "Disconnected from remote device, waiting 5s before deleting controller."; + QTest::qWait(5000); + mController.reset(); +} + +void tst_qlowenergycontroller_device::cleanupTestCase() { } + +// The readServerPlatform should always be the first actual test function to execute. +// It reads a characteristic where the server reports on which platform it runs on. +// This information can then be used to adjust the test case's behavior accordingly; +// different platforms support slightly different things. +void tst_qlowenergycontroller_device::readServerPlatform() +{ + QVERIFY(mController->services().isEmpty()); + mController->discoverServices(); + QTRY_COMPARE(mController->state(), QLowEnergyController::DiscoveredState); + QCOMPARE(mController->error(), QLowEnergyController::NoError); + + QSharedPointer service( + mController->createServiceObject(QBluetoothUuid(platformIdentifierServiceUuid))); + QVERIFY(service != nullptr); + service->discoverDetails(QLowEnergyService::FullDiscovery); + QTRY_COMPARE(service->state(), QLowEnergyService::ServiceState::RemoteServiceDiscovered); + + auto characteristic = service->characteristic(QBluetoothUuid(platformIdentifierCharUuid)); + mServerPlatform = characteristic.value(); + qDebug() << "Server reported its running on: " << mServerPlatform; + QVERIFY(!mServerPlatform.isEmpty()); +} + + +#if defined(QT_BLUETOOTH_MTU_SUPPORTED) +void tst_qlowenergycontroller_device::checkMtuNegotiation() +{ + // service discovery, including MTU negotiation + qDebug() << "Client-side MTU after connect" << mController->mtu(); + QVERIFY(mController->services().isEmpty()); + mController->discoverServices(); + QTRY_COMPARE(mController->state(), QLowEnergyController::DiscoveredState); + QCOMPARE(mController->error(), QLowEnergyController::NoError); + + checkconnectionCounter(mController); + + // now a larger MTU should have been negotiated + QTRY_VERIFY(mController->mtu() > 23); + qDebug() << "MTU after service discovery" << mController->mtu(); + + // check that central and peripheral agree on negotiated mtu + QSharedPointer service( + mController->createServiceObject(QBluetoothUuid(mtuServiceUuid))); + QVERIFY(service != nullptr); + service->discoverDetails(QLowEnergyService::FullDiscovery); + QTRY_COMPARE(service->state(), QLowEnergyService::ServiceState::RemoteServiceDiscovered); + + auto characteristic = service->characteristic(QBluetoothUuid(mtuCharUuid)); + int mtu; + memcpy(&mtu, characteristic.value().constData(), sizeof(int)); + qDebug() << "MTU reported by server-side:" << mtu; + // Server-side mtu is not supported on all platforms + if (mServerPlatform != "linux" && mServerPlatform != "darwin") + QCOMPARE(mtu, mController->mtu()); +} +#endif +#undef QT_BLUETOOTH_MTU_SUPPORTED + +#if defined(QT_BLUETOOTH_RSSI_SUPPORTED) + +#define READ_AND_VERIFY_RSSI_VALUE \ + errorSpy.clear(); \ + rssiSpy.clear(); \ + mController->readRssi(); \ + QTRY_VERIFY(!rssiSpy.isEmpty()); \ + QVERIFY(errorSpy.isEmpty()); \ + rssi = rssiSpy.takeFirst().at(0).toInt(); \ + QCOMPARE_GE(rssi, -127); \ + QCOMPARE_LE(rssi, 127); \ + +void tst_qlowenergycontroller_device::rssiRead() +{ + QSignalSpy errorSpy(mController.get(), &QLowEnergyController::errorOccurred); + QSignalSpy rssiSpy(mController.get(), &QLowEnergyController::rssiRead); + int rssi = 1000; // valid values are -127..127 + + // 1) Read RSSI in connected state + QCOMPARE(mController->state(), QLowEnergyController::ConnectedState); + READ_AND_VERIFY_RSSI_VALUE; + // Check that the value changes. This might seem flaky with stationary bluetooth + // devices but in practice the RSSI constantly fluctuates + const int initialRssi = rssi; + for (int attempt = 1; attempt < 20; attempt++) { + READ_AND_VERIFY_RSSI_VALUE; + QTest::qWait(200); // Provide a bit time for the RSSI to change + if (rssi != initialRssi) + break; + } + QVERIFY(rssi != initialRssi); + + // 2) Read RSSI while discovering services + QVERIFY(mController->services().isEmpty()); + mController->discoverServices(); + QCOMPARE(mController->state(), QLowEnergyController::DiscoveringState); + READ_AND_VERIFY_RSSI_VALUE; + + // 3) Read RSSI after services have been discovered + QTRY_COMPARE(mController->state(), QLowEnergyController::DiscoveredState); + READ_AND_VERIFY_RSSI_VALUE; + + // 4) Read RSSI while discovering service details + QSharedPointer service(mController->createServiceObject( + QBluetoothUuid(repeatedWriteServiceUuid))); + QVERIFY(service != nullptr); + service->discoverDetails(QLowEnergyService::FullDiscovery); + QCOMPARE(service->state(), QLowEnergyService::ServiceState::RemoteServiceDiscovering); + READ_AND_VERIFY_RSSI_VALUE; + + // 5) Read RSSI after service detail discovery + QTRY_COMPARE(service->state(), QLowEnergyService::ServiceState::RemoteServiceDiscovered); + READ_AND_VERIFY_RSSI_VALUE; + + checkconnectionCounter(mController); + + // 6) Read RSSI amidst characteristic reads and writes + QSignalSpy writeSpy(service.get(), &QLowEnergyService::characteristicWritten); + QSignalSpy readSpy(service.get(), &QLowEnergyService::characteristicRead); + auto characteristic = service->characteristic(QBluetoothUuid(repeatedWriteTargetCharUuid)); + QByteArray value(8, 'a'); + service->writeCharacteristic(characteristic, value); + READ_AND_VERIFY_RSSI_VALUE; + QTRY_VERIFY(!writeSpy.isEmpty()); + + service->readCharacteristic(characteristic); + READ_AND_VERIFY_RSSI_VALUE; + QTRY_VERIFY(!readSpy.isEmpty()); + + // A bit of stress-testing to check that read/write and + // RSSI reading don't interfere with one another + writeSpy.clear(); + readSpy.clear(); + rssiSpy.clear(); + errorSpy.clear(); + const int TIMES = 5; + for (int i = 0; i < TIMES; i++) { + mController->readRssi(); + service->writeCharacteristic(characteristic, value); + mController->readRssi(); + service->readCharacteristic(characteristic); + } + QTRY_COMPARE(writeSpy.size(), TIMES); + QTRY_COMPARE(readSpy.size(), TIMES); +#if defined(Q_OS_ANDROID) + QTRY_COMPARE(rssiSpy.size(), TIMES * 2); +#else + // On darwin several pending requests will get one callback + QTRY_COMPARE_GE(rssiSpy.size(), 1); +#endif + QVERIFY(errorSpy.isEmpty()); + + // 7) Disconnect the device and verify we get error for RSSI read + errorSpy.clear(); + rssiSpy.clear(); + mController->disconnectFromDevice(); + // First right after requesting disconnect + mController->readRssi(); + QTRY_COMPARE(errorSpy.size(), 1); + QCOMPARE(errorSpy.takeFirst().at(0).value(), + QLowEnergyController::Error::RssiReadError); + QCOMPARE(mController->error(), QLowEnergyController::Error::RssiReadError); + QVERIFY(rssiSpy.isEmpty()); + + // Then once the disconnection is complete + QTRY_COMPARE(mController->state(), QLowEnergyController::UnconnectedState); + errorSpy.clear(); + mController->readRssi(); + QTRY_COMPARE(errorSpy.size(), 1); + QCOMPARE(errorSpy.takeFirst().at(0).value(), + QLowEnergyController::Error::RssiReadError); + QCOMPARE(mController->error(), QLowEnergyController::Error::RssiReadError); + QVERIFY(rssiSpy.isEmpty()); +} +#endif +#undef QT_BLUETOOTH_RSSI_SUPPORTED + +void tst_qlowenergycontroller_device::checkconnectionCounter( + std::unique_ptr &mController) +{ + // on darwin the server-side connect/disconnect events are not reported reliably + if (mServerPlatform == "darwin") + return; + QSharedPointer service( + mController->createServiceObject(QBluetoothUuid(connectionCountServiceUuid))); + QVERIFY(service != nullptr); + service->discoverDetails(QLowEnergyService::FullDiscovery); + QTRY_COMPARE(service->state(), QLowEnergyService::ServiceState::RemoteServiceDiscovered); + + auto counterCharacteristic = service->characteristic(QBluetoothUuid(connectionCountCharUuid)); + // If we have just started the test, read the current connection counter from the server. + // The connection counter is essentially the number of "connected" events the server + // has had. + if (connectionCounter == -1) { + memcpy(&connectionCounter, counterCharacteristic.value().constData(), sizeof(int)); + qDebug() << "Connection counter initialized from the server to:" << connectionCounter; + } else { + connectionCounter++; + QByteArray value((const char *)&connectionCounter, sizeof(int)); + QCOMPARE(counterCharacteristic.value(), value); + } +} + +void tst_qlowenergycontroller_device::readWriteLargeCharacteristic() +{ + // This tests reading and writing a large characteristic value + // + // Most modern platforms cope with up-to 512 bytes. One exception is Bluez DBus peripheral, + // which may reject a write from client when going above 508 due to the way it internally + // checks the payload size (tested with Bluez 5.64). + // + // This test can also be used for testing long (aka prepared) writes & reads by setting + // the MTU to for example 50 bytes. Asking a specific MTU is platform-specific and + // there is no Qt API for it + QVERIFY(mController->services().isEmpty()); + mController->discoverServices(); + QTRY_COMPARE(mController->state(), QLowEnergyController::DiscoveredState); + + checkconnectionCounter(mController); + + QSharedPointer service( + mController->createServiceObject(QBluetoothUuid(largeAttributeServiceUuid))); + QVERIFY(service != nullptr); + service->discoverDetails(QLowEnergyService::SkipValueDiscovery); + QTRY_COMPARE(service->state(), QLowEnergyService::ServiceState::RemoteServiceDiscovered); + + QSignalSpy readSpy(service.get(), &QLowEnergyService::characteristicRead); + QSignalSpy writtenSpy(service.get(), &QLowEnergyService::characteristicWritten); + + // The service discovery skipped the values => check that the default values are all zeroes + auto characteristic = service->characteristic(QBluetoothUuid(largeAttributeCharUuid)); + QVERIFY(characteristic.isValid()); + QByteArray testArray(0); + qDebug() << "Initial large characteristic value:" << characteristic.value(); + QCOMPARE(characteristic.value(), testArray); + + // Read the characteristic value and verify it is the one the server-side sets (0x0b 0x00 ..) + service->readCharacteristic(characteristic); + QTRY_COMPARE(readSpy.size(), 1); + qDebug() << "Large characteristic value after read:" << characteristic.value(); + testArray = QByteArray(largeAttributeSize, 0); + testArray[0] = 0x0b; + QCOMPARE(characteristic.value(), testArray); + + // Write a new value to characteristic and read it back + for (int i = 0; i < largeAttributeSize; ++i) { + testArray[i] = i % 5; + } + service->writeCharacteristic(characteristic, testArray); + QCOMPARE(service->error(), QLowEnergyService::ServiceError::NoError); + QTRY_COMPARE(writtenSpy.size(), 1); + + service->readCharacteristic(characteristic); + QTRY_COMPARE(readSpy.size(), 2); + qDebug() << "Large characteristic value after write/read:" << characteristic.value(); + QCOMPARE(characteristic.value(), testArray); +} + +void tst_qlowenergycontroller_device::readWriteLargeDescriptor() +{ + // This tests reading and writing a large descriptor value + QVERIFY(mController->services().isEmpty()); + mController->discoverServices(); + QTRY_COMPARE(mController->state(), QLowEnergyController::DiscoveredState); + + checkconnectionCounter(mController); + + QSharedPointer service( + mController->createServiceObject(QBluetoothUuid(largeAttributeServiceUuid))); + QVERIFY(service != nullptr); + service->discoverDetails(QLowEnergyService::FullDiscovery); + QTRY_COMPARE(service->state(), QLowEnergyService::ServiceState::RemoteServiceDiscovered); + + QSignalSpy readSpy(service.get(), &QLowEnergyService::descriptorRead); + QSignalSpy writtenSpy(service.get(), &QLowEnergyService::descriptorWritten); + + auto characteristic = service->characteristic(QBluetoothUuid(largeAttributeCharUuid)); + QVERIFY(characteristic.isValid()); + auto descriptor = characteristic.descriptor(QBluetoothUuid(largeAttributeDescUuid)); + QVERIFY(descriptor.isValid()); + + QByteArray testArray = QByteArray(largeAttributeSize, 0); + testArray[0] = 0xdd; + + // Read descriptor value and verify it is what the server set (0xdd 0x00 ..) + QVERIFY(readSpy.isEmpty()); + QVERIFY(writtenSpy.isEmpty()); + service->readDescriptor(descriptor); + QTRY_COMPARE(readSpy.size(), 1); + qDebug() << "Large descriptor value after read:" << descriptor.value(); + QCOMPARE(descriptor.value(), testArray); + + // Write a new value to descriptor and read it back + for (int i = 0; i < largeAttributeSize; ++i) { + testArray[i] = i % 5; + } + service->writeDescriptor(descriptor, testArray); + QCOMPARE(service->error(), QLowEnergyService::ServiceError::NoError); + QTRY_COMPARE(writtenSpy.size(), 1); + + service->readDescriptor(descriptor); + QTRY_COMPARE(readSpy.size(), 2); + qDebug() << "Large descriptor value after write/read:" << descriptor.value(); + QCOMPARE(descriptor.value(), testArray); +} + +void tst_qlowenergycontroller_device::readDuringServiceDiscovery() +{ + QVERIFY(mController->services().isEmpty()); + mController->discoverServices(); + QTRY_COMPARE(mController->state(), QLowEnergyController::DiscoveredState); + + checkconnectionCounter(mController); + + QSharedPointer service( + mController->createServiceObject(QBluetoothUuid(largeAttributeServiceUuid))); + QVERIFY(service != nullptr); + service->discoverDetails(QLowEnergyService::FullDiscovery); + QTRY_COMPARE(service->state(), QLowEnergyService::ServiceState::RemoteServiceDiscovered); + + QSignalSpy readSpy(service.get(), &QLowEnergyService::characteristicRead); + QSignalSpy writtenSpy(service.get(), &QLowEnergyService::characteristicWritten); + QCOMPARE(readSpy.size(), 0); + QCOMPARE(writtenSpy.size(), 0); + + // Value that is initially set on the characteristic at the server-side (0x0b 0x00 ..) + QByteArray testArray(largeAttributeSize, 0); + testArray[0] = 0x0b; + + // We did a full service discovery and should have an initial value to compare + auto characteristic = service->characteristic(QBluetoothUuid(largeAttributeCharUuid)); + QByteArray valueFromServiceDiscovery = characteristic.value(); + qDebug() << "Large characteristic value from service discovery:" << valueFromServiceDiscovery; + // On darwin the server does not restart (disconnect) in-between the case runs + // and the initial value may be from a previous test function + if (mServerPlatform != "darwin") + QCOMPARE(characteristic.value(), testArray); + + // Check that the value from service discovery and explicit characteristic read match + service->readCharacteristic(characteristic); + QTRY_COMPARE(readSpy.size(), 1); + qDebug() << "Large characteristic value after read:" << characteristic.value(); + QCOMPARE(characteristic.value(), valueFromServiceDiscovery); + + // Write a new value to the characteristic and read it back + for (int i = 0; i < largeAttributeSize; ++i) { + testArray[i] = i % 5; + } + service->writeCharacteristic(characteristic, testArray); + QCOMPARE(service->error(), QLowEnergyService::ServiceError::NoError); + QTRY_COMPARE(writtenSpy.size(), 1); + + service->readCharacteristic(characteristic); + QTRY_COMPARE(readSpy.size(), 2); + qDebug() << "Large characteristic value after write/read:" << characteristic.value(); + QCOMPARE(characteristic.value(), testArray); +} + +void tst_qlowenergycontroller_device::readNotificationAndIndicationProperty() +{ + // discover services + QVERIFY(mController->services().isEmpty()); + mController->discoverServices(); + QTRY_COMPARE(mController->state(), QLowEnergyController::DiscoveredState); + + checkconnectionCounter(mController); + + // check test service is available + QVERIFY(mController->services().contains(QBluetoothUuid(notificationIndicationTestServiceUuid))); + + // get service object + QSharedPointer service(mController->createServiceObject( + QBluetoothUuid(notificationIndicationTestServiceUuid))); + QVERIFY(service != nullptr); + service->discoverDetails(QLowEnergyService::FullDiscovery); + QTRY_COMPARE(service->state(), QLowEnergyService::ServiceState::RemoteServiceDiscovered); + + // check that all four characteristics are found + QCOMPARE(service->characteristics().size(), 4); + + // check that properties are correctly set + auto notifyOrIndicate = QLowEnergyCharacteristic::PropertyType::Notify + | QLowEnergyCharacteristic::PropertyType::Indicate; + { + QLowEnergyCharacteristic characteristic = + service->characteristic(QBluetoothUuid(notificationIndicationTestChar1Uuid)); + QCOMPARE(characteristic.properties() & notifyOrIndicate, 0); + } + { + QLowEnergyCharacteristic characteristic = + service->characteristic(QBluetoothUuid(notificationIndicationTestChar2Uuid)); + QCOMPARE(characteristic.properties() & notifyOrIndicate, + QLowEnergyCharacteristic::PropertyType::Notify); + } + { + QLowEnergyCharacteristic characteristic = + service->characteristic(QBluetoothUuid(notificationIndicationTestChar3Uuid)); + QCOMPARE(characteristic.properties() & notifyOrIndicate, + QLowEnergyCharacteristic::PropertyType::Indicate); + } + { + QLowEnergyCharacteristic characteristic = + service->characteristic(QBluetoothUuid(notificationIndicationTestChar4Uuid)); + QCOMPARE(characteristic.properties() & notifyOrIndicate, notifyOrIndicate); + } +} + +void tst_qlowenergycontroller_device::testNotificationAndIndication() +{ + // discover services + QVERIFY(mController->services().isEmpty()); + mController->discoverServices(); + QTRY_COMPARE(mController->state(), QLowEnergyController::DiscoveredState); + + checkconnectionCounter(mController); + + // get service object + QSharedPointer service(mController->createServiceObject( + QBluetoothUuid(notificationIndicationTestServiceUuid))); + QVERIFY(service != nullptr); + service->discoverDetails(QLowEnergyService::FullDiscovery); + QTRY_COMPARE(service->state(), QLowEnergyService::ServiceState::RemoteServiceDiscovered); + + // Verify that notification works + { + QLowEnergyCharacteristic characteristic = + service->characteristic(QBluetoothUuid(notificationIndicationTestChar2Uuid)); + auto notifyOrIndicate = QLowEnergyCharacteristic::PropertyType::Notify + | QLowEnergyCharacteristic::PropertyType::Indicate; + QCOMPARE(characteristic.properties() & notifyOrIndicate, + QLowEnergyCharacteristic::PropertyType::Notify); + + // getting cccd + QLowEnergyDescriptor cccd = characteristic.clientCharacteristicConfiguration(); + QVERIFY(cccd.isValid()); + + // write to cccd + bool cccdWritten = false; + QObject dummy; // for lifetime management + QObject::connect( + service.get(), &QLowEnergyService::descriptorWritten, &dummy, + [&cccdWritten](const QLowEnergyDescriptor &info, const QByteArray &) { + if (info.uuid() + == QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration) { + cccdWritten = true; + } + }); + service->writeDescriptor(cccd, QLowEnergyCharacteristic::CCCDEnableNotification); + QTRY_VERIFY(cccdWritten); + + // notification should be enabled + auto oldvalue = characteristic.value(); + QCOMPARE(characteristic.value(), oldvalue); + // wait for change + QTRY_VERIFY(characteristic.value() != oldvalue); + // wait again + oldvalue = characteristic.value(); + QCOMPARE(characteristic.value(), oldvalue); + // wait for change + QTRY_VERIFY(characteristic.value() != oldvalue); + + // disable notification + cccdWritten = false; + service->writeDescriptor(cccd, QLowEnergyCharacteristic::CCCDDisable); + QTRY_VERIFY(cccdWritten); + + // wait for a moment in case there is a value change just happening, + // then check that there are no more notifications: + QTest::qWait(200); + oldvalue = characteristic.value(); + for (int i = 0; i < 3; ++i) { + QTest::qWait(100); + QCOMPARE(characteristic.value(), oldvalue); + } + } + + // Verify that indication works + { + QLowEnergyCharacteristic characteristic = + service->characteristic(QBluetoothUuid(notificationIndicationTestChar3Uuid)); + auto notifyOrIndicate = QLowEnergyCharacteristic::PropertyType::Notify + | QLowEnergyCharacteristic::PropertyType::Indicate; + QCOMPARE(characteristic.properties() & notifyOrIndicate, + QLowEnergyCharacteristic::PropertyType::Indicate); + + // getting cccd + QLowEnergyDescriptor cccd = characteristic.clientCharacteristicConfiguration(); + QVERIFY(cccd.isValid()); + + // write to cccd + bool cccdWritten = false; + QObject dummy; // for lifetime management + QObject::connect( + service.get(), &QLowEnergyService::descriptorWritten, &dummy, + [&cccdWritten](const QLowEnergyDescriptor &info, const QByteArray &) { + if (info.uuid() + == QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration) { + cccdWritten = true; + } + }); + QByteArray newValue = QByteArray::fromHex("0200"); + service->writeDescriptor(cccd, newValue); + QTRY_VERIFY(cccdWritten); + + // indication should be enabled + auto oldvalue = characteristic.value(); + QCOMPARE(characteristic.value(), oldvalue); + // wait for change + QTRY_VERIFY(characteristic.value() != oldvalue); + // wait again + oldvalue = characteristic.value(); + QCOMPARE(characteristic.value(), oldvalue); + // wait for change + QTRY_VERIFY(characteristic.value() != oldvalue); + + // disable indication + cccdWritten = false; + newValue = QByteArray::fromHex("0000"); + service->writeDescriptor(cccd, newValue); + QTRY_VERIFY(cccdWritten); + + // wait for a moment in case there is a value change just happening, + // then check that there are no more notifications: + QTest::qWait(200); + oldvalue = characteristic.value(); + for (int i = 0; i < 3; ++i) { + QTest::qWait(100); + QCOMPARE(characteristic.value(), oldvalue); + } + } + + // indication and notification works +#if defined(Q_OS_LINUX) + // If the client (this testcase) is linux and the characteristic has both + // NTF & IND supported, the Bluez stack will try to enable both NTF & IND + // at the same time regardless of what we write to CCCD. Darwin server will + // reject this as an error (ATT error 0xf5, which is a reserved error) + if (mServerPlatform != "darwin") +#endif + { + QLowEnergyCharacteristic characteristic = + service->characteristic(QBluetoothUuid(notificationIndicationTestChar4Uuid)); + auto notifyOrIndicate = QLowEnergyCharacteristic::PropertyType::Notify + | QLowEnergyCharacteristic::PropertyType::Indicate; + QCOMPARE(characteristic.properties() & notifyOrIndicate, notifyOrIndicate); + + // getting cccd + QLowEnergyDescriptor cccd = characteristic.clientCharacteristicConfiguration(); + QVERIFY(cccd.isValid()); + + // write to cccd + bool cccdWritten = false; + QObject dummy; // for lifetime management + QObject::connect( + service.get(), &QLowEnergyService::descriptorWritten, &dummy, + [&cccdWritten](const QLowEnergyDescriptor &info, const QByteArray &) { + if (info.uuid() + == QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration) { + cccdWritten = true; + } + }); + QByteArray newValue = QByteArray::fromHex("0100"); + service->writeDescriptor(cccd, newValue); + QTRY_VERIFY(cccdWritten); + + // notification should be enabled + auto oldvalue = characteristic.value(); + QCOMPARE(characteristic.value(), oldvalue); + // wait for change + QTRY_VERIFY(characteristic.value() != oldvalue); + // wait again + oldvalue = characteristic.value(); + QCOMPARE(characteristic.value(), oldvalue); + // wait for change + QTRY_VERIFY(characteristic.value() != oldvalue); + + // disable notification + cccdWritten = false; + newValue = QByteArray::fromHex("0000"); + service->writeDescriptor(cccd, newValue); + QTRY_VERIFY(cccdWritten); + + // wait for a moment in case there is a value change just happening, + // then check that there are no more notifications: + QTest::qWait(200); + oldvalue = characteristic.value(); + for (int i = 0; i < 3; ++i) { + QTest::qWait(100); + QCOMPARE(characteristic.value(), oldvalue); + } + + newValue = QByteArray::fromHex("0200"); + service->writeDescriptor(cccd, newValue); + QTRY_VERIFY(cccdWritten); + + // indication should be enabled + oldvalue = characteristic.value(); + QCOMPARE(characteristic.value(), oldvalue); + // wait for change + QTRY_VERIFY(characteristic.value() != oldvalue); + // wait again + oldvalue = characteristic.value(); + QCOMPARE(characteristic.value(), oldvalue); + // wait for change + QTRY_VERIFY(characteristic.value() != oldvalue); + + // disable indication + cccdWritten = false; + newValue = QByteArray::fromHex("0000"); + service->writeDescriptor(cccd, newValue); + QTRY_VERIFY(cccdWritten); + + // wait for a moment in case there is a value change just happening, + // then check that there are no more indications: + QTest::qWait(200); + oldvalue = characteristic.value(); + for (int i = 0; i < 3; ++i) { + QTest::qWait(100); + QCOMPARE(characteristic.value(), oldvalue); + } + } +} + +void tst_qlowenergycontroller_device::testRepeatedCharacteristicsWrite() +{ + // This test generates multiple consecutive writes to the same characteristic + // and waits for the notifications (on other characteristic) with the same + // values. After that it verifies that the received values are the same (and + // in the same order) as written values. The server writes each received + // value to a notifying characteristic, which allows us to perform the check. + + // Discover services + QVERIFY(mController->services().isEmpty()); + mController->discoverServices(); + QTRY_COMPARE(mController->state(), QLowEnergyController::DiscoveredState); + + checkconnectionCounter(mController); + + // Get service object. + QSharedPointer service(mController->createServiceObject( + QBluetoothUuid(repeatedWriteServiceUuid))); + QVERIFY(service != nullptr); + service->discoverDetails(QLowEnergyService::FullDiscovery); + QTRY_COMPARE(service->state(), QLowEnergyService::ServiceState::RemoteServiceDiscovered); + + // Enable notification. + QLowEnergyCharacteristic notifyChar = + service->characteristic(QBluetoothUuid(repeatedWriteNotifyCharUuid)); + const auto notifyOrIndicate = QLowEnergyCharacteristic::PropertyType::Notify + | QLowEnergyCharacteristic::PropertyType::Indicate; + QCOMPARE(notifyChar.properties() & notifyOrIndicate, + QLowEnergyCharacteristic::PropertyType::Notify); + + QLowEnergyDescriptor cccd = notifyChar.clientCharacteristicConfiguration(); + QVERIFY(cccd.isValid()); + + QObject dummy; // for lifetime management + bool cccdWritten = false; + connect(service.get(), &QLowEnergyService::descriptorWritten, &dummy, + [&cccdWritten](const QLowEnergyDescriptor &info, const QByteArray &) { + if (info.uuid() + == QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration) { + cccdWritten = true; + } + }); + service->writeDescriptor(cccd, QLowEnergyCharacteristic::CCCDEnableNotification); + QTRY_VERIFY(cccdWritten); + + // Track the notifications of value changes. + QList receivedValues; + connect(service.get(), &QLowEnergyService::characteristicChanged, &dummy, + [&receivedValues](const QLowEnergyCharacteristic &characteristic, + const QByteArray &value) + { + if (characteristic.uuid() == QBluetoothUuid(repeatedWriteNotifyCharUuid)) { + receivedValues.push_back(value); + } + }); + + // Write characteristics multiple times. This shouldn't crash, and all + // values should be written. We use the notifications to track it. + receivedValues.clear(); + QList sentValues; + QLowEnergyCharacteristic writeChar = + service->characteristic(QBluetoothUuid(repeatedWriteTargetCharUuid)); + static const int totalWrites = 50; + QByteArray value(8, 0); + for (int i = 0; i < totalWrites; ++i) { + value[0] += 1; + value[7] += 1; + service->writeCharacteristic(writeChar, value); + sentValues.push_back(value); + } + + // We expect to get notifications about all writes. + // We set a large timeout to be on a safe side. + QTRY_COMPARE_WITH_TIMEOUT(receivedValues.size(), totalWrites, 60000); + QCOMPARE(receivedValues, sentValues); +} + +QTEST_MAIN(tst_qlowenergycontroller_device) + +#include "tst_qlowenergycontroller_device.moc" diff --git a/tests/manual/qlowenergycontroller_peripheral/CMakeLists.txt b/tests/manual/qlowenergycontroller_peripheral/CMakeLists.txt new file mode 100644 index 0000000..377e2dd --- /dev/null +++ b/tests/manual/qlowenergycontroller_peripheral/CMakeLists.txt @@ -0,0 +1,67 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.16...3.21) + +if(NOT TARGET Qt::Bluetooth) + # for standalone build (and the only way for iOS) + project(tst_qlowenergycontroller_peripheral LANGUAGES CXX) + + set(CMAKE_AUTOMOC ON) + + find_package(Qt6 REQUIRED COMPONENTS Bluetooth Core Test Gui) + + qt_add_executable(tst_qlowenergycontroller_peripheral + tst_qlowenergycontroller_peripheral.cpp + ) + target_link_libraries(tst_qlowenergycontroller_peripheral + PUBLIC + Qt::Core + Qt::Bluetooth + Qt::Test + Qt::Gui + ) + +else() + + qt_internal_add_test(tst_qlowenergycontroller_peripheral + SOURCES + tst_qlowenergycontroller_peripheral.cpp + LIBRARIES + Qt::Bluetooth + ) + + qt_internal_extend_target(tst_qlowenergycontroller_peripheral + CONDITION ANDROID AND NOT ANDROID_EMBEDDED + DEFINES + QT_ANDROID_BLUETOOTH + ) + + if(MACOS) + # Explicitly link against the static permission plugin because tests + # currently don't have finalizers run for them except for iOS. + # TODO: Remove this when qtbase automatically runs finalizers for tests: QTBUG-112212 + target_link_libraries(tst_qlowenergycontroller_peripheral + PRIVATE Qt6::QDarwinBluetoothPermissionPlugin) + endif() + +endif() + +set_target_properties(tst_qlowenergycontroller_peripheral PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +if(APPLE) + # Ninja has trouble with relative paths, convert to absolute as a workaround + get_filename_component(SHARED_PLIST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../shared ABSOLUTE) + if(IOS) + set_target_properties(tst_qlowenergycontroller_peripheral PROPERTIES + MACOSX_BUNDLE_INFO_PLIST "${SHARED_PLIST_DIR}/Info.ios.plist" + ) + else() + set_target_properties(tst_qlowenergycontroller_peripheral PROPERTIES + MACOSX_BUNDLE_INFO_PLIST "${SHARED_PLIST_DIR}/Info.macos.plist" + ) + endif() +endif() diff --git a/tests/manual/qlowenergycontroller_peripheral/tst_qlowenergycontroller_peripheral.cpp b/tests/manual/qlowenergycontroller_peripheral/tst_qlowenergycontroller_peripheral.cpp new file mode 100644 index 0000000..061f614 --- /dev/null +++ b/tests/manual/qlowenergycontroller_peripheral/tst_qlowenergycontroller_peripheral.cpp @@ -0,0 +1,167 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include + +#include +#include +#include +#include +#include + +#if QT_CONFIG(permissions) +#include +#include +#include +#include +#endif // permissions + +using namespace Qt::Literals::StringLiterals; + +static constexpr auto leServiceUuid{"10f5e37c-ac16-11eb-ae5c-93d3a763feed"_L1}; +static constexpr auto leCharUuid1{"11f4f68e-ac16-11eb-9956-cfe55a8ccafe"_L1}; +static const qsizetype leCharacteristicSize = 4; // Set to 1...512 bytes +static QByteArray leCharacteristicValue = QByteArray{leCharacteristicSize, 1}; +static QByteArray leDescriptorValue = "a descriptor value"_ba; + +class tst_qlowenergycontroller_peripheral : public QObject +{ + Q_OBJECT +private slots: + void initTestCase(); + void init(); + void cleanup(); + + void localCharacteristicReadAfterUpdate(); + void localDescriptorReadAfterUpdate(); + +private: + QBluetoothHostInfo mDevice; + std::unique_ptr mController; + QList> mServices; +}; + +void tst_qlowenergycontroller_peripheral::initTestCase() +{ +#ifndef Q_OS_IOS + auto devices = QBluetoothLocalDevice::allDevices(); + if (devices.isEmpty()) + QSKIP("Failed to find local adapter"); + else + mDevice = devices.back(); +#endif // Q_OS_IOS + +#if QT_CONFIG(permissions) + Qt::PermissionStatus permissionStatus = qApp->checkPermission(QBluetoothPermission{}); + // FIXME: Android will add more specific BT permissions, fix when appropriate + // change is in qtbase. + if (qApp->checkPermission(QBluetoothPermission{}) == Qt::PermissionStatus::Undetermined) { + QTestEventLoop loop; + qApp->requestPermission(QBluetoothPermission{}, [&permissionStatus, &loop](const QPermission &permission){ + permissionStatus = permission.status(); + loop.exitLoop(); + }); + if (permissionStatus == Qt::PermissionStatus::Undetermined) + loop.enterLoopMSecs(30000); + } + if (permissionStatus != Qt::PermissionStatus::Granted) + QSKIP("This manual test requires Blutooth permissions granted."); +#endif // permissions +} + +void tst_qlowenergycontroller_peripheral::init() +{ + QList serviceDefinitions; + + QLowEnergyServiceData sd; + sd.setType(QLowEnergyServiceData::ServiceTypePrimary); + sd.setUuid(QBluetoothUuid(leServiceUuid)); + + QLowEnergyCharacteristicData charData; + charData.setUuid(QBluetoothUuid(leCharUuid1)); + charData.setValue(leCharacteristicValue); + charData.setValueLength(leCharacteristicSize, leCharacteristicSize); + charData.setProperties(QLowEnergyCharacteristic::PropertyType::Read + | QLowEnergyCharacteristic::PropertyType::Write + | QLowEnergyCharacteristic::PropertyType::Notify + | QLowEnergyCharacteristic::ExtendedProperty); + + const QLowEnergyDescriptorData clientConfig( + QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration, + QLowEnergyCharacteristic::CCCDDisable); + charData.addDescriptor(clientConfig); + + const QLowEnergyDescriptorData userDescription( + QBluetoothUuid::DescriptorType::CharacteristicUserDescription, + leDescriptorValue); + charData.addDescriptor(userDescription); + + const QLowEnergyDescriptorData extendedProperties( + QBluetoothUuid::DescriptorType::CharacteristicExtendedProperties, + // From bluetooth specs: length 2 bytes + // bit 0: reliable write, bit 1: writable auxiliaries + QByteArray::fromHex("0300")); + charData.addDescriptor(extendedProperties); + + sd.addCharacteristic(charData); + + serviceDefinitions << sd; + + +#ifndef Q_OS_IOS + mController.reset(QLowEnergyController::createPeripheral(mDevice.address())); +#else + mController.reset(QLowEnergyController::createPeripheral()); +#endif // Q_OS_IOS + QVERIFY(mController); + + for (const auto &serviceData : serviceDefinitions) { + mServices.emplaceBack(mController->addService(serviceData)); + } +} + +void tst_qlowenergycontroller_peripheral::cleanup() +{ + if (mController) + mController->stopAdvertising(); + + mController.reset(); + mServices.clear(); +} + +void tst_qlowenergycontroller_peripheral::localCharacteristicReadAfterUpdate() +{ +#ifdef Q_OS_WINDOWS + QSKIP("Windows does not support peripheral"); +#endif + auto characteristic = mServices[0]->characteristic(QBluetoothUuid(leCharUuid1)); + QVERIFY(characteristic.isValid()); + const auto initialValue = characteristic.value(); + auto newValue = initialValue; + newValue[0] = newValue[0] + 1; + mServices[0]->writeCharacteristic(characteristic, newValue); + QTRY_COMPARE(characteristic.value(), newValue); +} + +void tst_qlowenergycontroller_peripheral::localDescriptorReadAfterUpdate() +{ +#ifdef Q_OS_WINDOWS + QSKIP("Windows does not support peripheral"); +#elif defined Q_OS_DARWIN + QSKIP("Apple devices do not support descriptor value update"); +#endif + auto characteristic = mServices[0]->characteristic(QBluetoothUuid(leCharUuid1)); + QVERIFY(characteristic.isValid()); + auto descriptor = characteristic.descriptor( + QBluetoothUuid::DescriptorType::CharacteristicUserDescription); + QVERIFY(descriptor.isValid()); + const auto initialValue = descriptor.value(); + auto newValue = initialValue; + newValue[0] = newValue[0] + 1; + mServices[0]->writeDescriptor(descriptor, newValue); + QCOMPARE(descriptor.value(), newValue); +} + +QTEST_MAIN(tst_qlowenergycontroller_peripheral) + +#include "tst_qlowenergycontroller_peripheral.moc" diff --git a/tests/shared/Info.ios.plist b/tests/shared/Info.ios.plist new file mode 100644 index 0000000..8dc7f08 --- /dev/null +++ b/tests/shared/Info.ios.plist @@ -0,0 +1,35 @@ + + + + + CFBundleDisplayName + ${MACOSX_BUNDLE_EXECUTABLE_NAME} + CFBundleExecutable + ${MACOSX_BUNDLE_EXECUTABLE_NAME} + CFBundleIconFile + ${MACOSX_BUNDLE_ICON_FILE} + CFBundleIdentifier + ${MACOSX_BUNDLE_GUI_IDENTIFIER} + CFBundleName + ${MACOSX_BUNDLE_BUNDLE_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + ${MACOSX_BUNDLE_SHORT_VERSION_STRING} + CFBundleVersion + ${MACOSX_BUNDLE_BUNDLE_VERSION} + LSRequiresIPhoneOS + + NSBluetoothAlwaysUsageDescription + BT test component wants to access your bluetooth adapter + UILaunchStoryboardName + LaunchScreen + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/tests/shared/Info.macos.plist b/tests/shared/Info.macos.plist new file mode 100644 index 0000000..7c18450 --- /dev/null +++ b/tests/shared/Info.macos.plist @@ -0,0 +1,24 @@ + + + + + CFBundleExecutable + ${MACOSX_BUNDLE_EXECUTABLE_NAME} + CFBundleIconFile + ${MACOSX_BUNDLE_ICON_FILE} + CFBundleIdentifier + ${MACOSX_BUNDLE_GUI_IDENTIFIER} + CFBundlePackageType + APPL + CFBundleSignature + ???? + LSMinimumSystemVersion + ${CMAKE_OSX_DEPLOYMENT_TARGET} + NSPrincipalClass + NSApplication + NSBluetoothAlwaysUsageDescription + BT test component wants to access your bluetooth adapter + NSSupportsAutomaticGraphicsSwitching + + + diff --git a/tests/shared/bttestutil_p.h b/tests/shared/bttestutil_p.h new file mode 100644 index 0000000..fb58c6b --- /dev/null +++ b/tests/shared/bttestutil_p.h @@ -0,0 +1,47 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef BTTESTUTIL_P_H +#define BTTESTUTIL_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 + +#ifdef Q_OS_ANDROID +#include +#endif + +QT_BEGIN_NAMESPACE + +bool androidBluetoothEmulator() +{ +#ifdef Q_OS_ANDROID + // QTBUG-106614, the Android-12+ emulator (API level 31+) emulates bluetooth. + // We need to skip tests on the CI to avoid timeouts when Android waits for bluetooth + // permission confirmation from the user. Currently the check below skips generally + // on emulator though, not only on CI + if (QNativeInterface::QAndroidApplication::sdkVersion() >= 31) { + const auto property = QJniObject::fromString("ro.kernel.qemu"); + const char sysPropsClass[] = "android/os/SystemProperties"; + const auto isQemu = QJniObject::callStaticObjectMethod( + sysPropsClass, "get", property.object()); + if (isQemu.toString() == "1") + return true; + } +#endif + return false; +} + +QT_END_NAMESPACE + +#endif // BTTESTUTIL_P_H