first commit
|
@ -0,0 +1,4 @@
|
|||
*.json
|
||||
!WingHexPy.json
|
||||
**/*.pro.user
|
||||
push.sh
|
|
@ -0,0 +1,73 @@
|
|||
WingSummer Commercial License
|
||||
Last Updated: June 11, 2022.
|
||||
|
||||
COMMERCIAL SOFTWARE LICENSE AGREEMENT
|
||||
|
||||
PLEASE READ THE FOLLOWING TERMS AND CONDITIONS CAREFULLY BEFORE DOWNLOADING, INSTALLING OR USING THE SOFTWARE THAT ACCOMPANIES THIS SOFTWARE LICENSE AGREEMENT OR ANY ACCOMPANYING DOCUMENTATION (COLLECTIVELY, AND INCLUDING ANY UPDATES THERETO PROVIDED BY WINGSUMMER, THE “SOFTWARE”).
|
||||
|
||||
THE TERMS AND CONDITIONS OF THIS SOFTWARE LICENSE AGREEMENT AND THE ORDER FOR THE SOFTWARE THAT YOU AGREED TO (“ORDER”) AND, [COLLECTIVELY WITH THE ORDER AND] THIS SOFTWARE LICENSE AGREEMENT, THIS “AGREEMENT”) ARE AN AGREEMENT BETWEEN YOU AND WINGSUMMER AND GOVERN USE OF THE SOFTWARE, UNLESS YOU AND WINGSUMMER HAVE EXECUTED A SEPARATE WRITTEN AGREEMENT GOVERNING USE OF THE SOFTWARE.
|
||||
|
||||
WingSummer is willing to license the Software to you only upon the condition that you accept all the terms contained in this Agreement. By downloading, installing or using the Software, you have indicated that you understand this Agreement and accept all of its terms. If you are accepting the terms of this Agreement on behalf of a company or other legal entity, you represent and warrant that you have the authority to bind that company or other legal entity to the terms of this Agreement, and, in such event, “you” and “your” will refer to that company or other legal entity. If you do not accept all of the terms of this Agreement, then WingSummer is unwilling to license the Software to you, and you must return the Software to WingSummer or destroy all copies of the Software.
|
||||
|
||||
1. License.
|
||||
1.1 License Grant. Subject to your compliance with the terms and conditions of this Agreement (including payment of the applicable fees in accordance with Section 3), WingSummer grants to you a non-exclusive, non-transferable, non-sublicenseable, worldwide limited license to (a) use the software products internally, in executable code form, and related Documentation (as defined in Section 6.1), as specified in the Order, including any error corrections, modifications and updates thereto provided by WingSummer to you under this Agreement (the “Software”), but only in the Licensed Configuration and only during the term of this Agreement and (b) copy and adapt the Software as provided herein. For purposes of this Agreement, “Licensed Configuration” means the features and usage limits for a specified time period, in each case, as specified in the Order. Your use of the Software is further limited according to the license type and other terms in the Order. You may copy the Software, as reasonably required to exercise your rights under this Section 1.1, and you may make a reasonable number of copies for backup or archival purposes.
|
||||
|
||||
1.2 Benefit of Third Parties. If the Order specifies a Right to Embed the Software for the benefit of end users, then the license in Section 1.1 shall be modified to allow you to operate the Software within a Customer Application (identified on the Order Form) and allow your end user customers (“End Users”) to access the Software as a part of the Customer Application.
|
||||
|
||||
1.3. Distribution License. If the Order specifies a Right to Distribute, then subject to your compliance with the terms and conditions of this Agreement (including payment of the applicable fees in accordance with Section 3), WingSummer grants to you a non-exclusive, non-transferable, non-sublicenseable, worldwide limited license to distribute the Software to End Users (i) as embedded in the Customer Application identified in the Order Form, (ii) solely for use by the end users of the Customer Application and not for further distribution and (iii) provided the End User executes an end user license agreement that protects WingSummer to the same extent this Agreement protects WingSummer (“End User License Agreement”).
|
||||
|
||||
1.4. Source Code Access; Modifications. Solely if your license type and pricing tier, as specified in the Order, includes access to the source code of the Software, subject to your compliance with the terms and conditions of this Agreement (including payment of the applicable fees in accordance with Section 3), WingSummer grants to you a non-exclusive, non-transferable, worldwide limited license to (i) use, reproduce, modify and create derivative works based upon the Software, solely for the purpose of customizing the Software to interface, embed, combine, or otherwise use with your products or services (as distributed to your customers). Notwithstanding anything to the contrary, you agree that you have the right to use any and all modifications, customizations, enhancements and extensions to the Software to the same extent, and solely to such extent, that you have the right to use the Software pursuant to this Agreement and your valid subscription. In addition, WingSummer prohibits you from modifying, and you agree not to modify, the Software (a) to enable features not available to customers at your license type and pricing tier by contacting me; or (b) to disable usage limits.
|
||||
|
||||
1.5. Limited Rights; License Restrictions. Your rights in the Software will be limited to those expressly granted in this Agreement. WingSummer reserves all rights and licenses in and to the Software not expressly granted to you under this Agreement. Except as expressly provided in this Agreement, you will not: (i) copy or modify the Software, in whole or in part; (ii) transfer, sublicense, lease, lend or rent or otherwise distribute the Software to any third party; (iii) make the functionality of the Software available to third-party users through any means; or (iv) disassemble, decompile or reverse engineer the Software or permit or authorize a third party to do so, except to the extent such restrictions are expressly prohibited by law.
|
||||
|
||||
1.6. Ownership. You expressly acknowledge that, as between WingSummer and you, WingSummer and its licensors own all worldwide right, title and interest in and to the Software, including all worldwide patent rights, copyrights, trade secrets, know-how and any other intellectual property rights embodied therein. You will not delete or in any manner alter the copyright, trademark or other proprietary rights notices appearing on the Software as delivered to you. You will reproduce such notices on all copies you make of the Software. Subject to Section 1.4, you will own your modifications to the Software (“Modifications”); provided that your ownership thereof will be subject to WingSummers’s underlying intellectual property rights in the Software. At your option, you may submit your Modifications to the WingSummer open source project. In addition, you own all worldwide right, title and interest in and to all your data that is processed by the Software and the analyses that are generated by the Software based on such data.
|
||||
|
||||
1.7. Verification and Audit. At WingSummer’s written request, you will furnish WingSummer with an officer’s written certification verifying that the Software is being used in accordance with the terms of this Agreement. Upon at least thirty (30) days prior written notice, WingSummer may audit your use of the Software to ensure that you are in compliance with the terms of this Agreement, provided that no audit may take longer than 30 days to complete, and further provided that all individuals involved in the audit must sign a non-disclosure agreement consistent with Section 5, make no copies of documents, remove no materials from your premises, and agree to comply with all of your reasonable rules, policies and instructions that apply to persons accessing your premises or systems . If an audit reveals that you have underpaid fees to WingSummer during the period audited, then you will promptly pay WingSummer for such underpaid fees based on WingSummer’s price list in effect at the time the audit is completed.
|
||||
|
||||
2. Obligations and Support.
|
||||
2.1 Customer Support by WingSummer. Subject to your compliance with the terms and conditions of this Agreement (including payment of the applicable fees in accordance with Section 3), WingSummer will make available to you at no additional cost WingSummer’s standard support for the license type and pricing tier specified in the Order in accordance with WingSummer’s then-standard support terms. WingSummer reserves the right to designate any additional new content or features as requiring separate payment or purchase of a separate subscription at any time. If you have entered into a separate support or similar agreement with WingSummer, then WingSummer will provide Software maintenance and support in accordance with the terms of that agreement, not this Agreement. For the avoidance of doubt, WingSummer shall have no obligation to provide support to End Users or any users of the Customer Application.
|
||||
|
||||
2.2 Customer Obligations. Customer shall make no representations or warranties with respect to the Software or any related services beyond those contained herein. Customer shall be solely responsible for, and WingSummer shall have no legal obligation to honor, any warranties that Customer provides to End Users to the extent that such warranties are broader or greater in scope than those made by WingSummer to Customer hereunder. Customer shall defend, indemnify and hold WingSummer and its affiliated companies harmless from any and all costs, losses, damages, liabilities and expenses (including reasonable attorney’s fees and costs of litigation) resulting from Customer’s failure to comply with this Section.
|
||||
|
||||
3. Payment.
|
||||
3.1 Subscription Fees. You will pay the fees and charges stated in the Order (“Subscription Fees”) for use of the Software. The base Subscription Fee for each Subscription Term (as defined in Section 4) will be specified in the Order (“Base Subscription Fee”) and is payable and charged at the beginning of each Subscription Term.
|
||||
|
||||
3.2 Units; True-Up. If specified in the Order, Subscription Fees will be calculated based on units of use of the Software (such as per server, per installation, per customer or per user) (each, a “Unit”). Where applicable, the Base Subscription Fee includes the number of Units specified in the Order for each Subscription Term. At the end of each Subscription Term, you will promptly confirm in writing to WingSummer (at the latest within five (5) business days of a request from WingSummer) the number of Units used by you during that Subscription Term. If your actual usage of the Software exceeds the Units covered by the Base Subscription Fee prepaid by you for a Subscription Term, WingSummer will charge you for the difference between the Units covered by the Base Subscription Fee and the number of Units actually used by you during that Subscription Term (“Additional Units Fee”).
|
||||
|
||||
3.3 Payment Terms. Because it is my own project,and is not the project of any company,only Wechat payment and Alipay payment are allowed.The payment QR codes are shown in the WingHexExplorer's code repository ,and I'm very sorry I can not issue an invoice to you.All amounts are stated and shall be paid in yuan and are exclusive of taxes. You are responsible for payment of all Taxes and any related interest and/or penalties resulting from any payments made to us, other than any taxes based on WingSummer’s net income. Except as specifically outlined in Section 4 and Section 7.3, all fees are non-refundable.
|
||||
|
||||
4. Term and Termination.
|
||||
This Agreement will commence on the Effective Date and, unless terminated earlier in accordance with the terms of this Section 4, will continue in effect for the initial subscription term specified in the Order. At the end of such initial subscription term and each renewal subscription term thereafter, subject always to timely payment of the Subscription Fees, this Agreement will automatically renew for additional renewal subscription terms having the duration specified in the Order (or if no renewal term length is stated in the Order, having the same duration as the Initial Subscription Term), unless either party provides at least 30 days’ prior written notice of non-renewal. Such initial subscription term and each renewal subscription term are each individually referred to herein as a “Subscription Term.” Each party will have the right to terminate this Agreement if the other party breaches this Agreement and fails to cure such breach within 10 days after written notice thereof, provided that, for breaches that cannot be cured using reasonable efforts within 10 days, then up to an additional 20 days to cure. Notwithstanding the foregoing, if you fail to pay the applicable fees as specified in the Order and this Agreement, and that failure persists for 5 days after written notice, your license to the Software ends automatically. You acknowledge that upon expiration or termination of this Agreement, the Software and any license key may automatically de-activate and you may no longer be able to access and use the Software. Upon termination: (1), you must, at WingSummer’s option, either promptly destroy or return to WingSummer all copies of the Software and any WingSummer Confidential Information in your possession or control, provided that, upon agreeing to pay 25% of the prior years’ fee, we will allow you and your customers to continue to use the WingSummer Software for an additional three months; and (2) you shall not be entitled to a refund of any pre-paid fees, except that you will be entitled to a refund of pre-paid fees if this Agreement is terminated by you for our breach and as provided in Section 7.3. Sections 4, 5, 6.3, 8, 9 and 10 will survive any expiration or termination of the Agreement. Upon termination of this Agreement for any reason, the rights granted in Section 1.1 and 1.2 and 1.3 shall immediately terminate and you must ensure that your End Users delete the Customer Application.
|
||||
|
||||
5. Confidentiality.
|
||||
Continuing until 5 years after the expiration or termination of this Agreement, each party (as such, a “recipient”) agrees to keep all information, documents and data received from the other party (as such, a “discloser”), which are marked as or which would reasonably be considered to be confidential (“Confidential Information”) as strictly confidential and to use such information only as follows: (i) with respect to WingSummer Confidential Information, within the scope of the licenses granted to you, and (ii) with respect to your Confidential Information, only as needed to provide you with the Software and services contemplated by this Agreement. The Software and its pricing are WingSummer’s Confidential Information. Notwithstanding the foregoing, “Confidential Information” shall not include any information, proven by documentation, which: (i) becomes generally available to the public other than as a result of a disclosure by the recipient; (ii) was available to the recipient on a non-confidential basis prior to its disclosure by the discloser; (iii) becomes available to the recipient on a non-confidential basis from a source other than the discloser, provided that such source is not known by the recipient to be bound by any duty to the discloser or another entity, to keep such information confidential; or (iv) is independently developed by the recipient, without use of the discloser’s Confidential Information.
|
||||
|
||||
6. Warranties.
|
||||
6.1. Limited Software Warranty WingSummer warrants that, for thirty (30) days following the Effective Date, the Software will perform in all material respects in accordance with the standard user documentation for the Software that WingSummer makes generally available to its customers (“Documentation”). As your sole and exclusive remedy and WingSummer’s entire liability for any breach of this limited warranty, WingSummer will at its option and expense promptly correct or replace the Software so that it conforms to this limited warranty. WingSummer does not warrant that the Software will meet your requirements, that the Software will operate in the combinations that you may select, that the operation of the Software will be error-free or uninterrupted, or that all Software errors will be corrected. The limited warranty set forth in this Section 6.1 does not apply to the extent that WingSummer provides you with the Software (or portions of the Software) for beta, evaluation, testing, or demonstration purposes.
|
||||
|
||||
6.2. No Excluded Licenses The Software and Documentation do not incorporate, combine with, or use software or materials distributed under an Excluded License (“Open Source Materials”). “Excluded License” means a license that requires, as a condition of use, modification, and/or distribution of such Open Source Materials that other software incorporated into, derived from, or distributed with such Open Source Materials be (i) disclosed or distributed in source code form, (ii) licensed for the purpose of making derivative works, or (iii) redistributedable at no charge.
|
||||
|
||||
6.3. Disclaimer EXCEPT AS EXPRESSLY SET FORTH ABOVE, THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND. WINGSUMMER DISCLAIMS ALL OTHER WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT, AND ANY WARRANTIES ARISING OUT OF COURSE OF DEALING OR USAGE OF TRADE. NO ADVICE OR INFORMATION, WHETHER ORAL OR WRITTEN, OBTAINED FROM WINGSUMMER OR ELSEWHERE WILL CREATE ANY WARRANTY NOT EXPRESSLY STATED IN THIS AGREEMENT.
|
||||
|
||||
7. Indemnification.
|
||||
7.1 WingSummer Indemnity. WingSummer will defend, indemnify and hold you harmless from and against any damages, costs and expenses (including reasonable attorneys’ fees and other professional fees) awarded against you in a final non-appealable judgment or that are agreed to in settlement, to the extent based on a third-party claim that the Software, as provided by WingSummer to you, infringes any patent, copyright or misappropriates any trade secret of any third party; provided that you: (a) promptly notify WingSummer in writing of any such claim; (b) grant WingSummer sole control of the defense and settlement of the claim; and (c) provide WingSummer, at WingSummer’s expense, with all assistance, information and authority reasonably required for the defense and settlement of the claim. You have the right to retain counsel, at your expense, to participate in the defense or settlement of any claim. WingSummer will not be liable for any settlement or compromise that you enter into without WingSummer’s prior written consent.
|
||||
|
||||
7.2 Exclusions. WingSummer’s obligation to indemnify you pursuant to Section 7.1 will not apply to the extent any claim results from or is based on: (i) any combination, operation or use of the Software with any product, system, device, method or data not provided by WingSummer, if such claim would have been avoided but for such combination, operation or use; (ii) modification of the Software by anyone other than WingSummer, if a claim would have been avoided but for such modification; (iii) your failure to install and use any upgrades to the Software furnished by WingSummer, if such claim could have been avoided by such installation and use of such upgrades; or (iv) use of the Software other than in accordance with this Agreement. You will indemnify, defend and hold WingSummer harmless and will pay any costs damages and reasonable attorney’s fees in connection with any third party claim to the extent it results from any of the foregoing activities in this Section 7.2, provided that WingSummer (a) promptly notifies you in writing of any such claim; (b) grants you sole control of the defense and settlement of the claim; and (c) provides you, at your expense, with all assistance, information and authority reasonably required for the defense and settlement of the claim.
|
||||
|
||||
7.3 Injunction. If your use of the Software is, or in WingSummer’s opinion is likely to be, enjoined due to the type of claim specified in Section 7.1, then WingSummer will at its sole option and expense: procure for you the right to continue using the Software under the terms of this Agreement; (ii) replace or modify the Software to make it non-infringing and of equivalent functionality; or (iii) if WingSummer is unable to accomplish either (i) or despite using its reasonable efforts, then WingSummer may terminate your rights and WingSummer’s obligation under this Agreement with respect to such Software and refund to you a pro-rata portion of the prepaid license fees you paid for such Software.
|
||||
|
||||
7.4 Customer Indemnity. In the event Customer has rights granted under Sections 1.2 and 1.3 herein, Customer agrees to defend and indemnify WingSummer, at Customer’s expense, against any legal action brought against WingSummer by a third party to the extent that it is based on a claim that Customer Application or any software, hardware, materials or technology therein (except for Software), or the combination of the Software with any other software, hardware, materials or technology used by Customer as part of the applicable Customer Application, infringes a patent, copyright or trademark of such third party or makes unlawful use of such party’s trade secret, and Customer shall pay any settlement of such claim or final judgment against WingSummer in any such action if attributable to any such claim. However, such defense and payments are subject to the conditions that WingSummer must: (i) notify Customer promptly in writing of such claim, (ii) permit Customer to have sole control of the defense, compromise or settlement of such claim, including any appeals, and (iii) fully cooperate with Customer, at Customer’s expense, in the defense or settlement of such claim.
|
||||
|
||||
7.5 Sole Remedy. THIS SECTION 7 SETS FORTH WINGSUMMER’S SOLE AND EXCLUSIVE OBLIGATIONS, AND YOUR SOLE AND EXCLUSIVE REMEDIES, WITH RESPECT TO INFRINGEMENT OR MISAPPROPRIATION OF INTELLECTUAL PROPERTY RIGHTS OF ANY KIND.
|
||||
|
||||
8. Limitation of Liability.
|
||||
IN NO EVENT WILL EITHER PARTY BE LIABLE FOR ANY SPECIAL, INCIDENTAL, EXEMPLARY, PUNITIVE OR CONSEQUENTIAL DAMAGES, OR FOR ANY LOSS OF USE, LOSS OF DATA, LOSS OF PROFITS OR LOSS OF GOODWILL, OR THE COSTS OF PROCURING SUBSTITUTE PRODUCTS, WHETHER OR NOT FORESEEABLE, ARISING OUT OF OR IN CONNECTION WITH THIS AGREEMENT OR THE USE, OPERATION OR PERFORMANCE OF THE SOFTWARE, WHETHER SUCH LIABILITY ARISES FROM ANY CLAIM BASED UPON CONTRACT, WARRANTY, TORT (INCLUDING NEGLIGENCE), PRODUCT LIABILITY OR OTHERWISE, AND WHETHER OR NOT WINGSUMMER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH LOSS OR DAMAGE. EACH PARTY’S TOTAL AGGREGATE LIABILITY ARISING UNDER THIS AGREEMENT, FROM ALL CAUSES OF ACTION AND ALL THEORIES OF LIABILITY, WILL NOT EXCEED THE AMOUNTS PAID TO WINGSUMMER BY YOU FOR THE SPECIFIC SOFTWARE GIVING RISE TO A CLAIM FOR LIABILITY HEREUNDER DURING THE 12 MONTH PERIOD PRIOR TO THE FIRST CLAIM, PROVIDED THAT THIS SHALL NOT RELEASE YOU FROM PAYING ALL FEES AND CHARGES DUE HEREUNDER. The parties agree that the limitations and exclusions contained in this Section 8 and elsewhere in this Agreement will (a) not apply to any claims under indemnity and (b) survive and apply even if any exclusive remedy specified in this Agreement is found to have failed of its essential purpose.
|
||||
|
||||
9. Feedback; Modifications.
|
||||
If you make any Modifications or provide any ideas, suggestions, or recommendations regarding the Software (“Feedback,” which term does not include Modifications), WingSummer will be free to use, disclose, reproduce, license or otherwise distribute, and exploit such Feedback as it sees fit, entirely without obligation or restriction of any kind; but shall not be free to use your Modifications (or any of your other intellectual property) without an express written license or grant of rights by you. By providing Feedback, you grant WingSummer a worldwide, perpetual, irrevocable, sublicenseable, fully-paid and royalty-free license to use and exploit in any manner such Feedback.
|
||||
|
||||
10. General.
|
||||
This Agreement will be governed by and construed in accordance with the laws of China, without regard to or application of conflict of laws rules or principles. Any legal action or proceeding arising under this Agreement will be brought exclusively in courts located in China and each party irrevocably consents to the personal jurisdiction thereof and venue therein. You may not assign or transfer this Agreement or any rights granted hereunder, by operation of law or otherwise, without WingSummer’s prior written consent, and any attempt by you to do so, without such consent, will be void. WingSummer may freely assign this Agreement. Except as expressly set forth in this Agreement, the exercise by either party of any of its remedies under this Agreement will be without prejudice to its other remedies under this Agreement or otherwise. All notices or approvals required or permitted under this Agreement will be in writing and delivered by confirmed email transmission, by overnight delivery service, or by certified mail, and in each instance will be deemed given upon receipt. All notices or approvals will be sent to the addresses set forth in the Order or to such other address as may be specified by either party to the other in accordance with this Section. The failure by either party to enforce any provision of this Agreement will not constitute a waiver of future enforcement of that or any other provision. Any waiver, modification or amendment of any provision of this Agreement will be effective only if in writing and signed by authorized representatives of both parties. If any provision of this Agreement is held to be unenforceable or invalid, that provision will be enforced to the maximum extent possible, and the other provisions will remain in full force and effect. This Agreement is the complete and exclusive understanding and agreement between the parties regarding its subject matter, and supersedes all proposals, understandings or communications between the parties, oral or written, regarding its subject matter. This Agreement may be executed in counterparts, each of which will be deemed an original, but all of which together will constitute one and the same instrument.
|
||||
|
||||
11. Contact Information.
|
||||
If you have any questions regarding this Agreement, you may contact WingSummer on Gitee or by the email wing-summer@qq.com .
|
|
@ -0,0 +1,7 @@
|
|||
Source code in this repository is variously licensed under the WingSummer OpenSource Lincense (OpenSource-LICENSE), or the WingHexExplorer Commercial License (Commerical-LICENSE).
|
||||
|
||||
本仓库的源代码采用多协议的授权模式: “羽夏开源协议” 和 “羽夏商业协议”,它们分别在 OpenSource-LICENSE 和 Commerical-LICENSE 有详细的说明。
|
||||
|
||||
When built, binary files are generated for the WingSummer OpenSource Lincense source code. Binaries located at my Gitee, Gitlink or Github repository and the spark store are released under the WingSummer OpenSource Lincense.
|
||||
|
||||
当你编译代码时,二进制文件遵守 “羽夏开源协议”。在我的 Gitee ,Gitlink 或 Github 和星火商店发布的二进制都遵守 “羽夏开源协议”。
|
|
@ -0,0 +1,160 @@
|
|||
WingSummer OpenSource Lincense
|
||||
Version 1,13 June 2022
|
||||
|
||||
Copyright (c) WingSummer
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
0. Definitions.
|
||||
“This License” refers to WingSummer OpenSource Lincense.
|
||||
|
||||
“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, subject to section 13. 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.
|
||||
|
||||
Subject to section 13, 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 not charge any price for each copy that you convey, but 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 only can convey the machine-readable Corresponding Source under the terms of this License free of charge.
|
||||
|
||||
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 for ANY COMMERICAL PURPOSE except as expressly provided under this License. Any attempt otherwise to propagate or modify FOR COMMERICAL PURPOSE it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).
|
||||
|
||||
In other words,you can fork my repository and propagate or modify it for NON-COMMERICAL USE freely.It doesn't mean you can not make a profit from it for anyway.Any INCOME from any donation to maintain an open source code repository is allowed.
|
||||
|
||||
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 30 May 2022.
|
||||
|
||||
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 use, propagate or 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 use, propagate or 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. Offering the Program as a Service.
|
||||
If you make the functionality of the Program or a modified version available to third parties as a service, you must make the Service Source Code available via network download to everyone at no charge, under the terms of this License. Making the functionality of the Program or modified version available to third parties as a service includes, without limitation, enabling third parties to interact with the functionality of the Program or modified version remotely through a computer network, offering a service the value of which entirely or primarily derives from the value of the Program or modified version, or offering a service that accomplishes for users the primary purpose of the Program or modified version.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
WingSummer may publish revised and/or new versions of the WingSummer OpenSource Lincense 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 WingSummer OpenSource Lincense “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 WingSummer. If the Program does not specify a version number of the WingSummer OpenSource Lincense, you may choose any version ever published by MongoDB, Inc.
|
||||
|
||||
If the Program specifies that a proxy can decide which future versions of the Server Side 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
|
|
@ -0,0 +1,587 @@
|
|||
// QCodeEditor
|
||||
#include "QCodeEditor.hpp"
|
||||
#include "QFramedTextAttribute.hpp"
|
||||
#include "QLineNumberArea.hpp"
|
||||
#include "QPythonHighlighter.hpp"
|
||||
#include "QStyleSyntaxHighlighter.hpp"
|
||||
#include "QSyntaxStyle.hpp"
|
||||
|
||||
// Qt
|
||||
#include <QAbstractItemView>
|
||||
#include <QAbstractTextDocumentLayout>
|
||||
#include <QCompleter>
|
||||
#include <QCursor>
|
||||
#include <QFontDatabase>
|
||||
#include <QMimeData>
|
||||
#include <QPaintEvent>
|
||||
#include <QScrollBar>
|
||||
#include <QShortcut>
|
||||
#include <QTextBlock>
|
||||
#include <QTextCharFormat>
|
||||
|
||||
static QVector<QPair<QString, QString>> parentheses = {
|
||||
{"(", ")"}, {"{", "}"}, {"[", "]"}, {"\"", "\""}, {"'", "'"}};
|
||||
|
||||
QCodeEditor::QCodeEditor(QWidget *widget)
|
||||
: QTextEdit(widget), m_highlighter(nullptr), m_syntaxStyle(nullptr),
|
||||
m_lineNumberArea(new QLineNumberArea(this)), m_completer(nullptr),
|
||||
m_framedAttribute(new QFramedTextAttribute(this)),
|
||||
m_autoIndentation(true), m_autoParentheses(true), m_replaceTab(true),
|
||||
m_tabReplace(QString(4, ' ')) {
|
||||
initDocumentLayoutHandlers();
|
||||
initFont();
|
||||
performConnections();
|
||||
|
||||
setSyntaxStyle(QSyntaxStyle::defaultStyle());
|
||||
}
|
||||
|
||||
void QCodeEditor::initDocumentLayoutHandlers() {
|
||||
document()->documentLayout()->registerHandler(QFramedTextAttribute::type(),
|
||||
m_framedAttribute);
|
||||
}
|
||||
|
||||
void QCodeEditor::initFont() {
|
||||
auto fnt = QFontDatabase::systemFont(QFontDatabase::FixedFont);
|
||||
fnt.setFixedPitch(true);
|
||||
fnt.setPointSize(10);
|
||||
|
||||
setFont(fnt);
|
||||
}
|
||||
|
||||
void QCodeEditor::performConnections() {
|
||||
connect(document(), &QTextDocument::blockCountChanged, this,
|
||||
&QCodeEditor::updateLineNumberAreaWidth);
|
||||
|
||||
connect(verticalScrollBar(), &QScrollBar::valueChanged,
|
||||
[this](int) { m_lineNumberArea->update(); });
|
||||
|
||||
connect(this, &QTextEdit::cursorPositionChanged, this,
|
||||
&QCodeEditor::updateExtraSelection);
|
||||
|
||||
connect(this, &QTextEdit::selectionChanged, this,
|
||||
&QCodeEditor::onSelectionChanged);
|
||||
}
|
||||
|
||||
void QCodeEditor::setHighlighter(QStyleSyntaxHighlighter *highlighter) {
|
||||
if (m_highlighter) {
|
||||
m_highlighter->setDocument(nullptr);
|
||||
}
|
||||
|
||||
m_highlighter = highlighter;
|
||||
|
||||
if (m_highlighter) {
|
||||
m_highlighter->setSyntaxStyle(m_syntaxStyle);
|
||||
m_highlighter->setDocument(document());
|
||||
}
|
||||
}
|
||||
|
||||
void QCodeEditor::setSyntaxStyle(QSyntaxStyle *style) {
|
||||
m_syntaxStyle = style;
|
||||
|
||||
m_framedAttribute->setSyntaxStyle(m_syntaxStyle);
|
||||
m_lineNumberArea->setSyntaxStyle(m_syntaxStyle);
|
||||
|
||||
if (m_highlighter) {
|
||||
m_highlighter->setSyntaxStyle(m_syntaxStyle);
|
||||
}
|
||||
|
||||
updateStyle();
|
||||
}
|
||||
|
||||
void QCodeEditor::updateStyle() {
|
||||
if (m_highlighter) {
|
||||
m_highlighter->rehighlight();
|
||||
}
|
||||
|
||||
if (m_syntaxStyle) {
|
||||
auto currentPalette = palette();
|
||||
|
||||
// Setting text format/color
|
||||
currentPalette.setColor(
|
||||
QPalette::ColorRole::Text,
|
||||
m_syntaxStyle->getFormat("Text").foreground().color());
|
||||
|
||||
// Setting common background
|
||||
currentPalette.setColor(
|
||||
QPalette::Base, m_syntaxStyle->getFormat("Text").background().color());
|
||||
|
||||
// Setting selection color
|
||||
currentPalette.setColor(
|
||||
QPalette::Highlight,
|
||||
m_syntaxStyle->getFormat("Selection").background().color());
|
||||
|
||||
setPalette(currentPalette);
|
||||
}
|
||||
|
||||
updateExtraSelection();
|
||||
}
|
||||
|
||||
void QCodeEditor::onSelectionChanged() {
|
||||
auto selected = textCursor().selectedText();
|
||||
|
||||
auto cursor = textCursor();
|
||||
|
||||
// Cursor is null if setPlainText was called.
|
||||
if (cursor.isNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
cursor.movePosition(QTextCursor::MoveOperation::Left);
|
||||
cursor.select(QTextCursor::SelectionType::WordUnderCursor);
|
||||
|
||||
QSignalBlocker blocker(this);
|
||||
m_framedAttribute->clear(cursor);
|
||||
|
||||
if (selected.size() > 1 && cursor.selectedText() == selected) {
|
||||
auto backup = textCursor();
|
||||
|
||||
// Perform search selecting
|
||||
handleSelectionQuery(cursor);
|
||||
|
||||
setTextCursor(backup);
|
||||
}
|
||||
}
|
||||
|
||||
void QCodeEditor::resizeEvent(QResizeEvent *e) {
|
||||
QTextEdit::resizeEvent(e);
|
||||
|
||||
updateLineGeometry();
|
||||
}
|
||||
|
||||
void QCodeEditor::updateLineGeometry() {
|
||||
QRect cr = contentsRect();
|
||||
m_lineNumberArea->setGeometry(QRect(
|
||||
cr.left(), cr.top(), m_lineNumberArea->sizeHint().width(), cr.height()));
|
||||
}
|
||||
|
||||
void QCodeEditor::updateLineNumberAreaWidth(int) {
|
||||
setViewportMargins(m_lineNumberArea->sizeHint().width(), 0, 0, 0);
|
||||
}
|
||||
|
||||
void QCodeEditor::updateLineNumberArea(const QRect &rect) {
|
||||
m_lineNumberArea->update(0, rect.y(), m_lineNumberArea->sizeHint().width(),
|
||||
rect.height());
|
||||
updateLineGeometry();
|
||||
|
||||
if (rect.contains(viewport()->rect())) {
|
||||
updateLineNumberAreaWidth(0);
|
||||
}
|
||||
}
|
||||
|
||||
void QCodeEditor::handleSelectionQuery(QTextCursor cursor) {
|
||||
|
||||
auto searchIterator = cursor;
|
||||
searchIterator.movePosition(QTextCursor::Start);
|
||||
searchIterator = document()->find(cursor.selectedText(), searchIterator);
|
||||
while (searchIterator.hasSelection()) {
|
||||
m_framedAttribute->frame(searchIterator);
|
||||
|
||||
searchIterator = document()->find(cursor.selectedText(), searchIterator);
|
||||
}
|
||||
}
|
||||
|
||||
void QCodeEditor::updateExtraSelection() {
|
||||
QList<QTextEdit::ExtraSelection> extra;
|
||||
|
||||
highlightCurrentLine(extra);
|
||||
highlightParenthesis(extra);
|
||||
|
||||
setExtraSelections(extra);
|
||||
}
|
||||
|
||||
void QCodeEditor::highlightParenthesis(
|
||||
QList<QTextEdit::ExtraSelection> &extraSelection) {
|
||||
auto currentSymbol = charUnderCursor();
|
||||
auto prevSymbol = charUnderCursor(-1);
|
||||
|
||||
for (auto &pair : parentheses) {
|
||||
int direction;
|
||||
|
||||
QChar counterSymbol;
|
||||
QChar activeSymbol;
|
||||
auto position = textCursor().position();
|
||||
|
||||
if (pair.first == currentSymbol) {
|
||||
direction = 1;
|
||||
counterSymbol = pair.second[0];
|
||||
activeSymbol = currentSymbol;
|
||||
} else if (pair.second == prevSymbol) {
|
||||
direction = -1;
|
||||
counterSymbol = pair.first[0];
|
||||
activeSymbol = prevSymbol;
|
||||
position--;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto counter = 1;
|
||||
|
||||
while (counter != 0 && position > 0 &&
|
||||
position < (document()->characterCount() - 1)) {
|
||||
// Moving position
|
||||
position += direction;
|
||||
|
||||
auto character = document()->characterAt(position);
|
||||
// Checking symbol under position
|
||||
if (character == activeSymbol) {
|
||||
++counter;
|
||||
} else if (character == counterSymbol) {
|
||||
--counter;
|
||||
}
|
||||
}
|
||||
|
||||
auto format = m_syntaxStyle->getFormat("Parentheses");
|
||||
|
||||
// Found
|
||||
if (counter == 0) {
|
||||
ExtraSelection selection{};
|
||||
|
||||
auto directionEnum = direction < 0 ? QTextCursor::MoveOperation::Left
|
||||
: QTextCursor::MoveOperation::Right;
|
||||
|
||||
selection.format = format;
|
||||
selection.cursor = textCursor();
|
||||
selection.cursor.clearSelection();
|
||||
selection.cursor.movePosition(
|
||||
directionEnum, QTextCursor::MoveMode::MoveAnchor,
|
||||
std::abs(textCursor().position() - position));
|
||||
|
||||
selection.cursor.movePosition(QTextCursor::MoveOperation::Right,
|
||||
QTextCursor::MoveMode::KeepAnchor, 1);
|
||||
|
||||
extraSelection.append(selection);
|
||||
|
||||
selection.cursor = textCursor();
|
||||
selection.cursor.clearSelection();
|
||||
selection.cursor.movePosition(directionEnum,
|
||||
QTextCursor::MoveMode::KeepAnchor, 1);
|
||||
|
||||
extraSelection.append(selection);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void QCodeEditor::highlightCurrentLine(
|
||||
QList<QTextEdit::ExtraSelection> &extraSelection) {
|
||||
if (!isReadOnly()) {
|
||||
QTextEdit::ExtraSelection selection{};
|
||||
|
||||
selection.format = m_syntaxStyle->getFormat("CurrentLine");
|
||||
selection.format.setForeground(QBrush());
|
||||
selection.format.setProperty(QTextFormat::FullWidthSelection, true);
|
||||
selection.cursor = textCursor();
|
||||
selection.cursor.clearSelection();
|
||||
|
||||
extraSelection.append(selection);
|
||||
}
|
||||
}
|
||||
|
||||
void QCodeEditor::paintEvent(QPaintEvent *e) {
|
||||
updateLineNumberArea(e->rect());
|
||||
QTextEdit::paintEvent(e);
|
||||
}
|
||||
|
||||
int QCodeEditor::getFirstVisibleBlock() {
|
||||
// Detect the first block for which bounding rect - once translated
|
||||
// in absolute coordinated - is contained by the editor's text area
|
||||
|
||||
// Costly way of doing but since "blockBoundingGeometry(...)" doesn't
|
||||
// exists for "QTextEdit"...
|
||||
|
||||
QTextCursor curs = QTextCursor(document());
|
||||
curs.movePosition(QTextCursor::Start);
|
||||
for (int i = 0; i < document()->blockCount(); ++i) {
|
||||
QTextBlock block = curs.block();
|
||||
|
||||
QRect r1 = viewport()->geometry();
|
||||
QRect r2 = document()
|
||||
->documentLayout()
|
||||
->blockBoundingRect(block)
|
||||
.translated(viewport()->geometry().x(),
|
||||
viewport()->geometry().y() -
|
||||
verticalScrollBar()->sliderPosition())
|
||||
.toRect();
|
||||
|
||||
if (r1.intersects(r2)) {
|
||||
return i;
|
||||
}
|
||||
|
||||
curs.movePosition(QTextCursor::NextBlock);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool QCodeEditor::proceedCompleterBegin(QKeyEvent *e) {
|
||||
if (m_completer && m_completer->popup()->isVisible()) {
|
||||
switch (e->key()) {
|
||||
case Qt::Key_Enter:
|
||||
case Qt::Key_Return:
|
||||
case Qt::Key_Escape:
|
||||
case Qt::Key_Tab:
|
||||
case Qt::Key_Backtab:
|
||||
e->ignore();
|
||||
return true; // let the completer do default behavior
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// todo: Replace with modifiable QShortcut
|
||||
auto isShortcut =
|
||||
((e->modifiers() & Qt::ControlModifier) && e->key() == Qt::Key_Space);
|
||||
|
||||
return !(!m_completer || !isShortcut);
|
||||
}
|
||||
|
||||
void QCodeEditor::proceedCompleterEnd(QKeyEvent *e) {
|
||||
auto ctrlOrShift = e->modifiers() & (Qt::ControlModifier | Qt::ShiftModifier);
|
||||
|
||||
if (!m_completer || (ctrlOrShift && e->text().isEmpty()) ||
|
||||
e->key() == Qt::Key_Delete) {
|
||||
return;
|
||||
}
|
||||
|
||||
static QString eow(R"(~!@#$%^&*()_+{}|:"<>?,./;'[]\-=)");
|
||||
|
||||
auto isShortcut =
|
||||
((e->modifiers() & Qt::ControlModifier) && e->key() == Qt::Key_Space);
|
||||
auto completionPrefix = wordUnderCursor();
|
||||
|
||||
if (!isShortcut && (e->text().isEmpty() || completionPrefix.length() < 2 ||
|
||||
eow.contains(e->text().right(1)))) {
|
||||
m_completer->popup()->hide();
|
||||
return;
|
||||
}
|
||||
|
||||
if (completionPrefix != m_completer->completionPrefix()) {
|
||||
m_completer->setCompletionPrefix(completionPrefix);
|
||||
m_completer->popup()->setCurrentIndex(
|
||||
m_completer->completionModel()->index(0, 0));
|
||||
}
|
||||
|
||||
auto cursRect = cursorRect();
|
||||
cursRect.setWidth(
|
||||
m_completer->popup()->sizeHintForColumn(0) +
|
||||
m_completer->popup()->verticalScrollBar()->sizeHint().width());
|
||||
|
||||
m_completer->complete(cursRect);
|
||||
}
|
||||
|
||||
void QCodeEditor::keyPressEvent(QKeyEvent *e) {
|
||||
#if QT_VERSION >= 0x050A00
|
||||
const int defaultIndent =
|
||||
int(tabStopDistance() / fontMetrics().averageCharWidth());
|
||||
#else
|
||||
const int defaultIndent = tabStopWidth() / fontMetrics().averageCharWidth();
|
||||
#endif
|
||||
|
||||
auto completerSkip = proceedCompleterBegin(e);
|
||||
|
||||
if (!completerSkip) {
|
||||
if (m_replaceTab && e->key() == Qt::Key_Tab &&
|
||||
e->modifiers() == Qt::NoModifier) {
|
||||
insertPlainText(m_tabReplace);
|
||||
return;
|
||||
}
|
||||
|
||||
// Auto indentation
|
||||
int indentationLevel = getIndentationSpaces();
|
||||
|
||||
#if QT_VERSION >= 0x050A00
|
||||
int tabCounts = int(indentationLevel * fontMetrics().averageCharWidth() /
|
||||
tabStopDistance());
|
||||
#else
|
||||
int tabCounts =
|
||||
indentationLevel * fontMetrics().averageCharWidth() / tabStopWidth();
|
||||
#endif
|
||||
|
||||
// Have Qt Edior like behaviour, if {|} and enter is pressed indent the two
|
||||
// parenthesis
|
||||
if (m_autoIndentation &&
|
||||
(e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) &&
|
||||
charUnderCursor() == '}' && charUnderCursor(-1) == '{') {
|
||||
int charsBack = 0;
|
||||
insertPlainText("\n");
|
||||
|
||||
if (m_replaceTab)
|
||||
insertPlainText(QString(indentationLevel + defaultIndent, ' '));
|
||||
else
|
||||
insertPlainText(QString(tabCounts + 1, '\t'));
|
||||
|
||||
insertPlainText("\n");
|
||||
charsBack++;
|
||||
|
||||
if (m_replaceTab) {
|
||||
insertPlainText(QString(indentationLevel, ' '));
|
||||
charsBack += indentationLevel;
|
||||
} else {
|
||||
insertPlainText(QString(tabCounts, '\t'));
|
||||
charsBack += tabCounts;
|
||||
}
|
||||
|
||||
while (charsBack--)
|
||||
moveCursor(QTextCursor::MoveOperation::Left);
|
||||
return;
|
||||
}
|
||||
|
||||
// Shortcut for moving line to left
|
||||
if (m_replaceTab && e->key() == Qt::Key_Backtab) {
|
||||
indentationLevel = std::min(indentationLevel, m_tabReplace.size());
|
||||
|
||||
auto cursor = textCursor();
|
||||
|
||||
cursor.movePosition(QTextCursor::MoveOperation::StartOfLine);
|
||||
cursor.movePosition(QTextCursor::MoveOperation::Right,
|
||||
QTextCursor::MoveMode::KeepAnchor, indentationLevel);
|
||||
|
||||
cursor.removeSelectedText();
|
||||
return;
|
||||
}
|
||||
|
||||
QTextEdit::keyPressEvent(e);
|
||||
|
||||
if (m_autoIndentation &&
|
||||
(e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter)) {
|
||||
if (m_replaceTab)
|
||||
insertPlainText(QString(indentationLevel, ' '));
|
||||
else
|
||||
insertPlainText(QString(tabCounts, '\t'));
|
||||
}
|
||||
|
||||
if (m_autoParentheses) {
|
||||
for (auto &&el : parentheses) {
|
||||
// Inserting closed brace
|
||||
if (el.first == e->text()) {
|
||||
insertPlainText(el.second);
|
||||
moveCursor(QTextCursor::MoveOperation::Left);
|
||||
break;
|
||||
}
|
||||
|
||||
// If it's close brace - check parentheses
|
||||
if (el.second == e->text()) {
|
||||
auto symbol = charUnderCursor();
|
||||
|
||||
if (symbol == el.second) {
|
||||
textCursor().deletePreviousChar();
|
||||
moveCursor(QTextCursor::MoveOperation::Right);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proceedCompleterEnd(e);
|
||||
}
|
||||
|
||||
void QCodeEditor::setAutoIndentation(bool enabled) {
|
||||
m_autoIndentation = enabled;
|
||||
}
|
||||
|
||||
bool QCodeEditor::autoIndentation() const { return m_autoIndentation; }
|
||||
|
||||
void QCodeEditor::setAutoParentheses(bool enabled) {
|
||||
m_autoParentheses = enabled;
|
||||
}
|
||||
|
||||
bool QCodeEditor::autoParentheses() const { return m_autoParentheses; }
|
||||
|
||||
void QCodeEditor::setTabReplace(bool enabled) { m_replaceTab = enabled; }
|
||||
|
||||
bool QCodeEditor::tabReplace() const { return m_replaceTab; }
|
||||
|
||||
void QCodeEditor::setTabReplaceSize(int val) {
|
||||
m_tabReplace.clear();
|
||||
|
||||
m_tabReplace.fill(' ', val);
|
||||
}
|
||||
|
||||
int QCodeEditor::tabReplaceSize() const { return m_tabReplace.size(); }
|
||||
|
||||
void QCodeEditor::setCompleter(QCompleter *completer) {
|
||||
if (m_completer) {
|
||||
disconnect(m_completer, nullptr, this, nullptr);
|
||||
}
|
||||
|
||||
m_completer = completer;
|
||||
|
||||
if (!m_completer) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_completer->setWidget(this);
|
||||
m_completer->setCompletionMode(QCompleter::CompletionMode::PopupCompletion);
|
||||
|
||||
connect(m_completer, QOverload<const QString &>::of(&QCompleter::activated),
|
||||
this, &QCodeEditor::insertCompletion);
|
||||
}
|
||||
|
||||
void QCodeEditor::focusInEvent(QFocusEvent *e) {
|
||||
if (m_completer) {
|
||||
m_completer->setWidget(this);
|
||||
}
|
||||
|
||||
QTextEdit::focusInEvent(e);
|
||||
}
|
||||
|
||||
void QCodeEditor::insertCompletion(QString s) {
|
||||
if (m_completer->widget() != this) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto tc = textCursor();
|
||||
tc.select(QTextCursor::SelectionType::WordUnderCursor);
|
||||
tc.insertText(s);
|
||||
setTextCursor(tc);
|
||||
}
|
||||
|
||||
QCompleter *QCodeEditor::completer() const { return m_completer; }
|
||||
|
||||
QChar QCodeEditor::charUnderCursor(int offset) const {
|
||||
auto block = textCursor().blockNumber();
|
||||
auto index = textCursor().positionInBlock();
|
||||
auto text = document()->findBlockByNumber(block).text();
|
||||
|
||||
index += offset;
|
||||
|
||||
if (index < 0 || index >= text.size()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return text[index];
|
||||
}
|
||||
|
||||
QString QCodeEditor::wordUnderCursor() const {
|
||||
auto tc = textCursor();
|
||||
tc.select(QTextCursor::WordUnderCursor);
|
||||
return tc.selectedText();
|
||||
}
|
||||
|
||||
void QCodeEditor::insertFromMimeData(const QMimeData *source) {
|
||||
insertPlainText(source->text());
|
||||
}
|
||||
|
||||
int QCodeEditor::getIndentationSpaces() {
|
||||
auto blockText = textCursor().block().text();
|
||||
|
||||
int indentationLevel = 0;
|
||||
|
||||
for (auto i = 0;
|
||||
i < blockText.size() && QString("\t ").contains(blockText[i]); ++i) {
|
||||
if (blockText[i] == ' ') {
|
||||
indentationLevel++;
|
||||
} else {
|
||||
#if QT_VERSION >= 0x050A00
|
||||
indentationLevel += tabStopDistance() / fontMetrics().averageCharWidth();
|
||||
#else
|
||||
indentationLevel += tabStopWidth() / fontMetrics().averageCharWidth();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return indentationLevel;
|
||||
}
|
|
@ -0,0 +1,273 @@
|
|||
#ifndef QCODEEDITOR_H
|
||||
#define QCODEEDITOR_H
|
||||
|
||||
// Qt
|
||||
#include <QTextEdit> // Required for inheritance
|
||||
|
||||
class QCompleter;
|
||||
class QLineNumberArea;
|
||||
class QSyntaxStyle;
|
||||
class QStyleSyntaxHighlighter;
|
||||
class QFramedTextAttribute;
|
||||
|
||||
/**
|
||||
* @brief Class, that describes code editor.
|
||||
*/
|
||||
class QCodeEditor : public QTextEdit {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor.
|
||||
* @param widget Pointer to parent widget.
|
||||
*/
|
||||
explicit QCodeEditor(QWidget *widget = nullptr);
|
||||
|
||||
// Disable copying
|
||||
QCodeEditor(const QCodeEditor &) = delete;
|
||||
QCodeEditor &operator=(const QCodeEditor &) = delete;
|
||||
|
||||
/**
|
||||
* @brief Method for getting first visible block
|
||||
* index.
|
||||
* @return Index.
|
||||
*/
|
||||
int getFirstVisibleBlock();
|
||||
|
||||
/**
|
||||
* @brief Method for setting highlighter.
|
||||
* @param highlighter Pointer to syntax highlighter.
|
||||
*/
|
||||
void setHighlighter(QStyleSyntaxHighlighter *highlighter);
|
||||
|
||||
/**
|
||||
* @brief Method for setting syntax sty.e.
|
||||
* @param style Pointer to syntax style.
|
||||
*/
|
||||
void setSyntaxStyle(QSyntaxStyle *style);
|
||||
|
||||
/**
|
||||
* @brief Method setting auto parentheses enabled.
|
||||
*/
|
||||
void setAutoParentheses(bool enabled);
|
||||
|
||||
/**
|
||||
* @brief Method for getting is auto parentheses enabled.
|
||||
* Default value: true
|
||||
*/
|
||||
bool autoParentheses() const;
|
||||
|
||||
/**
|
||||
* @brief Method for setting tab replacing
|
||||
* enabled.
|
||||
*/
|
||||
void setTabReplace(bool enabled);
|
||||
|
||||
/**
|
||||
* @brief Method for getting is tab replacing enabled.
|
||||
* Default value: true
|
||||
*/
|
||||
bool tabReplace() const;
|
||||
|
||||
/**
|
||||
* @brief Method for setting amount of spaces, that will
|
||||
* replace tab.
|
||||
* @param val Number of spaces.
|
||||
*/
|
||||
void setTabReplaceSize(int val);
|
||||
|
||||
/**
|
||||
* @brief Method for getting number of spaces, that will
|
||||
* replace tab if `tabReplace` is true.
|
||||
* Default: 4
|
||||
*/
|
||||
int tabReplaceSize() const;
|
||||
|
||||
/**
|
||||
* @brief Method for setting auto indentation enabled.
|
||||
*/
|
||||
void setAutoIndentation(bool enabled);
|
||||
|
||||
/**
|
||||
* @brief Method for getting is auto indentation enabled.
|
||||
* Default: true
|
||||
*/
|
||||
bool autoIndentation() const;
|
||||
|
||||
/**
|
||||
* @brief Method for setting completer.
|
||||
* @param completer Pointer to completer object.
|
||||
*/
|
||||
void setCompleter(QCompleter *completer);
|
||||
|
||||
/**
|
||||
* @brief Method for getting completer.
|
||||
* @return Pointer to completer.
|
||||
*/
|
||||
QCompleter *completer() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
|
||||
/**
|
||||
* @brief Slot, that performs insertion of
|
||||
* completion info into code.
|
||||
* @param s Data.
|
||||
*/
|
||||
void insertCompletion(QString s);
|
||||
|
||||
/**
|
||||
* @brief Slot, that performs update of
|
||||
* internal editor viewport based on line
|
||||
* number area width.
|
||||
*/
|
||||
void updateLineNumberAreaWidth(int);
|
||||
|
||||
/**
|
||||
* @brief Slot, that performs update of some
|
||||
* part of line number area.
|
||||
* @param rect Area that has to be updated.
|
||||
*/
|
||||
void updateLineNumberArea(const QRect &rect);
|
||||
|
||||
/**
|
||||
* @brief Slot, that will proceed extra selection
|
||||
* for current cursor position.
|
||||
*/
|
||||
void updateExtraSelection();
|
||||
|
||||
/**
|
||||
* @brief Slot, that will update editor style.
|
||||
*/
|
||||
void updateStyle();
|
||||
|
||||
/**
|
||||
* @brief Slot, that will be called on selection
|
||||
* change.
|
||||
*/
|
||||
void onSelectionChanged();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Method, that's called on any text insertion of
|
||||
* mimedata into editor. If it's text - it inserts text
|
||||
* as plain text.
|
||||
*/
|
||||
void insertFromMimeData(const QMimeData *source) override;
|
||||
|
||||
/**
|
||||
* @brief Method, that's called on editor painting. This
|
||||
* method if overloaded for line number area redraw.
|
||||
*/
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
/**
|
||||
* @brief Method, that's called on any widget resize.
|
||||
* This method if overloaded for line number area
|
||||
* resizing.
|
||||
*/
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
|
||||
/**
|
||||
* @brief Method, that's called on any key press, posted
|
||||
* into code editor widget. This method is overloaded for:
|
||||
*
|
||||
* 1. Completion
|
||||
* 2. Tab to spaces
|
||||
* 3. Low indentation
|
||||
* 4. Auto parenthesis
|
||||
*/
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
|
||||
/**
|
||||
* @brief Method, that's called on focus into widget.
|
||||
* It's required for setting this widget to set
|
||||
* completer.
|
||||
*/
|
||||
void focusInEvent(QFocusEvent *e) override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Method for initializing document
|
||||
* layout handlers.
|
||||
*/
|
||||
void initDocumentLayoutHandlers();
|
||||
|
||||
/**
|
||||
* @brief Method for initializing default
|
||||
* monospace font.
|
||||
*/
|
||||
void initFont();
|
||||
|
||||
/**
|
||||
* @brief Method for performing connection
|
||||
* of objects.
|
||||
*/
|
||||
void performConnections();
|
||||
|
||||
/**
|
||||
* @brief Method, that performs selection
|
||||
* frame selection.
|
||||
*/
|
||||
void handleSelectionQuery(QTextCursor cursor);
|
||||
|
||||
/**
|
||||
* @brief Method for updating geometry of line number area.
|
||||
*/
|
||||
void updateLineGeometry();
|
||||
|
||||
/**
|
||||
* @brief Method, that performs completer processing.
|
||||
* Returns true if event has to be dropped.
|
||||
* @param e Pointer to key event.
|
||||
* @return Shall event be dropped.
|
||||
*/
|
||||
bool proceedCompleterBegin(QKeyEvent *e);
|
||||
void proceedCompleterEnd(QKeyEvent *e);
|
||||
|
||||
/**
|
||||
* @brief Method for getting character under
|
||||
* cursor.
|
||||
* @param offset Offset to cursor.
|
||||
*/
|
||||
QChar charUnderCursor(int offset = 0) const;
|
||||
|
||||
/**
|
||||
* @brief Method for getting word under
|
||||
* cursor.
|
||||
* @return Word under cursor.
|
||||
*/
|
||||
QString wordUnderCursor() const;
|
||||
|
||||
/**
|
||||
* @brief Method, that adds highlighting of
|
||||
* currently selected line to extra selection list.
|
||||
*/
|
||||
void highlightCurrentLine(QList<QTextEdit::ExtraSelection> &extraSelection);
|
||||
|
||||
/**
|
||||
* @brief Method, that adds highlighting of
|
||||
* parenthesis if available.
|
||||
*/
|
||||
void highlightParenthesis(QList<QTextEdit::ExtraSelection> &extraSelection);
|
||||
|
||||
/**
|
||||
* @brief Method for getting number of indentation
|
||||
* spaces in current line. Tabs will be treated
|
||||
* as `tabWidth / spaceWidth`
|
||||
*/
|
||||
int getIndentationSpaces();
|
||||
|
||||
QStyleSyntaxHighlighter *m_highlighter;
|
||||
QSyntaxStyle *m_syntaxStyle;
|
||||
QLineNumberArea *m_lineNumberArea;
|
||||
QCompleter *m_completer;
|
||||
|
||||
QFramedTextAttribute *m_framedAttribute;
|
||||
|
||||
bool m_autoIndentation;
|
||||
bool m_autoParentheses;
|
||||
bool m_replaceTab;
|
||||
QString m_tabReplace;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,85 @@
|
|||
// QCodeEditor
|
||||
#include "QFramedTextAttribute.hpp"
|
||||
#include "QSyntaxStyle.hpp"
|
||||
|
||||
// Qt
|
||||
#include <QDebug>
|
||||
#include <QFontMetrics>
|
||||
#include <QPainter>
|
||||
#include <QTextBlock>
|
||||
|
||||
int QFramedTextAttribute::type() { return QTextFormat::UserFormat + 1; }
|
||||
|
||||
QFramedTextAttribute::QFramedTextAttribute(QObject *parent)
|
||||
: QObject(parent), m_style(nullptr) {}
|
||||
|
||||
void QFramedTextAttribute::setSyntaxStyle(QSyntaxStyle *style) {
|
||||
m_style = style;
|
||||
}
|
||||
|
||||
QSyntaxStyle *QFramedTextAttribute::syntaxStyle() const { return m_style; }
|
||||
|
||||
QSizeF QFramedTextAttribute::intrinsicSize(QTextDocument *, int,
|
||||
const QTextFormat &) {
|
||||
return {0, 0};
|
||||
}
|
||||
|
||||
void QFramedTextAttribute::drawObject(QPainter *painter, const QRectF &rect,
|
||||
QTextDocument *, int,
|
||||
const QTextFormat &format) {
|
||||
// Casting
|
||||
auto textCharFormat = reinterpret_cast<const QTextCharFormat &>(format);
|
||||
|
||||
// Getting font data
|
||||
auto font = textCharFormat.font();
|
||||
QFontMetrics metrics(font);
|
||||
|
||||
// Getting required size
|
||||
auto string = format.property(FramedString).toString();
|
||||
auto stringSize = metrics.boundingRect(string).size();
|
||||
|
||||
// Creating frame rect
|
||||
QRectF drawRect(rect.topLeft(), stringSize);
|
||||
drawRect.moveTop(rect.top() - stringSize.height());
|
||||
drawRect.adjust(0, 4, 0, 4);
|
||||
|
||||
// Drawing
|
||||
painter->setPen(m_style->getFormat("Occurrences").background().color());
|
||||
painter->setRenderHint(QPainter::Antialiasing);
|
||||
painter->drawRoundedRect(drawRect, 4, 4);
|
||||
}
|
||||
|
||||
void QFramedTextAttribute::frame(QTextCursor cursor) {
|
||||
auto text = cursor.document()->findBlockByNumber(cursor.blockNumber()).text();
|
||||
|
||||
QTextCharFormat format;
|
||||
format.setObjectType(type());
|
||||
format.setProperty(FramedString, cursor.selectedText());
|
||||
|
||||
if (cursor.selectionEnd() > cursor.selectionStart()) {
|
||||
cursor.setPosition(cursor.selectionStart());
|
||||
} else {
|
||||
cursor.setPosition(cursor.selectionEnd());
|
||||
}
|
||||
|
||||
cursor.insertText(QString(QChar::ObjectReplacementCharacter), format);
|
||||
}
|
||||
|
||||
void QFramedTextAttribute::clear(QTextCursor cursor) {
|
||||
auto doc = cursor.document();
|
||||
|
||||
for (auto blockIndex = 0; blockIndex < doc->blockCount(); ++blockIndex) {
|
||||
auto block = doc->findBlockByNumber(blockIndex);
|
||||
|
||||
auto formats = block.textFormats();
|
||||
int offset = 0;
|
||||
|
||||
for (auto &format : formats) {
|
||||
if (format.format.objectType() == type()) {
|
||||
cursor.setPosition(block.position() + format.start - offset);
|
||||
cursor.deleteChar();
|
||||
++offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
#ifndef QFRAMEDTEXTATTRIBUTE_H
|
||||
#define QFRAMEDTEXTATTRIBUTE_H
|
||||
|
||||
// Qt
|
||||
#include <QObject> // Required for inheritance
|
||||
#include <QTextObjectInterface> // Required for inheritance
|
||||
|
||||
class QSyntaxStyle;
|
||||
|
||||
/**
|
||||
* @brief Class, that describes
|
||||
* attribute for making text frame.
|
||||
*/
|
||||
class QFramedTextAttribute : public QObject, public QTextObjectInterface {
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(QTextObjectInterface)
|
||||
|
||||
public:
|
||||
enum Property { FramedString = 1 };
|
||||
|
||||
/**
|
||||
* @brief Static method for getting framed text
|
||||
* attribute type.
|
||||
*/
|
||||
static int type();
|
||||
|
||||
/**
|
||||
* @brief Constructor.
|
||||
* @param parent Pointer to parent QObject.
|
||||
*/
|
||||
explicit QFramedTextAttribute(QObject *parent = nullptr);
|
||||
|
||||
// Disable copying
|
||||
QFramedTextAttribute(const QFramedTextAttribute &) = delete;
|
||||
QFramedTextAttribute &operator=(const QFramedTextAttribute &) = delete;
|
||||
|
||||
/**
|
||||
* @brief Method for getting custom element (frame)
|
||||
* size. Though frame symbol has no size, this
|
||||
* method returns {0, 0}
|
||||
*/
|
||||
QSizeF intrinsicSize(QTextDocument *doc, int posInDocument,
|
||||
const QTextFormat &format) override;
|
||||
|
||||
/**
|
||||
* @brief Method for drawing frame.
|
||||
*/
|
||||
void drawObject(QPainter *painter, const QRectF &rect, QTextDocument *doc,
|
||||
int posInDocument, const QTextFormat &format) override;
|
||||
|
||||
/**
|
||||
* @brief Method for creating frame in cursor
|
||||
* selection.
|
||||
* @param cursor Cursor.
|
||||
*/
|
||||
void frame(QTextCursor cursor);
|
||||
|
||||
/**
|
||||
* @brief Method for clearing all frames
|
||||
* with desired cursor.
|
||||
*/
|
||||
void clear(QTextCursor cursor);
|
||||
|
||||
/**
|
||||
* @brief Method for setting syntax style
|
||||
* for rendering.
|
||||
*/
|
||||
void setSyntaxStyle(QSyntaxStyle *style);
|
||||
|
||||
/**
|
||||
* @brief Method for getting syntax style.
|
||||
*/
|
||||
QSyntaxStyle *syntaxStyle() const;
|
||||
|
||||
private:
|
||||
QSyntaxStyle *m_style;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
|
||||
// Qt
|
||||
#include <QRegularExpression>
|
||||
#include <QString>
|
||||
|
||||
struct QHighlightBlockRule
|
||||
{
|
||||
QHighlightBlockRule() :
|
||||
startPattern(),
|
||||
endPattern(),
|
||||
formatName()
|
||||
{}
|
||||
|
||||
QHighlightBlockRule(QRegularExpression start, QRegularExpression end, QString format) :
|
||||
startPattern(std::move(start)),
|
||||
endPattern(std::move(end)),
|
||||
formatName(std::move(format))
|
||||
{}
|
||||
|
||||
QRegularExpression startPattern;
|
||||
QRegularExpression endPattern;
|
||||
QString formatName;
|
||||
};
|
|
@ -0,0 +1,21 @@
|
|||
#pragma once
|
||||
|
||||
// Qt
|
||||
#include <QRegularExpression>
|
||||
#include <QString>
|
||||
|
||||
struct QHighlightRule
|
||||
{
|
||||
QHighlightRule() :
|
||||
pattern(),
|
||||
formatName()
|
||||
{}
|
||||
|
||||
QHighlightRule(QRegularExpression p, QString f) :
|
||||
pattern(std::move(p)),
|
||||
formatName(std::move(f))
|
||||
{}
|
||||
|
||||
QRegularExpression pattern;
|
||||
QString formatName;
|
||||
};
|
|
@ -0,0 +1,57 @@
|
|||
// QCodeEditor
|
||||
#include "QLanguage.hpp"
|
||||
|
||||
// Qt
|
||||
#include <QIODevice>
|
||||
#include <QXmlStreamReader>
|
||||
|
||||
QLanguage::QLanguage(QIODevice *device, QObject *parent)
|
||||
: QObject(parent), m_loaded(false), m_list() {
|
||||
load(device);
|
||||
}
|
||||
|
||||
bool QLanguage::load(QIODevice *device) {
|
||||
if (device == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QXmlStreamReader reader(device);
|
||||
|
||||
QString name;
|
||||
QStringList list;
|
||||
bool readText = false;
|
||||
|
||||
while (!reader.atEnd() && !reader.hasError()) {
|
||||
auto type = reader.readNext();
|
||||
|
||||
if (type == QXmlStreamReader::TokenType::StartElement) {
|
||||
if (reader.name() == "section") {
|
||||
if (!list.empty()) {
|
||||
m_list[name] = list;
|
||||
list.clear();
|
||||
}
|
||||
|
||||
name = reader.attributes().value("name").toString();
|
||||
} else if (reader.name() == "name") {
|
||||
readText = true;
|
||||
}
|
||||
} else if (type == QXmlStreamReader::TokenType::Characters && readText) {
|
||||
list << reader.text().toString();
|
||||
readText = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!list.empty()) {
|
||||
m_list[name] = list;
|
||||
}
|
||||
|
||||
m_loaded = !reader.hasError();
|
||||
|
||||
return m_loaded;
|
||||
}
|
||||
|
||||
QStringList QLanguage::keys() { return m_list.keys(); }
|
||||
|
||||
QStringList QLanguage::names(const QString &key) { return m_list[key]; }
|
||||
|
||||
bool QLanguage::isLoaded() const { return m_loaded; }
|
|
@ -0,0 +1,61 @@
|
|||
#pragma once
|
||||
|
||||
// Qt
|
||||
#include <QObject> // Required for inheritance
|
||||
#include <QString>
|
||||
#include <QMap>
|
||||
|
||||
class QIODevice;
|
||||
|
||||
/**
|
||||
* Class, that describes object for parsing
|
||||
* language file.
|
||||
*/
|
||||
class QLanguage : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Constructor.
|
||||
* @param parent Pointer to parent QObject.
|
||||
*/
|
||||
explicit QLanguage(QIODevice* device=nullptr, QObject* parent=nullptr);
|
||||
|
||||
/**
|
||||
* @brief Method for parsing.
|
||||
* @param device Pointer to device.
|
||||
* @return Success.
|
||||
*/
|
||||
bool load(QIODevice* device);
|
||||
|
||||
/**
|
||||
* @brief Method for getting available keys.
|
||||
*/
|
||||
QStringList keys();
|
||||
|
||||
/**
|
||||
* @brief Method for getting names
|
||||
* from key.
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
QStringList names(const QString& key);
|
||||
|
||||
/**
|
||||
* @brief Method for getting is object loaded.
|
||||
*/
|
||||
bool isLoaded() const;
|
||||
|
||||
private:
|
||||
|
||||
bool m_loaded;
|
||||
|
||||
QMap<
|
||||
QString,
|
||||
QStringList
|
||||
> m_list;
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
// QCodeEditor
|
||||
#include "QLineNumberArea.hpp"
|
||||
#include "QCodeEditor.hpp"
|
||||
#include "QSyntaxStyle.hpp"
|
||||
|
||||
// Qt
|
||||
#include <QAbstractTextDocumentLayout>
|
||||
#include <QPaintEvent>
|
||||
#include <QPainter>
|
||||
#include <QScrollBar>
|
||||
#include <QTextBlock>
|
||||
#include <QTextEdit>
|
||||
|
||||
QLineNumberArea::QLineNumberArea(QCodeEditor *parent)
|
||||
: QWidget(parent), m_syntaxStyle(nullptr), m_codeEditParent(parent) {}
|
||||
|
||||
QSize QLineNumberArea::sizeHint() const {
|
||||
if (m_codeEditParent == nullptr) {
|
||||
return QWidget::sizeHint();
|
||||
}
|
||||
|
||||
// Calculating width
|
||||
int digits = 1;
|
||||
int max = qMax(1, m_codeEditParent->document()->blockCount());
|
||||
while (max >= 10) {
|
||||
max /= 10;
|
||||
++digits;
|
||||
}
|
||||
|
||||
#if QT_VERSION >= 0x050B00
|
||||
int space =
|
||||
13 + m_codeEditParent->fontMetrics().horizontalAdvance(QLatin1Char('9')) *
|
||||
digits;
|
||||
#else
|
||||
int space =
|
||||
13 + m_codeEditParent->fontMetrics().width(QLatin1Char('9')) * digits;
|
||||
#endif
|
||||
|
||||
return {space, 0};
|
||||
}
|
||||
|
||||
void QLineNumberArea::setSyntaxStyle(QSyntaxStyle *style) {
|
||||
m_syntaxStyle = style;
|
||||
}
|
||||
|
||||
QSyntaxStyle *QLineNumberArea::syntaxStyle() const { return m_syntaxStyle; }
|
||||
|
||||
void QLineNumberArea::paintEvent(QPaintEvent *event) {
|
||||
QPainter painter(this);
|
||||
|
||||
// Clearing rect to update
|
||||
painter.fillRect(event->rect(),
|
||||
m_syntaxStyle->getFormat("Text").background().color());
|
||||
|
||||
auto blockNumber = m_codeEditParent->getFirstVisibleBlock();
|
||||
auto block = m_codeEditParent->document()->findBlockByNumber(blockNumber);
|
||||
auto top = (int)m_codeEditParent->document()
|
||||
->documentLayout()
|
||||
->blockBoundingRect(block)
|
||||
.translated(0, -m_codeEditParent->verticalScrollBar()->value())
|
||||
.top();
|
||||
auto bottom = top + (int)m_codeEditParent->document()
|
||||
->documentLayout()
|
||||
->blockBoundingRect(block)
|
||||
.height();
|
||||
|
||||
auto currentLine =
|
||||
m_syntaxStyle->getFormat("CurrentLineNumber").foreground().color();
|
||||
auto otherLines = m_syntaxStyle->getFormat("LineNumber").foreground().color();
|
||||
|
||||
painter.setFont(m_codeEditParent->font());
|
||||
|
||||
while (block.isValid() && top <= event->rect().bottom()) {
|
||||
if (block.isVisible() && bottom >= event->rect().top()) {
|
||||
QString number = QString::number(blockNumber + 1);
|
||||
|
||||
auto isCurrentLine =
|
||||
m_codeEditParent->textCursor().blockNumber() == blockNumber;
|
||||
painter.setPen(isCurrentLine ? currentLine : otherLines);
|
||||
|
||||
painter.drawText(-5, top, sizeHint().width(),
|
||||
m_codeEditParent->fontMetrics().height(), Qt::AlignRight,
|
||||
number);
|
||||
}
|
||||
|
||||
block = block.next();
|
||||
top = bottom;
|
||||
bottom = top + (int)m_codeEditParent->document()
|
||||
->documentLayout()
|
||||
->blockBoundingRect(block)
|
||||
.height();
|
||||
++blockNumber;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
#ifndef QLINENUMBERAREA_H
|
||||
#define QLINENUMBERAREA_H
|
||||
|
||||
// Qt
|
||||
#include <QWidget> // Required for inheritance
|
||||
|
||||
class QCodeEditor;
|
||||
class QSyntaxStyle;
|
||||
|
||||
/**
|
||||
* @brief Class, that describes line number area widget.
|
||||
*/
|
||||
class QLineNumberArea : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor.
|
||||
* @param parent Pointer to parent QTextEdit widget.
|
||||
*/
|
||||
explicit QLineNumberArea(QCodeEditor *parent = nullptr);
|
||||
|
||||
// Disable copying
|
||||
QLineNumberArea(const QLineNumberArea &) = delete;
|
||||
QLineNumberArea &operator=(const QLineNumberArea &) = delete;
|
||||
|
||||
/**
|
||||
* @brief Overridden method for getting line number area
|
||||
* size.
|
||||
*/
|
||||
QSize sizeHint() const override;
|
||||
|
||||
/**
|
||||
* @brief Method for setting syntax style object.
|
||||
* @param style Pointer to syntax style.
|
||||
*/
|
||||
void setSyntaxStyle(QSyntaxStyle *style);
|
||||
|
||||
/**
|
||||
* @brief Method for getting syntax style.
|
||||
* @return Pointer to syntax style.
|
||||
*/
|
||||
QSyntaxStyle *syntaxStyle() const;
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
private:
|
||||
QSyntaxStyle *m_syntaxStyle;
|
||||
|
||||
QCodeEditor *m_codeEditParent;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,36 @@
|
|||
// QCodeEditor
|
||||
#include "QPythonCompleter.hpp"
|
||||
#include "QLanguage.hpp"
|
||||
|
||||
// Qt
|
||||
#include <QFile>
|
||||
#include <QStringListModel>
|
||||
|
||||
QPythonCompleter::QPythonCompleter(QObject *parent) : QCompleter(parent) {
|
||||
// Setting up Python types
|
||||
QStringList list;
|
||||
|
||||
QFile fl(":/python.xml");
|
||||
|
||||
if (!fl.open(QIODevice::ReadOnly)) {
|
||||
return;
|
||||
}
|
||||
|
||||
QLanguage language(&fl);
|
||||
|
||||
if (!language.isLoaded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto keys = language.keys();
|
||||
for (auto &&key : keys) {
|
||||
auto names = language.names(key);
|
||||
list.append(names);
|
||||
}
|
||||
|
||||
setModel(new QStringListModel(list, this));
|
||||
setCompletionColumn(0);
|
||||
setModelSorting(QCompleter::CaseInsensitivelySortedModel);
|
||||
setCaseSensitivity(Qt::CaseSensitive);
|
||||
setWrapAround(true);
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef QPYTHONCOMPLETER_H
|
||||
#define QPYTHONCOMPLETER_H
|
||||
|
||||
// Qt
|
||||
#include <QCompleter> // Required for inheritance
|
||||
|
||||
/**
|
||||
* @brief Class, that describes completer with
|
||||
* glsl specific types and functions.
|
||||
*/
|
||||
class QPythonCompleter : public QCompleter {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor.
|
||||
* @param parent Pointer to parent QObject.
|
||||
*/
|
||||
explicit QPythonCompleter(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,121 @@
|
|||
// QCodeEditor
|
||||
#include "QPythonHighlighter.hpp"
|
||||
#include "QLanguage.hpp"
|
||||
#include "QSyntaxStyle.hpp"
|
||||
|
||||
// Qt
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
|
||||
QPythonHighlighter::QPythonHighlighter(QTextDocument *document)
|
||||
: QStyleSyntaxHighlighter(document), m_highlightRules(),
|
||||
m_highlightBlockRules(),
|
||||
m_includePattern(QRegularExpression(R"(import \w+)")),
|
||||
m_functionPattern(QRegularExpression(
|
||||
R"(\b([A-Za-z0-9_]+(?:\.))*([A-Za-z0-9_]+)(?=\())")),
|
||||
m_defTypePattern(QRegularExpression(
|
||||
R"(\b([A-Za-z0-9_]+)\s+[A-Za-z]{1}[A-Za-z0-9_]+\s*[;=])")) {
|
||||
QFile fl(":/python.xml");
|
||||
|
||||
if (!fl.open(QIODevice::ReadOnly)) {
|
||||
return;
|
||||
}
|
||||
|
||||
QLanguage language(&fl);
|
||||
|
||||
if (!language.isLoaded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto keys = language.keys();
|
||||
for (auto &&key : keys) {
|
||||
auto names = language.names(key);
|
||||
for (auto &&name : names) {
|
||||
m_highlightRules.append(
|
||||
{QRegularExpression(QString(R"(\b%1\b)").arg(name)), key});
|
||||
}
|
||||
}
|
||||
|
||||
// Following rules has higher priority to display
|
||||
// than language specific keys
|
||||
// So they must be applied at last.
|
||||
// Numbers
|
||||
m_highlightRules.append(
|
||||
{QRegularExpression(R"(\b(0b|0x){0,1}[\d.']+\b)"), "Number"});
|
||||
|
||||
// Strings
|
||||
m_highlightRules.append({QRegularExpression(R"("[^\n"]*")"), "String"});
|
||||
m_highlightRules.append({QRegularExpression(R"('[^\n"]*')"), "String"});
|
||||
|
||||
// Single line comment
|
||||
m_highlightRules.append({QRegularExpression("#[^\n]*"), "Comment"});
|
||||
|
||||
// Multiline string
|
||||
m_highlightBlockRules.append(
|
||||
{QRegularExpression("(''')"), QRegularExpression("(''')"), "String"});
|
||||
m_highlightBlockRules.append({QRegularExpression("(\"\"\")"),
|
||||
QRegularExpression("(\"\"\")"), "String"});
|
||||
}
|
||||
|
||||
void QPythonHighlighter::highlightBlock(const QString &text) {
|
||||
// Checking for function
|
||||
{
|
||||
auto matchIterator = m_functionPattern.globalMatch(text);
|
||||
|
||||
while (matchIterator.hasNext()) {
|
||||
auto match = matchIterator.next();
|
||||
|
||||
setFormat(match.capturedStart(), match.capturedLength(),
|
||||
syntaxStyle()->getFormat("Type"));
|
||||
|
||||
setFormat(match.capturedStart(2), match.capturedLength(2),
|
||||
syntaxStyle()->getFormat("Function"));
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &rule : m_highlightRules) {
|
||||
auto matchIterator = rule.pattern.globalMatch(text);
|
||||
|
||||
while (matchIterator.hasNext()) {
|
||||
auto match = matchIterator.next();
|
||||
|
||||
setFormat(match.capturedStart(), match.capturedLength(),
|
||||
syntaxStyle()->getFormat(rule.formatName));
|
||||
}
|
||||
}
|
||||
|
||||
setCurrentBlockState(0);
|
||||
int startIndex = 0;
|
||||
int highlightRuleId = previousBlockState();
|
||||
if (highlightRuleId < 1 || highlightRuleId > m_highlightBlockRules.size()) {
|
||||
for (int i = 0; i < m_highlightBlockRules.size(); ++i) {
|
||||
startIndex = text.indexOf(m_highlightBlockRules.at(i).startPattern);
|
||||
|
||||
if (startIndex >= 0) {
|
||||
highlightRuleId = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (startIndex >= 0) {
|
||||
const auto &blockRules = m_highlightBlockRules.at(highlightRuleId - 1);
|
||||
auto match = blockRules.endPattern.match(
|
||||
text, startIndex + 1); // Should be + length of start pattern
|
||||
|
||||
int endIndex = match.capturedStart();
|
||||
int matchLength = 0;
|
||||
|
||||
if (endIndex == -1) {
|
||||
setCurrentBlockState(highlightRuleId);
|
||||
matchLength = text.length() - startIndex;
|
||||
} else {
|
||||
matchLength = endIndex - startIndex + match.capturedLength();
|
||||
}
|
||||
|
||||
setFormat(startIndex, matchLength,
|
||||
syntaxStyle()->getFormat(blockRules.formatName));
|
||||
startIndex =
|
||||
text.indexOf(blockRules.startPattern, startIndex + matchLength);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
#ifndef QPYTHONHIGHLIGHTER_H
|
||||
#define QPYTHONHIGHLIGHTER_H
|
||||
|
||||
// QCodeEditor
|
||||
#include "QHighlightBlockRule.hpp"
|
||||
#include "QHighlightRule.hpp"
|
||||
#include "QStyleSyntaxHighlighter.hpp" // Required for inheritance
|
||||
|
||||
// Qt
|
||||
#include <QRegularExpression>
|
||||
#include <QVector>
|
||||
|
||||
class QSyntaxStyle;
|
||||
|
||||
/**
|
||||
* @brief Class, that describes Glsl code
|
||||
* highlighter.
|
||||
*/
|
||||
class QPythonHighlighter : public QStyleSyntaxHighlighter {
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor.
|
||||
* @param document Pointer to document.
|
||||
*/
|
||||
explicit QPythonHighlighter(QTextDocument *document = nullptr);
|
||||
|
||||
protected:
|
||||
void highlightBlock(const QString &text) override;
|
||||
|
||||
private:
|
||||
QVector<QHighlightRule> m_highlightRules;
|
||||
QVector<QHighlightBlockRule> m_highlightBlockRules;
|
||||
|
||||
QRegularExpression m_includePattern;
|
||||
QRegularExpression m_functionPattern;
|
||||
QRegularExpression m_defTypePattern;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,13 @@
|
|||
// QCodeEditor
|
||||
#include "QStyleSyntaxHighlighter.hpp"
|
||||
|
||||
QStyleSyntaxHighlighter::QStyleSyntaxHighlighter(QTextDocument *document)
|
||||
: QSyntaxHighlighter(document), m_syntaxStyle(nullptr) {}
|
||||
|
||||
void QStyleSyntaxHighlighter::setSyntaxStyle(QSyntaxStyle *style) {
|
||||
m_syntaxStyle = style;
|
||||
}
|
||||
|
||||
QSyntaxStyle *QStyleSyntaxHighlighter::syntaxStyle() const {
|
||||
return m_syntaxStyle;
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
#pragma once
|
||||
|
||||
// Qt
|
||||
#include <QSyntaxHighlighter> // Required for inheritance
|
||||
|
||||
class QSyntaxStyle;
|
||||
|
||||
/**
|
||||
* @brief Class, that descrubes highlighter with
|
||||
* syntax style.
|
||||
*/
|
||||
class QStyleSyntaxHighlighter : public QSyntaxHighlighter
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Constructor.
|
||||
* @param document Pointer to text document.
|
||||
*/
|
||||
explicit QStyleSyntaxHighlighter(QTextDocument* document=nullptr);
|
||||
|
||||
// Disable copying
|
||||
QStyleSyntaxHighlighter(const QStyleSyntaxHighlighter&) = delete;
|
||||
QStyleSyntaxHighlighter& operator=(const QStyleSyntaxHighlighter&) = delete;
|
||||
|
||||
/**
|
||||
* @brief Method for setting syntax style.
|
||||
* @param style Pointer to syntax style.
|
||||
*/
|
||||
void setSyntaxStyle(QSyntaxStyle* style);
|
||||
|
||||
/**
|
||||
* @brief Method for getting syntax style.
|
||||
* @return Pointer to syntax style. May be nullptr.
|
||||
*/
|
||||
QSyntaxStyle* syntaxStyle() const;
|
||||
|
||||
private:
|
||||
QSyntaxStyle* m_syntaxStyle;
|
||||
};
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
// QCodeEditor
|
||||
#include "QSyntaxStyle.hpp"
|
||||
|
||||
// Qt
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QXmlStreamReader>
|
||||
|
||||
QSyntaxStyle::QSyntaxStyle(QObject *parent)
|
||||
: QObject(parent), m_name(), m_data(), m_loaded(false) {}
|
||||
|
||||
bool QSyntaxStyle::load(QString fl) {
|
||||
QXmlStreamReader reader(fl);
|
||||
|
||||
while (!reader.atEnd() && !reader.hasError()) {
|
||||
auto token = reader.readNext();
|
||||
|
||||
if (token == QXmlStreamReader::StartElement) {
|
||||
if (reader.name() == "style-scheme") {
|
||||
if (reader.attributes().hasAttribute("name")) {
|
||||
m_name = reader.attributes().value("name").toString();
|
||||
}
|
||||
} else if (reader.name() == "style") {
|
||||
auto attributes = reader.attributes();
|
||||
|
||||
auto name = attributes.value("name");
|
||||
|
||||
QTextCharFormat format;
|
||||
|
||||
if (attributes.hasAttribute("background")) {
|
||||
format.setBackground(
|
||||
QColor(attributes.value("background").toString()));
|
||||
}
|
||||
|
||||
if (attributes.hasAttribute("foreground")) {
|
||||
format.setForeground(
|
||||
QColor(attributes.value("foreground").toString()));
|
||||
}
|
||||
|
||||
if (attributes.hasAttribute("bold") &&
|
||||
attributes.value("bold") == "true") {
|
||||
format.setFontWeight(QFont::Weight::Bold);
|
||||
}
|
||||
|
||||
if (attributes.hasAttribute("italic") &&
|
||||
attributes.value("italic") == "true") {
|
||||
format.setFontItalic(true);
|
||||
}
|
||||
|
||||
if (attributes.hasAttribute("underlineStyle")) {
|
||||
auto underline = attributes.value("underlineStyle");
|
||||
|
||||
auto s = QTextCharFormat::UnderlineStyle::NoUnderline;
|
||||
|
||||
if (underline == "SingleUnderline") {
|
||||
s = QTextCharFormat::UnderlineStyle::SingleUnderline;
|
||||
} else if (underline == "DashUnderline") {
|
||||
s = QTextCharFormat::UnderlineStyle::DashUnderline;
|
||||
} else if (underline == "DotLine") {
|
||||
s = QTextCharFormat::UnderlineStyle::DotLine;
|
||||
} else if (underline == "DashDotLine") {
|
||||
s = QTextCharFormat::DashDotLine;
|
||||
} else if (underline == "DashDotDotLine") {
|
||||
s = QTextCharFormat::DashDotDotLine;
|
||||
} else if (underline == "WaveUnderline") {
|
||||
s = QTextCharFormat::WaveUnderline;
|
||||
} else if (underline == "SpellCheckUnderline") {
|
||||
s = QTextCharFormat::SpellCheckUnderline;
|
||||
} else {
|
||||
qDebug() << "Unknown underline value " << underline;
|
||||
}
|
||||
|
||||
format.setUnderlineStyle(s);
|
||||
}
|
||||
|
||||
m_data[name.toString()] = format;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_loaded = !reader.hasError();
|
||||
|
||||
return m_loaded;
|
||||
}
|
||||
|
||||
QString QSyntaxStyle::name() const { return m_name; }
|
||||
|
||||
QTextCharFormat QSyntaxStyle::getFormat(QString name) const {
|
||||
auto result = m_data.find(name);
|
||||
|
||||
if (result == m_data.end()) {
|
||||
return QTextCharFormat();
|
||||
}
|
||||
|
||||
return result.value();
|
||||
}
|
||||
|
||||
bool QSyntaxStyle::isLoaded() const { return m_loaded; }
|
||||
|
||||
QSyntaxStyle *QSyntaxStyle::defaultStyle() {
|
||||
static QSyntaxStyle style;
|
||||
|
||||
if (!style.isLoaded()) {
|
||||
QFile fl(":/default_style.xml");
|
||||
|
||||
if (!fl.open(QIODevice::ReadOnly)) {
|
||||
return &style;
|
||||
}
|
||||
|
||||
if (!style.load(fl.readAll())) {
|
||||
qDebug() << "Can't load default style.";
|
||||
}
|
||||
}
|
||||
|
||||
return &style;
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
#pragma once
|
||||
|
||||
// Qt
|
||||
#include <QObject> // Required for inheritance
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
#include <QTextCharFormat>
|
||||
|
||||
/**
|
||||
* @brief Class, that describes Qt style
|
||||
* parser for QCodeEditor.
|
||||
*/
|
||||
class QSyntaxStyle : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Constructor.
|
||||
* @param parent Pointer to parent QObject
|
||||
*/
|
||||
explicit QSyntaxStyle(QObject* parent=nullptr);
|
||||
|
||||
/**
|
||||
* @brief Method for loading and parsing
|
||||
* style.
|
||||
* @param fl Style.
|
||||
* @return Success.
|
||||
*/
|
||||
bool load(QString fl);
|
||||
|
||||
/**
|
||||
* @brief Method for getting style name.
|
||||
* @return Name.
|
||||
*/
|
||||
QString name() const;
|
||||
|
||||
/**
|
||||
* @brief Method for checking is syntax style loaded.
|
||||
* @return Is loaded.
|
||||
*/
|
||||
bool isLoaded() const;
|
||||
|
||||
/**
|
||||
* @brief Method for getting format for property
|
||||
* name.
|
||||
* @param name Property name.
|
||||
* @return Text char format.
|
||||
*/
|
||||
QTextCharFormat getFormat(QString name) const;
|
||||
|
||||
/**
|
||||
* @brief Static method for getting default style.
|
||||
* @return Pointer to default style.
|
||||
*/
|
||||
static QSyntaxStyle* defaultStyle();
|
||||
|
||||
private:
|
||||
|
||||
QString m_name;
|
||||
|
||||
QMap<
|
||||
QString,
|
||||
QTextCharFormat
|
||||
> m_data;
|
||||
|
||||
bool m_loaded;
|
||||
};
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<style-scheme version="1.0" name="Default">
|
||||
<style name="Text" foreground="#000000" background="#ffffff"/>
|
||||
<style name="Link" foreground="#0000ff"/>
|
||||
<style name="Selection" foreground="#eff0f1" background="#3daee9"/>
|
||||
<style name="LineNumber" foreground="#6272a4"/>
|
||||
<style name="SearchResult" background="#ffef0b"/>
|
||||
<style name="SearchScope" background="#2d5c76"/>
|
||||
<style name="Parentheses" foreground="#ff0000" background="#b4eeb4"/>
|
||||
<style name="ParenthesesMismatch" background="#ff00ff"/>
|
||||
<style name="AutoComplete" foreground="#000080" background="#c0c0ff"/>
|
||||
<style name="CurrentLine" background="#eeeeee"/>
|
||||
<style name="CurrentLineNumber" foreground="#808080" bold="true"/>
|
||||
<style name="Occurrences" background="#b4b4b4"/>
|
||||
<style name="Occurrences.Unused" underlineColor="#808000" underlineStyle="SingleUnderline"/>
|
||||
<style name="Occurrences.Rename" background="#ff6464"/>
|
||||
<style name="Number" foreground="#000080"/>
|
||||
<style name="String" foreground="#008000"/>
|
||||
<style name="Type" foreground="#800080"/>
|
||||
<style name="Local" foreground="#092e64"/>
|
||||
<style name="Global" foreground="#ce5c00"/>
|
||||
<style name="Field" foreground="#800000"/>
|
||||
<style name="Static" foreground="#800080"/>
|
||||
<style name="VirtualMethod" foreground="#00677c" background="#ffffff" italic="true"/>
|
||||
<style name="Function" foreground="#00677c" background="#ffffff"/>
|
||||
<style name="Keyword" foreground="#808000"/>
|
||||
<style name="PrimitiveType" foreground="#808000"/>
|
||||
<style name="Operator"/>
|
||||
<style name="Overloaded Operator"/>
|
||||
<style name="Preprocessor" foreground="#000080"/>
|
||||
<style name="Label" foreground="#800000"/>
|
||||
<style name="Comment" foreground="#008000"/>
|
||||
<style name="Doxygen.Comment" foreground="#000080"/>
|
||||
<style name="Doxygen.Tag" foreground="#0000ff"/>
|
||||
<style name="VisualWhitespace" foreground="#c0c0c0"/>
|
||||
<style name="QmlLocalId" foreground="#000000" background="#ffffff" italic="true"/>
|
||||
<style name="QmlExternalId" foreground="#000080" background="#ffffff" italic="true"/>
|
||||
<style name="QmlTypeId" foreground="#800080"/>
|
||||
<style name="QmlRootObjectProperty" foreground="#000000" background="#ffffff" italic="true"/>
|
||||
<style name="QmlScopeObjectProperty" foreground="#000000" background="#ffffff" italic="true"/>
|
||||
<style name="QmlExternalObjectProperty" foreground="#000080" background="#ffffff" italic="true"/>
|
||||
<style name="JsScopeVar" foreground="#2985c7" background="#ffffff" italic="true"/>
|
||||
<style name="JsImportVar" foreground="#0055af" background="#ffffff" italic="true"/>
|
||||
<style name="JsGlobalVar" foreground="#0055af" background="#ffffff" italic="true"/>
|
||||
<style name="QmlStateName" foreground="#000000" background="#ffffff" italic="true"/>
|
||||
<style name="Binding" foreground="#800000"/>
|
||||
<style name="DisabledCode" background="#efefef"/>
|
||||
<style name="AddedLine" foreground="#00aa00"/>
|
||||
<style name="RemovedLine" foreground="#ff0000"/>
|
||||
<style name="DiffFile" foreground="#000080"/>
|
||||
<style name="DiffLocation" foreground="#0000ff"/>
|
||||
<style name="DiffFileLine" background="#ffff00"/>
|
||||
<style name="DiffContextLine" background="#afd7e7"/>
|
||||
<style name="DiffSourceLine" background="#ffdfdf"/>
|
||||
<style name="DiffSourceChar" background="#ffafaf"/>
|
||||
<style name="DiffDestLine" background="#dfffdf"/>
|
||||
<style name="DiffDestChar" background="#afffaf"/>
|
||||
<style name="LogChangeLine" foreground="#c00000"/>
|
||||
<style name="Warning" underlineColor="#ffbe00" underlineStyle="SingleUnderline"/>
|
||||
<style name="WarningContext" underlineColor="#ffbe00" underlineStyle="DotLine"/>
|
||||
<style name="Error" underlineColor="#ff0000" underlineStyle="SingleUnderline"/>
|
||||
<style name="ErrorContext" underlineColor="#ff0000" underlineStyle="DotLine"/>
|
||||
<style name="Declaration" bold="true"/>
|
||||
<style name="FunctionDefinition"/>
|
||||
<style name="OutputArgument" italic="true"/>
|
||||
</style-scheme>
|
|
@ -0,0 +1,66 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<style-scheme version="1.0" name="Dracula">
|
||||
<style name="Text" foreground="#f8f8f2" background="#282a36"/>
|
||||
<style name="Link" foreground="#8be9fd" underlineStyle="SingleUnderline"/>
|
||||
<style name="Selection" background="#44475a"/>
|
||||
<style name="LineNumber" foreground="#6272a4"/>
|
||||
<style name="SearchResult" foreground="#d57544" bold="true"/>
|
||||
<style name="SearchScope" foreground="#000000" background="#f8f8f2"/>
|
||||
<style name="Parentheses" foreground="#f8f8f2" bold="true"/>
|
||||
<style name="ParenthesesMismatch" foreground="#f8f8f2"/>
|
||||
<style name="AutoComplete" foreground="#f8f8f2"/>
|
||||
<style name="CurrentLine" foreground="#000000" background="#383b4c"/>
|
||||
<style name="CurrentLineNumber" foreground="#f8f8f2"/>
|
||||
<style name="Occurrences" foreground="#000000" background="#f8f8f2"/>
|
||||
<style name="Occurrences.Unused" foreground="#f8f8f2"/>
|
||||
<style name="Occurrences.Rename" foreground="#000000" background="#f8f8f2"/>
|
||||
<style name="Number" foreground="#bd93f9"/>
|
||||
<style name="String" foreground="#f1fa8c"/>
|
||||
<style name="Type" foreground="#7ce4fb"/>
|
||||
<style name="Local" foreground="#ffffff"/>
|
||||
<style name="Global" foreground="#ffb86c"/>
|
||||
<style name="Field" foreground="#ffffff"/>
|
||||
<style name="Static" foreground="#ffb86c"/>
|
||||
<style name="VirtualMethod" foreground="#50fa7b" italic="true"/>
|
||||
<style name="Function" foreground="#50fa7b"/>
|
||||
<style name="Keyword" foreground="#ff79c6" bold="true"/>
|
||||
<style name="PrimitiveType" foreground="#7ce4fb" italic="true"/>
|
||||
<style name="Operator" foreground="#ffffff"/>
|
||||
<style name="Overloaded Operator"/>
|
||||
<style name="Preprocessor" foreground="#ff79c6"/>
|
||||
<style name="Label" foreground="#ffb86c"/>
|
||||
<style name="Comment" foreground="#6272a4" bold="true"/>
|
||||
<style name="Doxygen.Comment" foreground="#6272a4"/>
|
||||
<style name="Doxygen.Tag" foreground="#6272a4" bold="true"/>
|
||||
<style name="VisualWhitespace" foreground="#6272a4"/>
|
||||
<style name="QmlLocalId" foreground="#50fa7b" italic="true"/>
|
||||
<style name="QmlExternalId" foreground="#ffb86c" italic="true"/>
|
||||
<style name="QmlTypeId" foreground="#8be9fd"/>
|
||||
<style name="QmlRootObjectProperty" foreground="#50fa7b" italic="true"/>
|
||||
<style name="QmlScopeObjectProperty" foreground="#50fa7b" italic="true"/>
|
||||
<style name="QmlExternalObjectProperty" foreground="#ffb86c" italic="true"/>
|
||||
<style name="JsScopeVar" foreground="#bd93f9" italic="true"/>
|
||||
<style name="JsImportVar" foreground="#8be9fd" italic="true"/>
|
||||
<style name="JsGlobalVar" foreground="#8be9fd" italic="true"/>
|
||||
<style name="QmlStateName" foreground="#50fa7b" italic="true"/>
|
||||
<style name="Binding" foreground="#ff79c6"/>
|
||||
<style name="DisabledCode" foreground="#6272a4"/>
|
||||
<style name="AddedLine" foreground="#50fa7b"/>
|
||||
<style name="RemovedLine" foreground="#ff5555"/>
|
||||
<style name="DiffFile" foreground="#8be9fd"/>
|
||||
<style name="DiffLocation" foreground="#ffb86c"/>
|
||||
<style name="DiffFileLine" foreground="#282a36" background="#f1fa8c"/>
|
||||
<style name="DiffContextLine" foreground="#282a36" background="#8be9fd"/>
|
||||
<style name="DiffSourceLine" background="#ff5555"/>
|
||||
<style name="DiffSourceChar" background="#cc2222"/>
|
||||
<style name="DiffDestLine" foreground="#282a36" background="#50fa7b"/>
|
||||
<style name="DiffDestChar" foreground="#282a36" background="#1dc748"/>
|
||||
<style name="LogChangeLine" foreground="#ff5555"/>
|
||||
<style name="Warning" underlineColor="#ffb86c" underlineStyle="SingleUnderline"/>
|
||||
<style name="WarningContext" underlineColor="#ffb86c" underlineStyle="DotLine"/>
|
||||
<style name="Error" underlineColor="#ff5555" underlineStyle="SingleUnderline"/>
|
||||
<style name="ErrorContext" underlineColor="#ff5555" underlineStyle="DotLine"/>
|
||||
<style name="Declaration" bold="true"/>
|
||||
<style name="FunctionDefinition"/>
|
||||
<style name="OutputArgument" italic="true"/>
|
||||
</style-scheme>
|
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<root>
|
||||
<section name="Keyword">
|
||||
<name>break</name>
|
||||
<name>continue</name>
|
||||
<name>do</name>
|
||||
<name>for</name>
|
||||
<name>while</name>
|
||||
<name>if</name>
|
||||
<name>else</name>
|
||||
<name>def</name>
|
||||
<name>import</name>
|
||||
<name>return</name>
|
||||
<name>class</name>
|
||||
<name>in</name>
|
||||
<name>is</name>
|
||||
<name>not</name>
|
||||
<name>or</name>
|
||||
<name>and</name>
|
||||
<name>enumerate</name>
|
||||
</section>
|
||||
<section name="Function">
|
||||
<name>min</name>
|
||||
<name>max</name>
|
||||
<name>len</name>
|
||||
</section>
|
||||
<section name="PrimitiveType">
|
||||
<name>float</name>
|
||||
<name>int</name>
|
||||
<name>bool</name>
|
||||
<name>True</name>
|
||||
<name>False</name>
|
||||
<name>str</name>
|
||||
<name>unicode</name>
|
||||
<name>byte</name>
|
||||
<name>set</name>
|
||||
<name>dict</name>
|
||||
</section>
|
||||
</root>
|
|
@ -0,0 +1,138 @@
|
|||
<h1 align="center"> WingSummer.WingHexPy</h1>
|
||||
|
||||
<p align="center">
|
||||
<img alt="WingHexPy" src="/img/icon.png">
|
||||
<p align="center">WingHexPy</p>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<img alt="作者" src="authorband.svg">
|
||||
<img alt="开源协议" src="olband.svg">
|
||||
<img alt="商用协议" src="clband.svg">
|
||||
</p>
|
||||
|
||||
- 开源不易,给个 Star 或者 [捐助](#捐助) 吧
|
||||
|
||||
## WingHexPy
|
||||
|
||||
### 使用声明
|
||||
|
||||
1. 开发本软件目的是让羽云十六进制编辑器具有强大的脚本分析功能,使用 C++ 的 Python 拓展来弥补羽云十六进制编辑器相对于 010 Editor 的不足之处。
|
||||
2. 本软件仅供学习交流使用,不得私自用于商业用途。如需将本软件某些部分用于商业用途,必须找我购买商业授权,价格私聊。
|
||||
3. 本人学生,由于本软件是用我的业余时间编写,不能及时修复 Bug 或者提供技术支持,请见谅。
|
||||
4. 本人非计算机专业,编写程序难免有 Bug ,欢迎提交 PR 。
|
||||
|
||||
### 参与贡献
|
||||
|
||||
1. 如果您有想参与本软件代码开发递交,请在 pull request 联系我。
|
||||
2. 本项目支持捐助,如有意愿请到本仓库通过微信或者支付宝的方式进行,一瓶水的价钱足以提高我的维护该项目的热情,感谢大家的支持。
|
||||
3. 如果您想提交修复或者增进程序的代码,请在 pull request 递交。
|
||||
4. 任何成功参与代码 Bug 修复以及增进程序功能的同志和 Sponsor ,都会在本仓库 ReadMe 和附属说明文件中体现,您如果是其中之一,本人可以按照您合理的意愿来进行说明。
|
||||
|
||||
**加入我们并不意味着就是代码的维护,你可以选择下列一项或多项进行参与:**
|
||||
|
||||
1. 代码维护:实现新功能或修复 BUG ,对代码进行维护和升级。
|
||||
2. 文档编辑:主要是接口文档和教程需要撰写编辑,这很重要。
|
||||
3. 参与讨论:主要是讨论本项目未来发展和方向等。
|
||||
4. 编写插件:一起增强该软件的功能。
|
||||
|
||||
### 协议
|
||||
|
||||
  本软件如果用于非商业用途,采用`WingSummer OpenSource Lincense`协议,对应的协议内容在仓库`OpenSource-LICENSE`文件。 **没有我的任何授权,不得将该软件用于任何形式的商业用途,包括我改良的部分,除非你直接使用原组件,不限于商业二次开发、换 UI 套壳、二手转卖等,我不允许任何人随意把我当作免费劳动力作为赚钱的工具!** 我的初衷是让 Linux 的生态更加完整,早日让祖国推动操作系统国产化。我不希望“吸血鬼”们利益归自己,脏活累活给开源,都那么理所当然,开源就是这么被败坏的。我不希望因为版权的事情牵扯了大量的精力。
|
||||
|
||||
  如果你想将本软件或者本软件的部分代码用于商业用途,必须亲自咨询我,商讨商业授权相关事宜。如果得到授权则采用`WingSummer Commerical License`协议,也就是本仓库的`Commerical-LICENSE`文件的内容。
|
||||
|
||||
### issue 前必读
|
||||
|
||||
  如果你有任何形式的建议,在提交 issue 之前,请一定要阅读下面的声明,以免浪费我们双方宝贵的时间:
|
||||
|
||||
1. 本人不考虑多语言支持,主要是没时间和资金。由于本人是中国人,本人不考虑其他语言使用者。但如果使用其他语言,如果你有语言包,只需要简单的替换文件即可。
|
||||
2. 本人不会将此插件单独打包为 deb ,会捆绑在“羽云十六进制编辑器”的安装包内供大家使用。
|
||||
3. 本人不考虑主题 UI 层面的问题,开发本插件与窗体相关一切采用 DTK 原生样式,觉得丑找官方,或者自己写个样式编译加载。
|
||||
|
||||
  上面一切的一切,如果你是志同道合的开源贡献者,欢迎 fork 我的仓库进行相应的维护!
|
||||
|
||||
### 有关 QCodeEditor
|
||||
|
||||
  本软件自带的编写脚本编辑器基于`QCodeEditor`,我对该软件进行的删减和修改以适配该插件的功能。如下是原仓库的必要说明,详情请点击 [此链接](https://github.com/Megaxela/QCodeEditor) :
|
||||
|
||||
---
|
||||
|
||||
# Qt Code Editor Widget
|
||||
It's a widget for editing/viewing code.
|
||||
|
||||
This project uses a resource named `qcodeeditor_resources.qrc`. The main application
|
||||
must not use a resource file with the same name.
|
||||
|
||||
(It's not a project from a Qt example.)
|
||||
|
||||
## Requirements
|
||||
0. C++11 featured compiler.
|
||||
0. Qt 5.
|
||||
|
||||
## Abilities
|
||||
1. Auto parentheses.
|
||||
1. Different highlight rules.
|
||||
1. Auto indentation.
|
||||
1. Replace tabs with spaces.
|
||||
1. GLSL completion rules.
|
||||
1. GLSL highlight rules.
|
||||
1. C++ highlight rules.
|
||||
1. XML highlight rules.
|
||||
1. JSON highligh rules.
|
||||
1. Frame selection.
|
||||
1. Qt Creator styles.
|
||||
|
||||
## LICENSE
|
||||
|
||||
<img align="right" src="http://opensource.org/trademarks/opensource/OSI-Approved-License-100x137.png">
|
||||
|
||||
Library is licensed under the [MIT License](https://opensource.org/licenses/MIT)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
---
|
||||
|
||||
## 效果图
|
||||
|
||||
<p align="center">
|
||||
<img alt="效果图" src="">
|
||||
<p align="center">WingHexPy</p>
|
||||
</p>
|
||||
|
||||
## 捐助
|
||||
|
||||
**<p align="center">您的每一份支持都将是本项目推进的强大动力,十分感谢您的支持</p>**
|
||||
|
||||
<p align="center">
|
||||
|
||||
<img alt="支付宝" src="WingHexExplorer/支付宝捐助.jpg" height=50% width=50%>
|
||||
<p align="center">感谢支持</p>
|
||||
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<img alt="微信" src="WingHexExplorer/微信捐助.png" height=50% width=50%>
|
||||
<p align="center">感谢支持</p>
|
||||
|
||||
</p>
|
||||
|
||||
## 有关仓库
|
||||
|
||||
## WIKI
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"Keys" : [ ]
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
#-------------------------------------------------
|
||||
#
|
||||
# Project created by QtCreator 2022-07-12T10:53:26
|
||||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
QT += core gui dtkwidget
|
||||
|
||||
TARGET = WingHexPy
|
||||
TEMPLATE = lib
|
||||
CONFIG += plugin
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
|
||||
# The following define makes your compiler emit warnings if you use
|
||||
# any feature of Qt which has been marked as deprecated (the exact warnings
|
||||
# depend on your compiler). Please consult the documentation of the
|
||||
# deprecated API in order to know how to port your code away from it.
|
||||
DEFINES += QT_DEPRECATED_WARNINGS
|
||||
|
||||
# You can also make your code fail to compile if you use deprecated APIs.
|
||||
# In order to do so, uncomment the following line.
|
||||
# You can also select to disable deprecated APIs only up to a certain version of Qt.
|
||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
SOURCES += \
|
||||
winghexpy.cpp \
|
||||
plginterface.cpp \
|
||||
QCodeEditor/QCodeEditor.cpp \
|
||||
QCodeEditor/QFramedTextAttribute.cpp \
|
||||
QCodeEditor/QLineNumberArea.cpp \
|
||||
QCodeEditor/QPythonCompleter.cpp \
|
||||
QCodeEditor/QPythonHighlighter.cpp \
|
||||
QCodeEditor/QStyleSyntaxHighlighter.cpp \
|
||||
QCodeEditor/QSyntaxStyle.cpp \
|
||||
QCodeEditor/QLanguage.cpp \
|
||||
scriptwindow.cpp
|
||||
|
||||
HEADERS += \
|
||||
winghexpy.h \
|
||||
plginterface.h\
|
||||
../WingHexExplorer/wing-hex-explorer.sourcecode/WingHexExplorer/plugin/iwingplugin.h \
|
||||
QCodeEditor/QCodeEditor.hpp \
|
||||
QCodeEditor/QFramedTextAttribute.hpp \
|
||||
QCodeEditor/QLineNumberArea.hpp \
|
||||
QCodeEditor/QPythonCompleter.hpp \
|
||||
QCodeEditor/QPythonHighlighter.hpp \
|
||||
QCodeEditor/QStyleSyntaxHighlighter.hpp \
|
||||
QCodeEditor/QSyntaxStyle.hpp \
|
||||
QCodeEditor/QHighlightBlockRule.hpp \
|
||||
QCodeEditor/QHighlightRule.hpp \
|
||||
QCodeEditor/QLanguage.hpp \
|
||||
scriptwindow.h
|
||||
|
||||
DISTFILES += WingHexPy.json
|
||||
|
||||
TRANSLATIONS += \
|
||||
$$PWD/WingHexPy.ts
|
||||
|
||||
INCLUDEPATH += -I /usr/include/python3.7
|
||||
LIBS += /usr/lib/x86_64-linux-gnu/libpython3.7m.so.1
|
||||
|
||||
FORMS +=
|
||||
|
||||
RESOURCES += \
|
||||
resources.qrc
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="130" height="20" role="img" aria-label="Author: Wingsummer"><title>Author: Wingsummer</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="130" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="47" height="20" fill="#555"/><rect x="47" width="83" height="20" fill="#97ca00"/><rect width="130" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="245" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="370">Author</text><text x="245" y="140" transform="scale(.1)" fill="#fff" textLength="370">Author</text><text aria-hidden="true" x="875" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="730">Wingsummer</text><text x="875" y="140" transform="scale(.1)" fill="#fff" textLength="730">Wingsummer</text></g></svg>
|
After Width: | Height: | Size: 1.1 KiB |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="318" height="20" role="img" aria-label="Commerical License: WingSummer Commerical License"><title>Commerical License: WingSummer Commerical License</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="318" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="119" height="20" fill="#555"/><rect x="119" width="199" height="20" fill="#e05d44"/><rect width="318" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="605" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="1090">Commerical License</text><text x="605" y="140" transform="scale(.1)" fill="#fff" textLength="1090">Commerical License</text><text aria-hidden="true" x="2175" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="1890">WingSummer Commerical License</text><text x="2175" y="140" transform="scale(.1)" fill="#fff" textLength="1890">WingSummer Commerical License</text></g></svg>
|
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 5.7 KiB |
After Width: | Height: | Size: 4.7 KiB |
After Width: | Height: | Size: 53 KiB |
After Width: | Height: | Size: 77 KiB |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="322" height="20" role="img" aria-label="OpenSource License: WingSummer OpenSource License"><title>OpenSource License: WingSummer OpenSource License</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="322" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="121" height="20" fill="#555"/><rect x="121" width="201" height="20" fill="#e05d44"/><rect width="322" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="615" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="1110">OpenSource License</text><text x="615" y="140" transform="scale(.1)" fill="#fff" textLength="1110">OpenSource License</text><text aria-hidden="true" x="2205" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="1910">WingSummer OpenSource License</text><text x="2205" y="140" transform="scale(.1)" fill="#fff" textLength="1910">WingSummer OpenSource License</text></g></svg>
|
After Width: | Height: | Size: 1.3 KiB |
|
@ -0,0 +1,289 @@
|
|||
#ifndef PLGINTERFACE_H
|
||||
#define PLGINTERFACE_H
|
||||
|
||||
#include "../WingHexExplorer/wing-hex-explorer.sourcecode/WingHexExplorer/plugin/iwingplugin.h"
|
||||
#include <Python.h>
|
||||
#include <QObject>
|
||||
|
||||
#define INFOLOG(msg) "<font color=\"green\">" + msg + "</font><br />"
|
||||
#define ERRLOG(msg) "<font color=\"red\">" + msg + "</font><br />"
|
||||
#define WARNLOG(msg) "<font color=\"yellow\">" + msg + "</font><br />"
|
||||
|
||||
class PlgInterface : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit PlgInterface(IWingPlugin *parent);
|
||||
|
||||
signals:
|
||||
void log(QString message);
|
||||
|
||||
public:
|
||||
bool init();
|
||||
|
||||
bool RunPyFile(QString filename);
|
||||
bool RunPyText(QString content);
|
||||
|
||||
private slots:
|
||||
//--------------reader--------------
|
||||
|
||||
static PyObject *currentDoc(PyObject *self, PyObject *args); // int
|
||||
static PyObject *currentDocFilename(PyObject *self,
|
||||
PyObject *args); // QString
|
||||
|
||||
// document
|
||||
static PyObject *isReadOnly(PyObject *self, PyObject *args); // bool
|
||||
static PyObject *isKeepSize(PyObject *self, PyObject *args); // bool
|
||||
static PyObject *isLocked(PyObject *self, PyObject *args); // bool
|
||||
|
||||
static PyObject *documentLines(PyObject *self, PyObject *args); // quint64
|
||||
static PyObject *documentBytes(PyObject *self, PyObject *args); // quint64
|
||||
static PyObject *currentPos(PyObject *self, PyObject *args); // HexPosition
|
||||
static PyObject *selectionPos(PyObject *self, PyObject *args); // HexPosition
|
||||
static PyObject *currentRow(PyObject *self, PyObject *args); // quint64
|
||||
static PyObject *currentColumn(PyObject *self, PyObject *args); // quint64
|
||||
static PyObject *currentOffset(PyObject *self, PyObject *args); // quint64
|
||||
static PyObject *selectlength(PyObject *self, PyObject *args); // quint64
|
||||
|
||||
static PyObject *stringVisible(PyObject *self, PyObject *args); // bool
|
||||
static PyObject *addressVisible(PyObject *self, PyObject *args); // bool
|
||||
static PyObject *headerVisible(PyObject *self, PyObject *args); // bool
|
||||
static PyObject *addressBase(PyObject *self, PyObject *args); // quint64
|
||||
static PyObject *isModified(PyObject *self, PyObject *args); // bool
|
||||
|
||||
static PyObject *isEmpty(PyObject *self, PyObject *args); // bool
|
||||
static PyObject *atEnd(PyObject *self, PyObject *args); // bool
|
||||
static PyObject *canUndo(PyObject *self, PyObject *args); // bool
|
||||
static PyObject *canRedo(PyObject *self, PyObject *args); // bool
|
||||
|
||||
static PyObject *copy(PyObject *self,
|
||||
PyObject *args); // void : bool hex = false
|
||||
static PyObject *read(PyObject *self,
|
||||
PyObject *args); // QByteArray : qint64 offset, int len
|
||||
static PyObject *
|
||||
searchForward(PyObject *self,
|
||||
PyObject *args); // qint64 : qint64 begin, const QByteArray &ba
|
||||
|
||||
static PyObject *
|
||||
searchBackward(PyObject *self,
|
||||
PyObject *args); // qint64 : qint64 begin, const QByteArray &ba
|
||||
|
||||
static PyObject *findAllBytes(PyObject *self, PyObject *args);
|
||||
// void : qlonglong begin, qlonglong end, QByteArray b,
|
||||
// QList<quint64>&results, int maxCount = -1
|
||||
|
||||
// render
|
||||
static PyObject *documentLastLine(PyObject *self, PyObject *args); // quint64
|
||||
static PyObject *documentLastColumn(PyObject *self, PyObject *args); // int
|
||||
|
||||
// metadata
|
||||
static PyObject *lineHasMetadata(PyObject *self,
|
||||
PyObject *args); // bool : quint64 line
|
||||
static PyObject *getMetadatas(
|
||||
PyObject *self,
|
||||
PyObject *args); // QList<HexMetadataAbsoluteItem> : qint64 offset
|
||||
static PyObject *
|
||||
getMetaLine(PyObject *self,
|
||||
PyObject *args); // HexLineMetadata : quint64 line
|
||||
|
||||
// bookmark
|
||||
static PyObject *lineHasBookMark(PyObject *self,
|
||||
PyObject *args); // bool : quint64 line
|
||||
static PyObject *
|
||||
getsBookmarkPos(PyObject *self,
|
||||
PyObject *args); // QList<qint64> : quint64 line
|
||||
static PyObject *bookMark(PyObject *self,
|
||||
PyObject *args); // BookMark : qint64 pos
|
||||
static PyObject *bookMarkComment(PyObject *self,
|
||||
PyObject *args); // QString : qint64 pos
|
||||
static PyObject *
|
||||
getBookMarks(PyObject *self,
|
||||
PyObject *args); // void : QList<BookMark> &bookmarks
|
||||
static PyObject *existBookMark(PyObject *self,
|
||||
PyObject *args); // bool : qint64 pos
|
||||
|
||||
// extension
|
||||
static PyObject *getOpenFiles(PyObject *self,
|
||||
PyObject *args); // QList<QString>
|
||||
static PyObject *getSupportedEncodings(PyObject *self,
|
||||
PyObject *args); // QStringList
|
||||
static PyObject *currentEncoding(PyObject *self, PyObject *args); // QString
|
||||
|
||||
//--------------controller--------------
|
||||
|
||||
// document
|
||||
static PyObject *
|
||||
switchDocument(PyObject *self,
|
||||
PyObject *args); // bool : int index, bool gui = false
|
||||
static PyObject *setLockedFile(PyObject *self,
|
||||
PyObject *args); // bool : bool b
|
||||
static PyObject *setKeepSize(PyObject *self,
|
||||
PyObject *args); // bool : bool b
|
||||
static PyObject *setStringVisible(PyObject *self,
|
||||
PyObject *args); // void : bool b
|
||||
static PyObject *setAddressVisible(PyObject *self,
|
||||
PyObject *args); // void : bool b
|
||||
static PyObject *setHeaderVisible(PyObject *self,
|
||||
PyObject *args); // void : bool b
|
||||
static PyObject *setAddressBase(PyObject *self,
|
||||
PyObject *args); // void : quint64 base
|
||||
|
||||
static PyObject *undo(PyObject *self, PyObject *args); // void
|
||||
static PyObject *redo(PyObject *self, PyObject *args); // void
|
||||
static PyObject *cut(PyObject *self,
|
||||
PyObject *args); // bool : bool hex = false
|
||||
static PyObject *paste(PyObject *self,
|
||||
PyObject *args); // void : bool hex = false
|
||||
static PyObject *
|
||||
insert(PyObject *self,
|
||||
PyObject *args); // bool : qint64 offset, const QByteArray &data
|
||||
static PyObject *
|
||||
replace(PyObject *self,
|
||||
PyObject *args); // bool : qint64 offset, const QByteArray &data
|
||||
static PyObject *remove(PyObject *self,
|
||||
PyObject *args); // bool : qint64 offset, int len
|
||||
|
||||
// cursor
|
||||
static PyObject *moveTo(PyObject *self,
|
||||
PyObject *args); // void:
|
||||
// quint64 line, int column, int nibbleindex
|
||||
// qint64 offset
|
||||
static PyObject *
|
||||
select(PyObject *self,
|
||||
PyObject *args); // void : quint64 line, int column, int nibbleindex
|
||||
// qint64 offset, int length
|
||||
static PyObject *
|
||||
selectOffset(PyObject *self,
|
||||
PyObject *args); // void : qint64 offset, int length
|
||||
static PyObject *setInsertionMode(PyObject *self,
|
||||
PyObject *args); // void : bool isinsert
|
||||
static PyObject *enabledCursor(PyObject *self,
|
||||
PyObject *args); // void : bool b
|
||||
|
||||
// metadata
|
||||
static PyObject *metadata(PyObject *self, PyObject *args);
|
||||
// bool : qint64 begin, qint64 end, const QColor &fgcolor,
|
||||
// const QColor &bgcolor, const QString &comment
|
||||
static PyObject *removeMetadata(PyObject *self,
|
||||
PyObject *args); // bool : qint64 offset
|
||||
static PyObject *clearMeta(PyObject *self,
|
||||
PyObject *args); // bool
|
||||
static PyObject *color(PyObject *self,
|
||||
PyObject *args); // bool
|
||||
// quint64 line, int start, int length, const QColor &fgcolor,
|
||||
// const QColor &bgcolor
|
||||
static PyObject *foreground(PyObject *self,
|
||||
PyObject *args); // bool
|
||||
// quint64 line, int start, int length, const QColor &fgcolor
|
||||
static PyObject *background(PyObject *self,
|
||||
PyObject *args); // bool
|
||||
// quint64 line, int start, int length, const QColor &bgcolor
|
||||
static PyObject *comment(PyObject *self,
|
||||
PyObject *args); // bool
|
||||
// quint64 line, int start, int length, const QString &comment
|
||||
static PyObject *
|
||||
applyMetas(PyObject *self,
|
||||
PyObject *args); // void : QList<HexMetadataAbsoluteItem> metas
|
||||
static PyObject *setMetaVisible(PyObject *self,
|
||||
PyObject *args); // bool : bool b
|
||||
static PyObject *setMetafgVisible(PyObject *self,
|
||||
PyObject *args); // void : bool b
|
||||
static PyObject *setMetabgVisible(PyObject *self,
|
||||
PyObject *args); // void : bool b
|
||||
static PyObject *setMetaCommentVisible(PyObject *self,
|
||||
PyObject *args); // void : bool b
|
||||
|
||||
// mainwindow
|
||||
static PyObject *newFile(PyObject *self,
|
||||
PyObject *args); // void : bool bigfile = false
|
||||
static PyObject *
|
||||
openFile(PyObject *self,
|
||||
PyObject *args); // ErrFile : QString filename, bool readonly
|
||||
static PyObject *openDriver(PyObject *self,
|
||||
PyObject *args); // ErrFile : QString driver
|
||||
static PyObject *closeFile(PyObject *self,
|
||||
PyObject *args); // ErrFile : int index, bool force
|
||||
static PyObject *saveFile(PyObject *self,
|
||||
PyObject *args); // ErrFile : int index
|
||||
static PyObject *
|
||||
exportFile(PyObject *self,
|
||||
PyObject *args); // ErrFile : QString filename, int index
|
||||
static PyObject *exportFileGUI(PyObject *self,
|
||||
PyObject *args); // void
|
||||
static PyObject *
|
||||
saveasFile(PyObject *self,
|
||||
PyObject *args); // ErrFile : QString filename, int index
|
||||
static PyObject *saveasFileGUI(PyObject *self,
|
||||
PyObject *args); // void
|
||||
static PyObject *closeCurrentFile(PyObject *self,
|
||||
PyObject *args); // ErrFile : bool force
|
||||
static PyObject *saveCurrentFile(PyObject *self,
|
||||
PyObject *args); // ErrFile
|
||||
static PyObject *openFileGUI(PyObject *self,
|
||||
PyObject *args); // void
|
||||
static PyObject *openDriverGUI(PyObject *self,
|
||||
PyObject *args); // void
|
||||
static PyObject *findGUI(PyObject *self,
|
||||
PyObject *args); // void
|
||||
static PyObject *gotoGUI(PyObject *self,
|
||||
PyObject *args); // void
|
||||
static PyObject *fillGUI(PyObject *self,
|
||||
PyObject *args); // void
|
||||
static PyObject *fillzeroGUI(PyObject *self,
|
||||
PyObject *args); // void
|
||||
static PyObject *fillnopGUI(PyObject *self,
|
||||
PyObject *args); // void
|
||||
|
||||
// bookmark
|
||||
static PyObject *
|
||||
addBookMark(PyObject *self,
|
||||
PyObject *args); // bool : qint64 pos, QString comment
|
||||
static PyObject *
|
||||
modBookMark(PyObject *self,
|
||||
PyObject *args); // bool : qint64 pos, QString comment
|
||||
static PyObject *
|
||||
applyBookMarks(PyObject *self,
|
||||
PyObject *args); // void : QList<BookMark> books
|
||||
static PyObject *removeBookMark(PyObject *self,
|
||||
PyObject *args); // bool : qint64 pos
|
||||
static PyObject *clearBookMark(PyObject *self,
|
||||
PyObject *args); // bool
|
||||
|
||||
// workspace
|
||||
static PyObject *
|
||||
openWorkSpace(PyObject *self,
|
||||
PyObject *args); // bool : QString filename, bool readonly
|
||||
static PyObject *
|
||||
setCurrentEncoding(PyObject *self,
|
||||
PyObject *args); // bool : QString encoding
|
||||
|
||||
// extension
|
||||
static PyObject *toast(PyObject *self,
|
||||
PyObject *args); // void : QIcon icon, QString message
|
||||
|
||||
//--------------service--------------
|
||||
|
||||
static PyObject *print(PyObject *self, PyObject *args);
|
||||
static PyObject *errPrint(PyObject *self, PyObject *args);
|
||||
static PyObject *infoPrint(PyObject *self, PyObject *args);
|
||||
static PyObject *warnPrint(PyObject *self, PyObject *args);
|
||||
|
||||
static PyObject *requestControl(PyObject *self,
|
||||
PyObject *args); // bool : int timeout = 1500
|
||||
static PyObject *hasControl(PyObject *self,
|
||||
PyObject *args); // bool
|
||||
static PyObject *requestRelease(PyObject *self, PyObject *args); // bool
|
||||
|
||||
private:
|
||||
static PyMethodDef rEmbMethods[], cEmbMethods[], sEmbMethods[];
|
||||
|
||||
static PyModuleDef WingPlgReader, WingPlgCtl, WingPlgService;
|
||||
static IWingPlugin *plg;
|
||||
static PlgInterface *self;
|
||||
|
||||
private:
|
||||
static PyObject *PyInit_WingPlgReader(void);
|
||||
static PyObject *PyInit_WingPlgCtl(void);
|
||||
static PyObject *PyInit_WingPlgService(void);
|
||||
};
|
||||
|
||||
#endif // PLGINTERFACE_H
|
|
@ -0,0 +1,8 @@
|
|||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file alias="python.xml">QCodeEditor/python.xml</file>
|
||||
<file alias="default_style.xml">QCodeEditor/default_style.xml</file>
|
||||
<file>img/pys.png</file>
|
||||
<file alias="drakula.xml">QCodeEditor/drakula.xml</file>
|
||||
</qresource>
|
||||
</RCC>
|
|
@ -0,0 +1,86 @@
|
|||
#include "scriptwindow.h"
|
||||
#include "../WingHexExplorer/wing-hex-explorer.sourcecode/WingHexExplorer/plugin/iwingplugin.h"
|
||||
#include "QCodeEditor/QPythonCompleter.hpp"
|
||||
#include "QCodeEditor/QPythonHighlighter.hpp"
|
||||
#include <DTitlebar>
|
||||
#include <DWidgetUtil>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
ScriptWindow *ScriptWindow::m_instance = nullptr;
|
||||
|
||||
ScriptWindow *ScriptWindow::instance() {
|
||||
if (m_instance == nullptr) {
|
||||
m_instance = new ScriptWindow;
|
||||
}
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
ScriptWindow::ScriptWindow(DMainWindow *parent) : DMainWindow(parent) {
|
||||
setMinimumSize(QSize(600, 500));
|
||||
|
||||
auto _title = titlebar();
|
||||
auto picon = QIcon(":/img/pys.png");
|
||||
setWindowIcon(picon);
|
||||
_title->setIcon(picon);
|
||||
_title->setTitle(tr("WingHexPyScriptWindow"));
|
||||
|
||||
auto w = new QWidget(this);
|
||||
setCentralWidget(w);
|
||||
auto vlayout = new QVBoxLayout(w);
|
||||
|
||||
m_styles[0] = QSyntaxStyle::defaultStyle();
|
||||
auto darkstyle = new QSyntaxStyle(this);
|
||||
QFile file(":/drakula.xml");
|
||||
if (file.open(QFile::ReadOnly)) {
|
||||
darkstyle->load(file.readAll());
|
||||
file.close();
|
||||
}
|
||||
auto guihelper = DGuiApplicationHelper::instance();
|
||||
connect(guihelper, &DGuiApplicationHelper::themeTypeChanged, this,
|
||||
&ScriptWindow::setTheme);
|
||||
|
||||
m_styles[1] = darkstyle;
|
||||
editor = new QCodeEditor(this);
|
||||
editor->setCompleter(new QPythonCompleter(this));
|
||||
editor->setHighlighter(new QPythonHighlighter);
|
||||
editor->setSyntaxStyle(
|
||||
m_styles[guihelper->themeType() == DGuiApplicationHelper::LightType ? 0
|
||||
: 1]);
|
||||
editor->setWordWrapMode(QTextOption::NoWrap);
|
||||
editor->setTabReplace(true);
|
||||
editor->setAutoIndentation(true);
|
||||
|
||||
vlayout->addWidget(editor);
|
||||
|
||||
PluginMenuInitBegin(menu, "") {
|
||||
PluginMenuAddItemLamba(menu, tr("New"), [=] {
|
||||
|
||||
});
|
||||
}
|
||||
PluginMenuInitEnd();
|
||||
|
||||
_title->setMenu(menu);
|
||||
_title->setFullScreenButtonVisible(true);
|
||||
_title->setSwitchThemeMenuVisible(false);
|
||||
|
||||
PluginToolBarInitBegin(toolbar, "") {
|
||||
PluginToolBarAddLamba(
|
||||
toolbar, QIcon(), [=] {}, tr(""));
|
||||
}
|
||||
PluginToolBarInitEnd();
|
||||
|
||||
addToolBar(toolbar);
|
||||
|
||||
status = new DStatusBar(this);
|
||||
setStatusBar(status);
|
||||
|
||||
Dtk::Widget::moveToCenter(this);
|
||||
}
|
||||
|
||||
void ScriptWindow::setTheme(DGuiApplicationHelper::ColorType theme) {
|
||||
if (theme == DGuiApplicationHelper::LightType) {
|
||||
editor->setSyntaxStyle(m_styles[0]);
|
||||
} else {
|
||||
editor->setSyntaxStyle(m_styles[1]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
#ifndef SCRIPTWINDOW_H
|
||||
#define SCRIPTWINDOW_H
|
||||
|
||||
#include "QCodeEditor/QCodeEditor.hpp"
|
||||
#include "QCodeEditor/QSyntaxStyle.hpp"
|
||||
#include <DGuiApplicationHelper>
|
||||
#include <DMainWindow>
|
||||
#include <DStatusBar>
|
||||
#include <DToolBar>
|
||||
|
||||
DWIDGET_USE_NAMESPACE
|
||||
|
||||
class ScriptWindow : public DMainWindow {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ScriptWindow(DMainWindow *parent = nullptr);
|
||||
static ScriptWindow *instance();
|
||||
|
||||
private:
|
||||
void setTheme(DGuiApplicationHelper::ColorType theme);
|
||||
|
||||
private:
|
||||
QCodeEditor *editor;
|
||||
static ScriptWindow *m_instance;
|
||||
QSyntaxStyle *m_styles[2];
|
||||
DToolBar *toolbar;
|
||||
DStatusBar *status;
|
||||
DMenu *menu;
|
||||
};
|
||||
|
||||
#endif // SCRIPTWINDOW_H
|
|
@ -0,0 +1,86 @@
|
|||
#include "winghexpy.h"
|
||||
#include "scriptwindow.h"
|
||||
#include <QFileDialog>
|
||||
|
||||
WingHexPy::WingHexPy(QObject *parent) { Q_UNUSED(parent) }
|
||||
|
||||
WingHexPy::~WingHexPy() {}
|
||||
|
||||
#if QT_VERSION < 0x050000
|
||||
Q_EXPORT_PLUGIN2(WingHexPy, GenericPlugin)
|
||||
#endif // QT_VERSION < 0x050000
|
||||
|
||||
int WingHexPy::sdkVersion() { return SDKVERSION; }
|
||||
|
||||
QString WingHexPy::signature() { return WINGSUMMER; }
|
||||
|
||||
bool WingHexPy::init(QList<WingPluginInfo> loadedplugin) {
|
||||
Q_UNUSED(loadedplugin);
|
||||
|
||||
plgint = new PlgInterface(this);
|
||||
if (!plgint->init()) {
|
||||
return false;
|
||||
}
|
||||
connect(plgint, &PlgInterface::log, this, &WingHexPy::log);
|
||||
|
||||
PluginMenuInitBegin(menu, tr("WingHexPy")) {
|
||||
PluginMenuAddItemLamba(menu, tr("Run File"), [=] {
|
||||
auto py = QFileDialog::getOpenFileName(nullptr, tr("ChooseFile"),
|
||||
QString(), "Py (*.py)");
|
||||
if (py.isEmpty())
|
||||
return;
|
||||
this->RunPyFile(py);
|
||||
});
|
||||
}
|
||||
PluginMenuInitEnd();
|
||||
|
||||
txt = new QTextBrowser;
|
||||
PluginDockWidgetInit(dw, txt, tr("WingHexPyConsole"), "WingHexPyConsole");
|
||||
|
||||
PluginToolBarInitBegin(tb, "WingHexPy") {
|
||||
PluginToolBarAddLamba(
|
||||
tb, QIcon(":/img/pys.png"), [=] { ScriptWindow::instance()->show(); },
|
||||
tr("ScriptWindow"));
|
||||
}
|
||||
PluginToolBarInitEnd();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WingHexPy::RunPyFile(QString filename) {
|
||||
return plgint->RunPyFile(filename);
|
||||
}
|
||||
|
||||
bool WingHexPy::RunPyText(QString content) {
|
||||
return plgint->RunPyText(content);
|
||||
}
|
||||
|
||||
void WingHexPy::unload() { Py_Finalize(); }
|
||||
|
||||
void WingHexPy::plugin2MessagePipe(WingPluginMessage type,
|
||||
QList<QVariant> msg) {
|
||||
Q_UNUSED(type);
|
||||
Q_UNUSED(msg);
|
||||
}
|
||||
|
||||
QString WingHexPy::pluginName() { return tr("WingHexPy"); }
|
||||
|
||||
QString WingHexPy::pluginAuthor() { return WINGSUMMER; }
|
||||
|
||||
QString WingHexPy::pluginComment() {
|
||||
return tr("A useful plugin for python3.7 support.");
|
||||
}
|
||||
|
||||
uint WingHexPy::pluginVersion() { return 1; }
|
||||
|
||||
Qt::DockWidgetArea WingHexPy::registerDockWidgetDockArea() {
|
||||
return Qt::DockWidgetArea::BottomDockWidgetArea;
|
||||
}
|
||||
|
||||
QMenu *WingHexPy::registerMenu() { return menu; }
|
||||
|
||||
QDockWidget *WingHexPy::registerDockWidget() { return dw; }
|
||||
|
||||
QToolBar *WingHexPy::registerToolBar() { return tb; }
|
||||
|
||||
void WingHexPy::log(QString message) { txt->insertHtml(message); }
|
|
@ -0,0 +1,51 @@
|
|||
#ifndef GENERICPLUGIN_H
|
||||
#define GENERICPLUGIN_H
|
||||
|
||||
#include "../WingHexExplorer/wing-hex-explorer.sourcecode/WingHexExplorer/plugin/iwingplugin.h"
|
||||
#include "plginterface.h"
|
||||
#include <Python.h>
|
||||
#include <QTextBrowser>
|
||||
|
||||
class WingHexPy : public IWingPlugin {
|
||||
Q_OBJECT
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
Q_PLUGIN_METADATA(IID IWINGPLUGIN_INTERFACE_IID FILE "WingHexPy.json")
|
||||
#endif // QT_VERSION >= 0x050000
|
||||
|
||||
Q_INTERFACES(IWingPlugin)
|
||||
|
||||
public:
|
||||
WingHexPy(QObject *parent = nullptr);
|
||||
int sdkVersion() override;
|
||||
bool init(QList<WingPluginInfo> loadedplugin) override;
|
||||
~WingHexPy() override;
|
||||
void unload() override;
|
||||
QMenu *registerMenu() override;
|
||||
QToolBar *registerToolBar() override;
|
||||
QDockWidget *registerDockWidget() override;
|
||||
QString pluginName() override;
|
||||
QString pluginAuthor() override;
|
||||
uint pluginVersion() override;
|
||||
QString signature() override;
|
||||
QString pluginComment() override;
|
||||
void plugin2MessagePipe(WingPluginMessage type, QList<QVariant> msg) override;
|
||||
Qt::DockWidgetArea registerDockWidgetDockArea() override;
|
||||
|
||||
public:
|
||||
void log(QString message);
|
||||
|
||||
public:
|
||||
bool RunPyFile(QString filename);
|
||||
bool RunPyText(QString content);
|
||||
|
||||
private:
|
||||
PlgInterface *plgint;
|
||||
QMenu *menu;
|
||||
QToolBar *tb;
|
||||
QDockWidget *dw;
|
||||
|
||||
QTextBrowser *txt;
|
||||
};
|
||||
|
||||
#endif // GENERICPLUGIN_H
|