commit e9ae80694875f869892f13f4fcaf1170a00dea41 Author: toma Date: Wed Nov 25 17:56:58 2009 +0000 Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features. BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdewebdev@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 00000000..b1e30751 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,38 @@ +Quanta Plus (quanta): + Current maintainers: + Eric Laffoon + Andras Mantia + Original authors: + Dmitry Poplavsky + Alexander Yakovlev + + CSS/Frame editor: Luciano Gulmini + PHP Debugger: Linus McCabe + VPL part: + Nicolas Deschildre + Paulo Moura Guedes + + Home page: http://kdewebdev.org + Bug form: http://bugs.kde.org + +Kommander (kommander): + Authors: + Mark Britton + Eric Laffoon + Michal Rudolf + +KXSLDbg (kxsldbg): + Author: Keith Isdale + +KFileReplace: + Maintainer: + Emiliano Gulmini + Andras Mantia + Original author: + François Dupoux + +KImageMapEditor: + Author: Jan Schäfer + +KLinkStatus: + Author: Paulo Moura Guedes \ No newline at end of file diff --git a/COPYING b/COPYING new file mode 100644 index 00000000..ffe677b2 --- /dev/null +++ b/COPYING @@ -0,0 +1,280 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/COPYING-DOCS b/COPYING-DOCS new file mode 100644 index 00000000..4a0fe1c8 --- /dev/null +++ b/COPYING-DOCS @@ -0,0 +1,397 @@ + GNU Free Documentation License + Version 1.2, November 2002 + + + Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + +0. PREAMBLE + +The purpose of this License is to make a manual, textbook, or other +functional and useful document "free" in the sense of freedom: to +assure everyone the effective freedom to copy and redistribute it, +with or without modifying it, either commercially or noncommercially. +Secondarily, this License preserves for the author and publisher a way +to get credit for their work, while not being considered responsible +for modifications made by others. + +This License is a kind of "copyleft", which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + + +1. APPLICABILITY AND DEFINITIONS + +This License applies to any manual or other work, in any medium, that +contains a notice placed by the copyright holder saying it can be +distributed under the terms of this License. Such a notice grants a +world-wide, royalty-free license, unlimited in duration, to use that +work under the conditions stated herein. The "Document", below, +refers to any such manual or work. Any member of the public is a +licensee, and is addressed as "you". You accept the license if you +copy, modify or distribute the work in a way requiring permission +under copyright law. + +A "Modified Version" of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +A "Secondary Section" is a named appendix or a front-matter section of +the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document's overall subject +(or to related matters) and contains nothing that could fall directly +within that overall subject. (Thus, if the Document is in part a +textbook of mathematics, a Secondary Section may not explain any +mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +The "Invariant Sections" are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. If a +section does not fit the above definition of Secondary then it is not +allowed to be designated as Invariant. The Document may contain zero +Invariant Sections. If the Document does not identify any Invariant +Sections then there are none. + +The "Cover Texts" are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. A Front-Cover Text may +be at most 5 words, and a Back-Cover Text may be at most 25 words. + +A "Transparent" copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, that is suitable for revising the document +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup, or absence of markup, has been arranged to thwart +or discourage subsequent modification by readers is not Transparent. +An image format is not Transparent if used for any substantial amount +of text. A copy that is not "Transparent" is called "Opaque". + +Examples of suitable formats for Transparent copies include plain +ASCII without markup, Texinfo input format, LaTeX input format, SGML +or XML using a publicly available DTD, and standard-conforming simple +HTML, PostScript or PDF designed for human modification. Examples of +transparent image formats include PNG, XCF and JPG. Opaque formats +include proprietary formats that can be read and edited only by +proprietary word processors, SGML or XML for which the DTD and/or +processing tools are not generally available, and the +machine-generated HTML, PostScript or PDF produced by some word +processors for output purposes only. + +The "Title Page" means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, "Title Page" means +the text near the most prominent appearance of the work's title, +preceding the beginning of the body of the text. + +A section "Entitled XYZ" means a named subunit of the Document whose +title either is precisely XYZ or contains XYZ in parentheses following +text that translates XYZ in another language. (Here XYZ stands for a +specific section name mentioned below, such as "Acknowledgements", +"Dedications", "Endorsements", or "History".) To "Preserve the Title" +of such a section when you modify the Document means that it remains a +section "Entitled XYZ" according to this definition. + +The Document may include Warranty Disclaimers next to the notice which +states that this License applies to the Document. These Warranty +Disclaimers are considered to be included by reference in this +License, but only as regards disclaiming warranties: any other +implication that these Warranty Disclaimers may have is void and has +no effect on the meaning of this License. + + +2. VERBATIM COPYING + +You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no other +conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +You may also lend copies, under the same conditions stated above, and +you may publicly display copies. + + +3. COPYING IN QUANTITY + +If you publish printed copies (or copies in media that commonly have +printed covers) of the Document, numbering more than 100, and the +Document's license notice requires Cover Texts, you must enclose the +copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a computer-network location from which the general network-using +public has access to download using public-standard network protocols +a complete Transparent copy of the Document, free of added material. +If you use the latter option, you must take reasonably prudent steps, +when you begin distribution of Opaque copies in quantity, to ensure +that this Transparent copy will remain thus accessible at the stated +location until at least one year after the last time you distribute an +Opaque copy (directly or through your agents or retailers) of that +edition to the public. + +It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to give +them a chance to provide you with an updated version of the Document. + + +4. MODIFICATIONS + +You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + +A. Use in the Title Page (and on the covers, if any) a title distinct + from that of the Document, and from those of previous versions + (which should, if there were any, be listed in the History section + of the Document). You may use the same title as a previous version + if the original publisher of that version gives permission. +B. List on the Title Page, as authors, one or more persons or entities + responsible for authorship of the modifications in the Modified + Version, together with at least five of the principal authors of the + Document (all of its principal authors, if it has fewer than five), + unless they release you from this requirement. +C. State on the Title page the name of the publisher of the + Modified Version, as the publisher. +D. Preserve all the copyright notices of the Document. +E. Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices. +F. Include, immediately after the copyright notices, a license notice + giving the public permission to use the Modified Version under the + terms of this License, in the form shown in the Addendum below. +G. Preserve in that license notice the full lists of Invariant Sections + and required Cover Texts given in the Document's license notice. +H. Include an unaltered copy of this License. +I. Preserve the section Entitled "History", Preserve its Title, and add + to it an item stating at least the title, year, new authors, and + publisher of the Modified Version as given on the Title Page. If + there is no section Entitled "History" in the Document, create one + stating the title, year, authors, and publisher of the Document as + given on its Title Page, then add an item describing the Modified + Version as stated in the previous sentence. +J. Preserve the network location, if any, given in the Document for + public access to a Transparent copy of the Document, and likewise + the network locations given in the Document for previous versions + it was based on. These may be placed in the "History" section. + You may omit a network location for a work that was published at + least four years before the Document itself, or if the original + publisher of the version it refers to gives permission. +K. For any section Entitled "Acknowledgements" or "Dedications", + Preserve the Title of the section, and preserve in the section all + the substance and tone of each of the contributor acknowledgements + and/or dedications given therein. +L. Preserve all the Invariant Sections of the Document, + unaltered in their text and in their titles. Section numbers + or the equivalent are not considered part of the section titles. +M. Delete any section Entitled "Endorsements". Such a section + may not be included in the Modified Version. +N. Do not retitle any existing section to be Entitled "Endorsements" + or to conflict in title with any Invariant Section. +O. Preserve any Warranty Disclaimers. + +If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version's license notice. +These titles must be distinct from any other section titles. + +You may add a section Entitled "Endorsements", provided it contains +nothing but endorsements of your Modified Version by various +parties--for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. + + +5. COMBINING DOCUMENTS + +You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice, and that you preserve all their Warranty Disclaimers. + +The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +In the combination, you must combine any sections Entitled "History" +in the various original documents, forming one section Entitled +"History"; likewise combine any sections Entitled "Acknowledgements", +and any sections Entitled "Dedications". You must delete all sections +Entitled "Endorsements". + + +6. COLLECTIONS OF DOCUMENTS + +You may make a collection consisting of the Document and other documents +released under this License, and replace the individual copies of this +License in the various documents with a single copy that is included in +the collection, provided that you follow the rules of this License for +verbatim copying of each of the documents in all other respects. + +You may extract a single document from such a collection, and distribute +it individually under this License, provided you insert a copy of this +License into the extracted document, and follow this License in all +other respects regarding verbatim copying of that document. + + +7. AGGREGATION WITH INDEPENDENT WORKS + +A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, is called an "aggregate" if the copyright +resulting from the compilation is not used to limit the legal rights +of the compilation's users beyond what the individual works permit. +When the Document is included in an aggregate, this License does not +apply to the other works in the aggregate which are not themselves +derivative works of the Document. + +If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one half of +the entire aggregate, the Document's Cover Texts may be placed on +covers that bracket the Document within the aggregate, or the +electronic equivalent of covers if the Document is in electronic form. +Otherwise they must appear on printed covers that bracket the whole +aggregate. + + +8. TRANSLATION + +Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License, and all the license notices in the +Document, and any Warranty Disclaimers, provided that you also include +the original English version of this License and the original versions +of those notices and disclaimers. In case of a disagreement between +the translation and the original version of this License or a notice +or disclaimer, the original version will prevail. + +If a section in the Document is Entitled "Acknowledgements", +"Dedications", or "History", the requirement (section 4) to Preserve +its Title (section 1) will typically require changing the actual +title. + + +9. TERMINATION + +You may not copy, modify, sublicense, or distribute the Document except +as expressly provided for under this License. Any other attempt to +copy, modify, sublicense or distribute the Document is void, and will +automatically terminate your rights under this License. However, +parties who have received copies, or rights, from you under this +License will not have their licenses terminated so long as such +parties remain in full compliance. + + +10. FUTURE REVISIONS OF THIS LICENSE + +The Free Software Foundation may publish new, revised versions +of the GNU Free Documentation License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. See +http://www.gnu.org/copyleft/. + +Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License "or any later version" applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. + + +ADDENDUM: How to use this License for your documents + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and +license notices just after the title page: + + Copyright (c) YEAR YOUR NAME. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.2 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. + A copy of the license is included in the section entitled "GNU + Free Documentation License". + +If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, +replace the "with...Texts." line with this: + + with the Invariant Sections being LIST THEIR TITLES, with the + Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. + +If you have Invariant Sections without Cover Texts, or some other +combination of the three, merge those two alternatives to suit the +situation. + +If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of +free software license, such as the GNU General Public License, +to permit their use in free software. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 00000000..db65ad29 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,19 @@ +Global kdewebdev changelog. For detailed changes see each included +application's own ChangeLog file. + +2008-02-13: kdewebdev 3.5.9 +2006-10-10: kdewebdev 3.5.5 +2006-08-02: kdewebdev 3.5.4 +2006-05-31: kdewebdev 3.5.3 +2006-03-21: kdewebdev 3.5.2 +2006-01-31: kdewebdev 3.5.1 +2005-11-29: kdewebdev 3.5.0 +2005-02-22: kdewebdev 3.4.0 +2005-02-09: kdewebdev 3.4 Beta2 +2005-01-07: kdewebdev 3.4 Beta1 +2004-12-06: kdewebdev 3.4 Alpha1 +2004-08-18: kdewebdev 3.3.0 +2004-08-04: kdewebdev 3.3 RC1 +2004-07-07: kdewebdev 3.3 Beta1 +2004-06-01: kdewebdev 3.3 Alpha1 +2004-05-06: First kdewebdev release - kdewebdev 3.3 Bleeding Edge 2 \ No newline at end of file diff --git a/INSTALL b/INSTALL new file mode 100644 index 00000000..02a4a074 --- /dev/null +++ b/INSTALL @@ -0,0 +1,167 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes a while. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Type `make install' to install the programs and any data files and + documentation. + + 4. You can remove the program binaries and object files from the + source code directory by typing `make clean'. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. + diff --git a/INSTALL.docs b/INSTALL.docs new file mode 100644 index 00000000..9469cfa7 --- /dev/null +++ b/INSTALL.docs @@ -0,0 +1,8 @@ + +There are some docs ( at 11.04.2001 avaible docs for html, css, php, javascript ) +you need to download packages from http://quanta.sourceforge.net +( html.tar.bz2, php.tar.bz2, css.tar.bz2 ) and uncompress them +to $KDEDIR/share/apps/quanta/doc/ +or to ~/.kde/share/apps/quanta/doc/ +and restart quanta. + diff --git a/Makefile.am.in b/Makefile.am.in new file mode 100644 index 00000000..c2adbb73 --- /dev/null +++ b/Makefile.am.in @@ -0,0 +1,30 @@ +COMPILE_FIRST = lib +MAINTAINERCLEANFILES = subdirs configure.in acinclude.m4 configure.files + +dist-hook: + cd $(top_distdir) && perl admin/am_edit -padmin + cd $(top_distdir) && $(MAKE) -f admin/Makefile.common subdirs + + +install-data-local: + @echo "" + @echo "" + @echo "*************** Important *************************" + @echo "" + @echo " Add "$(bindir)" to your PATH and" + @echo " add "$(prefix)" to your KDEDIRS!" + @echo "" + @echo " Please report bugs with our web form at" + @echo " http://bugs.kde.org" + @echo " Current maintainers are" + @echo " Eric Laffoon " + @echo " Andras Mantia " + @echo "" + @echo " The KDE Web Dev developers hope you enjoy Quanta+," + @echo " Kommander, KFileReplace, KXSL dbg, KImageMapEditor" + @echo " and KLinkStatus!" + @echo "****************************************************" + @echo "" + +include admin/deps.am + diff --git a/Makefile.cvs b/Makefile.cvs new file mode 100644 index 00000000..030b1407 --- /dev/null +++ b/Makefile.cvs @@ -0,0 +1,15 @@ + +all: + @echo "This Makefile is only for the CVS repository" + @echo "This will be deleted before making the distribution" + @echo "" + @if test ! -d admin; then \ + echo "Please recheckout this module!" ;\ + echo "for cvs: use checkout once and after that update again" ;\ + echo "for cvsup: checkout kde-common from cvsup and" ;\ + echo " link kde-common/admin to ./admin" ;\ + exit 1 ;\ + fi + $(MAKE) -f admin/Makefile.common cvs + +.SILENT: diff --git a/NEWS b/NEWS new file mode 100644 index 00000000..c85b5a9b --- /dev/null +++ b/NEWS @@ -0,0 +1,2 @@ + For the latest new features and bugfixes in Quanta+ and the other included +applications take a look at the ChangeLog file in the subdirectories. diff --git a/PACKAGING b/PACKAGING new file mode 100644 index 00000000..b64226b4 --- /dev/null +++ b/PACKAGING @@ -0,0 +1,77 @@ + Here there is some information about requirements for packagers. Please take +care of the below compilation and runtime dependencies when packaging Quanta. + +Severity levels mean: +- Required: Quanta will not run without it +- Highly recommended: Quanta will run, but some important functionality will be missing +- Recommended: some functionality will be missing +- Optional: completes the functionalities in Quanta, making the development easier + +1. Compilation requirements: +------------------------------ +- KDE 3.4 libraries or above + Severity: Required +- cvsservice headers: + Description: cvsservice headers are used for the incorporated CVS actions. Without them + the CVS submenu from the file context menus will be missing. + Severity: Highly recommended + Location: kdesdk/cervisia + +2. Runtime dependencies: +--------------------------- +- Kommander: + Description: Required to run some of the dialogs in Quanta+ + Severity: Highly recommended + Location: kdewebdev module + +- KFileReplace: + Description: Used to search and replace in external files + Severity: Highly recommended + Location: kdewebdev module + +- KLinkStatus: + Description: Used to check the validity of the links + Severity: Highly recommended + Location: kdewebdev module + +- HTML Tidy: + Description: Used to check the validity of the HTML documents + Severity: Highly recommended + Location: http://tidy.sf.net + +- Gubed: + Description: the PHP Debugger used by Quanta + Severity: Highly recommended + Location: http://gubed.sf.net (only the server is required) + +- cvsservice: + Description: used by the *integrated* CVS commands. + Severity: Highly Recommended + Localtion: kdesdk module + +- Cervisia: + Description: Used to perform CVS operations + Severity: Recommended + Location: kdesdk module + +- KXSLDbg: + Description: XSLT debugger + Severity: Recommended + Location: kdewebdev module + +- KImageMapEditor: + Description: Helps creation and editing of HTML image-maps + Severity: Optional + Location: kdewebdev module + +- Kompare: + Description: compares two files by content. Used when a file was modified outside of Quanta. + Severity: Recommended + Localtion: kdesdk module + +- GPG (OpenPGP): + Description: digital signature tool. Makes possible the signature verification of downloaded + resources. + Severity: Highly Recommended + Location: http://www.gnupg.de + \ No newline at end of file diff --git a/README b/README new file mode 100644 index 00000000..4105a43d --- /dev/null +++ b/README @@ -0,0 +1,24 @@ +KDE WebDev - WEB Development package for the K Desktop Environment. + Version: 3.5 line + + + The kdewebdev package contains Quanta Plus and other applications, which are useful +for web development. They are runtime dependencies of Quanta Plus, and it is +highly recommended that you install them. + + The extra applications are: + +Kommander: a GUI script builder and executor tool. Needed for some Quanta functionality. +KFileReplace: powerful search and replace in multiple files +KXSLDbg: XSL debugger +KImageMapEditor: image map editor +KLinkStatus: link checker + +Be sure to read the README files in each application's directory! +Packagers, please read the PACKAGING file for detailed information about compilation +and runtime dependencies. + + +Enjoy Quanta+! + +The Quanta team diff --git a/TODO b/TODO new file mode 100644 index 00000000..6aa9e6fb --- /dev/null +++ b/TODO @@ -0,0 +1 @@ +Put here the global TODO list. \ No newline at end of file diff --git a/VERSION b/VERSION new file mode 100644 index 00000000..b3caaa9a --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +KDE WebDev 3.5.9 diff --git a/configure.in.bot b/configure.in.bot new file mode 100644 index 00000000..7e99abfb --- /dev/null +++ b/configure.in.bot @@ -0,0 +1,8 @@ +if test "$enable_editors" = "yes"; then + echo "" + echo "WARNING: You have enabled the editor chooser feature!" + echo "This feature is highly experimental, and officially only the" + echo "Kate part (Advanced Text Editor) is supported!" + echo "Some features are not accessible with other editors, and" + echo "Quanta may even crash with those!" +fi diff --git a/configure.in.in b/configure.in.in new file mode 100644 index 00000000..4e58ca89 --- /dev/null +++ b/configure.in.in @@ -0,0 +1,264 @@ +#MIN_CONFIG(3.3) +dnl If the quanta executable name and the data dirs are changed from the default "quanta", +dnl the following changes are needed: +dnl - change the quanta_datadir +dnl - change the QUANTA_PACKAGE and QUANTA_VERSION in quanta/src/quanta.h +dnl - change the KDE_ICON in quanta/data/icons/Makefile.am +dnl - create a .desktop file and the corresponding icons +dnl - make sure the .desktop file is installed in the quanta/src/Makefile.am +dnl (kdelnk_DATA = quanta.desktop line) +dnl - change the bin_PROGRAMS and the _SOURCES, _LDADD, _METASOURCES, _LDFLAGS +dnl below it in the quanta/src/Makefile.am, so it reflects the new executable name + +AM_INIT_AUTOMAKE(@MODULENAME@, @VERSION@) +KDE_ENABLE_HIDDEN_VISIBILITY + +quanta_datadir='${kde_datadir}/quanta' +package="quanta" +AC_SUBST(package) +AC_SUBST(quanta_datadir) +AM_CONDITIONAL(QUANTAUIRC_HOOK, test "x$package" != "xquanta") + +dnl These are common macros that you might or might not want to use + +dnl Checks for header files. +AC_HEADER_DIRENT +AC_HEADER_STDC +AC_HEADER_TIME +AC_CHECK_HEADERS(fcntl.h sys/time.h unistd.h stdlib.h paths.h sys/statvfs.h sys/statfs.h sys/vfs.h sys/mount.h sys/param.h stdarg.h) +AC_CHECK_FUNCS(usleep) +AC_CHECK_FUNCS(statvfs) + +AC_DEFINE_UNQUOTED(PREFIX,"$prefix",[Define the PREFIX to be used later]) + +dnl +dnl The following new parameters were added to offer +dnl the ability to specify the location of the libxml +dnl library during linking and compilation. +dnl Mathieu Lacage 30/03/2000 +dnl +LIBXML_PREFIX="" +AC_ARG_WITH(libxml-prefix, + [ --with-libxml-prefix=[PFX] Specify location of libxml], + LIBXML_PREFIX="$withval" +) + +if test "x${LIBXML_PREFIX}" != "x" +then + AC_MSG_RESULT(Using a libxml prefix of ${LIBXML_PREFIX}) +fi + + +AC_SUBST(LIBXML_LIBS) + +dnl Test for libxml2 version +XML_CONFIG="xml2-config" +AC_MSG_CHECKING(for libxml libraries >= "2.6.0") +XML_WARNING="" +if test "x$LIBXML_PREFIX" != "x" +then + if ${LIBXML_PREFIX}/bin/xml2-config --libs print > /dev/null 2>&1 + then + XML_CONFIG=${LIBXML_PREFIX}/bin/xml2-config + else + XML_WARNING="1" + XML_CONFIG=xml2-config + fi +fi + +AC_DEFUN([VERSION_TO_NUMBER], +[`$1 | sed -e 's/libxml //' | $AWK 'BEGIN { FS = "."; } { printf "%d", + ([$]1* 1000 + [$]2) * 1000 + [$]3;}'`]) + +dnl +dnl test version and init our variables +dnl +if test "x$XML_CONFIG" != "x" +then + vers=VERSION_TO_NUMBER($XML_CONFIG --version) + if test "$vers" -lt VERSION_TO_NUMBER(echo "2.6.0") + then + CXXFLAGS="$CXXFLAGS -DLIBXML_2_5" + AC_MSG_RESULT(not found - assuming 2.5.x) + else + AC_MSG_RESULT(found) + fi + LIBXML_LIBS="`$XML_CONFIG --libs`" + LIBXML_CFLAGS="`$XML_CONFIG --cflags`" + LIBXML_PREFIX="$XML_CONFIG --prefix" +else + AC_MSG_ERROR(Could not find libxml2 anywhere, check ftp://xmlsoft.org/.) +fi + +if test "x${XML_WARNING}" != "x" +then + AC_MSG_RESULT( +!!Warning!! using xml2-config in default path +) +fi + +LIBXML_PREFIX_DIR="`$XML_CONFIG --prefix`" + +AC_SUBST(XML_CONFIG) +AC_SUBST(LIBXML_PREFIX) +AC_SUBST(LIBXML_LIBS) +AC_SUBST(LIBXML_CFLAGS) + +LIBXSLT_PREFIX="" +AC_ARG_WITH(libxslt-prefix, + [ --with-libxslt-prefix=[PFX] Specify location of libxslt], + LIBXSLT_PREFIX="$withval" +) + +if test "x${LIBXSLT_PREFIX}" != "x" +then + AC_MSG_RESULT(Using a libxslt prefix of ${LIBXSLT_PREFIX}) +fi + +dnl +dnl find libxslt +dnl +XSLT_CONFIG="xslt-config" +XSLT_WARNING="" +AC_SUBST(LIBXSLT_REQUIRED_VERSION) +AC_MSG_CHECKING(for libxslt libraries >= $LIBXSLT_REQUIRED_VERSION) +if test "x$LIBXSLT_PREFIX" != "x" +then + if ${LIBXSLT_PREFIX}/bin/xslt-config --libs print > /dev/null 2>&1 + then + XSLT_CONFIG=${LIBXSLT_PREFIX}/bin/xslt-config + else + XSLT_WARNING="1" + XSLT_CONFIG=xslt-config + fi +fi + + +AC_DEFUN([VERSION_TO_NUMBER], +[`$1 | sed -e 's/libxslt //' | $AWK 'BEGIN { FS = "."; } { printf "%d", + ([$]1 * 1000 + [$]2) * 1000 + [$]3;}'`]) + +dnl +dnl test version and init our variables +dnl +if test "x$XSLT_CONFIG" != "x" +then + vers=VERSION_TO_NUMBER($XSLT_CONFIG --version) + if test "$vers" -ge VERSION_TO_NUMBER(echo $LIBXSLT_REQUIRED_VERSION) + then + LIBXSLT_LIBS="-lexslt `$XSLT_CONFIG --libs`" + LIBXSLT_CFLAGS="`$XSLT_CONFIG --cflags`" + AC_MSG_RESULT(found) + if test "x$LIBXSLT_PREFIX" != "x" + then + AC_MSG_RESULT( +Don't forget to make sure that ${LIBXSLT_PREFIX}/lib has been added + to your LD_LIBRARY_PATH environment variable) + else + LIBXSLT_PREFIX="$XSLT_CONFIG --prefix" + fi + else + AC_MSG_ERROR(You need at least libxslt $LIBXSLT_REQUIRED_VERSION for this + version of xsldbg) + fi +else + AC_MSG_ERROR(Could not find libxslt anywhere, check + ftp://xmlsoft.org/XSLT/.) +fi + +if test "x${XSLT_WARNING}" != "x" +then + AC_MSG_RESULT( +!!Warning!! using xslt-config in default path +) +fi + +AC_SUBST(XSLT_CONFIG) +AC_SUBST(LIBXSLT_PREFIX) +AC_SUBST(LIBXSLT_LIBS) +AC_SUBST(LIBXSLT_CFLAGS) + + +dnl ********** +dnl check whether we need the qextmdi lib +dnl (Shamlesly stolen from gideon souorces and +dnl modified for quanta by fredi) +dnl ********** + +AC_DEFUN([QUANTA_CHECK_MDI], +[ + AC_MSG_CHECKING(whether to use kmdi lib from kdelibs) + AC_CACHE_VAL(ac_cv_mdi_setup, + [ + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$KDE_INCLUDES $QT_INCLUDES" + + AC_TRY_LINK([ + #include + ], + [ + #if KDE_VERSION < ((3<<16) | (3<<8) | (92)) + KDE_choke me + #endif + ], + ac_cv_mdi_setup=yes, + ac_cv_mdi_setup=no + ) + CXXFLAGS="$save_CXXFLAGS" + AC_LANG_RESTORE + ]) + + if test "$ac_cv_mdi_setup" = "yes"; then + LIB_KMDI="-lkmdi" + QEXTMDI_SUBDIR="" + KMDI_INCLUDES="" + AC_MSG_RESULT(yes) + else + LIB_KMDI='$(top_builddir)/lib/compatibility/kmdi/libquantakmdi.la' + QEXTMDI_SUBDIR="kmdi" + KMDI_INCLUDES='-I$(top_srcdir)/lib/compatibility/kmdi/qextmdi' + CXXFLAGS="$CXXFLAGS -DCOMPAT_KMDI" + AC_MSG_RESULT(no) + fi + + AC_SUBST(LIB_KMDI) + AC_SUBST(KMDI_INCLUDES) + AC_SUBST(QEXTMDI_SUBDIR) + AM_CONDITIONAL(include_qextmdi, test -n "$QEXTMDI_SUBDIR") +]) + +dnl Check if kmdi is present, if not use giden's one +QUANTA_CHECK_MDI + +KDE_CHECK_HEADER(cvsservice_stub.h, [cvsservice_stub_h="found"], [cvsservice_stub_h="none"]) +AM_CONDITIONAL(include_cvsservice, test "$cvsservice_stub_h" = "found") +if test "$cvsservice_stub_h" = "found"; then + CXXFLAGS="$CXXFLAGS -DENABLE_CVSSERVICE" +fi + +#check for KNewStuffSecure headers +KNEWSTUFF_INCLUDES="" +LIB_KNEWSTUFF="-lknewstuff" +KDE_CHECK_HEADER(knewstuff/knewstuffsecure.h, [knewstuffsecure_h="found"], [knewstuffsecure_h="none"]) +AM_CONDITIONAL(include_knewstuff, test "$knewstuffsecure_h" != "found") +if test "$knewstuffsecure_h" != "found"; then + KNEWSTUFF_INCLUDES='-I$(top_srcdir)/lib/compatibility' + LIB_KNEWSTUFF='$(top_builddir)/lib/compatibility/knewstuff/libknewstuff.la' +fi +AC_SUBST(KNEWSTUFF_INCLUDES) +AC_SUBST(LIB_KNEWSTUFF) + + + +AC_ARG_ENABLE(editors, [ --enable-editors Enable selection of other editors aside of Kate], +[enable_editors=$enableval], [enable_editors="no"]) + +if test "$enable_editors" = "yes"; then + CXXFLAGS="$CXXFLAGS -DENABLE_EDITORS" +fi +AC_SUBST(enable_editors) + +AC_CHECK_PROGS(TAR, gnutar gtar tar, [AM_MISSING_PROG(tar)]) +AC_CHECK_PROG(GZIP_COMMAND, gzip, gzip) diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 00000000..85c6cdef --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,4 @@ +KDE_LANG = en +KDE_DOCS = AUTO +SUBDIRS = $(AUTODIRS) + diff --git a/doc/kfilereplace/Makefile.am b/doc/kfilereplace/Makefile.am new file mode 100644 index 00000000..e97402c7 --- /dev/null +++ b/doc/kfilereplace/Makefile.am @@ -0,0 +1,2 @@ +KDE_DOCS = AUTO +KDE_LANG = en diff --git a/doc/kfilereplace/addstringsdialog_window.png b/doc/kfilereplace/addstringsdialog_window.png new file mode 100644 index 00000000..7d6aeee7 Binary files /dev/null and b/doc/kfilereplace/addstringsdialog_window.png differ diff --git a/doc/kfilereplace/backup_option.png b/doc/kfilereplace/backup_option.png new file mode 100644 index 00000000..a0e1e02f Binary files /dev/null and b/doc/kfilereplace/backup_option.png differ diff --git a/doc/kfilereplace/casesensitive_option.png b/doc/kfilereplace/casesensitive_option.png new file mode 100644 index 00000000..6302c0f2 Binary files /dev/null and b/doc/kfilereplace/casesensitive_option.png differ diff --git a/doc/kfilereplace/command_option.png b/doc/kfilereplace/command_option.png new file mode 100644 index 00000000..1da3688b Binary files /dev/null and b/doc/kfilereplace/command_option.png differ diff --git a/doc/kfilereplace/edit.png b/doc/kfilereplace/edit.png new file mode 100644 index 00000000..ce8b2267 Binary files /dev/null and b/doc/kfilereplace/edit.png differ diff --git a/doc/kfilereplace/edit_add.png b/doc/kfilereplace/edit_add.png new file mode 100644 index 00000000..c46aed2b Binary files /dev/null and b/doc/kfilereplace/edit_add.png differ diff --git a/doc/kfilereplace/edit_remove.png b/doc/kfilereplace/edit_remove.png new file mode 100644 index 00000000..1a2f87c5 Binary files /dev/null and b/doc/kfilereplace/edit_remove.png differ diff --git a/doc/kfilereplace/eraser.png b/doc/kfilereplace/eraser.png new file mode 100644 index 00000000..33775463 Binary files /dev/null and b/doc/kfilereplace/eraser.png differ diff --git a/doc/kfilereplace/filereplace.png b/doc/kfilereplace/filereplace.png new file mode 100644 index 00000000..c3692e11 Binary files /dev/null and b/doc/kfilereplace/filereplace.png differ diff --git a/doc/kfilereplace/filesearch.png b/doc/kfilereplace/filesearch.png new file mode 100644 index 00000000..1be59c49 Binary files /dev/null and b/doc/kfilereplace/filesearch.png differ diff --git a/doc/kfilereplace/filesimulate.png b/doc/kfilereplace/filesimulate.png new file mode 100644 index 00000000..7cc5b284 Binary files /dev/null and b/doc/kfilereplace/filesimulate.png differ diff --git a/doc/kfilereplace/index.docbook b/doc/kfilereplace/index.docbook new file mode 100644 index 00000000..b790a5e0 --- /dev/null +++ b/doc/kfilereplace/index.docbook @@ -0,0 +1,613 @@ + +KFileReplace"> + + + + + kdewebdev"> + bc"> +]> + + + + +The &kfilereplace; Handbook + + + +Emiliano +Gulmini + +
emi_barbarossa@yahoo.it
+
+
+ + + +
+ + +2004 +Emiliano Gulmini + + +&FDLNotice; + +2004-08-09 +1.0.0 + + + + + +&kfilereplace; is an utility to search and replace strings. + + + + +KDE +KFileReplace +replace +search +string + + +
+ + + Introduction + &kfilereplace; is an application used to search and replace a list of strings in a file tree. The strings may be literal or Qt-like regular expressions. There are also other options to tune your search. + + + + +Using &kfilereplace; + + + + &kfilereplace; in its standalone incarnation + + + + + + &kfilereplace; in its standalone incarnation + + + + + + + +The Toolbar + +The &kfilereplace; toolbar should looks like this: + + &kfilereplace;'s toolbar + + + + + + + + + &kfilereplace;'s toolbar + + + + + +The toolbar shows you the buttons of the main functionalities. + + Toolbar Icons + + + + + + + + New session + + This button shows a session dialog in which you can set several basic options; if &kfilereplace; run as standalone application you should click this button as first step. + + + + + + + + + + Search only + + This button starts a search loop. + + + + + + + + + + Replace + + This button starts a search&replace loop. When a string has been found, &kfilereplace; replaces it with another string. + + + + + + + + + + Simulated Replace + + This button starts a simulated search&replace loop. Nothing really happens when you click this button. + + + + + + + + + + Stop + + This button stops an operation. + + + + + + + + + + Add Strings + + This button opens the Add Strings dialog in which you can edit your string list. + + + + + + + + + + Delete Strings + + This button deletes the selected (or the current if there is no selection) string from the list. + + + + + + + + + + Edit Strings + + This button edits a selected string. + + + + + + + + + + Delete List + + This button deletes all the strings in the list. + + + + + + + + + + Invert Strings + + This button swaps the search string with the replace string, so you can revert a search/replace operation. + + + + + + + + + + Load String List + + This button loads a string list saved in a xml file with a kfr extension. + + + + + + + + + + Search in Subfolders + + This button allows you to search/replace recursively in the subfolders of your base directory. + + + + + + + + + + Make Backup Files + + This button enables generation of backup files. + + + + + + + + + + Case-sensitive Search + + This button enables case-sensitive searching. + + + + + + + + + + Commands + + This button enables commands capability. Commands are special strings. See . + + + + + + + + + + Regular expressions + + This button enables Qt-like regular expressions. + + + + + + + + + + The Results List + + &kfilereplace;'s Results view + + + + + + + + + &kfilereplace;'s Results view + + + + The Results view shows the name of the files that contain the strings you have to retrieve (and replace), their path, their size, the number of strings found and the user id of the files. This view also provides the exact position of each match. You can also open a file by clicking with the &RMB; on an list entry that contains line and column position. + + + + + The String List + + This is the Strings view: + + &kfilereplace;'s Strings view + + + + + + &kfilereplace;'s Strings view + + + + + + The Strings view visualizes the list of strings you want search/replace. Please note that in search mode the Results view and the Strings view have a different layout. + + + + + The <guilabel>New Session</guilabel> Dialog + The New Session dialog is used to setup the basic parameters needed by &kfilereplace; to work. It consists of two tabs, General and Advanced. + + + + The <guilabel>General</guilabel> Tab + + &kfilereplace; General tab + + + + + + &kfilereplace; General tab + + + + When you want to begin a new session the first step is to click on the New Session button. Then you must enter the base path and a sequence of shell-like wildcards to use as filter. + Then you could set some useful options, like searching in all the subfolders, doing a case-sensitive search, enabling commands and/or regular expressionsPlease note that regular expressions and commands could slow down the speed performances., doing a backup copy of each file before replacing. + If you want to start searching, you can put a string in the search box and press Search Now, otherwise leave the search box empty and press Search Later. + + + + The <guilabel>Advanced</guilabel> Tab + + &kfilereplace; Advanced tab + + + + + + &kfilereplace; Advanced tab + + + + The Advanced tab allows you to set up some useful options to restrict the search to a subset of your target file tree. If you want to run &kfilereplace; only over files that have a size in the range of 10KB - 100KB, then you could use the size options. There is also a date option that restricts the search in a temporal range, and a last option that allows you to only search for files owned (or not owned) by a particular user (this may be more useful to the system administrators). + + + + + The <guilabel>Options</guilabel> Dialog + This dialog contains options that are in the toolbar and extra options that may come in handy in some situations. You can invoke it selecting SettingsConfigure KFileReplace... in the main menu. + + + General options + These options have been presented in the Toolbar section. + + The General tab of the Options window + + + + + + The General tab of the Options window + + + + + + + Advanced options + + + The Advanced tab of the Options window + + + + + + The Advanced tab of the Options window + + + + + Do not show files if no strings are found or replaced + When searching, stop on first string found + Follow symbolic links + Ignore hidden files and directories + + shows only the files that match some of your strings. This will speed up the search. + &kfilereplace; will stop when it finds a matching string, and will continue to search for other strings or, if you search for only one string, it will continue with the next file. + if a file is a link to another one, then search in the real file. + if hidden files or folders are encountered, ignore them. + + + + + + + The <guilabel>Add Strings</guilabel> Dialog + + &kfilereplace;'s Add Strings dialog + + + + + + &kfilereplace;'s Add Strings dialog + + + + This dialog is used to insert and edit a list of strings. You just have to insert either a search-only or a search-and-replace list, and then with the two mini-editors you will introduce your text. The arrow buttons allow you to add pairs of strings or delete them. When you finish, click OK. + + + + + &kfilereplace; features + This chapter provides informations about some useful capabilities of &kfilereplace;. + + How to save your string list + When you want to reuse a list of strings you can save it in a xml file. To do this select from the menubar Search/ReplaceStringsSave Strings List to File. When you save a list, a simple xml file with extension kfr is created. To load a kfr file select from menubar Search/ReplaceStringsLoad Strings List from File. The actual file looks like this: + +<?xml version="1.0" ?> +<kfr> + <mode search="false"/> + <replacement> + <oldstring><![CDATA[SEARCH_STRING_1]] ></oldstring> + <newstring><![CDATA[REPLACE_STRING_1]]></newstring> + </replacement> + <replacement> + <oldstring><![CDATA[SEARCH_STRING_2]]></oldstring> + <newstring><![CDATA[REPLACE_STRING_2]]></newstring> + </replacement> + + + <replacement> + <oldstring><![CDATA[SEARCH_STRING_N]]></oldstring> + <newstring><![CDATA[REPLACE_STRING_N]]></newstring> + </replacement> + +</kfr> + + If you are using a previous format, you can update by hand your file by simply modifying it according to the above scheme. Alternatively, you can load the file written in the old format and save it again with &kfilereplace; in the way explained before. + + + + How to Create a Simple Report + You can create a report by choosing Search/ReplaceResultsCreate Report File from the main menu. A report is a folder containing an xml and a css file. Reports may be useful to maintain a simple log of your operations. + + &kfilereplace;'s Report feature + + + + + + + + + &kfilereplace;'s Report feature + + + + + + + + How to use Regular Expressions + + If you want search for every string that starts with x, ht or u and ends with ml, you can write a regular expression like this: (x|ht|u)ml. Insert this expression in the search editor, click OK, and enable regular expressions by toggling the Regular Expression button. Please note that using regular expressions lets you to make very complicated searches, but the cost could be a performance degradation. Regular expression can be very tricky, and it is often the case that if you want to solve a problem with a regular expression, you have two problems. + + + + How to Protect Original Files + If you do not want to lose your original files, you can make a copy of them before replacing the strings. After inserting your strings, and before starting the replacement process, you have just to toggle the Backup button. If you want to customize the extension of the backup files open the Options dialog. + + + + + How to Open a File + If you want to open a file that matches some of your strings, you have to select a line in the result view and click on it with the &RMB;. A context menu will appear from which you can open the file. If you use &kfilereplace; embedded in &quantaplus;, you can open the file directly in it at the specified line and column. + + + + Commands + Suppose you want replace the phrase Alice's adventures in Wonderland with the entire file that contains Carroll's novel. Probably you don't want to do this by hand, what you need is a command that will do it for you. Click the Add button, select Search and Replace Mode and insert the following strings: Alice's adventure in Wonderland in the search mini-editor and the string [$loadfile:/the-path-to-my-folder/my-folder/my-file$] in the replacement mini-editor. Click OK. When you come back to the &kfilereplace; main window, toggle the Command action button that enables the commands, and start the replacement process. There are also other commands, see for a list of all of them. + + + + +Credits and License + +&kfilereplace;. Program copyright 1999 by Fran§ois Dupoux dupoux@dupoux.com, 2003 Andras Mantia amantia@kde.org, 2004 Emiliano Gulmini emi_barbarossa@yahoo.it + + + + The &kfilereplace; authors and maintainers: + + Fran§ois Dupoux dupoux@dupoux.com + Original author + + + Andras Mantia amantia@kde.org + Shell autor, KPart creator, co-maintainer + + + Emiliano Gulmini emi_barbarossa@yahoo.it + Current maintainer, code cleaner & rewriter + + + + +Documentation Copyright © 2004 Emiliano Gulmini emi_barbarossa@yahoo.it + + + + +&underFDL; +&underGPL; + + + + +Installation + + +How to install &kfilereplace; + +&kfilereplace; is currently part of &kdewebdev; package, so, in order to install it, you have to get a copy of &kdewebdev;. Note that if you are using a &kde; installation provided by your OS vendor, probably you already have &kdewebdev; installed; in this case, you can use &kfilereplace; either by opening &quantaplus; Web editor, or by calling it directly (unless you have an old &kde; version). Else you can download the &kdewebdev; package from the Internet: please refer to &kdewebdev; home site for more information. + + + + + + + Requirements + In order to use the command [$mathexp:some_math_expression$] you should install the &bc; mathematical utility (version 1.06 or newer) written by Philip A. Nelson (philnelson@acm.org). + + + + + + &kfilereplace; commands + + + [$datetime:iso$] + [$datetime:local$] + [$user:uid$] + [$user:gid$] + [$user:loginname$] + [$user:fullname$] + [$user:homedir$] + [$user:shell$] + [$loadfile:/my-path/my-directory/my-file$] + [$empty:$] + [$random:AN_INTEGER_NUMBER$] + [$random:$] + [$mathexp:bc-expression$] + + this command return the current date and time in Qt ISO format. + like above but in local format. + return the UID of the current user. + return the GID of the current user. + return the login name of the current user. + return the full name of the current user. + return the home directory of the current user. + return the shell of the current user. + return the content of the my-file file. + return the empty string. + return a random number string using AN_INTEGER_NUMBER as the initial seed. + like above, but without initial seed. + return the result of a &bc; v1.06 mathematical expression. + + + + + +&documentation.index; +
+ diff --git a/doc/kfilereplace/invert.png b/doc/kfilereplace/invert.png new file mode 100644 index 00000000..f3ab8be6 Binary files /dev/null and b/doc/kfilereplace/invert.png differ diff --git a/doc/kfilereplace/kfr_standalone_main_window_1.png b/doc/kfilereplace/kfr_standalone_main_window_1.png new file mode 100644 index 00000000..3e4f85db Binary files /dev/null and b/doc/kfilereplace/kfr_standalone_main_window_1.png differ diff --git a/doc/kfilereplace/optionsdialog_main_window_1.png b/doc/kfilereplace/optionsdialog_main_window_1.png new file mode 100644 index 00000000..959c3977 Binary files /dev/null and b/doc/kfilereplace/optionsdialog_main_window_1.png differ diff --git a/doc/kfilereplace/optionsdialog_main_window_2.png b/doc/kfilereplace/optionsdialog_main_window_2.png new file mode 100644 index 00000000..3213b6ff Binary files /dev/null and b/doc/kfilereplace/optionsdialog_main_window_2.png differ diff --git a/doc/kfilereplace/project.png b/doc/kfilereplace/project.png new file mode 100644 index 00000000..607e6aa8 Binary files /dev/null and b/doc/kfilereplace/project.png differ diff --git a/doc/kfilereplace/projectdialog_main_window_1.png b/doc/kfilereplace/projectdialog_main_window_1.png new file mode 100644 index 00000000..58c622f0 Binary files /dev/null and b/doc/kfilereplace/projectdialog_main_window_1.png differ diff --git a/doc/kfilereplace/projectdialog_main_window_2.png b/doc/kfilereplace/projectdialog_main_window_2.png new file mode 100644 index 00000000..6fe2cb98 Binary files /dev/null and b/doc/kfilereplace/projectdialog_main_window_2.png differ diff --git a/doc/kfilereplace/recursive_option.png b/doc/kfilereplace/recursive_option.png new file mode 100644 index 00000000..bc98df90 Binary files /dev/null and b/doc/kfilereplace/recursive_option.png differ diff --git a/doc/kfilereplace/regularexpression_option.png b/doc/kfilereplace/regularexpression_option.png new file mode 100644 index 00000000..f74c7b56 Binary files /dev/null and b/doc/kfilereplace/regularexpression_option.png differ diff --git a/doc/kfilereplace/report_example.png b/doc/kfilereplace/report_example.png new file mode 100644 index 00000000..359de5ab Binary files /dev/null and b/doc/kfilereplace/report_example.png differ diff --git a/doc/kfilereplace/results_view.png b/doc/kfilereplace/results_view.png new file mode 100644 index 00000000..8f91469d Binary files /dev/null and b/doc/kfilereplace/results_view.png differ diff --git a/doc/kfilereplace/stop.png b/doc/kfilereplace/stop.png new file mode 100644 index 00000000..73b27d9f Binary files /dev/null and b/doc/kfilereplace/stop.png differ diff --git a/doc/kfilereplace/strings_view.png b/doc/kfilereplace/strings_view.png new file mode 100644 index 00000000..7396e53c Binary files /dev/null and b/doc/kfilereplace/strings_view.png differ diff --git a/doc/kfilereplace/toolbar.png b/doc/kfilereplace/toolbar.png new file mode 100644 index 00000000..84e699eb Binary files /dev/null and b/doc/kfilereplace/toolbar.png differ diff --git a/doc/kfilereplace/unsortedList.png b/doc/kfilereplace/unsortedList.png new file mode 100644 index 00000000..bed281f1 Binary files /dev/null and b/doc/kfilereplace/unsortedList.png differ diff --git a/doc/klinkstatus/Makefile.am b/doc/klinkstatus/Makefile.am new file mode 100644 index 00000000..e97402c7 --- /dev/null +++ b/doc/klinkstatus/Makefile.am @@ -0,0 +1,2 @@ +KDE_DOCS = AUTO +KDE_LANG = en diff --git a/doc/klinkstatus/index.docbook b/doc/klinkstatus/index.docbook new file mode 100644 index 00000000..33dbbd7d --- /dev/null +++ b/doc/klinkstatus/index.docbook @@ -0,0 +1,498 @@ + +KLinkStatus"> + + + + +]> + + + + + + + + + + + + + + +The &klinkstatus; Handbook + + + +Paulo +Moura Guedes + +
moura@kdewebdev.org
+
+
+ + + +
+ + +2004 +Paulo Moura Guedes + + + +&FDLNotice; + + + +2004-04-29 +0.1.3 + + + + + +&klinkstatus; is a link checker for &kde;. + + + + + + +KDE +KLinkStatus +link checker +validation + + +
+ + + +Introduction + +&klinkstatus; is a link checker for &kde;. +It allows you to search internal and external links in your entire web site, +just a single page and choose the depth to search. +You can also check local files, ftp, fish, &etc;, as &klinkstatus; uses KIO. +For performance, links can be checked simultaneously. + +Please report any problems or feature requests to http://linkstatus.paradigma.co.pt/bugs/. + + + + +Using &klinkstatus; + + + + + + +Here's a screenshot of &klinkstatus; + + + + + + + + + Screenshot + + + + + + + + +Command Reference + + +The main &klinkstatus; window + + +The File Menu + + + + + +&Ctrl;N + +File +New Link Check + +Creates a new session, if none is empty + + + + +&Ctrl;O + +File +Open URL + +Opens a &URL; + + + + +&Ctrl;W + +File +Close Tab + +Close the current tab. + + + + + + + +The <guimenu>Help</guimenu> Menu + + + + + + +&help.menu.documentation; + + + + + + + + + + + + + + + + + + + +Credits and License + + +&klinkstatus; + + +Program Copyright © 2004 Paulo Moura Guedes pmg@netcabo.pt + + +Documentation Copyright © 2004 Paulo Moura Guedes pmg@netcabo.pt + + + + +&underFDL; +&underGPL; + + + + +Installation + + +How to obtain &klinkstatus; + + + + +http://kde-apps.org + + + + + + + + + + +Compilation and Installation + + + + + +&install.compile.documentation; + + + + + +&documentation.index; +
+ + + diff --git a/doc/klinkstatus/screenshot.png b/doc/klinkstatus/screenshot.png new file mode 100644 index 00000000..9c3c7bf0 Binary files /dev/null and b/doc/klinkstatus/screenshot.png differ diff --git a/doc/kommander/Makefile.am b/doc/kommander/Makefile.am new file mode 100644 index 00000000..41691557 --- /dev/null +++ b/doc/kommander/Makefile.am @@ -0,0 +1,3 @@ +KDE_LANG = en +KDE_DOCS = AUTO + diff --git a/doc/kommander/basics.docbook b/doc/kommander/basics.docbook new file mode 100644 index 00000000..5d7dc2cf --- /dev/null +++ b/doc/kommander/basics.docbook @@ -0,0 +1,135 @@ + + + + +&kommander; Basics + + +Tamara +King +
+tik@acm.org +
+
+ +Eric +Laffoon +
+sequitur@kde.org +
+
+ + + +
+
+ +&kommander; Basics + + + + +Concepts + + + +&kommander; was originally designed around a simple concept that has proven somewhat revolutionairy among visual design tools. Typically these tools allow you to create dialogs and possibly mainwindow interfaces. Of course a mainwindow interface is the main program window which typically has menus, toolbars, statusbar and the application area. Dialogs are child windows which typically don't have menus and are so named because their purpose is to have a dialog or exchange information between you and the main application. The elements on a dialog are called widgets and you hook your program into these widgets. &kommander; is different because it is inherently nonprogrammatic here. It uses the concept of associating text with the widgets on the dialog. Initially this was called Associated Text but now it is called &kommander; Text. Widgets on &kommander; dialogs can include the content of other widgets by reference and a widget can reference its own content by use of a Special that looks like this, @widgetText. Specials are commands with special meaning in &kommander;. So if you created a dialog with two LineEdit widgets and named the first FirstName and the second LastName you could create a button and set its &kommander; Text to My name is @FirstName @LastName. You would need to set @widgetText in the first and last name widgets. Remember? We need to tell &kommander; to reference the text in them. You could run this from a Konsole and it would output the string for you. So it would reference the first name like so: @FirstName -> get the widget named FirstName(@FirstName) -> @widgetText -> get the contents of the LineEdit widget. So in this case @FirstName returns Eric: @FirstName -> @widgetText -> Eric. + + + +That is the simple core of &kommander;. What you can do with this is where it gets interesting. First of all it is worth noting that compared to the normal approach of a language based tool &kommander; does not need programming statements to define these operations. This makes &kommander; quick for developers. For end users it's much simpler than learning language constructs. For everyone it means you can focus on your task instead of having your reference material eternally at hand. Initially when people are exposed to a tool like &kommander; the first question is Where could I find a use for this cool tool? As it turns out, manipulating strings is used just about anywhere you look. + + + +So what can &kommander; do? Here is the list distilled to the base operations. +&kommander; can: + + + +Pass strings to the calling program via stdout. +Call executable programs. +Use &DCOP; to interact with &kde; programs + + + +If you're not a programmer you may want that in laymans terms. In number one, if you launch &kommander; from a console then the console is the calling program. There is a parent child relationship there. Sending a message to console is done with the standard output (stdout) of the child program, so named because there is also error output. This is interesting because some programs, like &quantaplus;, use stdout to receive information from programs they launch. So &kommander; dialogs can output their text strings directly into &quantaplus;'s editor if they are called from &quantaplus;. This means &kommander; dialogs can be useful extentions to programs. + + + +The second case is calling an executable. Any program that runs on your system is an executable. Even a script program is run by the script's interpreter so technically it's executed too. &kommander; can run commands just like the console even if you run it from the menu. So for instance if you wanted it to open &GIMP; you would have a button derive the string gimp and put it in a special like so: @exec(gimp). Just like that you will see &GIMP; open when using this. You could also exec ls -l too but you would only see the output if you were running from a console. + + + +The third case is very interesting indeed. &DCOP; is short for &kde;'s Desktop COmmunication Protocol and it is very powerful. Go ahead and run the kdcop program and have a look around. You'll quickly see that any &kde; application that is built to standards has things happening in &DCOP; and the well designed ones have a lot going on. With &DCOP; you can query information of all sorts as well as set widget values and more. There is a section on using &DCOP; in this manual. &kommander; can send &DCOP; to any &kde; program as well as be controlled by &DCOP;. In fact you can send &DCOP; from the command line to any &kde; program. So what's the big deal? The deal is, if you want to do any volume of commands you begin to realized that command line &DCOP; is adequate for short commands, but it can cause delays for instance being called from a loop several hundred times. This is why &kommander; has a @dcop special, because this is roughly 1000 times faster. Because &kommander; can send and receive &DCOP;, &DCOP; can be used to script &kommander;. That is why we also have a local &DCOP; special, @ldcop, that allows you to type a lot less to issue a command. + + + +Is that all the core concepts in &kommander;? No, but it should help you to make sense of how it works so that what is covered does not look like a foreign language to you. There are a few more. Signals and slots are how &kommander; handles events. An event in a program basically means something happened like a widget was created or had its text changed. These changes emit signals and you can connect those signals to a receiving slot which will then do something when the event happens. One use of this in &kommander; is the sibling of &kommander; Text, Population Text. Population Text will populate a widget when called. Just like &kommander; Text, Population Text can contain text strings or scripts. + + + +That should give you the base concepts to begin using &kommander;. We try to keep the number of Specials low and we use &DCOP; a lot. The idea is that we want to keep the power of &kommander; as consistent and streamlined as possible. You will find that you can incorporate any scripting language into &kommander; where ever you need to and even multiple scripting languages in a dialog. The rest of the information in this document assumes you are familiar with the concepts and terms presented here. The examples and tutorials are also very useful to understanding what can be done with &kommander;. + + + +&editor; + + +The Executor + + +The executor, called kmdr-executor, runs &kommander; scripts. It loads .kmdr files and dynamically produces a fully functional dialog. +Starting with version 1.3, the executor warns if the script file is not executable. This is an extra security feature that tries to make the user think about the possible bad consequences of running a script from untrusted source. The user can confirm to run the dialog or if he trusts the source, can make the script executable and get rid of the warning completely. +Version 1.3 supports the #!/path/kmdr-executor shebang in the beginning of the .kmdr script files (replace path with path to the +Such files if they are made executable can be run from command line just like any executable application, without the need to pass the script to kmdr-executor as argument. + +Remember, that once you add the shebang at the beginning of the file, the dialog cannot be run or edited with older versions of &kommander;. +The recommended usage is + +#!/usr/bin/kommander + +and create a symlink from kmdr-executor to /usr/bin/kommander. +The shebang can be added to a dialog directly from the editor, by modifying the useShebang and shebang properties for the main dialog. + + + + + +Executor for Programmers + + +C++ developers can easily use the Instance class in their C++ programs so that the execution functionality is embedded in the their application obsoleting the need for running the external executor program. For standard dialog the dialog creation overhead is minimal but the creation of the &kde; application may delay the dialog for around a second. + +Another approach is to use the kommander_part KReadOnlyPart. This KPart can load and execute any &kommander; dialog inside another KDE application. + + + + + +Creating a Dialog + +To learn about how to create a dialog, add widgets, use layouts, modify widgets properties, please consult the &Qt; Designer (version 3.x) manual. You can access it by running designer from the command line or from your desktop menu. + + +The extra functionality that &kommander; offers is the Kommander Text associated with each widget. These texts are the executable (script) part of the dialog, written either in a script language (with the old &kommander; syntax) or using the internal &kommander; language, the so called new parser. + +To learn more about the language syntax, commands and how to use the text editor, consult the upcoming chapters and check the examples shipped with the &kommander; source. + + + +Executable bit - new in 1.3 + +For security reasons we introduced the executable bit requirement in version 1.3. Some will applaud this as long overdue. Others will consider it a terrible annoyance or even too scarey to use. Unfortunately there is no perfect solution. The problem is that you can download a Kommander dialog from anywhere or get one in your email and click on it and run it by accident. Because Kommander can run shell scripts it is sort of in an odd place. While other applications don't nag you this way you actually had to install them so clearly you felt safe and intended to run them. A single line of shell scripting could permanently wipe out your home directory. Our intent is to eliminate an accidental click on an untrusted dialog. We aplogize for any inconvenience, but there is no way to do this to even the developer's satisfaction that it will not annoy you while keeping you safe. + + +You are not prevented from running a dialog, just nagged. You can make it go away by using a file manager or the shell to set the executable bit. Right click on the dialog in Konqueror, select properties from the menu, choose the permissions tab and check the is executable checkbox. Now the nag will be gone from this dialog forever. Check our web site for a tool that searchesfor &kommander; dialogs and allows you to review them and choose whether any or all of them should have the bit set. To use the shell and make all the &kommander; dialogs in a directory executable use this command. + + +chmod u+x *.kmdr + +Do not set dialogs as executable if you are not confident of their origin. + + +
diff --git a/doc/kommander/buttongroup.png b/doc/kommander/buttongroup.png new file mode 100644 index 00000000..d89e28fd Binary files /dev/null and b/doc/kommander/buttongroup.png differ diff --git a/doc/kommander/checkbox.png b/doc/kommander/checkbox.png new file mode 100644 index 00000000..ab6f53e0 Binary files /dev/null and b/doc/kommander/checkbox.png differ diff --git a/doc/kommander/closebutton.png b/doc/kommander/closebutton.png new file mode 100644 index 00000000..63903b30 Binary files /dev/null and b/doc/kommander/closebutton.png differ diff --git a/doc/kommander/combobox.png b/doc/kommander/combobox.png new file mode 100644 index 00000000..7d4890a7 Binary files /dev/null and b/doc/kommander/combobox.png differ diff --git a/doc/kommander/commands.docbook b/doc/kommander/commands.docbook new file mode 100644 index 00000000..87a6dc54 --- /dev/null +++ b/doc/kommander/commands.docbook @@ -0,0 +1,14 @@ + + + + +Command Reference + + +Reference + +&widgets; +&specials; +&dcop-functions; + + diff --git a/doc/kommander/contents.png b/doc/kommander/contents.png new file mode 100644 index 00000000..7596e67a Binary files /dev/null and b/doc/kommander/contents.png differ diff --git a/doc/kommander/credits.docbook b/doc/kommander/credits.docbook new file mode 100644 index 00000000..95c38541 --- /dev/null +++ b/doc/kommander/credits.docbook @@ -0,0 +1,59 @@ + + + + +Credits and License + + +Tamara +King +
+tik@acm.org +
+
+ + + +
+
+ +Credits and License + + +The &kommander; Development Team + +Britton, Marc consume@optusnet.com.au +Developer and documentation + + +King, Tamara tik@acm.org +Documentation + + +Laffoon, Eric sequitur@kde.org +Project manager and documentation + + +Mantia, András amantia@kde.org +Developer + + +Rudolf, Michal mrudolf@kdewebdev.org +Developer + + + + +&kommander; 2004 - 2008 &kommander; Development Team. + + + +&kommander; User Manual 2004 - 2008 &kommander; Development Team. + + + + +&underFDL; +&underGPL; + +
diff --git a/doc/kommander/datepicker.png b/doc/kommander/datepicker.png new file mode 100644 index 00000000..4bcc6450 Binary files /dev/null and b/doc/kommander/datepicker.png differ diff --git a/doc/kommander/dcop.docbook b/doc/kommander/dcop.docbook new file mode 100644 index 00000000..2fbf70a1 --- /dev/null +++ b/doc/kommander/dcop.docbook @@ -0,0 +1,203 @@ + + + + +&DCOP; Functions + + +&DCOP; Functions + + +&kommander; began accessing it's widgets internally with &DCOP;, which evolved to widget functions. &DCOP; is still available and can be used to share information between dialogs. It can also be used to extend and integrate nearly every existing KDE application. +&DCOP; can be called in several ways in &kommander;. First is the console method. Open a &kommander; dialog and open a console and try this. + +This is largely focused on the old parser. If you are looking for internal widget functions please see the new parser. This information is particularly relevent to communicating between dialogs and applications, or running other scripting languages inside Kommander as scripts. + +dcop | grep kmdr +dcop `dcop | grep kmdr` +dcop `dcop | grep kmdr` KommanderIf + + +This will show you what dialogs are running and what interfaces are available, as well as what is available to call in the &kommander; special interface to internals. In the explanation of &DCOP; here remember that &DCOP; is used internally by KDE applications (replaced with DBUS in KDE4) and it is very useful. Have a look at kdcop by pressing Alt-F2 and typing it in a run dialog. Here you can explore everything running. Now back to &DCOP; in &kommander;. + + +dcop kmdr-executor-@pid KommanderIf setText myWidget new text + + +This assumes you are inside a &kommander; file and have access to the special @pid which contains the process ID. In fact it is simpler to replace kmdr-executor-@pid with @dcopid. However, you can use this syntax (obviously without the specials) from the command line or any external script to alter the &kommander; window. + + +&kommander; evolved the much faster internal &DCOP; function. Using it from another application window (console &DCOP; is very slow) is more complicated because you must give lots of information, including a prototype of the call. The above call would become: (Note that @dcopid is actually internal to the dialog, but you could replace it with a valid process ID) + + +@dcop(@dcopid, KommanderIf, enableWidget(QString, bool), Widget, true) + + +In the early &kommander; nesting &DCOP; calls inside script language structures (like bash) used console method calls. If you use internal &DCOP; all &kommander; specials will be executed first and then the script will be executed. Please read that again as it will cause you no end of grief with a bash loop using &kommander; specials. + + +There is a new simplified way to use &DCOP; inside &kommander; using an object syntax. Let's say you want to change the text in a widget name @LineEdit1. It would look like this. + + +@LineEdit1.setText(New text) + + +As you can see the new syntax is very easy, as well as consistent visually with function groups. All the &DCOP; reference here will use the new object syntax listed above. Please note that if you are referencing a widget using &DCOP; from another window or another application the first parameter will always be the widget name. All functions are listed here starting with the second parameter. + + + +&DCOP; for Global Variables + + +global(QString variableName) + + +Returns the value of the specified global variable. When a script is run from within a &kommander; window any (non-global) variables set in that script will cease to exist after the script completes and therfore will not be available to other script processes or in a new instance of the calling process. The global scope means the variable will exist for any process of the window until that window is closed. You may change these variables at any time with a new call to @setGlobal. + + + + +setGlobal(QString variableName, QString value) + + +Creates a variable that is global to the window process and assigns the value to it. This value can be retrieved with global(QString variableName) or set again. + + + + + + + +&DCOP; for all Widgets + + +The following list is old and left here for reference purposes only. For a complete and current reference to all widget functions please look at the Function Browser which is available from any &kommander; text editor window by pressing the lower left button. These are now widget functions, not &DCOP; functions but the &DCOP; functions are published in the KommanderIf &DCOP; interface as described above. Dialogs for listing and constructing calls for this functionality are available at our web site. + + + +setText(QString text) + + +This removes the text displayed in the widget and replaces it with the text supplied. + + + + +enableWidget(bool enable) + + +Enables or disables a widget. + + + + +associatedText + + +Returns the text associated with the specified widget. This is not the same as the displayed text. It would be @widgetText or the text and/or scripting used to arrive at the displayed value. + + + + +setAssociatedText(QString text) + + +This sets the &kommander; Text default string. This is typically set to @widgetText to display what is entered into the widget. It is unlikely you will have much need for this, but if you do it is there. Applies to all widgets that can contain data. + + + + + + + +&DCOP; for ListBox and ComboBox Widgets + + +addListItem(QString item, int index) + + +Adds an item to a ListBox widget at the specified index. List index starts at zero. To add to the end of the list use -1. + + + + +addListItems(QStringList items, int index) + + +This adds a list of strings all at once. The list should be delimited by EOL (\n - newlines). This is handy as you can use bash to derive the list rather easily. For instance, using @exec(ls -l ~/projects | grep kmdr) for items will give you a directory listing of &kommander; files in your projects folder. List index starts at zero. Use -1 to add to the end of the list. + + + + +addUniqueItem(QString item) + + +addUniqueItem will add an item to the end of the list only if it is unique. + + + + +clearList + + +Removes all items. + + + + +removeListItem(int index) + + +Removes the item at the specified index. + + + + +item(int index) + + +Returns the text of the item at the specified index. + + + + +setCurrentListItem(int index) + + +Set the current (or selected) item to the index specified. Applies to ListBox and ComboBox widgets. + + + + + + + +&DCOP; for CheckBox and RadioButton Widgets + + +setChecked(QString widgetName, bool checked) + + +Checks/unchecks CheckBox or RadioButton widgets. + + + + + + + +&DCOP; for TabWidget Widgets + + +setCurrentTab(QString widgetName, int index) + + +Selected the tab by index for TabWidgets. Index starts at 0. + + + + + + + + diff --git a/doc/kommander/editor.docbook b/doc/kommander/editor.docbook new file mode 100644 index 00000000..3b288e9c --- /dev/null +++ b/doc/kommander/editor.docbook @@ -0,0 +1,642 @@ + + + + +The Editor + + +Tamara +King +
+tik@acm.org +
+
+ + + +
+
+ +The Editor + + +The editor is based on &designer;, a tool for designing and implementing user interfaces created by Trolltech. We have modified &designer; in the following ways: + + +Its interface is much simpler +Built in our own widgets +Added the ability to setup &kommander; Text +Various other superficial changes + + +For those of you already familiar with using &designer;, using the &kmdr-editor; will be trivial. + + + +Main Window + + + + + + + + +Toolbars contain a number of buttons to provide quick access to number of functions. +The File Overview displays all of the files. Use the search field to rapidly switch between files. +The Object Explorer provides an overview of the relationships between the widgets in a form. It is useful for selecting widgets in a form with a complex layout. +The Property Editor is where the behavior and appearance of a widget is changed. +The Dialog Editor is where dialogs are created and edited. + + + + +The File Menu + + + + + +&Ctrl;N + +File +New + +Creates a new dialog + + + + +&Ctrl;O + +File +Open + +Search the file system to open an existing dialog + + + +File +Open Recent + +Quick list of the last several files you've opened. This list will change each time you open a file that is not on it with the oldest being bumped off first. + + + +File +Close + +Closes the active dialog + + + + +&Ctrl;S + +File +Save + +Saves the active dialog + + + +File +Save As + +Saves the active dialog with another name + + + +File +Save All + +Saves all open dialogs + + + +File +Exit + +Quits &kommander; + + + + + + + +The Edit Menu + + + + + +&Ctrl;Z + +Edit +Undo + +Undo the last action performed. + + + + +&Ctrl;Y + +Edit +Redo + +Redo the last action undone. + + + + +&Ctrl;X + +Edit +Cut + +Cut the current item and place it content on the clipboard. + + + + +&Ctrl;C + +Edit +Copy + +Copy the current item to the clipbard. + + + + +&Ctrl;V + +Edit +Paste + +Paste the contents of the clipboard at the current cursor position. + + + + +&Ctrl;Z + +Edit +Delete + +Delete the current item. + + + + +Del + +Edit +Select All + +Select all of the items in the current dialog. + + + + +&Alt;R + +Edit +Check Accelerators + +Verifies that all the accelerators are used only once. + + + +Edit +Connectors + +Displays the view and edit connections dialog. + + + +Edit +Form Setting + +Displays the form setting dialog. + + + +Edit +Preferences + +Displays the preferences dialog. + + + + + + +The Tools Menu + + + + + +F2 + +Tools +Pointer + + + + + + +F3 + +Tools +Connect Signal/Slots + + + + + + +F3 + +Tools +Tab Order + + + + + + +Tools +&kommander; + + +Here there are listed all the &kommander; widgets. This widgets are guaranteed to be available on every system running the same (or higher) version of &kommander;. + + + + + +Tools +Custom + + +The widgets provided by the plugins will be listed under this menu entry. The dialogs using these widgets will run only if the plugin that provides them is installed and configured. + + + + + + + + + + +The Layout Menu + + + + + +&Ctrl;J + +Layout +Adjust Size + + + + + + +&Ctrl;H + +Layout +Lay Out Horizontally + + + + + + +&Ctrl;L + +Layout +Lay Out Vertically + + + + + + +&Ctrl;G + +Layout +Lay Out in a Grid + + + + + +Layout +Lay Out Horizontally (in Splitter) + + + + + +Layout +Lay Out Vertically (in Splitter) + + + + + + +&Ctrl;B + +Layout +Break Layout + + + + + +Layout +Add Spacer + + + + + + + + +The Run Menu + + + + + +&Ctrl;R + +Run +Run Dialog + +Runs the current dialog. + + + + + + +The Window Menu + + + + + +&Ctrl;F4 + +Window +Close + +Closes current dialog. + + + +Window +Close All + +Closes all dialogs. + + + + +&Ctrl;F6 + +Window +Next + + + + + + +&Ctrl;&Shift;F6 + +Window +Previous + + + + + +Window +Tile + + + + + +Window +Cascade + + + + + +Window +Views + + + + + + +Window +Views +File Overview + + + + + + + +Window +Views +Object Explorer + + + + + + + +Window +Views +Property Editor/Signal Handlers + + + + + + + +Window +Views +Line Up + + + + + + + + + +Window +Toolbars + + + + + + +Window +Toolbars +File + + + + + + + +Window +Toolbars +Edit + + + + + + + +Window +Layout +File + + + + + + + +Window +Toolbars +Tools + + + + + + + +Window +Toolbars +&kommander; + + + + + + + +Window +Toolbars +Custom + + + + + + + +Window +Toolbars +Help + + + + + + + +Window +Toolbars +Line Up + + + + + + + + + + + + +The Settings Menu + + + + +Settings +Configure Shortcuts + +See and modify the editor keyboard shortcuts. + + + +Settings +Configure Plugins + +Add or remove &kommander; plugins. The editor needs to be restarted after a new plugin is added. + + + +Settings +Configure Editor + +Configure the text editor used for modifying the Kommander text associated with widgets. + + + +Settings +Configure &kommander; + +Configure how the editor looks and works. + + + + + + +The <guimenu>Help</guimenu> Menu + + + + + + +&help.menu.documentation; + + + + +
diff --git a/doc/kommander/editor.png b/doc/kommander/editor.png new file mode 100644 index 00000000..6c0db299 Binary files /dev/null and b/doc/kommander/editor.png differ diff --git a/doc/kommander/extending.docbook b/doc/kommander/extending.docbook new file mode 100644 index 00000000..a5b38b05 --- /dev/null +++ b/doc/kommander/extending.docbook @@ -0,0 +1,440 @@ + + + + + + +Andras +Mantia +
amantia@kde.org
+
+ +Michal +Rudolf +
mrudolf@kdewebdev.org
+
+ + + +
+
+Extending &kommander; + + +Creating &kommander; Widgets + +With &kommander; you can create new widgets based on non-&kommander; widgets +fairly easily. + +There are two ways of adding new widgets to &kommander;: by creating +plugins or by adding it directly to the &kommander; source. + + +Create the widget class + + The first step is to create the widget class. The approach is to derive your new &kommander; widget class from the +&Qt;/&kde; widget which you wish to integrate with &kommander;, and then also from the +KommanderWidget class. Overriding methods from this class gives the &kommander; +widget its functionality. + + +Most of the code of a &kommander; widget is just template code. +Therefore, you can use the KDevelop &kommander; plugin template to generate +most the &kommander; widget code for you. To do so run KDevelop (3.5 is recommended), +select Project->New Project, tick the Show all project templates checkbox, +select the C++/&kommander;/KommanderPlugin template. Give a name for your plugin and +follow the instructions in the wizard. + + +All you have to do is fill in the +important parts relating to your widget like any state information, widget text +etc. + + +Let's say we want to create a new line edit widget for &kommander;, +based on the KDE widget KLineEdit. Using the &kommander; widget generator +dialog, we get something like this in the generated header file: + + +#include <kommanderwidget.h> + +class QShowEvent; +class KomLineEdit : public KLineEdit, public KommanderWidget +{ + Q_OBJECT + + Q_PROPERTY(QString populationText READ populationText WRITE setPopulationText DESIGNABLE false) + Q_PROPERTY(QStringList associations READ associatedText WRITE setAssociatedText DESIGNABLE false) + Q_PROPERTY(bool KommanderWidget READ isKommanderWidget) + +public: + KomLineEdit(QWidget *a_parent, const char *a_name); + ~KomLineEdit(); + + virtual QString widgetText() const; + + virtual bool isKommanderWidget() const; + virtual void setAssociatedText(const QStringList&); + virtual QStringList associatedText() const; + virtual QString currentState() const; + + virtual QString populationText() const; + virtual void setPopulationText(const QString&); +public slots: + virtual void setWidgetText(const QString &); + virtual void populate(); +protected: + void showEvent( QShowEvent *e ); +signals: + void widgetOpened(); + void widgetTextChanged(const QString &); +}; + +Most of this is just template code that you don't need to worry about. +The only two things you need to take notice of are that the kommanderwidget.h +file is included at the top, and that the class is derived first from the +widget we wish to integrate with &kommander;, and secondly from KommanderWidget. + + +There are a few parts in the cpp file that are important to each particular widget. + + +KomLineEdit::KomLineEdit(QWidget *a_parent, const char *a_name) + : KLineEdit(a_parent, a_name), KommanderWidget(this) +{ + QStringList states; + states << "default"; + setStates(states); + setDisplayStates(states); +} + +In the constructor, we set the states this widget may have. +Our line edit doesn't have any kind of state, so we just +give it one state default. If you were creating a widget +that had different kinds of states, such as a check box, you might +set three states unchecked, semichecked and checked here. + + +QString KomLineEdit::currentState() const +{ + return QString("default"); +} +We set the states in the constructor above, and this just +returns the current state of the widget. For our widget +it will always be default, but you should put code here +that checks what state your widget is currently in and +return the appropriate string here. + + +QString KomLineEdit::widgetText() const +{ + return KLineEdit::text(); +} + +void KomLineEdit::setWidgetText(const QString &a_text) +{ + KLineEdit::setText(a_text); + emit widgetTextChanged(a_text); +} + +These are the two most important methods, where the bulk of the +functional code goes. +QString KomLineEdit::widgetText() const method returns the widget text of the +widget (the text that the @widgetText special is expanded to in text +associations). For our widget, the widget text is simply the text inside +the line edit, so we just return that. Similarly when setting the widget text, +we just set the text inside the line edit. We emit the widgetTextChanged() +signal after setting the widget text so other widgets can recognize the fact +that this widget was updated. + + +In order to add functionality to the widget, you need to register some function and add code to handle them. Here is the code to be used to register, put it in the beginning of the cpp file, above the constructor: + + +#include <klocale.h> //for i18n + +#include "kommanderplugin.h" +#include "specials.h" + +enum Functions { + FirstFunction = 1159, + Function1, + Function2, + LastFunction +}; +KomLineEdit::KomLineEdit(QWidget *a_parent, const char *a_name) + : KLineEdit(a_parent, a_name), KommanderWidget(this) +{ + ... //code like described above + KommanderPlugin::setDefaultGroup(Group::DCOP); + KommanderPlugin::registerFunction(Function1, "function1(QString widget, QString arg1, int arg2)", i18n("Call function1 with two arguments, second is optional."), 2, 3); + KommanderPlugin::registerFunction(function2, "function2(QString widget)", i18n("Get a QString as a result of function2."), 1); +} + +This registers two functions: function1 and function2. The number assigned to the functions (here 1160 and 1161) must be unique, not used in any other plugin or +inside &kommander;. function1 takes two arguments, one is optional, function2 takes no argument and returns a string. The QString widget argument in the signatures notes that this functions work on a widget, like: KomLineEdit.function1("foo", 1). + +To teach &kommander; that the widget supports these functions, add a method like this: + + +bool KomLineEdit::isFunctionSupported(int f) +{ + return (f > FirstFunction && f < LastFunction) || f == DCOP::text; +} + +This means that KomLineEdit supports the above functions and the standard text +function. +The function code should be handled inside the handleDCOP method: + + +QString KomLineEdit::handleDCOP(int function, const QStringList& args) +{ + switch (function) + { + case function1: + handleFunction1(arg[0], arg[1].toInt()); //call your function1 handler + break; + case function2: + return handleFunction2(); //call function2 + break; + case DCOP::text: + return text(); //call the standard KLineEdit::text() method + break; + default: + return KommanderWidget::handleDCOP(function, args); + } + return QString::null; +} + +There are cases when the widget should appear differently in the editor than in +the executor, like the case of ScriptObjects, about dialog, etc. The usual solution is to show a QLabel instead of the widget. For this, your widget must +derive from QLabel, and use this in the constructor: + + + if (KommanderWidget::inEditor) + { + setPixmap(KGlobal::iconLoader()->loadIcon("iconname", KIcon::NoGroup, KIcon::SizeMedium)); + setFrameStyle(QFrame::Box | QFrame::Plain); + setLineWidth(1); + setFixedSize(pixmap()->size()); + } + else + setHidden(true); + +You can create the widget itself (if you need a widget at all, maybe your +"widget" provides only functionality to access e.g databases) in one of your +functions, like in the execute function. Here is an example from the AboutDialog widget: + + +QString AboutDialog::handleDCOP(int function, const QStringList& args) +{ + switch (function) { + ... + case DCOP::execute: + { + if (m_aboutData) + { + KAboutApplication dialog(m_aboutData, this); + dialog.exec(); + } + break; + } + ... +} + +You now have a complete &kommander; widget. All that's left +to do is make it available to the &kommander; system via plugins. + + + + + +Create the &kommander; plugin + +All of the widgets in &kommander; are provided by plugins. +The standard widgets are loaded as widget plugins, but the &kommander; editor +is also linked against this library because certain mechanisms in the editor +are tied specifically to the standard widgets. + + +A plugin in &kommander; is simply a shared library that has the symbol +'kommander_plugin'. This symbol is a function returning a pointer +to an instance of a KommanderPlugin class. + + +&kommander; makes it easy to create a plugin for you widgets, so you don't +need to worry about this low level stuff. The basic idea is to derive +a new plugin class for your widgets from the KommanderPlugin base class +and implement a few specific details. A template code is generated by the above described KDevelop project template. + +The following code continues on our example of creating a Kommander line edit +widget. + + +#include <kommanderplugin.h> + +/* WIDGET INCLUDES */ +#include "komlineedit.h" + + + +First thing we do is include kommanderplugin.h. This contains the definition +of the KommanderPlugin class. We also include all header files of the widgets +this plugin provides - only komlineedit.h in this case. + + +class MyKomPlugin : public KommanderPlugin +{ +public: + MyKomPlugin(); + virtual QWidget *create( const QString &className, QWidget *parent = 0, const char *name = 0 ); +}; + + +We then create a KommanderPlugin sub-class called MyKomPlugin. +This class simply has a constructor and an overridden create method. + + +MyKomPlugin::MyKomPlugin() +{ + addWidget( "KomLineEdit", "My Widget Group", i18n("A Kommander line edit widget") new QIconSet(KGlobal::iconLoader()->loadIcon("iconname", KIcon::NoGroup, KIcon::SizeMedium))); + //add my other widgets here +} + +In the constructor of the plugin, we call addWidget() for each widget we wish +to provide in this plugin. addWidget() takes 6 arguments but only the first 4 +are required. In order, the arguments are the widget's class name, group, +tool tip, an iconset for the icon used in the editor toolbar, what's this information, and a bool indicating whether the widget +is a container for other widgets or not. This information is used +by the editor when grouping your widget in menus, providing help information +etc. + + +Regarding the icon, the above example loads a medium sized icon called iconname from the standard &kde; icon location. + + +QWidget *MyKomPlugin::create( const QString &className, QWidget *parent, const char *name ) +{ + if( className == "KomLineEdit" ) + return new KomLineEdit( parent, name ); + //create my other widgets here + return 0; +} + + +create() is where instances of our widgets actually get created. +Whenever &kommander; wants an instance of one of the classes provided +by our plugin, it will call create() with the name of the class it wants, +and the parent and name that should be used. +If the className matches any widget we know about, we return a new instance +of that class but otherwise we return 0. + + +Finally, we export our plugin. This just provides an entry point to our +plugin so the &kommander; system can get access to it. Without this, +&kommander; will not recognize your library as a &kommander; plugin. + + +KOMMANDER_EXPORT_PLUGIN(MyKomPlugin) + + +To compile your new &kommander; extension, you should compile all files +as a shared library, linking against the kommanderplugin, kommanderwidget +and any appropriate KDE libraries. +With the line edit example, if we had komlineedit.h, komlineedit.cpp and +mykomplugin.cpp, compiling and installing your plugin would involve +something similar to the following commands: + + +libtool --mode=compile g++ -$KDEDIR/include -IQTDIR/include \ + -I. -fPIC -c komlineedit.cpp +libtool --mode=compile g++ -$KDEDIR/include -IQTDIR/include \ + -I. -fPIC -c mykomplugin.cpp + +libtool --mode=link g++ -shared -L$KDEDIR/lib -lkdeui -lkommanderwidget \ + -lkommanderplugin komlineedit.cppkomlineedit.o mykomplugin.o + -o libmykomplugin.so + + +If you want to install new plugin system-wide, root, use: + + +su -c "cp libmykomplugin.so $KDEDIR/lib" + +If you use the KDevelop project generator, you will not need to do the above, but instead adapt the Makefile.am to link against extra libraries. By default, it will link to &Qt; and &kde; libraries and generate all the needed object files. Just run make to build, and su -c make install to install. + + +Configure the installed plugins + +Now that the plugin is installed, run the kmdr-plugins program or choose Settings->Configure Plugins from the Editor. The list in this program displays the +plugins that are currently loaded by &kommander;. Add the new plugin to the +list by clicking the Add button in the toolbar and choosing your plugin. +Closing the program saves changes. + + +If you now restart the &kommander; editor, the widgets your new plugin +provides should be available in the menus and toolbars. You can +now use your new widgets in &kommander; dialogs. + + + +Add the widget directly to &kommander; +This section is for &kommander; developers and describes how to add a new widget directly to &kommander;. + +Ironically, this one is more complicated, especially if the widget needs +extra editing methods. +First you create the widget like above. After that you need to register the +widget to the editor and the executor. +To register it inside the editor, add it to editor/widgetdatabase.cpp: + + +... +#include "mywidget.h" +... +void WidgetDatabase::setupDataBase( int id ) +{ + ... + r = new WidgetDatabaseRecord; + r->name = "MyWidgetName"; + r->iconName = "icon.png"; + r->group = widgetGroup( "Kommander" ); + r->toolTip = i18n("My new widget"); + append(r); + ... +} + + +You need to add to the editor/widgetfactory.cpp as well: + + +... +#include "mywidget.h" +... +QWidget *WidgetFactory::createWidget( const QString &className, QWidget *parent, const char *name, bool init, + const QRect *r, Qt::Orientation orient ) +{ + ... + else if (className == "MyWidgetName") + return new MyWidget(parent, name); + ... +} + + +To register to the executor (actually to the plugin system), add this to +widgets/plugin.cpp: + + +KomStdPlugin::KomStdPlugin() +{ + ... + addWidget("MyWidgetName", group, "", new QIconSet(KGlobal::iconLoader()->loadIcon("iconname", KIcon::NoGroup, KIcon::SizeMedium))); + ... +} + +This is similar to how the widget is registered via the plugin system in the +first case. + + + + +
diff --git a/doc/kommander/frame.png b/doc/kommander/frame.png new file mode 100644 index 00000000..e9fd684d Binary files /dev/null and b/doc/kommander/frame.png differ diff --git a/doc/kommander/glossary.docbook b/doc/kommander/glossary.docbook new file mode 100644 index 00000000..b8434888 --- /dev/null +++ b/doc/kommander/glossary.docbook @@ -0,0 +1,39 @@ + + + + + + + +Tamara +King +
+tik@acm.org +
+
+ + + +
+
+ + +Keywords + +Text Association + + +A piece of text that is associated or bound to a widget's particular state. + + + + +Widget Text + + +Text associated to a widget. This is represented in &kommander; with the special @widgetText. The widget text varies depending on the widget. + + + + +
diff --git a/doc/kommander/groupbox.png b/doc/kommander/groupbox.png new file mode 100644 index 00000000..4025b4dc Binary files /dev/null and b/doc/kommander/groupbox.png differ diff --git a/doc/kommander/index.docbook b/doc/kommander/index.docbook new file mode 100644 index 00000000..71582056 --- /dev/null +++ b/doc/kommander/index.docbook @@ -0,0 +1,121 @@ + +Kommander"> + + + + + + + + + + + + + + + + + + &Qt; Designer"> + + + The GIMP"> + IDE"> + PHP"> + PID"> + + +]> + + + + +The &kommander; Handbook + + + +Marc +Britton + +
consume@optushome.com.au
+
+
+ +Tamara +King + +
tik@acm.org
+
+
+ +Eric +Laffoon + +
eric@kdewebdev.org
+
+
+ +AndrĦs +ManĊ£ia + +
amantia@kde.org
+
+
+ + + +
+ + +2008 +&kommander; Development Team + + +&FDLNotice; + + + +2008-02-12 +3.2.95 + + + + +These docs have been partially complete for years, but not always available or easy to find. Since around 2002 little spurts of effort on &kommander; have produced dramtic results. &kommander; is a new approach to development and there have been modifications in approach and features. Consequently much of this documentation is out of date, however still useful due to legacy support. Please refer to our web site at http://kommander.kdewebdev.org for up to date information, news on KDE4 development, new tools, plugins, tips and tutorials. + +&kommander; is a set of tools that allow you to create dynamic &GUI; windows that has been used as a front end for command line programs, database front ends, simple program extentions and much more. The best part of it all? You aren't required to write a single line of code! Okay, that was old text... You can actually use the function browser and even with the new parser write almost none of the code. The inherent difference between &kommander; and other &GUI; scripting tools is that &kommander; doesn't care about how the window gets drawn. &kommander; was designed from the GUI down to the language elements and can embrace multiple languages. &kommander; does not use scripting to draw a window on the screen like other &GUI; scripting tools. As Kommander matures it will expose all it's internals to any scripting language people want to enable. We welcome anyone wishing to enhance support for any scripting language. + + + + + + +KDE +Kommander +Quanta + + +
+ +&introduction; +&basics; +&commands; +&parser; +&extending; +&translating; +&tutorials; +&q-and-a; +&credits; +&installation; +&glossary; + +
\ No newline at end of file diff --git a/doc/kommander/installation.docbook b/doc/kommander/installation.docbook new file mode 100644 index 00000000..707df7a0 --- /dev/null +++ b/doc/kommander/installation.docbook @@ -0,0 +1,50 @@ + + + +Installation + + +How to obtain &kommander; + + + +&install.intro.documentation; + +There is a dedicated homepage for &kommander; at http://kommander.kdewebdev.org. + + + + +Requirements + + + +&kommander; requires the latest version of &kde; 3.x series, currently 3.5.9. It might work with previous 3.5.x versions, but this was not tested throughfully. + + + + + +Compilation and Installation + + + + + +&install.compile.documentation; + + + + diff --git a/doc/kommander/interface.png b/doc/kommander/interface.png new file mode 100644 index 00000000..3cae0ef4 Binary files /dev/null and b/doc/kommander/interface.png differ diff --git a/doc/kommander/introduction.docbook b/doc/kommander/introduction.docbook new file mode 100644 index 00000000..7b40475a --- /dev/null +++ b/doc/kommander/introduction.docbook @@ -0,0 +1,134 @@ + + + + +Introduction + + +Eric +Laffoon + +
sequitur@kde.org
+
+
+ + + +
+
+ +Introduction + + +&kommander; is a visual dialog building tool which can be used to create +full mainwindow applications, provided the window is initially created in Qt Designer +or from a template in &kommander;. The primary objective is to create as much +functionality as possible with the absolute minimum use of scripting. This is +provided by the following features: + +Please note this document includes legacy documentation for compatibility reasons. In a nutshell &kommander; offers extremely rapid development and extensive abilities and capabilities. Following is a new list, followed by the legacy content. + + + +Capable internal scripting - &kommander; now offers nested logic structures, simple arrays and useful functions + + +Function Browsers - One never need know exact syntax for any function or command, just click the button and point and click your way to a functional program. Even the project lead finds it easier than typos much of the time. + + +Extensive widgets - &kommander; now has a tree/detail widget, spreadsheet like table widget, font dialog, color dialog, about dialog, timer, tab widgets, toolbox, popup menus, date picker and a lot more. + + +Plugins - &kommander; can run easy to create plugins. Plugins as of this writing are a database plugin offering a set of non visual tools, an HTTP plugin offering HTTPS and access to password protected areas and a KPart loader. + + +Scripting language support - The ability to run multiple scripting language in &kommander; scripts, inside your dialog + + +KPart creation - the ability to make your own plugins... and stranger yet you can even make a &kommander; window load a dialog as a KPart and directly access it with &kommander; functions! + + +Look for documentation on tips and tricks like how to make &kommander; fake programming techniques like including a file, creating and using custom widgets, making collapsable panels in windows and other unexpected tricks. Below is our legacy list. + + + +Specials are prefaced with an @ like @widgetText. The offer +special features like the value of a widget, functions, aliases, global +variables and such. + + +&DCOP; integration allows &kommander; dialogs to control and be +controlled in interactions with other &kde; applications. It is a very powerful +feature! + +Signals and Slots is a little less intuitive to a new user. It is +under review for how we process things in the first major release. These +offer a limited event model for when a button is pushed or a widget is +changed. Combined with Population Text it is rather powerful. + + + +The central key feature of &kommander; dialogs is that you can bind text +(&kommander; Text) to a widget. So if you have @widget1 and @widget2 and +they are line edits you can set &kommander; to show their contents by +entering @widgetText in their &kommander; Text area. Then enter hello in +@widget1 and world in @widget2. A button can have the string +My first @widget1 @widget2 program in &kommander; +If you run this dialog from a console it will output +My first hello world program in &kommander; + + + +Hopefully you begin to see a small glimmering of the potential. &kommander; +enables a much faster design model for simple applications because if allows +you to stop thinking so much about language and revert to the more basic and +natural conceptual model. In computers language is a means to define concepts +and as such it is a layer between concept and implementation that can impede +progress with minutia. &kommander; seeks to minimize that layer. + + + +&kommander; also seeks to build on standards. It is built on the &Qt; Designer +framework and creates *.ui files which it renames to *.kmdr. It can easily +import any &kde; widget and this can be done without having to rebuild +&kommander;, by using plugins. + + + +&kommander;'s other significant factor is how it addresses the requirements of +language. Computer languages can be wonderful things but they tend to have +their own dogmas and zealots often seeking to provide an advance to &GUI; +design in an integrated development environment. Ironically the acceptance +of such &IDE;s is limited by the number of people willing to adopt a new new +language to gain access to a desired feature. It is really not reasonable to +expect people to need to change over to a dozen languages to access various +feature sets. By being language neutral and allowing a &kommander; dialog to be +extended by using any scripting language &kommander; positions itself in a +unique position for wide spread adoption. Multiple script languages can be +used in a single dialog and applications can be taken over by people using +a different language than the original developer and gradually converting +and extending it. New widgets and features can be instantly leveraged by all +available languages. + + + +We hope that &kommander; begins to get the developer support and recognition +required to achieve the potential it offers. Our end goal is to make &kommander; +useful for novice users to extend and merge their applications. At the same +time it should become a good prototyping tool. Also it opens the door to the +promise of open source in a new way. We know that people can extend our GPL'd +programs, but the fact remains very few have the skills. With &kommander; those +numbers see a huge multiplier! Some applications may be most logical as a +&kommander; application. We already use it in areas we want to allow +extensibility in &quantaplus;. + + + +We hope you enjoy &kommander;. Please help us with bug reports and example +dialogs, as well as any requests you may have. You can join our user list +for help developing &kommander; applications. + + +Best Regards from the &kommander; development team! + +
diff --git a/doc/kommander/kfontcombo.png b/doc/kommander/kfontcombo.png new file mode 100644 index 00000000..87835d6c Binary files /dev/null and b/doc/kommander/kfontcombo.png differ diff --git a/doc/kommander/kommander.png b/doc/kommander/kommander.png new file mode 100644 index 00000000..f14697d6 Binary files /dev/null and b/doc/kommander/kommander.png differ diff --git a/doc/kommander/konsole.png b/doc/kommander/konsole.png new file mode 100644 index 00000000..3e60f289 Binary files /dev/null and b/doc/kommander/konsole.png differ diff --git a/doc/kommander/label.png b/doc/kommander/label.png new file mode 100644 index 00000000..5d7d7b4c Binary files /dev/null and b/doc/kommander/label.png differ diff --git a/doc/kommander/lineedit.png b/doc/kommander/lineedit.png new file mode 100644 index 00000000..dafdfdf3 Binary files /dev/null and b/doc/kommander/lineedit.png differ diff --git a/doc/kommander/listbox.png b/doc/kommander/listbox.png new file mode 100644 index 00000000..d467fc9f Binary files /dev/null and b/doc/kommander/listbox.png differ diff --git a/doc/kommander/listview.png b/doc/kommander/listview.png new file mode 100644 index 00000000..d71cc1c9 Binary files /dev/null and b/doc/kommander/listview.png differ diff --git a/doc/kommander/multilineedit.png b/doc/kommander/multilineedit.png new file mode 100644 index 00000000..e7f6db94 Binary files /dev/null and b/doc/kommander/multilineedit.png differ diff --git a/doc/kommander/parser.docbook b/doc/kommander/parser.docbook new file mode 100644 index 00000000..a008c431 --- /dev/null +++ b/doc/kommander/parser.docbook @@ -0,0 +1,751 @@ + + + + +&kommander; New Parser + + +Michal + +Rudolf + +
mrudolf@kdewebdev.org
+
+
+ +Eric + +Laffoon + +
eric@kdewebdev.org
+
+
+ +
+ +2005-2008 +Michal Rudolf +Eric Laffoon + +&FDLNotice; +
+ +New Parser Documentation + +The new parser was introduced in &kommander; with version 1.2, released with +KDE 3.4. This document was originally released to show all the features of new parser. +As of &kommander; 1.3, released with KDE 3.5.9, the new parser is now the default, except for MainWindow applications created in &Qt; Designer. Because +the new parser is so much richer in ability, overcomes the limitations of nesting in the +old parser and adds so many new features we strongly recommend using it. + + +&kommander; itself will not be described here. Please refer to other documents to +see what is &kommander; for, how to create dialogs and how to manipulate widgets +on runtime. + + + +Old parser + +Here we compare the two parsers. While we advocate the new one for most purposes the old one is still +supported and useful, particularly when working with other scripting languages. + + + +Old parser + +The old parser was in fact macro parser. Only strings beginning with @ were +recognized, locally parsed and expanded. + +@LineEdit1.setText(@ListBox.selection) + + + + +All the underlying functionality (local variables, expressions, file manipulation) +had to be done in another scripting language, such as Bash. While the intent with &kommander; is to support +all other scripting languages, and this is presently possible to some degree, there +was a need for a fast, native scripting language that was assured to be portable. +The biggest problem with the old parser is that the &kommander; specials are evaluated before the code is passed to the scripting language, making them impossible to use in loops and conditions. + +The developers considered bash slow and not friendly to new users, and the old parser +had been initially bash calling DCOP. The paradox for &kommander; being language neutral +resulted in a need to do more than just functions natively. + + + + +New parser + +The new parser is a full parser. It parses the whole script, not just functions. As we were interested +in GUI interaction, not the proliferation of scripting languages, we made compromises. +As a result you should find &kommander;'s scripting to be capable for most basic tasks +and natural and easy to use. There is also the Function Browser, which will help you +assemble statements. The Function Browser is intended to make &kommander; accessible to complete novice +programmers. It is similar to what you would find in KSpread to help you choose a function +and fill in the parameters. +If you want enhanced functionality found in other languages you can include +them in &kommander; script objects headed with a shebang. While in these scripts the Function +Browser will help you insert references to widgets. Just remember when using this functionality +that the parser makes one pass for the old parser functions and one pass for your script. So if you +try to change something in a widget and read it in the middle of a script you may not get what you expect. + +#!/usr/bin/php + + +The following feature list is from version 1.2 + +local and global variables and associative arrays +numerical expressions +string manipulation +various structure commands: if, while, for, foreach +most functions from old parser +direct widget manipulation +many additional functions +decent execution speed +receive parameters from signals in script slots + +This list is from version 1.3 + +pass parameters and receive them with script execute calls +return a value from a script +create widgets on the fly +connect signals and slots on the fly +use a variable alias for a widget name +simple indexed array functions +directly access a widgets slots + + + + +Invoking new parser + +To enable new parser, set useInternalParser property of the dialog to +true. You can also enable new parser in a single script by putting + +#!kommander + +on the first line of the script. Also note if you are using another scripting language in +a script with a shebang that &kommander; automatically enables the old parser for interacting +with the dialog. + +#!/bin/bash +echo @Self.item(0) +# returns first parameter passed to script +# echo $returnvalue passes back to calling script + + + + + + +New Parser Features + + +Types + +Each value is of one of three types: string, integer or double. Type conversion is +automatic and chooses most appropriate type (for example, if you add double to integer, +result will be double). If one of the values is string, result will be string too. + +Places you can get into trouble here are getting a numerical value from a widget +and trying to perform a mathematical function on it. Since &kommander; uses + +to concatonate two strings of text it can treat LineEdit1.text + 2 as +22 instead of 2. See the conversion functions in +String functions to avoid problems. + + + + +Expressions + +The following mathematical operators are supported: +, -, *, mod, . Standard brackets +are of course supported as well. + + + +All kinds of comparisons are supported: <, >, <=, +>=, ==, !=. Instead of +!= you can also use <>. +Also, logical operators and, or, not +are supported, as well as their C equivalents (&&, ||, !). + + + +For strings you can use + operator for string concatenation. + + + +Some examples of valid expressions: + +2+3 +-5 * (2 - 13 mod 3) +"This list has " + 12 + "items." + + + + + +Variables + +Variables don't need to be declared. Once you use variable, it is considered declared. +Type of a variable is recognized automatically and can be changed later. + + + +Associative arrays are supported as well. They map string keys onto values of any type. To declare +such array, you can just add some element to it, for example: A["Quanta"] = "Web editor". +Arrays are also handled by foreach command and +array functions. + + + +Local and global variables are supported. Global variables are marked by leading underscore. +So, myVar is a local variable, but _myVar is global. The same applies +to arrays. + + + +a = 5 +b = 2 * 5 - (a + 1) +c = "[Item " + b + "]" +d["MyKey"] = "MyValue" +d["MyKey2"] = 5 + + + +Using variables for widgets works much as you would expect. This is useful when looping widgets into a table. + + + +for i=0 to 10 do + mycombo = "ComboTable"+i + createWidget(mycombo, "ComboBox", "Form1") +end + + + + +Comments + +You can use comments in &kommander; using the two traditional program language comment forms for line comments. For those users who are new to programming wondering what traditional form? see below. You can copy and paste the text below into a button or dialog initialization and see how comments behave in action. + + +// this is a comment for one line +message_info("Hello World") //traditional first program +// the above comment also ignored - the messagebox is not +# this is also a comment +message_info("This message will show") + + +Using the following multi-line comment will not work and will cause the rest of the widget execution to fail. + + +/* +Hi, I was supposed to be a comment +None of the script after this will execute +DON'T USE THIS TYPE OF COMMENT IN KOMMANDER! +*/ + + + + +Built in Globals + +&kommander; has some built in globals you may find handy. + + + +_ARGS - the argument string passed to the dialog on opening + + +_ARGCOUNT - the count of arguments passed. These can be retrieved as ARG1 to ARGn where n is the total number of args passed + + +_KDDIR - the directory from which the dialog was run. &kommander; will default to your home directory, or a directory change if asked for it's current directory. This is useful for saving and reading files with the &kommander; file. + + +_NAME - there is no reason to use this so don't + + +_PID - the process id the current dialog is being run from - also available as just pid Avoid using this name for your variables! + + +_VERSION - this is handy if you want to display the version of &kommander; that is running + + + + +Passing arguments in &kommander; +You can pass arguments via script parameters, signals and slots, command line parameters and DCOP. Let's look at scripts. Call your script like: +result = ScriptObject1.execute("Hello World") +debug(result) +Inside your script you might have the following +var = str_upper(Self.Item(0)) +return(var) +Now you will get a return in your Stderr message log of HELLO WORLD + +Receiving a signal connected to a script slot works the same way. Self.Item(0) is parameter one and so on. You can retrieve the count of arguments passed with ScriptObject.count. + +Command line parameters allow for named or unnamed arguments. Unnamed look like +kmdr-executor myprog.kmdr 100 red +Where you will find _ARG1 = 100 and _ARG2 = red. One quirk is passing strings with spaces as an argument means they need to be quoted. Using the dialog command complicates matters as the entire argument string must pass as one string, meaning in quotes. +dialog("mydialog.kmdr", 100+" \"Hello World\"") +This returns _ARG1 = 100 and _ARG2 = Hello World. Without the escaped quotes you would have _ARG2 = Hello and _ARG3 = World. Using Named Parameters is rather nice and potentially less confusing. +dialog("mydialog.kmdr", "xcount=100 xquote=Hello world") +And now you access those with _xcount and _xquote global variables. + + +DCOP can be complex, which is why we recommend using the tools we develop to enable creating DCOP for remote &kommander; dialogs with something like a function browser. Here is an example DCOP call issued from a dialog opened from a parent &kommander; window. Since it knows who its parent is it can send information back while it is open and freely access all its parent's functionality with the exception of slots. Of course that can be done internally with a script which can be called externally, so in practice there is no limit to what can be done. +dcop("kmdr-executor-"+parentPid, "KommanderIf", "setText(QString,QString)", "StatusBar8", "Hello") +Let's look at this piece by piece. First of all we add parentPid to "kmdr-executor-" as we make no assumption a &kommander; window was the caller. You could use this with Quanta or KSpread or whatever. Next we are addressing KommanderIf, which is a nice interface for end users which has been cleaned up. We hope eventually as KDE moves from DCOP to DBUS on KDE4 that more applications adopt a nice interface for integration. The next parameter, "setText(QString,QString)" is important because it prototypes the parameters allowed. Otherwise &kommander; could not validate the call. So without a definition of the DCOP call being used you will get an error. The remaining parameters are of course what is being passed. We recommend you look at applications with kdcop to see how this works and practice dcop calls from the shell to get your syntax right. + + + + + + +Commands + +Various structure commands are supported. They can be freely nested. + + + +There are also three special commands: exit, break and continue. +The first one ends script execution and returns. The second exits current block (while, +for or foreach and the third exits just a current step, restarting +from the beginning of the loop. + + + + +if + +Command if has following syntax: + + + +if condition then +code elseif condition +then code else +code endif + + + +Both elseif and else parts are optional. Condition +is any expression. Code is executed if condition is true. That means: + +non-zero for integers and double +non-empty for strings + + + + +if a * 2 > 7 then + b = 1 +elseif a < 0 then + b = 2 +elseif + b = 0 +endif + + + + +while + +while condition do +code end + + + +Condition is recalculated each time loop is executed. + +while i < 15 do + i = i + a +end + + + + + + + +for + +Command for has following syntax: + + + +for variable = +start value to end value +step expression do +code end + + + +Loop is executed starting from start value and it is ended when variable's value is +bigger then end value. If step part is specified, on each step +variable's value is increased by given value instead of 1. + +foreach i = 1 to 20 step 5 do + a = a + 2 * i +end + + + + + +foreach + +Command foreach has following syntax: + + + +for variable in +array do +code end + + + +Loop is executed for each key in given array. In each step variable is assigned the next key from the array. + + +sum = 0 +foreach i in myArray do + sum = sum + myArray[i] +end + + + + + + + +Functions + +Most old parser functions are supported by new parser. Also, some new functions were added. + + + + +String functions +String functions are the same as in old parser, the only difference is that their names +are preceeded by str_ instead of @String. + + + +str_length(string) - returns length of string + + +str_contains(string, text) - returns 1 if string contains text + + +str_find(string, text, start) - returns position of the first occurrence of text in string; optional start + specifies start of the search + + +str_find(string, text, start) - returns position of the last occurrence of text in string; optional start + specifies start of the search + + +str_left(string, count) - returns first count characters of string + + +str_right(string, count) - returns last count characters of string + + +str_right(string, start, count) - returns substring of string starting from start and containing count +characters (or everything to the end of the string if last parameter is not specified) + + +str_remove(string, text) - returns string with all substrings equal to text removed + + +str_replace(string, text, text2) - returns string with all substrings equal to text replaced with text2 + + +str_lower(string) - returns string converted to lowercase + + +str_upper(string) - returns string converted to uppercase + + +str_section(string, separator, start, +end) - returns substring containing appropriate sections of string determined +by separator; if no end is given, single start section is returned + + +str_args(string, ...) - returns string with %1, %2, %3 replaced with following parameters. + + +str_isnumber(string) - returns 1 if string is a valid number + + +str_isempty(string) - returns 1 if string is empty + + +str_toint(string, default) - returns string converted to integer; if conversion is not possible, optional default value is returned + + +str_todouble(string, default) - returns string converted to double; if conversion is not possible, optional default value is returned + + + + + +&kommander; functions + +Most &kommander; functions are supported; some (such as expr) +were obsoleted by new parser and are not available. + + + + +debug(string, ...) - writes all parameters on stderr + + +echo(string, ...) - writes all parameters on stdout + + +dcop(string, ...) - calls DCOP function + + +exec(string, shell) - executes external program +(using optional shell); block the execution of the current dialog until the program passed as the parameter exits; returns output of that program + + +i18n(string) - marks string for future translation + + +env(string) - returns a value of environmental variable + + +readSetting(key, default) - returns a value stored in config +file with given key; if there is no such value default is returned + + +writeSetting(key, value) - writes pair +key and value in config file + + +New in &kommander; 1.3 + + +execBackground(string, shell) - executes external program +(using optional shell) in the background, without blocking the current dialog; contrary to the above exec function, it will not return the output of the program. + + +return(value) - returns a value to the calling object (script, button...) + + +createWidget(widgetname, widgettype, parent) - creates a new widget. You can then place it in a table or toolbox, for example and use mywidget.show(true) to make it visible. If you are putting an new widget on the form you need to consider layout issues. &kommander; will not create layouts on the fly or edit pixel by pixel positioning (in most cases). This is confusing even in C++ development. We recommend you use a groupbox and do a layout in the dialog +for best control. + + +connect(sender, signal, receiver, slot) - connect a widget signal to a widget slot. See the connection dialog and select similar widgets for possibilities. If for instance a signal looks like looks like execute(const QString&) that is exactly what must be in quotes there. + + +disconnect(sender, signal, receiver, slot) - undo the connection as listed above. Again, exact syntax is essential. + + +widgetExists(widgetname) - remember you can use a variable name to reference a widget now. Use this when accessing created widgets to insure they are there. Calling a non-existant widget obviously will throw an error. + + + + + +Array functions + +Most array functions are supported; some (such as value) +were obsoleted by new parser and are not available. The only difference is that their names +are preceeded by array_ instead of @Array. + + +Due to parser limitation, name of array has to be specified as string now; for example +array_count("MyArray"). + + + +array_clear(array) - removes all elements from array + + +array_count(array) - returns number of elements in array + + +array_keys(array) - returns string containing EOL-separated keys of array - note that if you had imported a scalar (keys without values, see below for an example) into an array with &kommander; you would not be able to access it with array_values("myarray") as you might think (since it seems to only have values) but would instead need to use array_keys("myarray"). You might find a better choice for this is to use the new indexed arrays described below. + + +array_values(array) - returns string containing EOL-separated values of array + + +array_tostring(array) - returns string containing whole array +as EOL-separated pairs containing key and value separated with TAB character + + +array_fromstring(array, string) - reads array from string (usually provided by array_tostring function) + + +array_remove(array, key) - removes item with key +key from array + + +Here is an example for array manipulation: + +array_fromstring("myArray", "1\tA\nsecond\tB\n3\tC") +foreach key in myArray do + debug("myArray[" + key + "]= " + myArray[key]) +end + +This will print out the following to the stderr. It is visible that there is no guarantee about the order of array elements, as well that the keys are strings, not numbers. + +myArray[1]= A +myArray[3]= C +myArray[second]= B + +Another example for keyless arrays: + +array_fromstring("myArray", "A\nB\nC") +foreach key in myArray do + debug(key) +end +debug("Array elements:\n" + array_keys("myArray")) + +This results in: + +A +B +C +Array elements: +A +B +C + + +New in &kommander; 1.3 + + +array_indexedFromString(array, string, separator) - this compensates for &kommander; not having indexed arrays. it creates an array with a zero based sequential index. Remember to use quotes on the array name and any strings not represented by a variable. The separator argument is optional and defaults to "\t" [TAB] which is used to separate fields reading and writing tables, arrays or detail widgets. Remember this array index does not enforce any rules on its self. It is just like you created it with a for loop, just more convenient. + + +array_indexedInsertElements(array, key, string, separator) - this function is part of the indexed array suite and enables you to insert elements in your array while maintaining an index that is sequential, contiguous and unique. Set the index key to start at and the text string and how it is separated. The elements will be added shifting all the index numbers after by the number added. + + +array_indexedRemoveElements(array, key start, number) - this enables you to remove elements from an indexed array and avoid gaps in your index. Specify the key to start at and optionally how many to remove. The default is one. You will end up with a re-indexed array less the removed elements. + + +array_indexedToString(array, separator) - this enables you to convert your indexed array back into a string, particularly useful for detail widgets. For instance if you are displaying a database query result in TreeWidget1 and it has six columns you can use TreeWidget1.selection to get the selected row. it will be separated by tabs and you could look at a the fifth element by using str_section(TreeWidget1.selection, "\t", 4) (remember it is zero based). That's nice for reading a value, but if you want to change it you can see you have a lot more work to do. After you split that string you have to reassemble with val1+"\t"+val2... Using indexed arrays you could edit that fifth element like so... + +idx = TreeWidget1.currentItem +array_indexedFromString("z", TreeWidget1.selection) +z[4] = "new value" +TreeWidget1.removeItem(idx) +TreeWidget1.insertItem(array_indexedToString("z"), idx) + +Note that only two short lines were added to accomplish this! This was very welcome for database use. + + + + + + +File functions + +All file functions are supported, the only difference is that their names +are preceeded by file_ instead of @File. + + + + +file_read(name) - returns content of file name + + +file_write(name, ...) - writes all arguments +to file name + + +file_append(name, ...) - appends all arguments +to file name + + + + + + +Input functions + +These functions show some dialog allowing user to enter some value. They are accessible in the old parser using @Input.. For most functions all parameters are optional, exception is +input_text which requires 2 parameters and input_value which requires 5 parameters. + + + + +input_color(caption, default) - returns color in #RRGGBB format + + +input_text(caption, label, default) - returns text entered by user + + +input_value(caption, label, default, +min, max, step) - returns value entered by user + + +input_directory(startdir, filter, caption) - returns directory selected by user + + +input_openfile(caption, label, default) - returns existing file entered by user + + +input_savefile(caption, label, default) - returns file entered by user (if file exists, confirmation will be required) + + +input_openfiles(caption, label, default) - returns string of EOL-separated existing files entered by user + + + + + + +Message functions + +These functions show some message for user or ask user to confirm some action. In the old parser use @Message. instead. + + + + +message_info(text, caption) - shows information text + + +message_error(text, caption) - shows error text + + +message_warning(text, caption, button1, +button2, button3) - shows question with warning and up to three buttons; number +of chosen button is returned; if no button names are specified, Yes and No will be displayed + + +message_question(text, caption, button1, +button2, button3) - shows question and up to three buttons; number +of chosen button is returned; if no button names are specified, Yes and No will be displayed + + + + +
+ + + diff --git a/doc/kommander/pixlabel.png b/doc/kommander/pixlabel.png new file mode 100644 index 00000000..32b90d82 Binary files /dev/null and b/doc/kommander/pixlabel.png differ diff --git a/doc/kommander/progress.png b/doc/kommander/progress.png new file mode 100644 index 00000000..29416702 Binary files /dev/null and b/doc/kommander/progress.png differ diff --git a/doc/kommander/pushbutton.png b/doc/kommander/pushbutton.png new file mode 100644 index 00000000..61f779ce Binary files /dev/null and b/doc/kommander/pushbutton.png differ diff --git a/doc/kommander/q-and-a.docbook b/doc/kommander/q-and-a.docbook new file mode 100644 index 00000000..2b76331c --- /dev/null +++ b/doc/kommander/q-and-a.docbook @@ -0,0 +1,11 @@ + + + + +Questions and Answers + + +Questions and Answers +The list of Frequently Asked Questions can be found on our home page. + + diff --git a/doc/kommander/radiobutton.png b/doc/kommander/radiobutton.png new file mode 100644 index 00000000..10c1d8c3 Binary files /dev/null and b/doc/kommander/radiobutton.png differ diff --git a/doc/kommander/richtextedit.png b/doc/kommander/richtextedit.png new file mode 100644 index 00000000..73573a8a Binary files /dev/null and b/doc/kommander/richtextedit.png differ diff --git a/doc/kommander/shadow.png b/doc/kommander/shadow.png new file mode 100644 index 00000000..37c44694 Binary files /dev/null and b/doc/kommander/shadow.png differ diff --git a/doc/kommander/shellscript.png b/doc/kommander/shellscript.png new file mode 100644 index 00000000..59de8cfe Binary files /dev/null and b/doc/kommander/shellscript.png differ diff --git a/doc/kommander/slider.png b/doc/kommander/slider.png new file mode 100644 index 00000000..525bd1ca Binary files /dev/null and b/doc/kommander/slider.png differ diff --git a/doc/kommander/specials.docbook b/doc/kommander/specials.docbook new file mode 100644 index 00000000..ddd3e3b6 --- /dev/null +++ b/doc/kommander/specials.docbook @@ -0,0 +1,371 @@ + + + + +Specials and Built-in Global Variables + + +Specials and Built-in Global Variables + + +Specials are functions that are processed by &kommander;. You should be aware that whe using the old style parser all &kommander; specials will be executed first and then the script will be executed. In most cases this is not a problem, but in a few (mostly in loops, conditions) it is. + +The below list might be slightly outdated. It is recommended to use the Function Browser to get help about the available functions. +The Function Browser can be reached from inside the Kommander Text editor, by clicking the Function... button. + + + + + +@dcop(appId, object, function, arguments) + + +Make a &DCOP; call. @dcop(kmail, KMailIface, checkMail(), ) + + + + + +@dcopid + + +The &DCOP; id of the process. (kmdr-executor-@pid) + + + + + +@dialog(dialog[,parameters]) + + +Launches the specified Kommander dialog. Dialog is sought in dialog directory and in current directory - in that order. This prepends the call to the executor and sets the default directory to the one the Kommander application is in. Parameters can be passed in the usual Unix way or you can pass named parameters like variable=value. You can then find passed parameters in the global pool. @global(variable) would return value. + + + + + +@env(environmentVariable) + + +Expands to the specified environment variable. @env(PWD) expands to $PWD. Remember that $ is part of the shell and shouldn't be used. + + + + + +@exec(command) + + +returns the output of executing the specified command. @exec(ls -l). + + + + + +@execBegin ... @execEnd + + +same as @exec, but supports shebang and multiline scripts. This serves for various scripting languages either by decalring them or using a shebang. + + +@execBegin(php) +@execBegin(#!/usr/bin/php) + +The first one uses the name of the PHP executable. &kommander; searches PATH for php and if it is not found looks to see if it is registered with &kommander; in a location outside of your path. If not it tells the user it cannot be found. The second examples uses the classic shebang which can have some benefits and also problems. If you have a beta copy of PHP5, for instance, in /usr/local/bin which would not be found because it would find on in /usr/bin this is useful. If, however, you distribute the dialog to someone who has PHP in /usr/local/bin only it will not be found with the shebang used. So using shebangs is cautioned and using the executable is recommenede if you are sharing files. + + + + +@global(variable) + +expands to the value of the specified global variable. + + + + + +@null + +Returns null. Now that Kommander checks for empty widgetText on execution this will prevent erroneous errors in the case of an unset state on a widget. + + + + +@parentPid + + +The &PID; of the parent process. + + + + + +@pid + + +The &PID; of the process. + + + + + +@readSetting(key, defaultValue) + + +reads a value from kommanderrc. See also @writeSetting. + + + + + +@selectedWidgetText + + +the selected content in a widget that can show more than one value, like list widgets + + + + + +@setGlobal(variable, value) + + +Sets the global variable to the specified value. + + + + + +@widgetText + + +the content of a widget + + + + + +@writeSetting(key, value) + + +write value to kommanderrc. All &kommander; dialogs share the same kommanderc file, each one will have its own section inside it. + + + + + + +Array Function Group + + + +@Array.values(array) + +Returns an EOL-separated list of all values in the array. Can be used to walk through an array. + + + + +@Array.keys(array) + +Returns an EOL-separated list of all keys in the array. + + + + +@Array.setValue(array, key, value) + +Sets a key and value for an element of an array. If no array exists it is created. + + + + +@Array.clear(array) + +Remove all elements from the array. + + + + +@Array.count(array) + +Return number of elements in the array. + + + + +@Array.value(array,key) + +Return the value associated with the given key. + + + + +@Array.remove(array,key) + +Remove element with the given key from the array. + + + + +@Array.fromString(array,string) + +Add all elements in the string to the array. String should have key\tvalue\n format." + + + + +@Array.toString(array,string) + +"Return all elements in the array in key\tvalue\n format." + + + + + + + +File Function Group + + + +@File.read(file) + +Return content of the given file. + + + + +@File.write(filestring) + +Write given string to a file. + + + + +@File.append(filestring) + +Append given string to the end of a file. + + + + + + + +String Function Group + + + +@String.length(string) + +Return number of chars in the string. + + + + +@String.contains(string,substring) + +Check if the string contains given substring. + + + + +@String.find(string) + +Return position of a substring in the string, or -1 if it isn't found." +This will have an optional integer start postion for find next uses in Alpha 6. + + + + +@String.left(string, int) + +Return first n chars of the string. + + + + +@String.right(string, int) + +Return last n chars of the string. + + + + +@String.mid(string, int start, int end) + +Return substring of the string, starting from given position. + + + + +@String.remove(string, substring) + +Remove all occurences of a given substring. + + + + +@String.replace(string, substring find, substring replace) + +Replace all occurences of a given substring with a given replacement. + + + + +@String.upper(string) + +Convert the string to uppercase. + + + + +@String.lower(string) + +Convert the string to lowercase. + + + + +@String.compare(string, string) + +Compare two strings. Return 0 if they are equal, -1 if the first one is lower, 1 if the first one is higher + + + + +@String.isEmpty(string) + +Check if string is empty. + + + + +@String.isNumber(string) + +Check if string is a valid number. + + + + + + + +Built-in Globals +Built-in globals are accessed just like regular global variables with @global. + + +@global(_KDDIR) + +The directory the current dialog is in. + + + +@global(_NAME) +The name of the dialog + + + + + diff --git a/doc/kommander/spinbox.png b/doc/kommander/spinbox.png new file mode 100644 index 00000000..7ae20630 Binary files /dev/null and b/doc/kommander/spinbox.png differ diff --git a/doc/kommander/statusbar.png b/doc/kommander/statusbar.png new file mode 100644 index 00000000..ac08552d Binary files /dev/null and b/doc/kommander/statusbar.png differ diff --git a/doc/kommander/table.png b/doc/kommander/table.png new file mode 100644 index 00000000..4bbd9c2d Binary files /dev/null and b/doc/kommander/table.png differ diff --git a/doc/kommander/tabwidget.png b/doc/kommander/tabwidget.png new file mode 100644 index 00000000..1254bb63 Binary files /dev/null and b/doc/kommander/tabwidget.png differ diff --git a/doc/kommander/textbrowser.png b/doc/kommander/textbrowser.png new file mode 100644 index 00000000..090e2f84 Binary files /dev/null and b/doc/kommander/textbrowser.png differ diff --git a/doc/kommander/textedit.png b/doc/kommander/textedit.png new file mode 100644 index 00000000..823d0818 Binary files /dev/null and b/doc/kommander/textedit.png differ diff --git a/doc/kommander/timer.png b/doc/kommander/timer.png new file mode 100644 index 00000000..e2e17452 Binary files /dev/null and b/doc/kommander/timer.png differ diff --git a/doc/kommander/toolbox.png b/doc/kommander/toolbox.png new file mode 100644 index 00000000..2ab71dc7 Binary files /dev/null and b/doc/kommander/toolbox.png differ diff --git a/doc/kommander/translating.docbook b/doc/kommander/translating.docbook new file mode 100644 index 00000000..15db90bd --- /dev/null +++ b/doc/kommander/translating.docbook @@ -0,0 +1,72 @@ + + + + + + +AndrĦs +Mantia +
amantia@kde.org
+
+ +Michal +Rudolf +
mrudolf@kdewebdev.org
+
+ + + +
+
+Translating &kommander; dialogs + + +Translating &kommander; dialogs + +&kommander; dialogs can be translated to different languages. The mechanism is similar to the translation of other &kde; applications. The dialog is written in English, the texts that are needed to be translated are specially marked. A tool extracts these strings, another tool can be used to translate them. The translation then can be compiled and installed and the dialog will automatically recognize and use it. + + +Here is a short description about the needed steps to make a dialog translatable and translated it: + +How to prepare dialog to be translated? +Always use @i18n("This is my text") when you use some English text. This marks "This is my text" as a text to be translated. + + +How to extract the messages and create the .po file? + + Use the kmdr2po script to extract the strings. The script is inside the working directory of the source release tarball and should be installed to $KDEDIR/share/apps/kommander/translating as well. + + +Just run: + +kmdr2po <your-kommander-dialog.kmdr> + +An appropriate <your-kommander-dialog.po> file will be created. + + + + +How to translate it? +Use KBabel to translate it. Use msgfmt to compile the translation. Look at http://i18n.kde.org for help on this subject. + + +How to install the translation? +Put the compiled *.mo file either to +$KDEDIR/share/locale/<your language>/LC_MESSAGES/ (will be available globally for all users) +or to +$HOME/.kde/share/locale/<your language>/LC_MESSAGES/ (will be available only for the current user) +directory. + + + + + +To open a different catalog (translation *.mo file) for a dialog, use the -c argument for kmdr-executor. The below example will take the translations from the Quanta translation file: + +kmdr-executor mydialog.kmdr -c quanta + + + + + +
diff --git a/doc/kommander/tutorials.docbook b/doc/kommander/tutorials.docbook new file mode 100644 index 00000000..095e9a28 --- /dev/null +++ b/doc/kommander/tutorials.docbook @@ -0,0 +1,380 @@ + + + + +Tips and Tutorials + + +Eric +Laffoon +
+eric@kdewebdev.org +
+
+ + + +
+
+ +Tips on use &kommander; +In this section we go beyond listing widgets to actually using &kommander;. If you want to have a good experience you will find this section very helpful. + + +Using the Editor + +At first glance the editor looks pretty obvious, and in many ways it is. Click on the icon to create a new form, then click a widget and click or click and drag on the form. There are the widget handles that will be familiar to anyone who ever put a picture in a word processing document. What is less obvious are the little things. One thing to mention up front is widget naming. Names must be unique and &kommander; employs a naming scheme of the formal widget name and a number unique to that widget type. You can rename a widget and &kommander; will not allow a duplicate name. However if you build a complex dialog and decide to start renaming you're going to have problems. Signals and slots will manage naming for you and any widget you change will be reflected in the signals and slots connections. Unfortunately we never got this feature in the widget functions. So ever call to that widget will be wrong. You could close the dialog and open it in a text editor like KWrite and do find and replace. A better solution is to start out with some idea what kind of descriptive names you want to give to key widgets. It may be a waste of time naming Labels, but scripts and container widgets for data quickly prove a real mistake not to name. You can also set icons for scripts making them even quicker to visually identify. + + + + +Editor Tools + +The first thing you will notice is a properties window, generally docked on the left. Explore this! Here you will find many useful settings for forms and widgets. Some of them would be layout settings, icons, if something is active, text and more. For instance if you put a TreeWidget in a form you can change the default path separator, which is useful if you have data in there. It's easy for a slash to create a sub-item accidentally. Here you will also find selection modes, whether to highlight the whole row in multi column widgets and more. Before you assune something is just how &kommander; is check this. + + +If you play with layouts and lose a widget behind another or off the form the object explorer will come in handy. It's also nice for seeing structure. The next very useful view is the log view which shows stdout and stderr. The error view is indispensable. This is where your debug() commands prints and where you get detailed information. For instance when using the database plugin this gives you additional information with data errors. It also shows you all shell calls and more. The Stdout view lets you see what would go to the shell or an application using this like Quanta. The dialog view is of little use unless you have a lot of dialogs open. The Action view is only active with MainWindow use and in that case it is the only way to add Actions, menu and toolbar items. + + + + +Adding Custom Tools + +&kommander; makes it easy to add custom tools, which you can develop in &kommander;, to the editor. We will be shipping some with &kommander; as well as making some available for download. You can add your own easily. First have a look and see where they are. If they are installed they are on the tools menu below the splitter. The &kommander; menu offers access to widgets. The Custom menu offers access to installed plugins. The Editor menu is where your custom tools go. To manually add a tool first decide if you are going to make it available system wide or just to your desktop. System wide start from the directory KDE is installed in. For your desktop user start in the hidden KDE directory in your home directory, usually ~/kde. From either the path is/share/apps/kmdr-editor/editor/ If the dialog you add needs access to tools or files you can put them in a subdirectory. Whatever &kommander; dialogs you put there will be recognized and added to your menu on startup. Clicking the menu will load the dialog. You will note there is a templates directory there too and you can add templates for new dialogs. + + + + +Included custom tools + +Several tools are included with this release, already installed on the tools meu under editor. More tools are under development for project management, database front end development, code snippets and more. The most imporant and useful tool to look for is the examples dialog. As the editor is no longer under development for KDE3 it cannot insert a dialog in the current editor, but it will open any selected dialog in a new instance of the editor. There are old dialogs from the early days of &kommander;, tutorials from more recent development and the current section showing new features of this release. Looking at these should help. Keep an eye on our web site for more. + + + + +Using Layout + +People love to share &kommander; dialogs. Almost without fail they don't know about laying them out. Make a dialog and then try resizing it and see what happens. Wouldn't it be nice if it behaved like it should instead of leaving your widgets the same? It gets worse when you share it and differences in fonts, monitor size and X pixel resolution conspire to make your masterpiece look like it was put together by a three year old using bubblegum and thumbtacks. Always, always always... Lay out your dialogs! + + +Okay, you're sold you don't want a frustrated email from me asking you to please layout your dialog. How do you do it. There are layout buttons on the toolbar and the context menu. Since &kommander; is based on an older version of Qt Designer you can look at Qt Designer docs and tutorials here. I'm just going to mention a few basics and a few tips. + + +Use the Grid. This will place everything in a best guess location +Remember containers are separate. A TabWidget, GroupBox or layout group has it's own layout. So don't forget the window. +Widgets that are not visible during execution can make layout seem more challenging. What to do with them? I recommend grouping them in their own layour next to or below your main layout. Your visible widgets will simply push these aside and give you a predictable result. +Look at your properties were you can set a widget to expand or do other things as well as minimum and maximum size. A little experimentation will teach you a lot. You can also set a tighter spacing here, + +And now for a few tricks and tips. + +Along with basic layout you can use splitters. When your dialog is running you can drag the splitter up and down or right and left to get a better look at things. It may look like there is a limitation here or it doesn't work. It works and has no limitations. Just make sure to put multiple widgets into two layouts and make sure when you click or right click to get the layout and not just a child widget. You are free to create a maze of splitters as long as you adhere to the rules. +Fake docs are possible! Create a GroupBox and drop widgets on it. Position it in your layout so that when it's invisible other widgets/layouts will expand to take it's place. Now toggle it's visibility with a button or menu. +ToolBox tricks - The Toolbox has an editor bug where you can't add widget panels in the editor without it going nuts. As a result you need to add them at run time. However it looks for one widget and if you want something complex you should use a groupbox and lay it out. then layout your dialog with the groupbox at the outside, even if it goes off the edge of the window. Now load it on initialization into the ToolBox. Your window layout will snap into place. +Layout glitches can occur where widgets set to something like Minimum/Expanding can end up obscured before you complete layout on the window. The layout system will honor your oddness and can be shrunk to obscure scrollbars and more. Make sure all is visible before finishing layout and consider not using minimum in that case. + +For more on this look up the Qt Designer docs for Qt 3.x. + + + +Signals and Slots + +One of the very useful features inherited from Qt Designer was signals and slots. Of course the interface has been redesigned in an attempt to make it friendly to &kommander;. Signals and slots are internal event control for Qt/KDE applications. We try to make it so you don't have to know the difference between C++ data types, but if you use the new function to create connections on the fly it is handy to be able to copy that information from the connection tool. Let's look at what all this means. Something happens in one of you widgets. It could be click on, double clicked, have it's value changed, something selected or a menu could be requested. That is just some of the possible events that would enable a signal to be sent. You may want to change the list in a ListBox if a new selection is made in a ComboBox. That's a useful feature in a sophisticated application and the only way to do it without having to press a button next is to have a signal connected to a slot. That slot could be in a script or button. When the slot receives the signal it goes about doing what it was told. There is a tool to edit these connections. Pay attention when do this as there are a good number of inherited signals and slots. Telling a script which is invisible when the dialog is run to adjust it's size by accident when you meant to execute will have you wondering what happened. + + +To access the connection tool you can open it by right clicking anywhere on the dialog and selecting it. Click the menu and you will see a list of connections made at the bottom. Above that are two lists of signals and slots and above them the respective sender and receiver are selected. An easy way to make connections is visually. Look at the toolbar or the Tools menu. There are three items grouped there. A pointer, signals and slot connections and the tab order or widgets. Selecting this sets connection mode for the curios. Click on your widget to send the signal and drag it to your widget to receive it in a slot. As you do this you will see a line and drop indications on the widget under the mouse. The StatusBar on the Editor will tell you what is being connected. + +In version 1.3 there is a &kommander; function connect() which allows you to connect signals and slots on the fly. This is useful if you just used createWidget. Obviously you can't use the dialog for something &kommander; doesn't yet know exists. Unfortunately there are too many combinations to list so you have to type out signals and slots. These must be typed verbatim or they will fail. This is where the connection tool is handy again. Open it and select two widgets like the two you want to connect and read the connection information. if it says execute(const QString&) that is exactly what you must type. + + + +Slot Functions + +As of version 1.3 &kommander; adds Slot functions. You can see this in the Function Browser, which is uncharacteristicly less than friendly with descriptions here. What &kommander; is doing is reading every slot registered for a given widget and making it available directly. This is very useful. For instance the Table widget doesn't have a default method to auto adjust column width. You may find this annoying, but if you look under slots there it is. The TextEdit is also lacking in built in functions for any real editing, but look under slots and there is anything you could wish for. You may have to reference some docs or just experiment. It is simply too difficult to document every slot available in builtin widgets and plugins. Most slots however are self explanatory. + + + + + +Basic Tutorials + +Most of the information in this section is based on example dialogs some time ago, which unfortunately were not widely available as they were shipped with the source, but not installed. You should find them in your tools menu under examples in the tutorial section. Keep in mind most of these particular examples use the old parser. That is neither good nor bad. Most of the functionality in &kommander; is shared in both parsers. It's just each is particularly suited to do a better job with a given task. As &kommander; now defaults to the new parser you can set either one. Please see the New Parser docs for more information on the two parsers. + + +When examining example dialogs remember to look in the following places to see how things are done. + + +Dialog Initialization - middle click on the dialog face or right click and select &kommander; Text. Here you see what is run when the dialog starts. +Buttons - middle click the button, or right click. Scripts are typically here. +Widgets - some widgets like Timers and Konsoles will hold instructions inside them. +Signals and Slots - this is how Qt/KDE programs internally communicate. + + +The following list of dialogs may be brief so as to focus on where more information is required to explain more complex tasks possible with &kommander;. They were copied from Michal's notes. + + + +Globals +Shows using global and setGlobal &DCOP; calls to provide global variables for script +
+Functions/concepts: +- global +- setGlobal +- changeWidgetText +
+
+ + +&DCOP; +Shows how to use both local and external &DCOP; calls to communicate with external application (here: KMail). +
+Functions/concepts: +- external DCOP +- addListItem +- enableWidget +- @selectedWidgetText +- @widgetText +
+
+ + +Slots +Shows how to us connections/slot to handle events. Both population and standard slots are used. +Population text was originally developed before &kommander; DCOP, specials and scripting. Given that everything it does can be done in other ways and that it is easy to forget to look here for problems, along with the inherent difference of introducing an additional behavior to explain, this is a deprecated function. It is left in for illustration, however while &kommander; dialogs will be easy to port to KDE4 this feature is not assured to work in the future. Don't use it! +
+standard slots are used. +- slots/connections +- populate() +
+
+ + +Settings +Shows how to use @readSetting and @writeSetting functions to write/restore widget content. Also, show how to use populate() slot to initialize widget content. +
+Functions/concepts: +- @readSetting +- @writeSetting +- populate() +- slots/connections +- destroy +
+
+ + +Append +Shows how you can append text to TextEdit and how you can use it to display formatted text. See newer examples for how to use slots to edit rich text and new font and color dialogs too. +
+Functions/concepts: +- changeWidetText +- RichTextEdit +
+
+ + +Command Line +Shows how you can pass parameters to &kommander; dialog via command line. Also, shows how to change list content and button text. See the section on passing arguments in the new parser for more on this. +
+Functions/concepts: +- command-line arguments +- global +- changeWidgetText +- addListItem +- clearList +
+
+ + +Initialize + +Shows how you use 'initialization' to 'destroy' scripts of main dialog to initialize and store some settings. + +
+Functions/concepts: +- initialization +- destroy +- readSetting +- writeSetting +
+
+ + +Array + +Shows how to use associative arrays to store and restore information +associated with container items. +
+Functions/concepts: +- @Array functions +
+
+ + +Strings + +Shows how to use string-handling functions +Functions/concepts: + +
+- @String functions +- rich text editor +
+
+ + +Tree + +Shows how to use tree widget + +
+- tree widget +- FileSelector +- initialization +- env +
+
+ + +Widgets + +Shows how to get widget information + +
+- type method +- children method +
+
+ + +StatusBar + +Shows how to use statusbar widget + +
+- statusbar widget +- populate +
+
+ + +Loop + +Shows how to use internal loops + +
+- for +- forEach +
+
+ + +Calc + +Shows how to use @expr function to do some calculations + +
+- expr +- String.replace +
+The @expr() function is no longer required in the new parser as expressions can be directly interpreted anywhere you would logically want to use them. +
+ + +Picview + +Shows how to use PixmapLabel widget using populate() function + +
+- PixmapLabel +- populate +- FileSelector +- slots/connections +
+
+ + +Table + +Shows how to use Table widget + +
+- insertRow +- insertColumn +- currentRow +- currentColumn +- setColumnCaption +- setRowCaption +- removeRow +- removeColumn +
+
+ +
+ + +Current Examples + +These examples reflect the most recent development state of &kommander;. In its current state &kommander; has few limitations for developing small to medium applications. It certainly is not suitable for building a KWord clone, but for a simple editor, database frontend, GUI for commandline programs or any application in the spirit of Unix/Linux small applications it is a good choice. The examples presented here are intended to show the potential as well as how to work around limitations. There are some useful tricks included in these if you want to do a more capable small application with &kommander;. Remember &kommander; is not intended to do everything, but to do most things. For this concession you should be able to build something in &kommander; faster than other alternatives ad add GUI to scripting languages not otherwise supported in KDE. + + +The examples are installed to $KDEDIR/share/apps/kmdr-editor/editor. In case you do not have them there, get from our home page, by downloading the latest release. + + + + +editor-poc.kmdr + +The little dialog that grew into a Mainwindow. As &kommander; does not have a native MainWindow widget it has been assumed it only does dialogs. In fact only dialogs are officially supported... but you can run MainWindows in &kommander;. This is an example editor. If you want to create a MainWindow application in &kommander; just open Qt Designer and make one, save it and rename the *.ui file to a *.kmdr file. Now open it in &kommander; and do what you would do normally. + +As of this writing what is known not to work on the &kommander; side is the settings read and write. There is no Initialize or Destroy section as there is no &kommander; Text, however there are signals for this on the window, so the functionality is intact. On the MainWindow side it is not possible to talk to any actions via DCOP as these are QActions from Designer and KActions are not derived from QActions in KDE 3.x. This means a DCOP call to list actions or set states will not work. It is also not possible to talk to the Statusbar. Also submenus on the menubar and dropdown actions on the Toolbar will not work. Even though this is not a &kommander; widget, or officicially supported, it seems suitable for many small application uses. + +There is a quick help dialog this editor launches that discusses in depth what is happening inside. + + + + +kevaluecombo.kmdr + +&kommander; can be used with databases and has an optional database plugin. One shortcoming is not being able to store key/value pairs in the ComboBox. An ingenious trick was realized for this. It requires only that the content of the ComboBox not be changed unless it is done using the arrays that go with it. As this is commonly used with SQL in small data sets it's quite fast even to reload the whole Combobox. The inherent problem is that &kommander; does not have internally indexed arrays by default. This is compounded by the fact that to accommodate shell commands that return lines separated by newlines &kommander;'s array functions will load what is effectively an array of keys. Such an array can only be accessed with a foreach loop. This is the reason new indexed array functions were added. It is important to remember that these arrays are not self maintaining, but their insert and delete functions will help you. + + +Getting back to the ComboBox, it will return selected text, but it also will return the current index. It does rigidly maintain a contiguous zero based array. That's the key. We loop through a data set with a zero based index counter and create two arrays, as &kommander; also cannot create arrays of arrays. It can however use an array value to represent a key just like any value could. .If you look at the included dialog the code actually managing this is in ScriptObject36. We will extract the key code here. + + +c = ListBox1.count-1 +for i = 0 to c do + array_indexedFromString("x", ListBox1.item(i)) + _a[x[0]] = x[1] + _b[i] = x[0] + ComboBox10.insertItem(_a[_b[i]], i) +end + + +There is more going on, like checking for duplicate keys, but this is the core. You can right click on the ListBox and try menu items. The net result is that it is using keyed index by proxy and returning both the key and the value. Use this code if you want to be 100% certain your key/value relationship is accurate. + + + + +Kpart demo + +As of Kommander 1.3 Kommander automatically makes KParts using the libkommander_part.la. In addition to this there is a KPart plugin which allows Kommander to load plugins. Being curious developers we tried loading a Kommander part into Kommander. Why do that? Why not? The results were interesting and are demonstrated here. One interesting thing is the parent part can directly access all of the child part. While this is handy it has a down side. Any child widget being called with the same name as a parent widget will cause a lock up! In addition to that the DCOP interface is generated all over again for the part which wipes out the parent interface and disables most of the old parser functionality as well as Kommander specific DCOP to the parent. This is too difficult to fix for the remaining life of the KDE3 version. Even with these limitations and cautions this can be useful, if used carefully. The example files to look at this are in the current examples as kpartmwframe.kmdr and kpartpart.kmdr. Remember you will need the KPart plugin to fully run this example. + + +You can also load KMail, KOrganizer and many other KDE applications right into Kommander, of course without the problems. KHTML and KDE's file manager widgets seem not to have some functionality but there is a special KHTML plugin if you really want to incorporate a browser. + + + +passvariables.kmdr + +As of &kommander; 1.3 you can pass and return variables with scripts. This dialog demonstrates that. Look carefully at the content of the buttons. You will see that neither button directly writes to any of the LineEdit boxes receiving text from the script. While one is written directly from the script another is written with the content passed from the button. The third is not written at all but passed back in a return() function where it is received by the button and written. This is also shown on the right side using PHP so you can see how this might work with Python, Ruby, Perl or even a less commonly used language like Rexx. Languages that Speak DCOP can do a lot more in &kommander; too. The point of this demo is the freedom provided. &kommander; does not have functions, yet it does. Create a script, declare some globals if you like, pass some parameters to another script and return a value. For an intentionally simplified GUI scripting tool that is capable behavior. This behavior is only in the new parser and is documented here. + + + + +tableselect.kmdr + +This example demonstrates how to use the new select function in the table widget. It is now possible to get four coordinates to enable a block selection. This also shows how it would have had to be done prior to this function. and how to use the parameters passed to a script. In addition this demonstrates a simple block copy and paste function for a table as well as summation of a block. + + + + +
diff --git a/doc/kommander/widgets.docbook b/doc/kommander/widgets.docbook new file mode 100644 index 00000000..fa187cfc --- /dev/null +++ b/doc/kommander/widgets.docbook @@ -0,0 +1,599 @@ + + + + +Widgets + + +Widgets + + +The building blocks of a &kommander; dialog are the widgets. They are like any other widget in the &Qt; and &kde; libraries except they have some extra functionality that allows them to have a text association. Text is associated with a state of the widget or its populate slot. The number of states depends on the widget. If a widget only has one state, that state is called default. + + + +The main dialog has two special states for &kommander; text. They are Initialization and Destroy. These are run when the dialog is initialized and when it is destroyed. These protect against what is know as race problems on open and mean that you do not require any special procedures on close to manage housekeeping. +In case of using a MainWindow based application (created with &Qt; Designer), there are no Initialization and Destroy states, instead the initialize and destroy signals can be used to get information when is the application constructed or closed + + + +Below are the standard &kommander; widgets. Each of them has numerous functions, you can learn about them by looking at the widget functions in the Function Browser. Many of them have signals and slots as well, documentation about these methods can be found in the &Qt; and &kde; API documentation. Each &kommander; widget has a note about its base widget. + + + + + + + + + +Label + + + +A simple widget that contains a piece of text. This widget lets you set a pixmap too. + + +See the QLabel documentation to learn more about text labels in &Qt;. + + + + + + + + + +PixmapLabel + + + +A simple widget that contains an image or text label. The pixmap to display is set in the pixmap property. The text is set in the text property. Only one of these properties can be set at the same time (I think, I can't get the editor to set both at the same time). If scaledContents is set to true the image will be scaled to fit the size of the widget. The format of the text can be set with the textFormat property. + + +See the QLabel documentation to learn more about text labels in &Qt;. + + + + + + + + + + +LineEdit + + + +A LineEdit widget is a one line text editor. It allows the user to enter and modify a single line of text. Initial text for the editor can be set in the text property. The widget can be set to read-only with the readOnly property. There are 3 modes for the widget, Normal, NoEcho, and Password. The mode is set with the echoMode property. + + +LineEdit has one state, default. + + +The widget text for LineEdit is the text contained in the editor. + + +See the KLineEdit documentation to learn more about text labels in &kde;. + + + + + + + + + +TextEdit + + + +A simple multi-line text editor. + + +See the KTextEdit documentation to learn more about multiline text edit in &kde;. + + + + + + + + + +TextBrowser + + + +A simple reach text browser with hyperlink navigation. + + +See the KTextBrowser documentation to learn more about it. + + + + + + + + + +ListBox + + + +A ListBox widget provides a list of selectable items. Normally one or no items are selected. This behavior can be changed with the selectionMode property. Items are added to the ListBox using the edit window. + + +A ListBox has only one state, default. + + +The widget text for a ListBox is the items contained in the ListBox. @selectedWidgetText will return only the items that are currently selected. + + +See the KListBox documentation to learn more about it. + + + + + + + + + +ComboBox + + + +ComboBox is a selection widget that combines a button and a pop-up menu. It shows the user's current choice from a list of options in minimal space. Items are added to the list using the edit window. If the editable property is set to true the user can enter arbitrary strings. + + +ComboBox has one state, default. + + +The widget text for a ComboBox is the text of the selected item. + + +See the KComboBox documentation to learn more about it. + + + + + + + + + +TreeWidget + + + +A widget that provides a list in the form of a tree structure. You can add child items and multi-column data. The current limitation is that you cannot modify columns. To add a child node use / as a separator. To add column data use the escaped tab \t character between columns. + + +See the KListView documentation to learn more about it. + + + + + + + + + + +Table + + + +A table widget that support different widgets in its cells. + + +See the QTable documentation to learn more about it. + + + + + + + + + +ExecButton + + + +A button that when clicked executes its text association. The label on the button is set with the text property. Output from the text association (how to say that) will be echoed to stdout if the writeStdout property is set to true. The button can be the default action for the dialog if the default property is set to true. + + +ExecButton has one state, default. + + +There isn't widget text associated with ExecButton. + + +See the KPushButton documentation to learn more about it. + + + + + + + + + +CloseButton + + + +A button that when clicked, executes its text association and then closes the dialog. The label on the button is set with the text property. Output from the text association (how to say that) will be echoed to stdout if the writeStdout property is set to true. The button can be the default action for the dialog if the default property is set to true. + + +CloseButton has one state, default. + + +There isn't any widget text associated with a CloseButton. + + +See the KPushButton documentation to learn more about it. + + + + + + + + + +Konsole + + + +A widget that captures the output of scripts in a text browser. The default state is executed and the output of those commands (internal or external) are shown in the widget. + + + + + + + + + +FileSelector + + + +The FileSelector widget combines a LineEdit with a button when clicked will present the user with dialog for the selection of files/folders. The file/folder selected is stored in the LineEdit. The type of the FileSelector is set with the selectionType property. Available types are Open, Save, and Directory. Multiple files/folders can be selected if the selectionOpenMutliple property is set to true. A caption for the FileChooser can be set with the selectionCaption property. This is display as the window title of the dialog. If a caption isn't specified, the type of selection will be display in the title. The files displayed in the dialog can be limited using the selectionFilter property. + + +FileSelector has one state, default. + + +The widget text for a FileSelector is the text contained in the LineEdit (the file chosen by the user). + + + + + + + + + +CheckBox + + + +A button that can be checked on and off. It can also be semi-checked if the tristate property is set to true. The label associated with the CheckBox is set in the text property. Setting the checked property will have the CheckBox initially checked. + + +A CheckBox has 3 states, checked, semichecked, and unchecked. + + +The widget text for a CheckBox is the value from the text property. + + +See the KCheckBox documentation to learn more about it. + + + + + + + + + +RadioButton + + + +A button that can be checked or unchecked, usually used in the ButtonGroup to make an exclusive choice. A label associated with the button can be set in the text property. A button can be initialized to checked by setting the checked property to true. If all RadioButtons in a ButtonGroup have the checked property set to true, then the last button will be the one that is checked. + + +RadioButton has 2 states checked and unchecked. + + +There is no widget text associated with a RadioButton. + + +See the KRadioButton documentation to learn more about it. + + + + + + + + + +ButtonGroup + + + +A container to organize buttons into a group. An optional title can be set using the title property. The frame can be adjusted with the lineWidth property. The button group can be set to exclusive by setting the exclusive property to true. This means when one toggle button is clicked all other toggle buttons will be set to off with the exception of radio buttons that are always mutual exclusive even if the group is non-exclusive. Radio buttons can be set to non-exclusive using the radioButtonExclusive property. (I am not so sure that this property actually works.) + +ButtonGroup has one state, default. + +The widget text for a ButtonGroup is the text associations for each of the buttons in the order they appear in the ButtonGroup. + + + + + + + + + +GroupBox + + + +A container widget that holds other widgets. The frame is adjusted with the lineWidth property. A title can be added by setting the title property. + + +GroupBox has one state, default. + + +The widget text for GroupBox is the text associations of each of the widgets it contains combined. They will be in the order they appear inside of the GroupBox. + + + + + + + + + +TabWidget + + + +A widget that provides multiple tabs each may contain other widgets. + + +See the KTabWidget documentation to learn more about it. + + + + + + + + + +SpinBoxInt + + + +A widget that allows the user to change a integer value by either press up and down arrows or entering a value into the box. Minimum and maximum values for the widget can be set with the minValue and maxValue properties. The specialValueText property is used to set a text value that will be displayed instead of the minimum value. + + +This widget has only one state, default. + + +The widget text for a SpinBoxInt is the currently displayed integer. + + +See the QSpinBox documentation to learn more about it. + + + + + + + + + +Slider + + + +A widget that provides horizontal or vertical slider. + + +See the QSlider documentation to learn more about it. + + + + + + + + + +RichTextEditor + + + +This widgets provides a text editor that allows for simple text formatting. + + +RichTextEditor has one state, default. + + +The widget text for RichTextEditor is the text contained in the editor in rich text format. Selected text can be returned with @selectedWidgetText. + + + + + + + + + +StatusBar + + + +A widget to display status information, usually used at the bottom of the dialogs. + + +See the KStatusBar documentation to learn more about it. + + + + + + + + + +ProgressBar + + + +A widget to display progress information. + + +See the KProgress documentation to learn more about it. + + + + + + + + + +ScriptObject + + + +This is a pseudo-widget, it does not appear when the dialog is run. It can be though about as a function. A ScriptObject holds code that can be executed anytime from the dialog by calling its execute function. Arguments can be passed to the ScripObject with the above method and accessed inside the ScriptObject as @Self.item(0), @Self.item(1), etc. if using the old style parsing or Self.item(0, Self.item(1), etc. with the new parser. + + +Signals can be connected to the execute function as well, as it acts also as a slot. + + + + + + + + + +Timer + + + +This is a pseudo-widget, it does not appear when the dialog is run. It can be used to perform an action after a specified time once, or regularly. Set the timeout interval in milliseconds, choose if it should run once (singleShot) or not. Connect its timeout signal to a slot, which will be executed once the specified time passes. + + +The timer is not started by default, run the execute function to start it. + + +See the QTimer documentation to learn more. + + + + + + + + + +DatePicker + + + +A widget used to select a date. The default date can be set in the date property or with the setText function in ISO format: YYYY-MM-DD. + + +The widget text is the currently displayed date. + + +See the KDatePicker documentation to learn more. + +New in Kommander 1.3. + + + + + + + + +AboutDialog + + + +This is a pseudo-widget, it does not appear when the dialog is run. It stores information about the application, the authors, the license. Shows the about dialog +when the execute function is called. +The initialize function must be called before anything else, including the execute function. + +New in Kommander 1.3. + + + + + + + + +FontDialog + + + +A pseudo-widget, that can be used to get a font selection dialog. The default font can be set with the setFont function, and the selected font's properties retrieved with the family, pointSize, bold, italic functions. The dialog is shown when the execute function is called. + +New in Kommander 1.3. + + + + + + + + +PopupMenu + + + +A pseudo-widget, that can be used to display a menu. Use the insert... functions to add menu entries. Whenever the user clicks on a menu entry, the specified executeWidget's execute function will be run. It is possible to connect the menu entries to the popupmenu's own execute function, in which case the text assigned to the default state is run. When adding menu items you can assign an index to them and handle the all the items on a menu in the menu widget as the request passes this index back. To see how this works look at the current example keyvaluecombo.kmdr included with this release. To find it look on the tools menu of the editor for the examples dialog. + +To show the menu, use popup slot. Usually this is connected to another widget's contextMenuRequested signal. +A menu can contain other PopupMenu submenus. +New in Kommander 1.3. + + + + + + + + +ToolBox + + + +A container widget, like TabWidget. It has several pages, each page can hold other widgets. + +This widget has an editor bug that does not affect it's use in execution, but does affect it's use in the editor. If you try to add pages in the editor it will become unreadable. Don't do this. If you want to use the ToolBox please use fill the widget on the fly using the addWidget command. If there is time an example will be added to the 1.3 release, or check the web site. +See the QToolBox documentation to learn more about it. +New in Kommander 1.3. + + + + + + diff --git a/doc/kxsldbg/1downarrow.png b/doc/kxsldbg/1downarrow.png new file mode 100644 index 00000000..b8a8b0ff Binary files /dev/null and b/doc/kxsldbg/1downarrow.png differ diff --git a/doc/kxsldbg/Makefile.am b/doc/kxsldbg/Makefile.am new file mode 100644 index 00000000..41691557 --- /dev/null +++ b/doc/kxsldbg/Makefile.am @@ -0,0 +1,3 @@ +KDE_LANG = en +KDE_DOCS = AUTO + diff --git a/doc/kxsldbg/breakpoints_window.png b/doc/kxsldbg/breakpoints_window.png new file mode 100644 index 00000000..b4033935 Binary files /dev/null and b/doc/kxsldbg/breakpoints_window.png differ diff --git a/doc/kxsldbg/callstack.docbook b/doc/kxsldbg/callstack.docbook new file mode 100644 index 00000000..20c46fab --- /dev/null +++ b/doc/kxsldbg/callstack.docbook @@ -0,0 +1,37 @@ + + + + + +Keith +Isdale + +
k_isdale@tpg.com.au
+
+
+ +
+
+ +Working With the Callstack + + +All call stack items found are listed here. The older the callstack entry +the lower the frame number it will have. See below for an example. + + +The Callstack Window + + + + +The Callstack Window + + + + +Clicking on a callstack entry in the list shown will cause the cursor in +the main window to move to the file and line number indicated. + +
+ diff --git a/doc/kxsldbg/callstack_window.png b/doc/kxsldbg/callstack_window.png new file mode 100644 index 00000000..0bccd8e5 Binary files /dev/null and b/doc/kxsldbg/callstack_window.png differ diff --git a/doc/kxsldbg/configure.png b/doc/kxsldbg/configure.png new file mode 100644 index 00000000..37fd0bc6 Binary files /dev/null and b/doc/kxsldbg/configure.png differ diff --git a/doc/kxsldbg/configure_window.png b/doc/kxsldbg/configure_window.png new file mode 100644 index 00000000..3910c99f Binary files /dev/null and b/doc/kxsldbg/configure_window.png differ diff --git a/doc/kxsldbg/credits.docbook b/doc/kxsldbg/credits.docbook new file mode 100644 index 00000000..0bd018d6 --- /dev/null +++ b/doc/kxsldbg/credits.docbook @@ -0,0 +1,44 @@ + + + + + +Keith +Isdale + +
k_isdale@tpg.com.au
+
+
+ +
+
+Credits and Licenses + +&kxsldbg; © 2004 Keith Isdale +Documentation © 2004 Keith Isdale + + + +Thanks to: + + +The writers the libxml and +libxslt. + + + + +Robert Jacolin for feedback on earlier version of &kxsldbg;. + + + + +Igor Zlatkovic for creating WIN32 binaries of +libxml/xslt and &xsldbg;. + + + +&underFDL; +&underGPL; + +
diff --git a/doc/kxsldbg/entities.docbook b/doc/kxsldbg/entities.docbook new file mode 100644 index 00000000..1f680971 --- /dev/null +++ b/doc/kxsldbg/entities.docbook @@ -0,0 +1,42 @@ + + + + + +Keith +Isdale + +
k_isdale@tpg.com.au
+
+
+ +
+
+Working With &XML; Data Files (Entities) + + If the inspector dialog is not showing use the +Tools Show inspectors + menu item. To work with entities click on the +Entities tab of dialog shown. + + All external &XML; entities included via the DATA file or one +of its siblings are listed here. For this example I have run &kxsldbg; +on testdoc.xsl with +testdoc.xml (found in the +<KDE PREFIX>/share/apps/kxsldbg folder so that you can see some entities. + + +The Entities Window + + + + +The Entities Window + + + + +Clicking on a entity entry in the list shown will cause the cursor in the +main window to move to the start of the file indicated. + +
diff --git a/doc/kxsldbg/entities_window.png b/doc/kxsldbg/entities_window.png new file mode 100644 index 00000000..29d57f6b Binary files /dev/null and b/doc/kxsldbg/entities_window.png differ diff --git a/doc/kxsldbg/exit.png b/doc/kxsldbg/exit.png new file mode 100644 index 00000000..6ea935d1 Binary files /dev/null and b/doc/kxsldbg/exit.png differ diff --git a/doc/kxsldbg/glossary.docbook b/doc/kxsldbg/glossary.docbook new file mode 100644 index 00000000..4a980984 --- /dev/null +++ b/doc/kxsldbg/glossary.docbook @@ -0,0 +1,47 @@ + + + + + +Keith +Isdale + +
k_isdale@tpg.com.au
+
+
+ +
+
+ + +Keywords + +&xsldbg; + + +See . + + + + + +XPath + + +A valid expression that defines what data is required. See +W3C web site. + + + + + +QName + + +A fully qualified name. For example, xsl:myvariable. +See W3C web site + + + + +
diff --git a/doc/kxsldbg/index.docbook b/doc/kxsldbg/index.docbook new file mode 100644 index 00000000..8b52c114 --- /dev/null +++ b/doc/kxsldbg/index.docbook @@ -0,0 +1,150 @@ + +KXSLDbg"> + + + + + + + + + + + + + + + xsldbg"> + DTD"> + XSD"> + XSLT"> +]> + + + + +The &kxsldbg; Handbook + + + +Keith +Isdale + +
k_isdale@tpg.com.au
+
+
+ + + +
+ + +2002 +2003 +2004 +Keith Isdale + + +&FDLNotice; +2004-11-18 +0.5 + + + +&kxsldbg; is a provides a graphic user interface front-end to +&xsldbg;, which supports +debugging of &XSLT; scripts. + + + + +KDE +xsldbg +libxslt +debugger + +
+ + +Introduction + + +Features + + +&kxsldbg; provides access to most of &xsldbg;'s commands to + + + + +Set and modify breakpoints + + + + +Display value of XPaths + + + + +Display information about the templates, variables, +callstack entries, stylesheets and entities present + + + + +Set and modify breakpoints and variables + + + + +Move around &XSL; source and &XML; document via XPaths + + + + +Lookup PUBLIC and SYSTEM ID's in the current &XML; catalog + + + + + + + +Recently added features +&kxsldbg; can now + + + + +Set and modify variables + + + + +Renders the text in the main window using the &kate; libraries + + + + + + + + + +Using &kxsldbg; +&configure-section; +&mainwindow-section; +&inspector-section; +&variables; +&callstack; +&templates; +&sources; +&entities; +&tools-section; + + +&credits-chapter; + +
diff --git a/doc/kxsldbg/kxsldbg_configure.docbook b/doc/kxsldbg/kxsldbg_configure.docbook new file mode 100644 index 00000000..115cd4d3 --- /dev/null +++ b/doc/kxsldbg/kxsldbg_configure.docbook @@ -0,0 +1,102 @@ + + + + + +Keith +Isdale + +
k_isdale@tpg.com.au
+
+
+ +
+
+ +Configuring a &kxsldbg; Session + + +You start configuration by clicking + +Debug +Configure + in the Menubar. + + + +The Configuration Dialog + + + + +The Configuration Dialog +The Configuration Dialog. + + + + +Getting Started + + +To be able to run a stylesheet you need to specify the: + +&XSL; source +&XML; data +Output file + + + + By using the ... button to choose file +desired. The &XSL; source and >&XML; data may refer +to URI that contains a http://, ftp:// or file://. The Output file +must refer to a writable local file. + +To follow along with the examples, select the following files in the +example <KDE PREFIX>/share/apps/kxsldbg folder + +&XSL; source: testdoc.xsl +&XML; data: testdoc.xml +Output file: /tmp/xsldbg_output.txt + + + + + +Working With Options + + +You can select zero or more options from the Options dialog. Each option has a tooltip with a hint on what effect it has. + + + + +Working With Parameters + + +You can add zero or more parameters via the LibXSLT Parameters +section of dialog. This allows you to provide parameter values to the +stylesheet. + + + +For example you could add a enter a Parameter name of myparam +with a Parameter value of 'Hello World!' and click the Add button. +. To update the value of an existing +parameter just use the navigate to the value you wish to change with the Prev or Next button, provide a new Parameter value then click the Apply. + + + + +Apply Changes + + +For the changes you have made to take effect press the Apply +button. To ignore any changes press the Cancel button. + + + +You can close the dialog using the X provided at the top right of the window. If you need to change the configuration just re-open the +configuration dialog as shown before. + + +
diff --git a/doc/kxsldbg/kxsldbg_inspector.docbook b/doc/kxsldbg/kxsldbg_inspector.docbook new file mode 100644 index 00000000..ec9995bc --- /dev/null +++ b/doc/kxsldbg/kxsldbg_inspector.docbook @@ -0,0 +1,103 @@ + + + + + +Keith +Isdale + +
k_isdale@tpg.com.au
+
+
+ +
+
+Setting and Modifying Breakpoints + + +The primary way to work with breakpoints is via the main window. See + + + + +Once you have started the style sheet, you can use the + +Tools +Show inspectors + +menu item. Then click on the Breakpoints tab. See below for an example. + + + +Setting Breakpoints + + + + +Setting Breakpoints + + + + +Adding a Breakpoint + + +You can add a breakpoint by supplying any of: + +a file and line number + +a template name + +a template name and a mode name + +a mode name + + + + + +And then pressing the Add button. + + + + +Argument Details + + +A file name may be absolute path to a local file. Or partial file (⪚ +xsldoc.xsl). + + + +A template or mode name may is fully Qualified Name where the non-local +part is optional ⪚ xsl:mytemplate is matched by +mytemplate + + + + +Deleting a Breakpoint + + +Firstly left mouse click the breakpoint you want to delete in the list of +current breakpoints. Then click the Delete button. + + + + +Deleting All Breakpoints + + +Click the Delete All button. + + + + +Enabling or Disabling a Breakpoint + + +Firstly &LMB; click the breakpoint you want to delete in the list of +current breakpoints. Then click the Enable button. + + +
diff --git a/doc/kxsldbg/kxsldbg_mainwindow.docbook b/doc/kxsldbg/kxsldbg_mainwindow.docbook new file mode 100644 index 00000000..3dcd3a55 --- /dev/null +++ b/doc/kxsldbg/kxsldbg_mainwindow.docbook @@ -0,0 +1,455 @@ + + + + + +Keith +Isdale + +
k_isdale@tpg.com.au
+
+
+ +
+
+Using the Main Window + + +The Main Window + + + + +A text view of the current file being debugged +A text view of the current file being debugged. + + + + +Working With the Main Window + + +The state of a given breakpoint is indicated via the relevant text with a different background color. +You can choose the color desired: see the +SettingsConfigure +Editor dialog, on the +Colors page. + + +You can set, disable or delete a breakpoint using keys, the Debug menu or the buttons on the tool bar. + +You can move the cursor around the text using the following keys: + + +Arrow keys: Left Arrow, Right Arrow, Up Arrow or Down Arrow. +Page keys: Page Up or Page Down + + + + + + +Working With &kxsldbg; Output + + +Most of the output from &kxsldbg; is captured and presented either in the +inspectors dialog or the &kxsldbg; output window. The exceptions to this rule +are: + + +An error message that comes from &kxsldbg; is displayed inside a message dialog. + + +The result of evaluating an expression is displayed in a message dialog. + + +The output of search is sent to the file indicated in the &kxsldbg; output window. + + + + + + + +
diff --git a/doc/kxsldbg/kxsldbg_tools.docbook b/doc/kxsldbg/kxsldbg_tools.docbook new file mode 100644 index 00000000..0fa7ae8a --- /dev/null +++ b/doc/kxsldbg/kxsldbg_tools.docbook @@ -0,0 +1,93 @@ + + + + + +Keith +Isdale + +
k_isdale@tpg.com.au
+
+
+ +
+
+ +Miscellenous Tools + + +Several tools are available via the tools menu the main tool is the +inspector tool. + + + +Inspector Tool + + +The inspector tool is the contains all the individual dialogs for working +with: + +Breakpoints +Templates +Variables +Callstack entries +&XSL; source files +&XML; Enties + + + + + +Execute by Walking + +By clicking on Start execution with +walking menu a dialog is shown to allow the walk speed +to be chosen. + + +The Walk Window + + + + +The Walk Window + + + +To stop walking either use the W key or select the +Start execution with walking menu item. + + + +Lookup &XML; Entities + +To lookup a System ID in the current &XML; catalog +use the Lookup System ID menu then enter the +value to find the the dialog that displays. + + +The System ID Window + + + + +The System ID Window + + + +To lookup a PUBLIC ID use the Lookup Public +ID menu entry then enter the value to find the the dialog that +displays. + + +The Public ID Window + + + + +The Public ID Window + + + + +
diff --git a/doc/kxsldbg/main_window.png b/doc/kxsldbg/main_window.png new file mode 100644 index 00000000..970459a5 Binary files /dev/null and b/doc/kxsldbg/main_window.png differ diff --git a/doc/kxsldbg/next.png b/doc/kxsldbg/next.png new file mode 100644 index 00000000..00d4fd9d Binary files /dev/null and b/doc/kxsldbg/next.png differ diff --git a/doc/kxsldbg/publicid_window.png b/doc/kxsldbg/publicid_window.png new file mode 100644 index 00000000..01af4d04 Binary files /dev/null and b/doc/kxsldbg/publicid_window.png differ diff --git a/doc/kxsldbg/run.png b/doc/kxsldbg/run.png new file mode 100644 index 00000000..e9b35a28 Binary files /dev/null and b/doc/kxsldbg/run.png differ diff --git a/doc/kxsldbg/sources.docbook b/doc/kxsldbg/sources.docbook new file mode 100644 index 00000000..ecfb658e --- /dev/null +++ b/doc/kxsldbg/sources.docbook @@ -0,0 +1,44 @@ + + + + +Keith +Isdale + +
k_isdale@tpg.com.au
+
+
+ +
+
+Working With &XSLT; Source Files (Sources) + + +If the inspector dialog is not showing use the + +Tools + +Show inspectors + +menu item. To work with sources click on the sources tab of dialog shown. + + + +All &XSLT; source files that are included by the &XSLT; file or one of its +siblings are listed here. + + +The Sources Window + + + + +The Sources Window + + + + +Clicking on a source entry in the list shown will cause the cursor in the +main window to move to the start of file indicated. + +
diff --git a/doc/kxsldbg/sources_window.png b/doc/kxsldbg/sources_window.png new file mode 100644 index 00000000..14e9d3da Binary files /dev/null and b/doc/kxsldbg/sources_window.png differ diff --git a/doc/kxsldbg/step.png b/doc/kxsldbg/step.png new file mode 100644 index 00000000..a0e64fc0 Binary files /dev/null and b/doc/kxsldbg/step.png differ diff --git a/doc/kxsldbg/systemid_window.png b/doc/kxsldbg/systemid_window.png new file mode 100644 index 00000000..04b7be70 Binary files /dev/null and b/doc/kxsldbg/systemid_window.png differ diff --git a/doc/kxsldbg/templates.docbook b/doc/kxsldbg/templates.docbook new file mode 100644 index 00000000..bdd0bdd2 --- /dev/null +++ b/doc/kxsldbg/templates.docbook @@ -0,0 +1,34 @@ + +Working With Templates + + +If the inspector dialog is not showing use the + +Tools +Show inspectors + +menu item. To work with templates click on the templates tab of dialog +shown. + + + +All templates found are listed here. Please note that the export rules of +&XSLT; apply. So only there may be more than one template with the same +match and mode details. + + +The Templates Window + + + + +The Templates Window + + + + +Clicking on a template entry in the list shown will cause the cursor in +the main window to move to the file and line number indicated. + + + diff --git a/doc/kxsldbg/templates_window.png b/doc/kxsldbg/templates_window.png new file mode 100644 index 00000000..f20f798f Binary files /dev/null and b/doc/kxsldbg/templates_window.png differ diff --git a/doc/kxsldbg/variables.docbook b/doc/kxsldbg/variables.docbook new file mode 100644 index 00000000..7cdd1cdf --- /dev/null +++ b/doc/kxsldbg/variables.docbook @@ -0,0 +1,69 @@ + + + + + +Keith +Isdale + +
k_isdale@tpg.com.au
+
+
+ +
+
+ +Working With Variables + + +If the inspector dialog is not showing use the + +Tools +Show inspectors + +menu item. + + + +Local and global variables are show in a tab on the inspector dialog. +The following example shows a XSLT code segment that declares a global and a local variable + + + + <xsl:variable name="globalvariable" select="'foo'"/> + + <xsl:template match="/"/> + <xsl:param name="localvariable" select="'bar'"/> + </xsl:template match="/"/> + + + +Clicking with with mouse on a variable in the list will cause summary +information to be displayed in the bottom of the dialog. If a variable has + a select expression, for example + + + + <xsl:variable name="changeable" select="'oldValue'" /> + + + +then a new XPath an be choosen by entering a new value + for Variable expression then clicking the Set expression button. + + +The Variables tab + + + + +The Variables Tab +The Variables Tab + + + + +Clicking on a variable entry in the list shown will cause the cursor in +the main window to move to the file and line number indicated. + +
diff --git a/doc/kxsldbg/variables_window.png b/doc/kxsldbg/variables_window.png new file mode 100644 index 00000000..d90cb92d Binary files /dev/null and b/doc/kxsldbg/variables_window.png differ diff --git a/doc/kxsldbg/walk_window.png b/doc/kxsldbg/walk_window.png new file mode 100644 index 00000000..b30ce81b Binary files /dev/null and b/doc/kxsldbg/walk_window.png differ diff --git a/doc/kxsldbg/xsldbg_break.png b/doc/kxsldbg/xsldbg_break.png new file mode 100644 index 00000000..68657082 Binary files /dev/null and b/doc/kxsldbg/xsldbg_break.png differ diff --git a/doc/kxsldbg/xsldbg_data.png b/doc/kxsldbg/xsldbg_data.png new file mode 100644 index 00000000..8feb8c2e Binary files /dev/null and b/doc/kxsldbg/xsldbg_data.png differ diff --git a/doc/kxsldbg/xsldbg_delete.png b/doc/kxsldbg/xsldbg_delete.png new file mode 100644 index 00000000..fbe766c2 Binary files /dev/null and b/doc/kxsldbg/xsldbg_delete.png differ diff --git a/doc/kxsldbg/xsldbg_enable.png b/doc/kxsldbg/xsldbg_enable.png new file mode 100644 index 00000000..56c5e5c8 Binary files /dev/null and b/doc/kxsldbg/xsldbg_enable.png differ diff --git a/doc/kxsldbg/xsldbg_output.png b/doc/kxsldbg/xsldbg_output.png new file mode 100644 index 00000000..5c8fdc53 Binary files /dev/null and b/doc/kxsldbg/xsldbg_output.png differ diff --git a/doc/kxsldbg/xsldbg_refresh.png b/doc/kxsldbg/xsldbg_refresh.png new file mode 100644 index 00000000..0297288e Binary files /dev/null and b/doc/kxsldbg/xsldbg_refresh.png differ diff --git a/doc/kxsldbg/xsldbg_source.png b/doc/kxsldbg/xsldbg_source.png new file mode 100644 index 00000000..17618fe8 Binary files /dev/null and b/doc/kxsldbg/xsldbg_source.png differ diff --git a/doc/kxsldbg/xsldbg_stepdown.png b/doc/kxsldbg/xsldbg_stepdown.png new file mode 100644 index 00000000..3430b61e Binary files /dev/null and b/doc/kxsldbg/xsldbg_stepdown.png differ diff --git a/doc/kxsldbg/xsldbg_stepup.png b/doc/kxsldbg/xsldbg_stepup.png new file mode 100644 index 00000000..3170b14c Binary files /dev/null and b/doc/kxsldbg/xsldbg_stepup.png differ diff --git a/doc/quanta/Makefile.am b/doc/quanta/Makefile.am new file mode 100644 index 00000000..febd406e --- /dev/null +++ b/doc/quanta/Makefile.am @@ -0,0 +1,3 @@ +KDE_LANG = en +KDE_DOCS = $(package) +KDE_MANS = AUTO diff --git a/doc/quanta/adv-quanta.docbook b/doc/quanta/adv-quanta.docbook new file mode 100644 index 00000000..d3a142ac --- /dev/null +++ b/doc/quanta/adv-quanta.docbook @@ -0,0 +1,623 @@ + + + + +Advanced Features + + +Christopher +Hornbaker + +
chrishornbaker@earthlink.net
+
+ +
+ + + +
+
+ +Advanced Features + + +This chapter outlines the advanced features of &quantaplus; and how to use +them. + + + +&XML; Tools + + +The 3.2 release of &quantaplus; brings with it many new &XML; tools and +features. The tools are unique in their integration within &quantaplus;. +All of these tools use Kommander as a front-end and +libxml2 and libxslt +as a back-end. The combination of these makes for fast, efficient, +productive, and complete tools. + + + +&kde; Documentation Tools + + +&quantaplus; supports &kde;'s two main documentation tools: +meinproc and checkXML. + + + +<command>meinproc</command> + + +Anyone who has worked with &kde; documentation knows +meinproc and how superb it is. Well, take it up a notch +with a great graphical interface! No longer resort to a shell; just click +the icon that resembles a processor and you are done! + + + + +Current Working Folder + + +This application expects an index.docbook +file to be present in a folder. If index.docbook +is in the current working folder, then simply leave Current Working +Folder checked. If it is not, then uncheck Current Working Folder +and enter the folder you wish to process in the Other Folder field. + + + + + + + +Outputted files are placed in the same folder as the sources files. +All &HTML; files are removed each time +meinproc is ran. + + + + + + +<command>checkXML</command> + + +Again, anyone who has worked with &kde; documentation knows this +helpful application. Again, &quantaplus; provides a great little graphical +front-end to this one. + + + + +Current Working Folder + + +If the currently opened file is the index.docbook +file, then simply leave Current Working Folder checked. +If it is not, then uncheck Current Working Folder and +enter the folder of where index.docbook can be found. + + + + + + +Output + +If there is output, then your file is invalid. Please correct the reported +errors and try again. + + + + + + +&XML; Validation + + +&quantaplus; has a great &XML; validation tool, which uses a +xmllint back-end. + + + + +Current File + + +If the file to be validated is currently focused on in &quantaplus;, then +simply leave Current File checked. If it is not, then +uncheck Current File and select the file to be +validated from the Other File file selector. + + + + + +Well-formed Checking + + +If you only wish to know only if the file is well-formed, click the +Well-formed Checking Only check box. + + + + + +Definition &URI; + + +If you are using a &DTD; and it is specified within the &XML; file, then +select &DTD; (Internal) (default), else select &DTD; (External) and locate +the &DTD; with the Definition &URI; file selector. Both &W3C; &XML; +Schema and RelaxNG validation are required to be +externally defined via the Definition &URI; file selector. + + + + + + + +&XSL; Processing + + +Yep, &quantaplus; has a &XSL; processing tool, too! This uses the +xsltproc tool provided with +libxml2. + + + + +Current File + + +If the file to be processed is currently focused on in &quantaplus;, then +simply leave Current File checked. If it is not, +then uncheck Current File and select the file to be +processed from the Other File selector. + + + + + +Stylesheet + + +Select the &XSL; file that you wish to be used. + + + + + +Output file name + + +Enter the name of the file that you want the resulting file to be called. +File is outputed to your home folder by default. + + + + + + + +This application lacks flexibility. Sorry, we will do better next time. + + + + + + + + + + +Using Plugins + + +Mathieu +Kooiman + +
quanta@map-is.nl
+
+
+ + + +
+
+ +Using Plugins + + +What is a Plugin? + + +&quantaplus; is able to load plugins, which are KParts. The +KPart framework is another very powerfull framework of &kde;. A KPart is a +relatively small, reusable container of functionality. It allows &kde; +developers to easily build on the work of other programmers. One +example of this is &quantaplus; itself. The editor &quantaplus; uses is +the &kate; KPart. The &kate; KPart already had a bunch of functionality that +&quantaplus; needed, like syntax highlighting. Integrating it into +&quantaplus; allowed the &quantaplus; developers to focus on what +&quantaplus; should be able to do, rather than facing the many problems +that developing a new editor KPart/component from scratch would bring. + + + +The plugins &quantaplus; loads might have nothing to do with &quantaplus; +itself. This makes it a very powerful plugin system. You can benefit from +extra functionality and need not to wait until someone integrates it into +&quantaplus;! The plugins can be loaded into a number of &GUI; elements. +More on this below. + + + + + +Understanding the Edit Plugin Dialog + +To install a Plugin or KPart we will work from the + +Plugins +Edit + menu. This will bring up the following dialog: + + + + + + +The Edit Plugin dialog. + + + +This dialog lets you manage all defined plugins and lets you add new ones. +We will describe each &GUI; element in here: + + + +Search paths + + +Here you can fill in a search path. When adding a plugin without a +Location, &quantaplus; will search these paths to +find the plugin. + + + + + +Add + + +This will bring up a dialog which allows you to add a new plugin. + + + + + +Configure + + +This will allow you to change the settings of a particular plugin. + + + + + +Remove + + +Removes the currently selected plugin. + + + + + +Refresh + + +Refreshes the dialog's contents. + + + + + +Read to learn more about plugins. + +
+ + Team Development + Often a project has more than one people working on it and there is some kind of hierarchical relationsship between them. &quantaplus; supports the notion of team members and they are configurable in the + + +&Shift;F7 + +Project +Project Properties + dialog. + + + + + + The team member editor dialog + + + The Name, Email entries are self explaining. Nickname is the nick of the user and acts as an unique identifier. + + Role specifies the role of the member in the project and can be one of the following: + + +Team leader + + +Subproject Leader + + +Task Leader + + +Simple Member + + + +Task is a description of the task assigned to this member. +Subproject: you can select a list of subproject. Subprojects can be configured and created by pressing the Edit subprojects button. Each subproject has a user visible name and a location entry, the later specifying a relative path to a directory under the project tree. This means that a subproject is a directory under the main project. For example the main project can be the website of your company, while a subproject can be the website for the intranet, located under the intranet folder in the project. +One member can have more than one role in the project, like both team leader and subproject leader. +The user should select who is himself from the list of the team members. This is possible by selecting a team member from the list and pressing the Set to Yourself button. The currently selected member (your identity) appears in bold after the You are: text. +Nicknames and setting yourself is important regarding messaging and annotations. See to learn more about annotations. +Aside of keeping track of your team, there is one more benefit of setting up the team members: you can configure an event to inform the team leaders when some action happens. See about how to do it. + + + Event Actions + Event actions are actions executed when some event happens in the project. An example would be logging when the project was opened and closed, so it can be later reviewed how much one worked on it, or sending a mail when a file is saved, or adding the file to the CVS with the help of a script when the file is added to the project and the list could continue. + On the Event Configuration page of the + + + &Shift;F7 + + Project + Project Properties + dialog you can create, edit and delete the event actions. + + + + + + The event editor dialog + +The entries in the dialog are: + + +Event +the action is executed when the event selected from the list happens. The event names are self explanatory. + + +Action + +the type of the executed action. The possible choices are + + + +Non-script action +an action that is not a user defined script action. See for user action. + +Action name specifies the action to be executed when the event happens. + + + + Send email + an email is sent when the action happens to the recipient selected in the Receiver list. The recipient can be a team or subproject leader. See for defining such leaders. + + + + + Log event + the event is logged in a file. The arguments for this action are: + + + + Log file + the filename with full path + + + Detail + How much information will the log contain + + + Behavior + Whether to create/overwrite the existing log file or append the new logged event to it. + + + + + +Script action +an user defined script action. See for user action. + + Action name specifies the action to be executed when the event happens. + + + + + + + +The other entries depend on the Action type as they were described. + + + + +Annotations +Annotations are special comments in the documents. They differ from regular comments by the following things: + + +the information is collected by Quanta and shown in the Annotations toolview. + + +the information can be addressed to a team member + + + +Entering annotations is simple. You can either use the Annotate entry from the editor context menu or enter the @annotation keyword in a comment area followed by the annotation text. +Annotation example in XML +<!-- @annotation It is possible that this code is wrong. --> + +<!-- @annotation + Multiline + annotation. +--> +Annotation example in PHP +/* @annotation +Use PHP comments when annotating a PHP area +*/ + + + +Annotations can be addressed for a specific member of your team. The syntax in this case is @annotation(nickname) or @annotation(role), where nickname is the nickname of a team member, while role is a project role from the following items: + + +team leader + + +task leader + + +subproject leader + + +The task and subproject leaders should be followed by the corresponding task and subproject name, like it is shown in the below examples. + + +Make a note to a team member with the nickname <emphasis>eric</emphasis> +<-- @annotation(eric) Eric, please look at this. Andras --> + +Inform the team leader +<-- @annotation(team leader) This is very important for the team --> + +Inform the <emphasis>PHP</emphasis> subproject leader +// @annotation(subproject leader:PHP) What do you think about it? + + +Nicknames and role names are case insensitive, but spaces around brackets and the : make the annotation invalid. +More about team members, roles and nicknames can be found in . + +The annotations found in the project can be inspected in the Annotations view. It consists of tree tabs: + + +Current File + +The annotation found in the current file. + + + +For You + +Annotations in the project addressed for you. The entries are groupped per file. + + + + +All Files + +The annotations found in all the project files, groupe dy files + + + +The annotations are scanned on project and file load for external modifications. This way even is somebody adds an annotation outside of &quantaplus;, it will be recognized. As scanning can take some time, the information dialog about new annotations addressed for you might appear after some seconds of the project loading. + + + + +&debugging-quanta; +
diff --git a/doc/quanta/attribute_tree.png b/doc/quanta/attribute_tree.png new file mode 100644 index 00000000..a823dc6c Binary files /dev/null and b/doc/quanta/attribute_tree.png differ diff --git a/doc/quanta/config-quanta.docbook b/doc/quanta/config-quanta.docbook new file mode 100644 index 00000000..4f8c9a1f --- /dev/null +++ b/doc/quanta/config-quanta.docbook @@ -0,0 +1,125 @@ + + + + + Configuring &quantaplus; + + + András + Mantia + +
amantia@kde.org
+
+
+ + + +
+
+ + Configuring &quantaplus; + + + This chapter describes how you can control the behavior of &quantaplus;. + + + The configuration dialogs are accessible from the Settings menu. Here we will discuss only few of them, the rest are not &quantaplus; specific and a short description can be found at . + + + + Configuring Quanta + The configuration dialog can be invoked by using SettingsConfigure Quanta.... The dialog has several pages, we will discuss them one by one. + + + +Tag Style +You can change the behavior of &quantaplus; related to tags, including autocompletion. The entries are: + +Tag case: the case of the automatically inserted tags. Default Case means the tags will be inserted as they are described in the tagXML files. +Attribute case: the case of the automatically inserted attributes. Default Case means the attributes will be inserted as they are described in the tagXML files. +Attribute quotation: how to quote attributes inserted by &quantaplus;. +Auto-close optional tags: if checked, tags for which closing tag is option will be automatically closed once the tag closing > is entered. +Auto-close non-single and non-optional tags: same as before for the rest of tags, exception being the single tags. +Use auto-completion: turn on/off the autocompletion of tags, attributes, functions, etc. + +Update opening/closing tag automatically: if enabled, whenever you change the opening tag, the corresponding closing tag will be changed as well and vice-versa. +Automatic replacement of the accented characters: if enabled the accented characters will be replaced with their codes as you type. + + + + + + + +Environment +A page to control the environment and some default settings. + + +Mimetypes: mimetypes used to recognize different kind of files. Use the Reset to Default button to fill in the entries with the default settings. +Default character encoding: the encoding of the newly created files, or files loaded in other way than FileOpen (where you can override the encoding). This setting is overridden by the same setting in the Project Properties if a project is loaded. +Default DTD: the DTD used for newly created files, or files whose DTD was not recognized. This setting is overridden by the same setting in the Project Properties if a project is loaded. +Create backups: &quantaplus; will create backup files periodically, so in case of power failure or crash, on the next startup the document can be restored from this backup. This is not the same as the backup created on file save. Even for not-yet saved documents there is a backup created. +Startup Options: self explanatory setting which control what will happen on startup. + + + + + + + +User Interface +Here you can control the look and feel of &quantaplus;. + +The preview and the documentation can appear in the editor area or in a separate toolview, in which case it's possible to look at the documentation/preview and the source as well. +It's also possible to configure the look of the toolview and document tabs. +Reset window layout to the default on the next startup is useful when you have messed up the user interface by changing the MDI modes and docking/undocking the toolviews. It is the same as the --resetlayout command line switch. +This is the place also to control the behavior of the file trees. +The Warning Messages section is useful to enable or disable the warning messages that can be dismissed by checking the Do not show again box in them. + + + + +VPL View +The place to change the &VPL; behavior. You can enable the showing of an icon in place of scripts as well as configure the synchronization of the VPL and source view when the splitted mode is activated. See to learn how to activate the different modes. + + + + +Parser +Here you can fine-tune the parser and the structure tree, which is the visual representation of the parser nodes in the document. +In the Clicks on Structure Tree Items it is possible to change the actions assigned to mouse buttons when you click on the structure tree. +In the Structure Tree Look & Feel it is possible to configure what kind of nodes are visible in the tree, how often is the tree updated while editing and on an update how deeply should be the structure tree automatically opened. Empty nodes are the white-space text nodes, while empty groups are groups for whom there was no element found in the current document. + + + + +Abbreviations + +The place to define abbreviations (some kind of templates), that can be expanded to bigger text while editing. Abbreviations are organized in groups, each group can be valid for more than one &DTEP;. This means you can have a group valid for PHP where the "ifclause" abbreviation template means something else than in a group valid for JavaScript. + + + + + + + +Configuring Actions +User defineable action creation and editing is described in . + + + + Configuring Plugins + Here you can manage your plugins. Plugins are KPart applications written by third parties that can be reused in any KPart aware application, the most known being &konqueror;. When creating a plugin you must specify the: + + Name: the user visible name + Output window: plugins can appear in a tab of the editor area or in a separate toolview at the bottom + Location: the path to the plugin, if it is not located in the standard locations, like $KDEDIR/lib . + File name: the relative path and the filename to the plugin's libtool file, like kde3/libcervisiapart.la + Input: the plugin will get this information on startup, so it can open the Current File, the folder of the current file (Current File Path) or the Project Folder. + Read only part: check if the plugin refuses to load. Read-only KParts usually refuse to load without this option checked. + Validate plugin: if checked, &quantaplus; will test if the entered information is correct or not. Uncheck if the plugin is not yet available, but you will install later, so you can close the dialog. + + + See and for information about using the plugins. + +
diff --git a/doc/quanta/contents2.png b/doc/quanta/contents2.png new file mode 100644 index 00000000..e2a44eca Binary files /dev/null and b/doc/quanta/contents2.png differ diff --git a/doc/quanta/credits-license.docbook b/doc/quanta/credits-license.docbook new file mode 100644 index 00000000..65f44e5a --- /dev/null +++ b/doc/quanta/credits-license.docbook @@ -0,0 +1,150 @@ + + + + +Credits and License + + +Christopher +Hornbaker + +
chrishornbaker@earthlink.net
+
+
+ + + +
+
+ +Credits and License + + + +Sorry to anyone I missed or if I mis-spelt your name! + + + + +Much thanks to everyone who has spent the time to contribute! + + + +The &quantaplus; Development Team: + + +Bergia, Andrea +Original &CSS; editor. + + +Britton, Marc +Kommander, various features, and bug fixes. + + +Colton, Matthew +Splash screen for many versions + + +Deschildre, Nicolas +Visual Page Layout & undo/redo system + + +Dmitrienko, Dmitri +&PHP;4 debugger + + +Gulmini, Luciano +Frame Wizard + + +Hanley, Jason P. +Various fixes, foundational code for &DTD; parsing, and other &DTD; related work + + +Hindsgaul, Claus +Danish translation + + +Hornbaker, Christopher +The Anal &XML; Guy & Documentation + + +Isdale, Keith +&XSL; 1.0 &DTEP;, &kxsl; + + +Kooiman, Mathieu +Documentation, bug fixes, and &PHP; debugger framework. + + +Laffoon, Eric +Project Manager and web site admin. + + +Mantia, András +Core Developer + + +Moore, Richard +Coding, original TagXML docs, and more + + +Mous, Fabrice +Documentation + + +Nickel, Robert C. +Documentation + + +Pibil, Ted +Addition and maintainence of &DTD;s + + +Poplavsky, Dmitry +ex-Core Developer — left for commercial version + + +Vilches, George +Tree-based upload dialog + + +Yakovlev, Alexander +ex-Core Developer — left for commercial version + + + + + + +Special Thanks To: + + +xmlsoft.org +The writers of libxml2 and libxslt. + + + + + + +&quantaplus; 2000, 2001, 2002, 2003 &quantaplus; Development Team. + + + +&quantaplus; User Manual 2002, 2003 &quantaplus; Development Team. + + +&underFDL; +&underGPL; +
diff --git a/doc/quanta/debugging-quanta.docbook b/doc/quanta/debugging-quanta.docbook new file mode 100644 index 00000000..88ad9bc1 --- /dev/null +++ b/doc/quanta/debugging-quanta.docbook @@ -0,0 +1,400 @@ + + + + +Debugging in &quantaplus; + + +Christopher +Hornbaker + +
chrishornbaker@earthlink.net
+
+
+ + +Linus +McCabe + +
Linus@McCabe.nu
+
+
+ + + +
+
+ +Debugging in &quantaplus; + + +Using the &PHP; Debugger + + +With &quantaplus; version 3.3, the debugger handling was reimplemented. +The support for the now obsolete &PHP; (3) builtin debugger and was dropped, +as was the support for the dbg debugger. Instead, a general debug plugin system +was developed, to allow different plugin implementations. + + +Currently only one plugin is available which adds support to use &gubed; with +&quantaplus;. + + +To use a debugger for your project, open the project settings and chose a suitable +debugger plugin. To alter debugger specific settings, press the 'Options' button +next to the debugger plugin drop down. + + + +General usage + +Once a project has a debugger activated, a few additional items will appear in the +&quantaplus; user interface: + + + + +Debugger menu + + +A new menu will appear where you can reach most of the debugger functionality. + + + + + +Debugger toolbar + + +A toolbar with access to the most common debugging commands. + + + + + +Variables toolview + + +A toolview where the contents of watched variables is showed. Appears in the left dock by default. + + + + + +Breakpoints toolview + + +A toolview where all the breakpoints, line and conditional, are listed. Appears in the bottom dock by default. + + + + + +Debug Output toolview + + +A toolview where the output (as in HTML) of the debugger is shown. Appears in the bottom dock by default. + + + + + + + +Depending on what the debugger plugin supports, all or a subset of the following functionality will be available. + + + + + + + + +Debug +Session +Start Session + + + + +This action is used to connect to the debugger if that is required, or tell the plugin to start listening for debug requests. +This action is triggered by default when a project using a debugger is opened, so usually you don't need to care about it. + + + + + + + +Debug +Session +End Session + + + + +The opposite of + +Debug +Session +Start Session +. Closes a connection to the debugger or stops listening for requests. + + + + + + + +Debug +Execution +Send HTTP Request + + + + +Sends a HTTP request to the server to initiate a debug request. Using this action is equivalent to +using a browser to look at the current document. The output of the request ends up in the Debug +Output dock. + + + + + + + +Debug +Execution +Pause + + + + +Pauses a running script + + + + + + + +Debug +Execution +Run + + + + +Tells the debugger to start executing the script and send information about watched variables and current +line of execution as it goes along. If this is done while a script is paused, execution will proceed. If it's done +before a debug request is initiated, the script will start running as soon as the request is initiated. + + + + + + + + +Debug +Execution +Leap + + + + +Tells the debugger to start executing the script without sending information about watched variables and current +line of execution. If this is done while a script is paused, execution will proceed. If it's done +before a debug request is initiated, the script will start leaping as soon as the request is initiated. + + + + + + + +Debug +Execution +Step + + + + +Tells the debugger to execute the next instruction in the script, without stepping into functions or inclusions. + + + + + + + +Debug +Execution +Step Into + + + + +Tells the debugger to execute the next instruction in the script, stepping into functions or inclusions if possible. + + + + + + + +Debug +Execution +Step Out + + + + +Tells the debugger to execute until it escapes the current function. + + + + + + + +Debug +Execution +Skip + + + + +Tells the debugger to skip the next instruction and proceed to the next one as if the current one didn't exist. + + + + + + + +Debug +Execution +Kill + + + + +Tells the debugger to kill the currently running script. + + + + + + + + +Debug +Breakpoints +Break when... + + + + +Opens a dialog where you can specify conditional breakpoints. + + + + + + + +Debug +Breakpoints +Toggle breakpoint + + + + +Toggles a line breakpoint at the line of the cursor in the current line + + + + + + + +Debug +Breakpoints +Clear breakpoints + + + + +Clears all the breakpoints. + + + + + + + + +Debug +Variables +Watch variable + + + + +Opens a dialog where you can enter a variable or expression you wish to watch. The value of the watch will appear +in the variables tool view. + + + + + + + +Debug +Variables +Set value of variable + + + + +Opens a dialog where you can enter a variable and a new value for it. + + + + + + + + + + + + + + +Using &kxsl;, the &XSL; Debugger + + +&kxsl; is the creation of Keith Isdale, as is this section of the +documentation. &kxsl; is a &kde; front-end and a KPart to +xsldbg, which you can find at +http://xsldbg.sf.net along with many other works by +Keith. + + + +To start &kxsl;, select + +Plugins +&kxsl; +. + + + +Please refer to the &kxsl; documentation for further information +regarding its usage. + + +
diff --git a/doc/quanta/doc-view1.png b/doc/quanta/doc-view1.png new file mode 100644 index 00000000..e6a405ff Binary files /dev/null and b/doc/quanta/doc-view1.png differ diff --git a/doc/quanta/dtd-conversion.png b/doc/quanta/dtd-conversion.png new file mode 100644 index 00000000..c0213063 Binary files /dev/null and b/doc/quanta/dtd-conversion.png differ diff --git a/doc/quanta/dtep_doc_img15.png b/doc/quanta/dtep_doc_img15.png new file mode 100644 index 00000000..0f7e31a1 Binary files /dev/null and b/doc/quanta/dtep_doc_img15.png differ diff --git a/doc/quanta/dtep_doc_img18.png b/doc/quanta/dtep_doc_img18.png new file mode 100644 index 00000000..078801bd Binary files /dev/null and b/doc/quanta/dtep_doc_img18.png differ diff --git a/doc/quanta/dtep_doc_img21.png b/doc/quanta/dtep_doc_img21.png new file mode 100644 index 00000000..f5d922bb Binary files /dev/null and b/doc/quanta/dtep_doc_img21.png differ diff --git a/doc/quanta/dtep_doc_img22.png b/doc/quanta/dtep_doc_img22.png new file mode 100644 index 00000000..8871bdd8 Binary files /dev/null and b/doc/quanta/dtep_doc_img22.png differ diff --git a/doc/quanta/dtep_doc_img23.png b/doc/quanta/dtep_doc_img23.png new file mode 100644 index 00000000..62e965c1 Binary files /dev/null and b/doc/quanta/dtep_doc_img23.png differ diff --git a/doc/quanta/dtep_doc_img24.png b/doc/quanta/dtep_doc_img24.png new file mode 100644 index 00000000..1fc30841 Binary files /dev/null and b/doc/quanta/dtep_doc_img24.png differ diff --git a/doc/quanta/dtep_doc_img25.png b/doc/quanta/dtep_doc_img25.png new file mode 100644 index 00000000..bac85056 Binary files /dev/null and b/doc/quanta/dtep_doc_img25.png differ diff --git a/doc/quanta/dtep_doc_img7.png b/doc/quanta/dtep_doc_img7.png new file mode 100644 index 00000000..a47ea1dc Binary files /dev/null and b/doc/quanta/dtep_doc_img7.png differ diff --git a/doc/quanta/dtep_doc_img8.png b/doc/quanta/dtep_doc_img8.png new file mode 100644 index 00000000..6ade4fe2 Binary files /dev/null and b/doc/quanta/dtep_doc_img8.png differ diff --git a/doc/quanta/edit-upload-profile.png b/doc/quanta/edit-upload-profile.png new file mode 100644 index 00000000..c9ea5c23 Binary files /dev/null and b/doc/quanta/edit-upload-profile.png differ diff --git a/doc/quanta/event-editing.png b/doc/quanta/event-editing.png new file mode 100644 index 00000000..2f0205dc Binary files /dev/null and b/doc/quanta/event-editing.png differ diff --git a/doc/quanta/exec.png b/doc/quanta/exec.png new file mode 100644 index 00000000..c6c1c8c3 Binary files /dev/null and b/doc/quanta/exec.png differ diff --git a/doc/quanta/extending-quanta.docbook b/doc/quanta/extending-quanta.docbook new file mode 100644 index 00000000..6dd0629e --- /dev/null +++ b/doc/quanta/extending-quanta.docbook @@ -0,0 +1,1789 @@ + + + + +Extending &quantaplus; + + +Christopher +Hornbaker + +
chrishornbaker@earthlink.net
+
+
+ +András +Mantia + +
amantia@kde.org
+
+
+ + + +
+
+ +Extending &quantaplus; + + +This chapter describes how to customize &quantaplus; to your particular +needs and how you can help &quantaplus; become better. + + + + + +Document Type Editing Package (&DTEP;) + + +Document Type Editing Packages (&DTEP;s) are used in &quantaplus; to add +support for markup, scripting languages, and &CSS;. They allow +&quantaplus; to provide features like auto-completion and node trees. +Their simplicity and flexibility are what make &quantaplus; a fast, +developer friendly &IDE; for web developers. They are what make &quantaplus; +an easy-to-use, productive environment. + + + +&DTEP;s come in two flavors, Family 1, which are markups, and Family 2, +which are scripting and &CSS;. &DTEP;s are made up of two parts, the Tag +Folder and the Toolbars. Tag Folders are composed of two types of files, +the &descriptionrc; and TagXML files, which carry the extension .tag. +Toolbars are the handy, icon-oriented tabs of buttons (above the editing +window) which place text into a document faster than the user can type. + + + + &DTEP;s can be created manually (see below), downloaded or automatically created from an existing DTD. See for details about the conversion. + + + +This document describes how to make TagXML files, the &descriptionrc;, and +toolbars. In short, a &DTEP;. + + + +TagXML files (.tag) define both the attributes specific to a tag and the +layout and contents of the properties dialog &quantaplus; shows for the tag. +The &descriptionrc; file provides rules and information on the &DTEP; +itself. Toolbars provide a quick means for adding tags into a document +without worry of mis-spellings and such. + + + +Packaging + + +Tag Folders are just that, folders. They are composed only of the +&descriptionrc; and TagXML files. Tag Folders carry the name of the mark-up +language and version, if applicable. (For example, html-4.01-strict) + + + + +TagXML + + +The table below lists the elements defined in TagXML and declares whether +they are required or not. While not all are required, it is recommended +that you use as many as you can so that other users can have a better +experience and more information to work with. + + + + + + +Element +Default Usage +Case Usage + + + + +TAGS +required +always + + +tag +required +always + + +label +optional +required to create a properties dialog + + +attr +optional +required to define an attribute + + +tooltip +optional +required to have the properties dialog display a tooltip + + +whatsthis +optional +required to have the properties dialog display a What's This + + + +list +optional +required when an attr is of the type list + + +item +optional +required when <list> is used + + +textlocation +optional +always + + +location +optional +required when label is used + + +text +optional +required when label is used + + +children +optional +list of tags that can appear within the tag being defined + + +child +required +a children entry + + +stoppingtags +optional +list of tags that tell another tag to end + + +stoppingtag +required +a stoppingtags entry + + + + + + + +TagXML Element Descriptions + + +The following sections will describe, in detail, each element. Everything +from where they can go to what goes in them is layed out in an +easy-to-follow manner. + + + +TAGS + + +This is the root element of a TagXML document. It may appear in a document +only once. It can contain the definition of multiple tags. This is an +element-only type element. + + + + + + +Parent(s) +Children + + + + +NONE +tag + + + + + + + +tag + + +Wrapper for tag being defined. This is an element-only type element. + + + + + + +Parent(s) +Children + + + + +TAGS +label, attr, stoppingtags + + + + + + + + + +AttributeTypeValues +DefaultUseDescription + + + + +namestring +requiredSpecifies the name of the tag being defined. + + +singleboolean +optionalSpecifies whether or not the tag requires a +closing tag </(tagname)>. + + +typestringxmltag +optionalSpecifies the type of tag being defined. + + +xmltag +Type of tag is XML-based. (Family 1 only.) + + + entity + The tag describes an entity. (Family 1 only.) + + +property +Type of tag is &CSS; related. (Family 2 only.) + + +function +Type of tag is a script function. When used, +<attr> becomes arguments of the function. (Family 2 only.) + + +class +Type of tag is a script class. (Family 2 only.) + + +method +Type of tag is a class method. (Family 2 only.) + + +returnTypestringvoid + +optionalSpecifies the return type of tag being +defined. (Family 2 only.) + + +void +Type of tag returns void. + + +int +Type of tag returns int. + + +float +Type of tag returns float. + + +long +Type of tag returns long. + + +string +Type of tag returns string. + + + versionstring + optionalSpecifies the version of the language for which this tag is valid + + + extendsstring + optionalValid only if the type of the tag is "class". The name of the base class for this class. (Family 2 only.) + + + classstring + optionalValid only if the type is "method". Specifies the name of the class to where this method belongs. (Family 2 only.) + + + commonboolean + optionalif "yes", the tag specifies a common attribute group and the attributes inside this tag can be attached to any other tag. (Family 1 only.) + + + commentstring + optionalthe comment string appears near the tag name in the completion box + + + + + + +label + + +Place a label in the dialog. The text is specified by the <text> tag. +This is an element-only type element. + + + + + + +Parent(s) +Children + + + + +tag +text, location + + + + + + + +attr + + +Defines an attribute of the tag. This element occurs once for each +attribute. It defines the name and type of attribute. It also contains +additional tags that specify how this attribute should be displayed, et cetera. +This is an element-only type element. + + + + + + +Parent(s) +Children + + + + +tag +location, list, tooltip, whatsthis, textlocation + + + + + + + + + +AttributeTypeValues +DefaultUseDescription + + + + +namestring +requiredSpecifies the name of the attribute being +defined. + + +typestringinput +requiredSpecifies the type of the attribute being +defined. + + +input +Field supports free text entries (text field). + + +check +Field value is boolean (check box). + + +color +Field value is a color. + + +url +Field value is a &URL;. (Local file to refer to.) + + +list +Field value is an item from a specified list. + + +statusstringoptional +requiredSpecifies whether or not the argument is +required. (Family 2 only.) + + +optional +Argument is optional. + + +required +Argument is required. + + +implied +Argument is implied. + + + sourcestring + optionalSpecifies the sources used to fill the entry for the attribute in the tag editor dialog and the attribute tree + + + selection + The selected text is used as source + + + dcop + The result of a dcop method is used as source + + + interfacestring + optionalRequires source="dcop". The dcop interface from inside &quantaplus; used to get the source data. + + + methodstring + optionalRequires source="dcop" and an interface name. The dcop method name from inside &quantaplus; used to get the source data. + + + argumentsstring + optionalRequires source="dcop", an interface and a method name. The arguments passed to the method. It can be empty or "%tagname%", meaning the current tags name. + + + + + + + +tooltip + + +Defines the tooltip for a field in the dialog. This element is text-only. + + + + +Currently only plain text is supported (you cannot use any markup). + + + + + + + +Parent(s) +Children + + + + +attr +NONE + + + + + + + +whatsthis + + +Defines the 'What's This' help for a field in the dialog. This element is +text-only. + + + + +Currently only plain text is supported (you cannot use any markup). + + + + + + + +Parent(s) +Children + + + + +attr +NONE + + + + + + + +list + + +A container tag that groups together the items in a list. It may appear +only once for each attribute description. This is an element-only type +element. + + + + + + +Parent(s) +Children + + + + +attr +item + + + + + + + +item + + +Defines an item in a list. This element is text-only. + + + + + + +Parent(s) +Children + + + + +list +NONE + + + + + + + +textlocation + + +Specifies the position of a tag's attribute text within a dialog. This tag +can only occur once for each attribute in the dialog (&ie; one for each +<attr> tag). This element is empty. + + + + + + +Parent(s) +Children + + + + +attr +NONE + + + + + + + + + +AttributeType +UseDescription + + + + +rownonNegativeInteger +requiredSpecifies the row in the dialog layout of a +field or label. + + +colnonNegativeInteger +requiredSpecifies the column in the dialog layout of +a field or label. + + +rowspannonNegativeInteger +optionalSpecifies the number of rows a field should +span. + + +colspannonNegativeInteger +optionalSpecifies the number of columns a field +should span. + + + + + + + +location + + +Specifies the position and size of a field in the dialog. This tag should +occur once for each field in the dialog (&ie; one for each <attr> and +<label> tag). This element is empty. + + + + + + +Parent(s)Children + + + + +label, attrNONE + + + + + + + + + +AttributeType +UseDescription + + + + +rownonNegativeInteger +requiredSpecifies the row in the dialog layout of a +field or label. + + +colnonNegativeInteger +requiredSpecifies the column in the dialog layout of +a field or label. + + +rowspannonNegativeInteger +optionalSpecifies the number of rows a field should +span. + + +colspannonNegativeInteger +optionalSpecifies the number of columns a field +should span. + + + + + + + +text + + +Define the text for a label or check box. This element is text-only. + + + + + + +Parent(s)Children + + + + +label, attrNONE + + + + + + + +children + + +Defines a list of elements that can appear within the tag being specified. +This element is an element-only type element. + + + + + + +Parent(s)Children + + + + +tagchild + + + + + + + +child + + +Defines a child tag. This element is empty. + + + + + + +Parent(s)Children + + + + +childrenNONE + + + + + + + + + +AttributeTypeValues +UseDescription + + + + +namestring +requiredSpecifies a tag that can appear within the a +certain tag. + + +usagestring +optionalSpecifies the relation with the parent. + + +required +The parent must have at least one child with this name. + + + + + + + +stoppingtags + + +Defines a list of elements that force a tag to end. This element is an +element-only type element. + + + + + + +Parent(s)Children + + + + +tagstoppingtag + + + + + + + +stoppingtag + + +Defines a stopping tag. This element is empty. + + + + + + +Parent(s)Children + + + + +stoppingtagsNONE + + + + + + + + + +AttributeType +UseDescription + + + + +namestring +requiredSpecifies which tags force the ending of +another tag. + + + + + + + + +TagXML Usage + + +All TagXML files must begin with the &XML; declaration: <?xml +version="1.0" encoding="UTF-8"?> and must be properly nested and closed. + + + + +White space does not adversely affect anything, but watch out for & and +< characters. These should likely be replaced with an &amp; and +&lt;, respectively, in elements such as <tooltip>, <whatsthis>, +and <text>. Not doing so will not cause a crash, but you will have +chunks of your work disappear if you do not. + + + + + +TagXML Validation + + +To validate your TagXML files, simply click the Tools +pop-up dialog at the top of &quantaplus; and select Validate +TagXML. A dialog will present itself and you need only to follow +the simple directions. + + + + +This feature is currently not present. Currently validation occurs when +the TagXML files are loaded into &quantaplus;. + + + + + +TagXML Examples + + +Family 1 + + +The following will show you a valid Family 1 TagXML file. This file +happens to describe &W3C; &XML; Schema's <schema> element. The file name +for this TagXML file would be schema.tag. Simple, eh? + + + + + +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE TAGS> +<TAGS> + <tag name="schema"> + <label> + <text>id</text> + <location col="0" row="0"/> + </label> + <attr name="id" type="input"> + <tooltip>A unique ID for the element.</tooltip> + <whatsthis>A unique ID for the element.</whatsthis> + <location col="1" row="0"/> + </attr> + + <label> + <text>version</text> + <location col="0" row="1"/> + </label> + <attr name="version" type="input"> + <tooltip>Version of the schema.</tooltip> + <whatsthis>Version of the schema.</whatsthis> + <location col="1" row="1"/> + </attr> + + <label> + <text>targetNamespace</text> + <location col="0" row="2"/> + </label> + <attr name="targetNamespace" type="input"> + <tooltip>&URI; reference of the namespace of this schema.</tooltip> + <whatsthis>&URI; reference of the namespace of this schema.</whatsthis> + <location col="1" row="2"/> + </attr> + + <label> + <text>xmlns</text> + <location col="0" row="3"/> + </label> + <attr name="xmlns" type="input"> + <tooltip>&URI; reference for one or more namespaces for use in this schema. + If no prefix is used, then components of that namespace may be used unqualified.</tooltip> + <whatsthis>&URI; reference for one or more namespaces for use in this schema. + If no prefix is used, then components of that namespace may be used unqualified.</whatsthis> + <location col="1" row="3"/> + </attr> + + <label> + <text>attributeFormDefault</text> + <location col="0" row="4"/> + </label> + <attr name="attributeFormDefault" type="list"> + <items> + <item>qualified</item> + <item>unqualified</item> + </items> + <tooltip>Default form for all attributes within this schema.</tooltip> + <whatsthis>Default form for all attributes within this schema.</whatsthis> + <location col="1" row="4"/> + </attr> + + <label> + <text>elementFormDefault</text> + <location col="0" row="5"/> + </label> + <attr name="elementFormDefault" type="list"> + <items> + <item>qualified</item> + <item>unqualified</item> + </items> + <tooltip>Default form for all elements within this schema.</tooltip> + <whatsthis>Default form for all elements within this schema.</whatsthis> + <location col="1" row="5"/> + </attr> + + <label> + <text>blockDefault</text> + <location col="0" row="6"/> + </label> + <attr name="blockDefault" type="input"> + <location col="1" row="6"/> + </attr> + + <label> + <text>finalDefault</text> + <location col="0" row="7"/> + </label> + <attr name="finalDefault" type="input"> + <location col="1" row="7"/> + </attr> + </tag> +</TAGS> + + + + + + +Family 2 + + +The following will show you a valid Family 2 TagXML file. This file +happens to describe &PHP;'s overload function. The file name for this +TagXML file would be overload.tag. + + + + + +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE tags> +<tags> + <tag name="overload" type="function" returnType="void"> +<attr name="class_name" type="string" status="optional"/> + </tag> +</tags> + + + + + + + + +&descriptionrc; + + +The &descriptionrc; file is, also, quite simple and there is an editor for it accessible from DTDEdit DTD Settings. This will edit the &descriptionrc; for a &DTEP; you can select from a list. In order to +edit the &descriptionrc; for a newly created &DTEP; you should create a simple &descriptionrc; with the following entries: + + + + + + [General] + Version = Use 1 for &quantaplus; version <=3.1.2 and 2 for any version greater. + Name = DTD definition string. (-//&W3C;//DTD HTML 4.01 Transitional//EN) + NickName = The beautified name of the DTD. (HTML 4.01 Transitional). If not defined, Name is + used as NickName. + + + + +Once you have created it at put aside of the tag files, load the newly created &DTEP; with DTDLoad DTD Package (DTEP) and after it is loaded you can proceed with editing the settings of the &DTEP;. Check the tooltips and the whatsthis text of the entries in the editor dialog to understand the meaning of each entry. Alternatively you can read the quanta/data/dtep/dtd-description.txt from the source tarball containing a description about the format. + + + + + +User Defined Actions + +Actions are very common in every application. You meed them often when you use any application. Clicking on a toolbar icon, selecting a menu item or using a shortcut usually executes an action. In &quantaplus; actions are taken to the next level. Instead of hardcoded actions (that are created by the application +programmer at the source code level) it is possible for the ordinary user to create and modify actions and by this way adding +new functionality to &quantaplus;. These are the user defined actions, and many of the standard &quantaplus; actions are user defined (and user modifiable) actions as well. + +There are three types of user definable actions: + +Text actions +Tag actions +Script actions + + + +Creating actions + + You can create an action by going to + +Settings +Configure Actions + +. Click on New Action and you will face a similar dialog: + + + + + + + +Type +Specifies the action's type (Text, Tag, Script). + + + +Text +The user visible name of the action. + + + +The button near the Text label +The icon assigned to this action. Click on it in order to change the current icon. + + + +Tool tip +Short description of what the action does. + + + +Shortcut +The shortcut assigned to this action. Click on Custom or the button near Custom to assign a shortcut; click on None to remove the currently assigned shortcut. + + + +Container toolbars +The user defined toolbars where this action appears. See . + + + +Detailed Settings +Specific settings for the different type of actions. See below. + + + + + + +Text actions + + + + + The simplest actions. You can enter some text in the Detailed Settings area and whenever the action is executed this text will be inserted in your document + at the current cursor position. See the below example. + + + +Tag actions + + Useful to insert XML tags, but of course you can use them for other purposes as well. + + + + + +<tag> +The name of the tag. + + +</tag> +If checked when the action is executed this text will be inserted as a closing tag. If there is a selected area in the document before you execute the action, the <tag> will be inserted before the selected area and the </tag> after. + + +Run "Edit tag" dialog if available +If checked and there is a tagXML file for this tag, a tag editing dialog will be shown prior of inserting the tag inside the document, so you can fine-tune the tag attributes. + + +The <tag> and </tag> will be inserted as you've typed there. The <, > or the / sign won't be automatically appended. + + + +Script actions + + + + + The most powerful action type. With the help of this action you +can run external applications (usually scripts, but it's +not limited to scripts), which can alter your document or use your document (or part of your document) as input. Examples from &quantaplus; itself are the Quick Start dialog, the various View In... actions for the (X)HTML DTEPs. + + +First you have to enter the name of your script with the interpreter as well. Example: +sh /home/myHome/myScript.sh. + + +Although you can use full paths, the recommended way is to use the %scriptdir variable in the command line, like sh %scriptdir/myScript.sh. This way &quantaplus; will try to locate your script in the following places: + +global script folder: $KDEDIR/share/apps/quanta/scripts +local script folder: $KDEHOME/share/apps/quanta/scripts +your path: $PATH + +There are other special variables that you can use in the command line: + +%f: will be replaced with the URL of the current document. In case of local documents, file:/ will be stripped from the document. +%input: will be replaced with the selected input. See below. +%projectbase: will be replaced with the URL of the current project. It is empty if no project is loaded. +%pid: will be replaced with the PID of the running &quantaplus; process. If &quantaplus; is running in unique mode, the "unique " text will be prepended to the PID number. Useful when you use DCOP to control &quantaplus; from the external script. +%userarguments: useful in case of events. This entry will be replaced by the event properties in the following order: + +First argument +The unique id of the script + + +Second argument +the event name + + +Third argument +the parameters for the event, usually the file name of the current document or the path to the project file. + + + + + + +Aside of the above methods the script can receive input from &quantaplus; on the standard input. In the Input combobox you can select what to send to the standard input. Choices are: + +None: nothing is sent to the script. +Current document: the whole document is sent to the script. +Selected text: the selected area of the document is sent to the script. Using the %input variable usually makes sense only when using this setting. + + + +Similar to the Input you can catch the output of the executed application. There are two kind of outputs: + +normal output, printed to the standard output; + +error messages, printed to the standard error. + + +You can specify what should happen with the text printed to the standard output. This can be done by modifying the value of the Output combobox: + +None: the output of the application is ignored. +Insert in cursor position: the output will be inserted in the current document and the cursor position. +Replace selection: the selected area of the document will be replaced with the output. +Replace selection: the selected area of the document will be replaced with the output. +Create a new document: a new document will be created and will contain all the output of the script. +Replace current document: the entire document will be replaced with the output. +Message window: the output will appear in the Messages toolview. + + +The choices for the standard error output (Error) are the same as for the normal output. + + + + +Creating Toolbars + + +The following will show you how to create toolbars for a &DTEP;. Toolbars +are graphical elements that are assigned to actions. Actions, in +&quantaplus;, are the basis for nearly all the extensions that +&quantaplus; has and will acquire in the future. The same mechanism that +defines an action in &quantaplus; also enables auto-completion and tag +dialogs. With actions, the limit of what you can do is virtually +limitless. For means of an example, we will use &HTML; tidy on our web pages. + + + +From Scratch to Complete + + +To begin, you will need to create a user toolbar. Select + +Toolbars +Add User Toolbar +. + + + +If there are many tags for the markup language, it is recommended that you +split up the tags into logical groups. You will need to create a new user +toolbar for each group. In this case, there are not many, so we will be +making one toolbar and naming it with the name of the markup. + + + +Once all your toolbars are created, you must add and configure the +actions. To do this, select + +Settings +Configure Actions + + +. + + + +The parts of this window are pretty straight forward. Press the +New action button at the bottom of the window to +enter the editing mode. + + + +Fill in all of the necessary fields and add the tag to the appropriate +toolbar(s). + + + +Complete the rest and, if the tag has attributes and you always plan to +use them, check the Run "Edit tag" dialog if available + box so that you will be prompted every time the action is used. + + + +You should now have something much like the following. + + + + + + + + + +Press the Apply button and you will see the action +added to the toolbar(s) you have selected. + + + + + + + + + +Egad! That's an awful icon. How will yourself and others remember that +icon goes with that action? Let's replace it before trouble arises. + + + +To create an icon that more accurately describes that action, we will be +using &kiconedit;. Select it from the &kmenu;, +Graphics +More Programs + (or where ever your distribution placed it). + + + +&kiconedit; defaults to the size 32x32 pixels, but we need 22x22. To +change this, select + +Edit +Resize +. + + + +Keep in mind that you are creating an icon that will assist in helping not +only yourself to remember which action does what, but also other users of +the &DTEP;. + + + +Since the tag I am creating the icon for is called start, +I have decided to create a Start sign. Using the color green +(green often interpreted as go, start, or +proceed) will, or, at least, should, convey a message +to the user that clicking this action will place the <start> tag in the +current document. + + + + + + + + + +Now that I am finished with the creation of the icon, I will save it. + + + +Once you are done with creating the icon(s), you must associate the icon +with the action. To do this, open + +Settings +Configure Actions + again (in &quantaplus;) and select the action you made +the icon for. Beside the Text field, you will see a +button, click it. + + + +Select Other Icons and then click the +Browse button. + + + +Goto the folder in which you saved the icon, select the icon, and click +OK. + + + +Press the Apply button and either continue to do the +same with the other tags, if any, or click OK to +finish. + + + + + + + + + +Let us say you would like to add some common &quantaplus; functions to your +toolbar or maybe you think the toolbar would be better off organized in a +different manner with some separators to group the actions. Open the +Configure Toolbars dialog by going + +Settings +Configure Toolbars +. Make sure your toolbar is selected. + + + +I will be choosing the separator (top of the left column) for my toolbar. +Once you have selected the item you wish to add to your toolbar, press the +right arrow button. This will add it to your toolbar. + + + + + + + + + +I think I would like a quick way to access the Konqueror +Preview. I will select it and add it to the toolbar. + + + + + + + + + +Note how the separator helps in grouping. Someone new to my toolbar might +have thought that the &konqueror; button was like or the opposite of the +start button. + + + + + + + + + +Apply your changes and, when you are done, press OK +to finish. + + + +Ah, look at the fantastic new toolbar! Much more handy now. + + + + + + + + + +Remember to test your toolbar, by clicking all the buttons, so that you +know the output is correct. + + + + + + + + + +Now to save the toolbar, we will select + +Toolbars +Save Toolbars +Save as Local Toolbar +. + + + +Save it to the correct folder. Since NeXML does not exist, I will just +have it to the top-level folder, but your toolbar(s) should be saved to +the correct folder. Make sure to adjust your &descriptionrc; to have it +load your toolbar(s) when a new file of that type is created. + + + + + + + +Creating Your Own Documentation + + +Robert +Nickel + +
robert@artnickel.com
+
+
+ + + +
+
+ +Creating Your Own Documentation + + +Probably the most notable additions to &quantaplus; for the general user +will be the addition of documentation for the markup or scripting language +that you like best. To that end, this chapter will explain how I create +the &PHP; documentation tree for my personal use. + + + +Before starting on creating your own documentation, you may wish to check +out the +&quantaplus; repository to see if someone else has already done +this set. + + + +There are two parts to this process. First, you must obtain the existing +documentation for the markup/scripting/&etc; language that you are after. +Second, you have to create the docrc file. The first +is up to you, the second is what we will cover here. + + + +The general form of the docrc file is as follows: + + + + +#KDE Config File +[Tree] +Doc dir=path, relative to this file, of the documentation html files ⪚ php42/ +#top level elements +Top Element=Your description for these documentation ⪚ &PHP; 4.2 documentation + +Section 1=Section1.html +Section 2=#Sec2.1,#Sec2.2,#Sec2.3 +Sec2.1=Sec2.1.html +Sec2.2=Sec2.2.html +Sec2.3=Sec2.3.html +... + +[Context] +ContextList=func1,func2,tag1,tag2,tag3 +func1=func1.html +func2=func2.html +tag1=tag1.html +tag2=tag2.html +tag3=tag3.html + + + + +The docrc is broken down into two sections: Tree and +Context. + + + +The Tree section defines the presentation aspect of the documentation in +the documentation tab. For example, you will see that in the &PHP; +documentation you have something akin to this: + + + + + + + + + +Relating this to the above, my &PHP; docrc looks like +this: + + + + +#KDE Config File + +[Tree] + +Doc dir=php42/ + +#top level elements +Top Element=PHP 4.2 documentation + +PHP 4.2 documentation=Table of Contents,#Getting Started,#Language Reference + +Table of Contents=index.html + +Getting Started=Introduction, ... +Introduction=introduction.html +... + +Language Reference=Basic syntax, ... +Basic syntax=language.basic-syntax.html +... + + + + + +Notice the # in front of Getting Started +and Language Reference. This indicates that these are sub +containers in the tree and have content of their own. I do not believe that +there is a set limit to the depth here (other than that driven by sanity) +— use your judgment. + + + +For the Table of Contents, you will notice that it is referenced directly to +a file (and consequently shows up at the bottom of the tree view — +folders first!). + + + + +Spaces do not adversely affect anything, but watch out for & and < +characters. These should likely be replaced by &amp; and &lt; +respectively in all of the &XML; based &quantaplus; resource files. + + + + +The Context section is the section of the docrc file that is used to +facilitate context sensitive help. For example, you are writing a &PHP; +script and you would like to see the documentation for the +mysql_fetch_array function. You simply highlight the +function and then press &Ctrl;H + for context help. The documentation on +mysql_fetch_array will immediately display. There are +only two entry types here: the ContextList and the file association lines. + + + + +ContextList + + +Really simple, this is just a comma separated list of the context items +you wish to have available (for &PHP;, these are the functions for &PHP;). + + + + +File association lines + + +These are of the form context item=html doc page. ⪚ +acos=function.acos.html + + + + + + +A pared down version of my docrc Context section is +as follows: + + + + +#Keywords for context help +[Context] +ContextList=abs,acos,acosh,addcslashes,addslashes,... + +abs=function.abs.html +acos=function.acos.html +acosh=function.acosh.html +addcslashes=function.addcslashes.html +addslashes=function.addslashes.html +... + + + + +Now you can just save your docrc file, save it in +$HOME/.kde/share/apps/quanta/doc +or $KDEDIR/share/apps/quanta/doc +for local or global use respectively. Then create a folder (the one +specified in your docrc file) in the same folder +as your docrc file and copy your &HTML; pages in +there. + + + +You will need to restart &quantaplus; to see your documentation. + + + +Once you are sure that they are good and worth sharing, send the +docrc file along with a description of any pertinent +information on what documentation you used to the +&quantaplus; +repository for use by the &quantaplus; community. You will not get +rich, but you will feel great knowing that you contributed to the best web +development platform around. + + +
+ + + Sharing Resources + With &quantaplus; you are not alone. It is possible to share the various resources (DTEP packages, toolbars with actions, scripts, templates) with others. There are two ways to do it: + + + + Sending in Email + The resources can be sent in email to your friends, partners or to whomever you want. You will see the Send in Email menu entries in various places, like DTDSend DTD Package (DTEP) in Email, ToolbarsSend Toolbar in Email, in the context menu of the files and folders in the Templates and Scripts tree. + + + + Uploading to the main server + The resources can be uploaded to our main repository, from where all other &quantaplus; users can download them. The submissions are reviewed and made available only if our team considers correct and useful will be published. In order to make a valid submission it is suggested to sign the resources, thus you need a GPG/PGP key. This information is used to verify the origin of the resources both by our team and by the downloaders. + About getting the resources from the main server see . + When uploading you will be asked to enter the passphrase for your secret GPG key (the passphrase will not be stored), or in the case of having more secret keys, you will be able to pick up the one you want to use. In the Share Hot New Stuff dialog fill the input fields (the Preview URL may remain empty) and start the upload by clicking OK. + + The upload can be initiated from + DTDUpload DTD Package (DTEP), ToolbarsUpload Toolbar, in the context menu of the files and folders in the Templates and Scripts tree. + + + + + + +Getting Resources +It is possible to upgrade your &quantaplus; without getting a new version, by getting new resources like DTEP packages, toolbars with actions, templates, scripts and documentation. One possibility is that you got the resources in email or have downloaded from a web server, in which cases you usually need to manually install them. In lucky case you also got an install script when you have downloaded the resources. But &quantaplus; has a dedicated server holding resources that were either not included in the main distribution because of their sizes or infrequent usage, or they were contributed later by users, and these resources are automatically installed. Do download such resources use the various Download menu entries. You can find them at DTDDownload DTD Package (DTEP), ToolbarsDownload Toolbar, in the context menu of an empty area or toplevel item in the Templates, Scripts and Documentation trees. + + +After a resource was downloaded, but before it is installed, &quantaplus; verifies if the resource is valid, by checking the integrity and the signature. In case of problems it warns you and you can decide if you want to continue or not. Please read the warning dialogs carefully. In the case when the integrity is correct and the resource is correctly signed, you will still get an information dialog, so you can see who created the resource. + + + Be sure that you install resources, especially toolbars and scripts, only from trusted sources! + + + + + Converting a DTD to a &DTEP; + It is possible to work on XML languages currently not supported by &quantaplus; by creating a DTEP package. But the creation can be time consuming, as you may need to write hundreds of tag files in tagXML format. Of course, there is a nicer way to go, by converting the DTD automatically into a DTEP package. + + The conversion can be started from the DTDLoad & Convert DTD menu. Select the .dtd file which defines the DTD you want to use, and after that you will see the following dialog: + + + + + + +The entries are: + + Target directory name:the newly created &DTEP; will go under this name to the $KDEHOME/share/apps/quanta/dtep folder. + + + Name:the name (definition string) of the DTD + Nickname: the user visible name of the &DTEP; + !DOCTYPE definition line: + the string that should appear in the !DOCTYPE tag, like + HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" + DTD URL: the URL pointing to the DTD file + Default extension: the extension usually used for files that were written in this DTD + Case-sensitive tags and attributes: self explaining, usually true for XML language variants + Fine-tune the DTEP after conversion: if checked, after the conversion is done, &quantaplus; will bring up the &descriptionrc; editor, so you can fine tune the newly created &DTEP;. It is recommended to leave this options checked. + + + +
diff --git a/doc/quanta/ftab.png b/doc/quanta/ftab.png new file mode 100644 index 00000000..b179f808 Binary files /dev/null and b/doc/quanta/ftab.png differ diff --git a/doc/quanta/fundamentals.docbook b/doc/quanta/fundamentals.docbook new file mode 100644 index 00000000..ccd293d5 --- /dev/null +++ b/doc/quanta/fundamentals.docbook @@ -0,0 +1,429 @@ + + + + +The Fundamentals of &quantaplus; + + +Robert +Nickel + +
robert@artnickel.com
+
+
+ + +Christopher +Hornbaker + +
chrishornbaker@earthlink.net
+
+Reviewer +
+ + +Fabrice +Mous + +
fabrice@kde.nl
+
+Reviewer +
+ + + +
+
+ +The Fundamentals of &quantaplus; + + +Within &quantaplus; there are several key concepts. To understand and +take advantage of &quantaplus;, you must first learn these concepts, the +fundamentals. This chapter will explain and show you these concepts, without +which &quantaplus; would be primitive. + + + +The Workspace + + +&quantaplus; divides the workspace into three scopes: Global, Local, and +Project. These distinctions affect various components in &quantaplus;. + + + + +Global + + +Global items are available to anyone that uses &quantaplus;. From toolbars +to actions, everything marked as global is stored in the common +&quantaplus; folder structure. This has the effect of allowing a group +of admins to save certain toolbars, actions, and templates in the global +tree, which can then be used to keep a multi-user installation of +&quantaplus; common to everyone on the system. + + + + + +Local + + +Local items make up a single user's personal collection of web development +resources. These items are made up of a user's templates and toolbars. +Local items are stored in a user's home folder. This makes all of the +user's Local items available for personal use at instance. + + + + + +Project + + +Project items are are only available to a particular project. These can +be anything from a &CSS; template to a toolbar with custom actions +which perform a special task on a project's files. Simply put, this is +the most limited scope. All of the items saved in the project workspace +will be saved in the project's folder tree, allowing you to share your +specialized tools and templates with whomever else you share your +project with. + + + + + + + + +The Multi-Document Interface + + + + + +&quantaplus; editing the document you are now reading. + + + + + +&quantaplus;' &MDI; is broken down into various parts: the editor window, +the quick info trees, informational tabs and the toolbars. Please see , +, , and for more +information on these parts. + + + +The Editor Window + + + + + + +&quantaplus;' editor window. + + + + +&quantaplus;' editor window allows for multiple files to be opened at the +same time. When just one file is open, the document fills the entire +editor window. As soon as a second document is opened, a small amount of +space is taken from the bottom of the editor window to allow for tabs to +be displayed with the filenames and a status icon. The above picture shows +a floppy icon beside the filename, indicating that the +file has been modified and should be saved. +You can right click on the tabs with the mouse to get a context menu with entries related to the current document, like closing the current, other or all tabs; switching to other tabs; reloading, deleting or uploading the document; switching to a bookmarked line ; performing CVS operations on the current document. +Right clicking in the editor area will give you another context menu related to the edited document content, like basic editing actions (cut/copy/paste), editing the tag under the cursor, selecting the area covered by the tag under the cursor, getting context help about the word under the cursor or open a file if the string under the cursor points to a file. + + + +At the top of the editor window is the editor toolbar set. Currently, +&quantaplus; defaults to &HTML; 4.01 Transitional, which has a default set +of toolbars that are loaded. As &quantaplus; progresses, the toolbars will +be updated to meet the needs of users and to make use of newer features. + + + +Toolbar usage is pretty straight forward. If you want to insert a basic +tag, like <p>, into your document, then you can click on the icon that +represents the tag. Now you can insert your data for the tag you have just +inserted. If you wish to insert a tag that requires certain attributes +(like an anchor), then you will get a dialog box with the various fields for +you to fill in. + + + + + +The anchor (<a>) dialog. + + + + + +The Toolviews + + + + + +The Toolviews. + + + +The Toolviews or Quick Info Trees (&QIT;) allow you to navigate, open, and gather +information in &quantaplus;. Its tabbed format presents you with the Files, Project, +Templates, Document Structure, Scripts, Attribute, and Documentation Trees. + + + +&QIT; Explained + + + +Files Tree + + + + + + + + +This is where you can browse your entire file system. You are presented +with two top-level roots of the file system. The first is your home folder +and the second is the filesystem root folder - /. Use these to find existing +files on your machine that you would like to edit or add to an active +project. Right mouse button clicking on a file in this view gives you several +options for managing the selected file and, also, allows you to insert the +file into an active project, if any, or toggle the view between tree and list. + + + + + +Project Tree + + + + + + + + +Project management is one of the +many powerful tools that &quantaplus; offers. This tab displays all files +within your project and allows you to manage the files within the project +through the use of &RMB; clicking. Actions, such as add, remove, upload, +or delete files entirely from the disk, can be performed through this menu. + + + + + +Templates Tree + + + + + + + + +Another feature of &quantaplus; is templates. Templates can be anything +you would like. Images, code snippets, an entire web page, et cetera. It +is entirely up to you. + + + +Templates are sorted into three categories, which are based on their scope +and the context they are being used. These scopes are carried over from +&quantaplus;' workspace. Global templates are usable all times, local +templates are usable to the current user, and project templates +are usable only within their specified project. More on templates can be +found in . + + + + + +Scripts Tree + + + + + + + + +Here you will find information about the various scripts available for use +by you. The Global, Local, and Project concept allows here as well. By +&LMB; clicking the entries, you gain access to all the available +information about the script. And &RMB; clicking allows you to perform a +few actions, such as running the script, editing the script, and mailing +the script, for example. + + + + + +Document Structure Tree + + + + + + + + +This tab displays the parser's internal representation of your document. +By &LMB; clicking on an element, your cursor will taken to the element's +position in the document. By &RMB; clicking on an element, you are +presented with a number of actions that deal with navigating and updating +the tree. + + + + + +Attribute Tree + + + + + + + + +This tree appears below all the other &QIT;s. Within it you can quickly +edit attributes and namespaces. The content-focused entry system +allows you to modify all the available attributes with little more than a +few clicks of the mouse. + + + + +Attribute Tree + + + + + + +Documentation Tree + + + + + + + + +Here you can find complete documentation on web technologies to aid your +development. You can download pre-packaged documentation for &quantaplus; +at &quantaplus;' +documentation site, you can create your own documentation, +and, by adding a folder named "doc" to a project, you can add, edit, +and view project-specific documentation. + + + + + + + +The Informational Tabs + + + + + +&quantaplus;' Informational Tabs. + + + +By default &quantaplus; has two tabs located at the bottom of the window +from which useful information can be obtained. These are the Messages +window and the Problems window. + + + + +Messages Window Tab + + + + + + + + +This tab displays information from any scripts run in quanta. +For example, the DTD being used for the current document +and any changes to the DTD are displayed. + + + + + + +Problems Tab + + + + + + + + +This tab shows any errors in the markup of the current document. +&quantaplus; scripts which are executed will also print error +messages (if present) in this tab. + + + + + + + +The Toolbars + + + + + +&quantaplus;' &HTML; toolbars. + + + +&quantaplus;' toolbars have been extended greatly and are easy to +understand. You click on the button and you get an associated action from +that button. The beautiful part about toolbars is that you can define your +own actions graphically within &quantaplus;. + + + +Managing toolbars in &quantaplus; is easy. By selecting the +Toolbars menu, you have the options to load, save, add, remove, and +email toolbars. When you choose to load a toolbar, you may choose from one +of the three workspaces in +&quantaplus;. When saving a newly created toolbar, you can save it in the +local scope or within a project's scope. If you would like to make a new +toolbar available in the global scope, ask your admin to place it in +&quantaplus;' global toolbar folder. + + + +Another feature of &quantaplus; is the ability to email your toolbars. +&quantaplus; sends the toolbar as a gzipped tar archive through &kmail;. +If you receive a toolbar in email, then you can save (and load) it into +&quantaplus; like any other toolbar! + + + +
diff --git a/doc/quanta/glossary.docbook b/doc/quanta/glossary.docbook new file mode 100644 index 00000000..30e83c3d --- /dev/null +++ b/doc/quanta/glossary.docbook @@ -0,0 +1,53 @@ + + + + + + + +Keith +Isdale + +
k_isdale@tpg.com.au
+
+
+ + +Christopher +Hornbaker + +
chrishornbaker@earthlink.net
+
+Reviewer +
+ + + +
+
+ + +Keywords + +xsldbg + +See + + + +XPath + +A valid expression that defines what data is required. See +&W3C; web site + + + + +QName + +A fully qualified name. For example xsl:myvariable. See &W3C; web site + + + + +
diff --git a/doc/quanta/index.docbook b/doc/quanta/index.docbook new file mode 100644 index 00000000..32d92c53 --- /dev/null +++ b/doc/quanta/index.docbook @@ -0,0 +1,183 @@ + + + + + + + + + + + + + + + + CGI"> + DTD"> + DTEP"> + HTML"> + IDE"> + PHP"> + PDF"> + SGML"> + XSD"> + W3C'> + QIT"> + MDI"> + Gubed PHP Debugger"> + KXsldbg"> + VPL"> + + + description.rc'> +]> + + +&quantaplus; User Manual + + + + + + +Christopher +Hornbaker + +
chrishornbaker@earthlink.net
+
+
+ + +Fabrice +Mous + +
fabrice@kde.nl
+
+
+ + +Robert +Nickel + +
robert@artnickel.com
+
+
+ + +András +Mantia + +
amantia@kde.org
+
+
+ + +Eric +Laffoon + +
sequitur@kde.org
+
+Developer +
+ + +András +Mantia + +
amantia@kde.org
+
+Developer +
+ + +Dmitry +Poplavsky + +
dima@kde.org
+
+Developer up to 2.0 +
+ + +Alexander +Yackovlev + +
yshurik@kde.org
+
+Developer up to 2.0 +
+ + + +
+ + +2002200320042005 +&quantaplus; Development Team + + + + +&FDLNotice; + + + +2005-08-24 +3.4.90 + + + +&quantaplus; is a Web &IDE; that strives to be neutral and +transparent to all markup languages, while supporting popular +web-based scripting languages, &CSS;, and other emerging &W3C; +recommendations. + + + + +KDE +Quanta +text +editor +Web +programmer +programming +development +Kommander +xsldbg +libxslt +debugger +projects +SGML +JSS +DTD +XML +XSD +W3C +CSS +Schema +DocBook +HTML +XHTML +CGI +PHP +Java +JavaScript +ColdFusion + +
+&introduction; +&fundamentals; +&working-with-quanta; + +&quanta-menus; +&config-quanta; +&advanced-quanta; +&extending-quanta; +&q-and-a; +&credits-license; +&installation; +&glossary; +
diff --git a/doc/quanta/info_tab.png b/doc/quanta/info_tab.png new file mode 100644 index 00000000..b1cdc3f2 Binary files /dev/null and b/doc/quanta/info_tab.png differ diff --git a/doc/quanta/installation.docbook b/doc/quanta/installation.docbook new file mode 100644 index 00000000..a89a6b2c --- /dev/null +++ b/doc/quanta/installation.docbook @@ -0,0 +1,43 @@ + + + +Installation + + +Acquiring &quantaplus; + +&install.intro.documentation; + + + +Building the Source + +&install.compile.documentation; + + +Considerations When Building + + +It is reasonable that you would want to customize the location of +the &quantaplus; files on your system. To this end, +autoconf has a number of options +that can be passed to the configure +script to control this setup. To get a complete listing of these +options, type ./configure +. These are straight forward and will +not be covered here. + + + +If you are having trouble with &quantaplus; running properly, you +should check your path to ensure that the &kde; 3 +bin folder is in there. +Also, be sure that you do not have any older versions of &kde; laying +about that appear in PATH before your &kde; 3 +bin folder. The same +holds true for &Qt;. + + + + + diff --git a/doc/quanta/introduction.docbook b/doc/quanta/introduction.docbook new file mode 100644 index 00000000..b4be671c --- /dev/null +++ b/doc/quanta/introduction.docbook @@ -0,0 +1,134 @@ + + + + +What is &quantaplus;? + + +Eric +Laffoon + +
sequitur@kde.org
+
+
+ + +Christopher +Hornbaker + +
chrishornbaker@earthlink.net
+
+Reviewer +
+ + +Fabrice +Mous + +
fabrice@kde.nl
+
+Reviewer +
+ + + +
+
+ +What is &quantaplus;? + +
+ +Eric Laffoon at http://quanta.sourceforge.net + + + +&quantaplus; is a web development tool for the K Desktop Environment. +&quantaplus; is designed for quick web development and is rapidly becoming +a mature editor with a number of great features. + + +Our objective remains to create the very best web development tool +anywhere. We realize that we will need many more people active to +accomplish this, so we are in the process of developing enhancements geared +toward making it easy for web developers to customize, extend, and enhance +&quantaplus;. Then we will be asking you, the web developers, to contribute +your feature enhancements. We will organize these so that &quantaplus; web +developers can find just the resources, extensions and custom plug-ins +they need to be the most kick butt developers ever. + +
+ + + +&quantaplus;: Where It Was And Where It Is Going + + +Robert +Nickel + +
robert@artnickel.com
+
+
+ + +Christopher +Hornbaker + +
chrishornbaker@earthlink.net
+
+Reviewer +
+ + +Fabrice +Mous + +
fabrice@kde.nl
+
+Reviewer +
+ + + +
+
+ +&quantaplus;: Where It Was And Where It Is Going + + +While striving to become the best &HTML; editor, the developers of +&quantaplus; began to think about a rather intriguing idea: What if +&quantaplus; was a generic, extensible, markup language editor? +Well, that would only make it the greatest Web Development Environment +for &kde;! So it was done. + + + +No longer bound to &HTML;, &quantaplus; is now well on its way to becoming +an all-purpose Web Development Environment. Essentially, if you can define +it in &XML;, then &quantaplus; should be able to serve as an &IDE; for it. + + + +Now, with the above said, it must be noted that &quantaplus; is an +outgrowth of the outstanding efforts that have been put forth by the +entire &kde; development community. &quantaplus;, in celebration of open +source, uses the idea of Why write something somebody already +wrote? Thanks to &kde;'s framework, not only is this possible, but +it also allows users and developers to extend &quantaplus; to match their +unique needs. + + + +&quantaplus; provides web developers with an intuitive and powerful +multiple document interface (&MDI;). It can dramatically increase your +productivity. Through the use of custom actions, scripting, and toolbars, +you can automate almost any task. With the use of +Kommander, you can extend &quantaplus; in a manner in which +you never have to remember scripting command syntax again. (More about this +can be found in .) + +
+ +
diff --git a/doc/quanta/kfr-icon.png b/doc/quanta/kfr-icon.png new file mode 100644 index 00000000..4ba2dcdf Binary files /dev/null and b/doc/quanta/kfr-icon.png differ diff --git a/doc/quanta/kfr-new-dialog.png b/doc/quanta/kfr-new-dialog.png new file mode 100644 index 00000000..8b483dcb Binary files /dev/null and b/doc/quanta/kfr-new-dialog.png differ diff --git a/doc/quanta/man-quanta.1.docbook b/doc/quanta/man-quanta.1.docbook new file mode 100644 index 00000000..bb493fac --- /dev/null +++ b/doc/quanta/man-quanta.1.docbook @@ -0,0 +1,95 @@ + + +]> + + + +BenBurtonbab@debian.org +April 8, 2003 + + + +quanta +1 + + + +quanta +A &kde; based web development environment + + + + +quanta + + + + + + + + + + + + +Description + +&quanta; Plus is a web development environment for HTML and +associate languages. It is designed for quick web development and is +rapidly becoming a mature editor with a number of great +features. &quanta; already has a good deal of PHP support in it +including the ability to run a debugger. + +&quanta; Plus is not in any way affiliated with any commercial +versions of &quanta;. The primary coders from the original team left +the GPL'd version to produce a commercial product. + + + + +Options + + +Application Options + + +Run as a one-instance application + + + + +Do not show the logo during startup + + + + + Reset the layout of the user interface to the default + + + + + + +See Also + +More detailed user documentation is available from help:/quanta (either enter this +URL into &konqueror;, or run +khelpcenter +help:/quanta). + +There is also further information available at http://sourceforge.net/projects/quanta/ + + + +Authors + +&quanta; is currently written and maintained by Eric Laffoon sequitur@kde.org and Andras Mantia amantia@kde.org. + +This manual page was prepared by BenBurtonbab@debian.org + + + + diff --git a/doc/quanta/plugin-edit.png b/doc/quanta/plugin-edit.png new file mode 100644 index 00000000..1dc8824e Binary files /dev/null and b/doc/quanta/plugin-edit.png differ diff --git a/doc/quanta/project-1.png b/doc/quanta/project-1.png new file mode 100644 index 00000000..8c86b8fb Binary files /dev/null and b/doc/quanta/project-1.png differ diff --git a/doc/quanta/project-properties.png b/doc/quanta/project-properties.png new file mode 100644 index 00000000..241af897 Binary files /dev/null and b/doc/quanta/project-properties.png differ diff --git a/doc/quanta/project-tree-view-dir-rmb-menu.png b/doc/quanta/project-tree-view-dir-rmb-menu.png new file mode 100644 index 00000000..a89b43fc Binary files /dev/null and b/doc/quanta/project-tree-view-dir-rmb-menu.png differ diff --git a/doc/quanta/project-tree-view-file-rmb-menu.png b/doc/quanta/project-tree-view-file-rmb-menu.png new file mode 100644 index 00000000..c587e02a Binary files /dev/null and b/doc/quanta/project-tree-view-file-rmb-menu.png differ diff --git a/doc/quanta/project-upload-dialog.png b/doc/quanta/project-upload-dialog.png new file mode 100644 index 00000000..2c641d5a Binary files /dev/null and b/doc/quanta/project-upload-dialog.png differ diff --git a/doc/quanta/ptab.png b/doc/quanta/ptab.png new file mode 100644 index 00000000..977f1dd9 Binary files /dev/null and b/doc/quanta/ptab.png differ diff --git a/doc/quanta/q-and-a.docbook b/doc/quanta/q-and-a.docbook new file mode 100644 index 00000000..020d4580 --- /dev/null +++ b/doc/quanta/q-and-a.docbook @@ -0,0 +1,70 @@ + + + + +Questions and Answers + + +Eric +Laffoon + +
sequitur@kde.org
+
+
+ + + +
+
+ +Questions and Answers + + + + + +How can I help &quantaplus; development? + + + + +We would be remiss not to point out that &quantaplus; is being built by +volunteers. Many people feel they cannot contribute to the open +source cause for one reason or another. Probably the greatest being a +feeling they do not have the skills. &quantaplus; has been developed in a +manner that allows both non-programmers and programmers help extend +&quantaplus;. There is also the issue of documentation. Software, be it +proprietary or Free/open source, is only as good as its documentation. +We are sure there is a place in &quantaplus; where your time will be most +beneficial. + + + + + + + +Where is &quantaplus; going from here? + + + + +We have released &quantaplus; 3.4 and are now in preparation for the next major +release. The targeted 4.0 release is a partial rewrite of Quanta to use the +features ofered by the KDevelop framework. +Our objective remains to create the very best web development +environment. We realize that we will need many more people actively developing +&quantaplus; to accomplish this, so we are in the process of developing +enhancements geared toward making it easy for web developers to +customize, extend, and enhance &quantaplus;. Much of this has been +accomplished with the 3.4 release. Soon will be asking you, the web +developers, to contribute your feature enhancements. We will organize +these so that &quantaplus; web developers can find just the resources, +extensions, and custom plug-ins they need to be the most reliable, +professional developers ever! + + + + + +
diff --git a/doc/quanta/quanta-menus.docbook b/doc/quanta/quanta-menus.docbook new file mode 100644 index 00000000..751f4591 --- /dev/null +++ b/doc/quanta/quanta-menus.docbook @@ -0,0 +1,2265 @@ + + + + +The Menubar + + +Robert +Nickel + +
robert@artnickel.com
+
+
+ + András + Mantia + +
amantia@kde.org
+
+
+ + +Christopher +Hornbaker + +
chrishornbaker@earthlink.net
+
+Reviewer +
+ + +Fabrice +Mous + +
fabrice@kde.nl
+
+Reviewer +
+ + + +
+
+ +The Menubar + + +This chapter explains all the various functions that can be found in the +menubar. + + + +The <guimenu>File</guimenu> Menu + + + + + + +&Ctrl;N + +File +New + + + + +Create a new, blank file. + + + + + + + + +&Ctrl;O + +File +Open... + + + + +Search the file system to open an existing file. + + + + + + + +File +Open Recent + + + + +Quick list of the last several files you've opened. This list will change +each time you open a file that is not on it, with the oldest being bumped +off first. + + + + + + + + + +&Ctrl;S + +File +Save + + + + +Save the active file's changes. + + + + + + + +File +Save As... + + + + +Save the active file with another name. + + + + + + + +File +Save as Template + + + + +This allows you to save code snippets and entire files as a template for +later use. See the section on templates. +If you try to save the selected text/file outside of the local/project +template dir, then you will receive an error. + + + + + + +File +Save as Template +Save as Local Template... + + + + +Allows you to save a file as a template within the local scope. + + + + + + + +File +Save as Template +Save as Project Template... + + + + +Allows you to save a file as a template within the project scope. + + + + + + + +File +Save as Template +Save Selection to Local Template File... + + + + +Allows you to save the selected text (⪚ a code snippet) in a local +template file. + + + + + + + +File +Save as Template +Save Selection to Project Template File... + + + + +Allows you to save the selected text (⪚ a code snippet) in a project +template file. + + + + + + + + + + + + +&Ctrl;&Shift;S + +File +Save All... + + + + +Save all modified files in the editor. + + + + + + + + +&Ctrl;F5 + +File +Reload + + + + +Reloads the current focused document. + + + + + + + + +&Ctrl;P + +File +Print... + + + + +You can actually print out your documents. Uses the kprinter + interface. + + + + + + + + +&Ctrl;Q + +File +Quit + + + + +Exit &quantaplus; + + + + + + + + +The <guimenu>Edit</guimenu> Menu + + + + + + +&Ctrl;Z + +Edit +Undo + + + + +Undo the last action performed. + + + + + + + + +&Ctrl;&Shift;Z + +Edit +Redo + + + + +Redo the last action undone. + + + + + + + + +&Ctrl;X + +Edit +Cut + + + + +Cut the current block of text and place its contents on the clipboard. + + + + + + + + +&Ctrl;C + +Edit +Copy + + + + +Copy the current block of text to the clipboard. + + + + + + + + +&Ctrl;V + +Edit +Paste + + + + +Paste the contents of the clipboard at the current cursor position. + + + + + + + +Edit +Paste Special + + + + + + + + +Edit +Paste Special +Paste HTML Quoted + + + + +Converts the clipboard text &HTML; special characters to &HTML; entities +before pasting into the text body, so they show up properly when viewed +and aren't picked up as tags by the client browser. + + + + + + +Edit +Paste Special +Paste &URL; Encoded + + + + +Converts the clipboard text into &URL; encoding, which is the correct way +to include special characters and spaces into &URL;s. Used primarily when +pasting a &URL; into an anchor tag. + + + + + + + + + + + +&Ctrl;A + +Edit +Select All + + + + +Select all of the text in the current document. + + + + + + + + +&Ctrl;&Shift;A + +Edit +Deselect + + + + +Unselect all text in the current document. + + + + + + + + +&Ctrl;&Shift;B + +Edit +Block Selection Mode + + + + +Turn on/off block highlighting. Allows you to select text blocks with your +keyboard without holding down the shift key. + + + + + + + + +Insert + +Edit +Overwrite Mode + + + + +Overrides the Insert key. + + + + + + + + +&Ctrl;F + +Edit +Find... + + + + +String or regular expression pattern to find in the current document. + + + + + + + + +F3 + +Edit +Find Next + + + + +Repeat the find downward in the document from the current location. + + + + + + + + +&Shift;F3 + +Edit +Find Previous + + + + +Repeat the find upward in the document from the current location. + + + + + + + + +&Ctrl;R + +Edit +Replace... + + + + +String or regular expression replacement of text in the current file. + + + + + + + + +&Ctrl;G + +Edit +Go to Line... + + + + +Go directly to a specific line number. This is really helpful when your +&PHP; script is breaking unexpectedly! + + + + + + + + +&Alt;&Ctrl;F + +Edit +Find in Files... + + + + +Find a string or expression in files in the selected folder. Sort of a +&GUI; grep or sed with some +predefined pattern spaces to help you out. + + + + + + + + +&Ctrl;J + +Edit +Expand Abbreviation + + + + + Expands the abbreviations. Abbreviations can be defined in the + Settings + Configure Quanta... + dialog. + + + + + + + +Edit +Apply Source Indentation + + + + + Reformats the source code accroding to the same rules as the &VPL; part inserts the tags. + + + + + + + + + +The <guimenu>View</guimenu> Menu + + + + + +View +Tool Views + + + + + + + +View +Tool Views +Show Files + + + + +Toggle display of the files tree. + + + + + + + +View +Tool Views +Show Project + + + + +Toggle display of the project tree. + + + + + + + +ViewTool Views +Show Templates + + + + +Toggle display of the template tree. + + + + + + + +ViewTool Views +Show Scripts + + + + +Toggle display of the scripts tree. + + + + + + + +ViewTool Views +Show Document Structure + + + + +Toggle display of the document structure tree. + + + + + + + +ViewTool Views +Show Attribute Editor + + + + +Toggle display of the attribute tree. + + + + + + + +ViewTool Views +Show Documentation + + + + +Toggle display of the documentation tree. + + + + + + + +&Ctrl;M + +ViewTool Views +Show Messages + + + + +Toggle display of the message window. This is the window where you see the +output of any scripting actions and the debugger. + + + + + + + +ViewTool Views +Show Problems + + + + +Toggle display of the Problem Reporter at the bottom +of the main &quantaplus; window. The Problem Reporter +activates when you switch to the Structure Tree. + + + + + + + +ViewTool Views +Show Annotations + + + + +Shows the annotation view. Read the for details. + + + + + + + +ViewTool Views +Show Upload Profile:... + + + + +Shows the files on the server for an upload profile. + + + + + + + + + + + + + +&Shift;F9 + +View +Show Icon Border + + + + +Toggle display of the icon border to the left of the main editor window. +This bar allows for click toggling of bookmarks. + + + + + + + + +F11 + +View +Show Line Numbers + + + + +Toggles the display of line numbers along the side of +the main editor window. + + + + + + + + +F10 + +View +Dynamic Word Wrap + + + + +Toggle on and off reformatting of text to a specific +width as you type. + + + + + + + + +&Alt;F9 + +View +Source Editor + + + + +Switch to the source of a document to edit. + + + + + + + + +&Ctrl;&Shift;F9 + +View +&VPL; Editor + + + + +Switch to the &VPL; Editor to edit a document. + + + + + + + + +F9 + +View +&VPL; & Source Editors + + + + +Switch to split screen mode to edit a document. + + + + + + + + +F6 + +View +Preview + + + + +Preview the current document. + + + + + + + + +&Alt;Left Arrow + +View +Back + + + + +Navigate back one step in the preview. + + + + + + + + +&Alt;Right Arrow + +View +Forward + + + + +Navigate forward one step in the preview after having gone back in the +preview. + + + + + + + + +F5 + +View +Reload Preview + + + + +Reload the preview from disk. + + + + + + + + +F12 + +ViewExternal Preview +View with &konqueror; + + + + +View the current file with &konqueror;. + + + + + + + + +&Ctrl;&Shift;F12 + +ViewExternal Preview +View with Firefox; + + + + +View the current file with the Mozilla Firefox browser. + + + + + + + + +&Shift;F12 + +ViewExternal Preview +View with Mozilla + + + + +View the current file with Mozilla. + + + + + + + + +&Shift;F6 + +ViewExternal Preview +View with &Netscape; + + + + +View the current file with &Netscape;. + + + + + + + + +&Alt;F6 + +ViewExternal Preview +View with Opera + + + + +View the current file with Opera. + + + + + + + +ViewExternal Preview +View with Lynx + + + + +View the current file with Lynx (a text based +browser). + + + + + + + + The <guimenu>Bookmarks</guimenu> Menu + + + + + + + &Ctrl;B + + Bookmarks + Set Bookmark + + + + + Sets a bookmark at the current line location in the current file. + + + + + + + + Bookmarks + Clear All Bookmarks + + + + + Clears all set bookmarks in the current document. + + + + + If you have bookmarks in the current file, they will appear in the menu together with a Previous or Next item, depending on the position of the cursor in the document. + If you have bookmarks in other opened documents, they will appear in the menu grouped by the file name of the other documents. + + + + +The <guimenu>Project</guimenu> Menu + + +How to use projects in &quantaplus; is described in . + + + + + + +Project +New Project... + + + + +Launch the project creation wizard. + + + + + + + +Project +Open Project... + + + + +Open an existing project file from disk. &quantaplus; projects are saved +with the .webprj extension. + + + + + + + +Project +Open Recent Project + + + + +Gives you a list of your most recently used projects for quick access. + + + + + + + +Project +Close Project + + + + +Close the current project. + + + + + + + +Project +Open Project View... + + + + +Open a View, a specific combination of open files that you +have previously saved. + + + + + + + +Project +Save Project View + + + + +Save the current set of open files as a View. + + + + + + + +Project +Save Project View As... + + + + +Save the current set of open files as a View under another +name. + + + + + + + +Project +Delete Project View + + + + +Delete a View. + + + + + + + +Project +Insert Files... + + + + +Presents a dialog that allows you to select files to add to your current +project. These files will then be copied into the project folder for +editing. + + + + + + + +Project +Insert Folder... + + + + +Insert a folder and all of its contents into the current project. + + + + + + + +Project +Rescan Project Folder... + + + + +Scan the project folder for any new files you may have there. This +allows you to copy graphics into your project folder or a subfolder +thereof and then add them to the project. + + + + + + + + +F8 + +Project +Upload Project... + + + + +Upload the files in your project to the hosting server. The list of +available transports depends on the version of &kde; you are running and +whether or not you've downloaded extra KIO slaves. + + + + + + + + +&Shift;F7 + +Project +Project Properties + + + + +Settings affecting the way &quantaplus; manages your project. See the +&quantaplus; projects section for +details. + + + + + + + +The <guimenu>Toolbars</guimenu> Menu + + + + + +Toolbars +Load Toolbars + + + + + + + + +Toolbars +Load Toolbars +Load Global Toolbar... + + + + +Loads a globally defined toolbar. These are kept in $KDEDIR/share/apps/quanta/toolbars +by default. + + + + + + + +Toolbars +Load Toolbars +Load Local Toolbar... + + + +Loads a locally defined toolbar. These are kept in $HOME/.kde/share/apps/quanta/toolbars +by default. + + + + + + + +Toolbars +Load Toolbars +Load Project Toolbar + + + +Loads a project toolbar. These are kept in ProjectDir/toolbars +and are only available in this menu if they have been assigned to this +project. + + + + + + + + + + +Toolbars +Save Toolbars + + + + +Dialog for saving your toolbars. Allows you to pick the type of toolbar; +Local or Project. + + + + + + +Toolbars +Save Toolbars +Save as Local Toolbar... + + + + +Save as a local toolbar to +$HOME/.kde/share/apps/quanta/toolbars + + + + + + + +Toolbars +Save Toolbars +Save as Project Toolbar... + + + + +Save as a project toolbar in +ProjectDir/toolbars + + + + + + + + + + +Toolbars +Add User Toolbar... + + + + +Brings up a dialog to create a new toolbar. This only creates the name. +Actions must be added from the + +Settings +Configure Actions + +menu item. Toolbars are saved via the + +Toolbars +Save Toolbars + +menu or on close unsaved toolbars will prompt for you to save. + + + + + + + +Toolbars +Remove User Toolbar... + + + + +Remove a toolbar from usage. This does not remove it from the disk. If +you've not saved the toolbar you are removing, you will be prompted to +save it. + + + + + + + +Toolbars +Rename User Toolbar.. + + + + +Allows you to rename a toolbar. + + + + + + + +Toolbars +Send Toolbar in E-Mail... + + + + +This is a hook to email your custom toolbar to someone (maybe the +&quantaplus; team for inclusion in the next release!) for their use. It +spawns an email window and attaches your toolbar file to it automatically. + + + + + + + + Toolbars + Send Toolbar in Email... + + + + + This is allows you to upload a toolbar to the main resource server. See . + + + + + + + +Toolbars +Upload Toolbar... + + + + + This is allows you to upload toolbars to the main server, from where others can download it.See . + + + + + + +Toolbars +Download Toolbar... + + + + + This is allows you to download toolbars from the Internet.See . + + + + + + + + + +The <guimenu>&DTD;</guimenu> Menu + + +Christopher +Hornbaker + +
chrishornbaker@earthlink.net
+
+
+
+
+ +The <guimenu>&DTD;</guimenu> Menu + + + + + +&DTD; +Change the &DTD;... + + + + +Pops up a dialog box that allows you to change the current documents &DTD; + + + + + + + &DTD; + Edit &DTD; Settings... + + + + + Makes possible to change the &descriptionrc; configuration file for a &DTEP;. + + + + + + + +&DTD; +Load & Convert &DTD;... + + + + +Load a &DTD; that you or someone else made and convert it to &quantaplus;' +native description format. + + + + + + + +&DTD; +Load &DTD; Entities... + + + + +Load/update the entities from a &DTD;. It is useful if you want to update the entities in a &DTEP; without regenerating the whole &DTEP;. +In case the &DTEP; is a global one and you do not have write permission to the global KDE directory, the entity loading will fail. + + + + + + + +&DTD; +Load &DTD; Package (&DTEP;)... + + + + +Load a your own &DTEP;. + + + + + + + +&DTD; +Send &DTD; Package (&DTEP;) in E-Mail... + + + + +Send your &DTEP; to a friend via &kmail;. + + + + + + + + &DTD; + Upload &DTD; Package (&DTEP;)... + + + + + This is allows you to upload a &DTEP;s. See . + + + + + + +&DTD; +Download &DTD; Package (&DTEP;)... + + + + + This is allows you to download &DTEP;s from the Internet. See . + + + + +
+ + +The <guimenu>Tags</guimenu> Menu + + +This menu contains a list of the elements that are in the currently loaded +toolbars. If you have the Standard (&HTML;) toolbar loaded, the +Tags menu will contain a submenu Standard + which will contain the list of tags/actions on that toolbar. + + + + + + + +&Ctrl;E + +Tags +Edit Current Tag... + + + + +Allows you to access the current markup tag settings dialog if one exists. +This entry is always present, followed by the &DTD; specific submenus. + + + + + + + +Tags +Select Current Tag Area + + + + +This highlights the current tag area. The tag area begins where the mouse +cursor is placed. + + + + + + + Tags + Smart Tag Insertion + + + + + Activates/deactivates the smart insertion of tags. Currently it works only in (X)HTML DTDs. Smart insertion means that &quantaplus; will refuse to insert a tag using the toolbar if the tag cannot be present in the current location. + + + + + + + +The <guimenu>Plugins</guimenu> Menu + + + + + +Plugins +Plugin + + + + +The Plugins menu lists the +available plugins under the above menu items. Clicking them will activate +them. Clicking an activated plugin will deactivate it. + + + + + + + + +The <guimenu>Tools</guimenu> Menu + + + + + + +Tools +Highlight Mode + + + + +Choose the syntax highlighting mode for the current file. The list of +available highlighting schemes varies depending on your version of &kate;. + + + + + + + +Tools +End of Line + + + + +Select the end of line encoding type. Useful if you have folks using other +&OS; platforms to develop on. Choose from +Unix, +Windows/DOS or +Macintosh. + + + + + + + + +&Ctrl;I + +Tools +Indent + + + + +Move the selected block of text one tab width to the right. + + + + + + + + +&Ctrl;&Shift;I + +Tools +Unindent + + + + +Move the selected block of text one tab width to the left. + + + + + + + +Tools +Clean Indentation + + + + +Removes all indentation. + + + + + + + +&Ctrl;D + +Tools +Comment + + + + +Comments selected text. + + + + + + + + +&Ctrl;&Shift;D + +Tools +Uncomment + + + + +Uncomments selected text. + + + + + + + +Tools +Word Wrap Document + + + + +Wrap the text in the current window to a predefined width. + + + + + + + +Tools +Spelling... + + + + +Check the spelling in the current document. + + + + + + + +Tools +Document Properties + + + + +Edit specific properties of a currently loaded document when using the +&VPL; Editor. + + + + + + + +Tools +Convert Tag & Attribute Case... + + + + +Convert all tags and/or attributes character cases to another. + + + + + + + + +&Alt;&Ctrl;T + +Tools +HTML Tidy Syntax Checking + + + + +Checks the syntax of the current document against the selected &DTD; using the external tidy application. + + + + + + + + The <guimenu>Window</guimenu> Menu + + + + + Window + Close + + + + + Closes the current tab (document, plugin, preview or documentation). + + + + + + + Window + Close All + + + + + Closes all opened tabs. + + + + + + + Window + MDI Mode + + + + + On-the-fly switching between different UI modes. Due to some limitations in the KDE libraries, the switching might take time and cause ugly artifacts. The recommended modes to use + are IDEAl Mode, which is the default or + Tab Page Mode, which is the same mode that was present in &quantaplus; 3.2 and earlier versions. + + + + + Furthermore this menu contains an entry for every opened tab. By selecting such an entry, that selected tab will become the active one. + + + +The <guimenu>Settings</guimenu> Menu + + + + + + Settings + Toolbars + + + + + Show or hide the non-user toolbars. + + + + + + + Settings + Show/Hide DTD Toolbar + + + + + Toggle on and off the display of the &DTD; specific toolbar. + + + + + + + + Settings + Show/Hide Statusbar + + + + + Toggle on and off the display of the status bar at the bottom of the main + &quantaplus; window. + + + + + + +Settings +Configure Quanta... + + + + +Setup the behavior of &quantaplus;. + + + + + + + + Settings + Configure Preview... + + + + + Setup the behavior of the integrated preview. The changes made in the dialog have effects on every application using the KHTML part, including the &konqueror; web browser. + + + + + + + + +Settings +Configure Actions... + + + + + This is where you define the actions for use on toolbars. See . + + + + + + + + Settings + Configure Plugins... + + + + + This is where you can define and modify the plugins. + + + + + + + + Settings + Configure Editor... + + + + + Setup the behavior of the editor window. See the documentation on &kate; + for details. + + + + + + + +Settings +Configure Toolbars... + + + + +Dialog that allows you to add/delete items to/from toolbars and change the +order the icons appear in. + + + + + + + +Settings +Configure Shortcuts... + + + + +Allows you to configure the many editor shortcuts available to +&quantaplus;. + + + + + + + + +The <guimenu>Help</guimenu> Menu + + +&quantaplus; contains a standard &kde; Help menu with +the addition of these items: + + + + + + + +&Ctrl;H + +Help +Context Help + + + + +This should produce help based on the current pointer context. At the time +of this writing this feature is not implemented. + + + + + + + +Help +Make A Donation + + + + +&quantaplus; is a high quality product that is freely available, and +freely licensed, but like any open source project, its developers can +always use help. If you would like to support &quantaplus; development in a +financial manner, you can find out how to here. + + + + + + + +The standard &kde; help menu items are as follows: + + +&help.menu.documentation; + + +
diff --git a/doc/quanta/quanta-projects.docbook b/doc/quanta/quanta-projects.docbook new file mode 100644 index 00000000..06814ebb --- /dev/null +++ b/doc/quanta/quanta-projects.docbook @@ -0,0 +1,792 @@ + + + + +Projects + + +Robert +Nickel + +
robert@artnickel.com
+
+
+ + András + Mantia + +
amantia@kde.org
+
+
+ + +Christopher +Hornbaker + +
chrishornbaker@earthlink.net
+
+Reviewer +
+ + +Fabrice +Mous + +
fabrice@kde.nl
+
+Reviewer +
+ + + +
+
+ +Projects + + +New Projects + + +The &quantaplus; project wizard +( +Project +New Project... +) makes project creation an easy task. + + + + + + +The Project Wizard. + + + +The fields are pretty straight forward. It is best to fill them in from +top to bottom. Filling in a project name will autocomplete all the +folder structure for the rest of the project. All of the paths and +author information fields can be configured later on clicking + + +&Shift;F7 + +Project +Project Properties +. + + + +General Project Settings + +Name + + +Here you fill in the name for your project. For example, we will call ours +foo. When you fill in +Name, File is filled out for +you automatically. + + + + + +File + + +This is the name of the &quantaplus; project file. By default, it is the +name of your project, but in lowercase letters and without spaces. It +uses the extension webprj (⪚ +foo.webprj). This file is stored in the root of the +project's Main Folder. + + + + + + + +Server Settings + + + +Protocol + + +Here you select the protocol you will be using to access you project. If +your project is on the same machine that you are using Quanta Plus on, +then leave the value at Local. The list of protocols shown here is +dependant of your system setup. Available protocols include SSH, FTP, NFS, +SMB, WebDAV, and others. The protocol list is powered by &kde;'s +powerful KIOSlave architecture. This framework allows every &kde; +application to easily access remote information as if it is local to the +machine. + + + + +Host + + +Here you fill in the server address of the machine you want to access, +unless you are working through the Local protocol. Either a hostname +(hostname.example.com) or an IP address (127.0.0.1) can go here. + + + + +User + + +User name for logging onto the remote machine. This is case-sensitive. + + + + +Password + + +Password for logging onto the remote machine. This is case-sensitive. + + + + +Port + + +Leave this field blank to use the default port for the protocol you are +using. You may need to change this depending on your server's +configuration. + + + + + + + + + + + +Directory Settings + + + +Main directory + + +This is the root folder where all of the project files and folders +will be stored. + + + + +Templates directory + + +This is where the templates for this project will be stored. It is a relative path to the project and by default, +it points to +templates. +If you have a common set of files that you use for several +projects, then it may be useful to point this field to it, instead of to +the default. + + + + +Toolbars directory + + + This is where the toolbars for this project will be stored. It is a relative path to the project and by default, +it points to toolbars. +If you have a common set of toolbars +that you use for several projects, it may be useful to point this there +instead of the default. + + + + + + + + + + + +Project Sources + + + +Add local or remote files + + +This allows you to get files from the local file system. You can choose +multiple files or entire folders. + + + + +Use wget to download files from site + + +This option is great if you have static web content that you wish to +download and modify. For server side scripting (⪚ &PHP;, Python, +&etc;.) you will have to get the files another way. + + + + + + + + + +Insert Files in Project + +Insert file from + + +Check this if you wish to include files found in the path of the Main +Folder. Leave unchecked when starting a project from scratch. + + + + +Filters + + + +Insert only markup, script and image files + + +Choosing this option will only insert markup, script, and image files into +your project. + + + + +Insert files with the following mask + + +Choosing this option will display all files and folders within the +Main Folder and allow you to be more specific with your choices. + + + + + + + +Included files + + +This displays a list of the files in the Main Folder. You can choose +the desired files for inclusion, by checking, or exclusion, by unchecking, +in your project. + + + + + + +More Project Settings + +Author + + +Insert your name (or alias) here. + + + + +Email + + +The address where you would like email regarding this project to go. + + + + +Project Defaults + + + +Default DTD + + +Choose the markup language you will be working with the most within this +project. + + + + +Default encoding + + +Choose the character encoding you wish the files in your project to be +opened and saved with. + + + + + + + +Use preview prefix + + +Check this to use a prefix for your previews. This allows you to set the +path prefix to something other than your local file system. This is most +useful for pages that contain dynamic content and are dependent on server +processing (like &PHP;, JSS, Python, &etc;). Simply +type in the first portion of the address as it exists on that server and +the filepath at the end will be complete by &quantaplus;. For example, if +you have the domain bar.com and you are editing the +index.html page, you could edit it on your remote +machine (foo.bar.com), upload it to the server +and press F6 to see the results from +www.bar.com instead of your local file system. + + + +Prefix + + +Enter the prefix you wish to use here. + + + + + + + +Insert global templates + + +This makes a copy of the global templates in your projects folder tree. + + + + +Insert local templates + + +This makes a copy of the local templates in your projects folder tree. + + + + + + +The last screen of the new project wizard has 3 settings that can make +your life easier. These settings are available for change from the + +Project +Project Properties + +menu tree on the Upload Profiles Tab or with the keyboard shortcut +&Shift;F7. + + + + + +Configuring Projects + + The project properties dialog looks like: + + + + + The general options page + + + + + Some of the items are the same as in the project wizard and are described in . The extra items are described below. + +General Project Settings + +Exclude from project + + + A list of file names (wildcards can be used) that will be ignored when you do project related operations like Rescan Project Folder. + + + + + Exclude files listed in .cvsignore + + + A complementary option to the above one, also files listed in the .cvsignore file will be excluded from the project. + + + + + Default view + + + The project view that will be loaded when the project is opened. + You can read more about project views in . + + + + + Debugger + + + Select the debugger you want to use. Currently only Gubed is support. You can find more information about Gubed at .The debugger plugin can be configured with the Options button. + read to learn more about debugging. + + + + + Default view + + + The project view that will be loaded when the project is opened. + You can read more about project views in . + + + + + +On the Upload Profiles page you can configure the upload profiles (see ), as well as enable the showing of a treeview with the content of the server for each profile by checking the Show a treeview for each profile checkbox. + + + On the Team Configuration page you can add, edit and remove members of the project as well as define a mailing list. Read for details. + + + On the Event Configuration page you can Enable the event actions, add, modify and remove these actions. Event actions are executed when some predefined event occurs, like saving a file. See for details. + + + + +Using Projects + + +Project Files + + +By default &quantaplus; will open the last project accessed when launched. +This behavior is not currently configurable. + + + +To open another project, select Open Project... from the +Project menu or the Open Project +icon on the toolbar. The open project dialog will pop up and allow you to +choose the project you wish. Projects have a webprj extension. + + + +When closing &quantaplus;, your project file will be saved automatically. +You will be asked to save any changes before exiting if &quantaplus; +detects any changed files. This same behavior occurs if you load a new +project. + + + + + +The Project Tree View + + +The project tree view gives you uncluttered access to the files in your +project. This is where you manage the files in the current project. + + +For files, a &RMB; click brings up the following menu: + + + + + + + + +These items are fairly self-explanatory and will be left to the reader +for exploration. + + + +Folders are similar but do not contain the Open +and Open With... &RMB; menu items: + + + + + + + + + +These items are left to the reader for exploration as well. + + + + + +Uploading Projects + + +The Upload Project dialog: + + + + + + +The Upload Project dialog. + + + + +Profile name + + +This is where different profiles can be chosen. The profile contains +information on where the uploaded files are to be placed. Read . + + + + +New + + +This button allows you to create new upload profiles. + + + + + +Edit + + +This allows you to edit the currently selected upload profile. + + + + + +Remove + + +This allows you to remove the current profile. If only +one profile is available the button is grayed out to prevent its +removal. + + + + + +Keep passwords in memory + + +The password is stored in memory and is lost as soon as the program is closed. +This option is useful if frequent uploading of files is necessary and you do +not want to use the more insecure Store password on disc option. + + + + + +All + + +Select all files in your project for upload. + + + + + +Modified + + +Select all modified files for upload. + + + + + +None + + +Unselects all files in the list. + + + + + +Invert + + +Selects/Unselects all files in the list. + + + + + +Expand All + + +Expands all folders. + + + + + +Collapse All + + +Collaspes all folders. + + + + + +Update All + + +Refreshes list. + + + + + +Proceed + + +Start the upload + + + + + +Cancel + + +This will abort your transfer in progress or just exit out of the dialog +if you change your mind before starting the upload. + + + + + + + + +Upload profiles + +With &quantaplus; you can define multiple upload profiles and, in this +way, upload your project (or parts of your project) to different servers. +When you edit or create a profile you will face the following dialog: + + + + + + + + +Profile name + +Enter the name you wish to give your profile here. + + + +Host + + +This is the hostname of the server you are copying the files to. Either a +fully qualified domain name, or an IP address is needed. + + + + + +Protocol + + +Transfer protocol to use for this upload. Depending on your version of +&kde; this list will vary. At the very least you should be able to choose +from &FTP;, file (&ie; local) and NFS. + + + + + +Port + + +Port for the transfer. Usually this will not need to be changed unless your +network administrator is hosting a service on a port other than its well +known port. + + + + + +User + + +Username to use for authentication. + + + + + +Password + + +Password to use for authentication. + + + + + +Store password on disc + + +Depending on your level of paranoia, this is a time saving feature, or a +danger. Use it at your discretion. The password is kept on disk as text in an obscured form, so it's not simple to read it, but anyone with programming knowledge can easily un-obscure it. + + + + + +Path + + +This is the base path on the remote host that you will be copying files +to. + + + + + +Use as default profile + + +Allows you to mark the profile currently being viewed as the default. + + + + + + + + + Project Views + + A project view is just a set of files and toolbars. You can have multiple views in a project, meaning that by simply changing the view you can load several files and toolbars which will replace the currently opened files and toolbars. + + + Views can be saved, opened, deleted using the Project menu or the Project Toolbar, accessible via SettingsToolbarsProject Toolbar. + + + You can have a default view (loaded when the project is opened). See . + + +
diff --git a/doc/quanta/quantamdi-editor.png b/doc/quanta/quantamdi-editor.png new file mode 100644 index 00000000..c20e92b0 Binary files /dev/null and b/doc/quanta/quantamdi-editor.png differ diff --git a/doc/quanta/quantamdi-treeview.png b/doc/quanta/quantamdi-treeview.png new file mode 100644 index 00000000..69f0a5c6 Binary files /dev/null and b/doc/quanta/quantamdi-treeview.png differ diff --git a/doc/quanta/quantamdi.png b/doc/quanta/quantamdi.png new file mode 100644 index 00000000..8c85833f Binary files /dev/null and b/doc/quanta/quantamdi.png differ diff --git a/doc/quanta/script-action.png b/doc/quanta/script-action.png new file mode 100644 index 00000000..6eaf85a6 Binary files /dev/null and b/doc/quanta/script-action.png differ diff --git a/doc/quanta/tag-actions.png b/doc/quanta/tag-actions.png new file mode 100644 index 00000000..3f5acd2a Binary files /dev/null and b/doc/quanta/tag-actions.png differ diff --git a/doc/quanta/tag_misc.png b/doc/quanta/tag_misc.png new file mode 100644 index 00000000..7ae77650 Binary files /dev/null and b/doc/quanta/tag_misc.png differ diff --git a/doc/quanta/taginputex.png b/doc/quanta/taginputex.png new file mode 100644 index 00000000..f2f8f87e Binary files /dev/null and b/doc/quanta/taginputex.png differ diff --git a/doc/quanta/team-editing.png b/doc/quanta/team-editing.png new file mode 100644 index 00000000..a81d2041 Binary files /dev/null and b/doc/quanta/team-editing.png differ diff --git a/doc/quanta/template-rmb.png b/doc/quanta/template-rmb.png new file mode 100644 index 00000000..ffa3b05f Binary files /dev/null and b/doc/quanta/template-rmb.png differ diff --git a/doc/quanta/text-action.png b/doc/quanta/text-action.png new file mode 100644 index 00000000..9372b95a Binary files /dev/null and b/doc/quanta/text-action.png differ diff --git a/doc/quanta/toolbars.png b/doc/quanta/toolbars.png new file mode 100644 index 00000000..0027e0fa Binary files /dev/null and b/doc/quanta/toolbars.png differ diff --git a/doc/quanta/ttab.png b/doc/quanta/ttab.png new file mode 100644 index 00000000..f6d5c08b Binary files /dev/null and b/doc/quanta/ttab.png differ diff --git a/doc/quanta/view_sidetree.png b/doc/quanta/view_sidetree.png new file mode 100644 index 00000000..ddf73f5f Binary files /dev/null and b/doc/quanta/view_sidetree.png differ diff --git a/doc/quanta/vplsourceview.png b/doc/quanta/vplsourceview.png new file mode 100644 index 00000000..ba6e3472 Binary files /dev/null and b/doc/quanta/vplsourceview.png differ diff --git a/doc/quanta/working-with-quanta.docbook b/doc/quanta/working-with-quanta.docbook new file mode 100644 index 00000000..4a0ca0b1 --- /dev/null +++ b/doc/quanta/working-with-quanta.docbook @@ -0,0 +1,650 @@ + + + + +Working With... + + +Robert +Nickel + +
robert@artnickel.com
+
+
+ + András + Mantia + +
amantia@kde.org
+
+
+ + +Christopher +Hornbaker + +
chrishornbaker@earthlink.net
+
+Reviewer +
+ + +Fabrice +Mous + +
fabrice@kde.nl
+
+Reviewer +
+ + + +
+
+ +Working With... + + +This chapter describes the parts of &quantaplus; that you will be +interacting with mostly. These not only make your more productive, but +they also allow you to customize &quantaplus; to your work-flow. + + + +Toolbars + + +As previously mentioned, toolbars in &quantaplus; are primarily managed +through the Toolbars menu. Usage and creation are +somewhat different. The creation of toolbars is discussed in a later +section entitled Creating +Toolbars. + + + +Using toolbars is quite simple. When you click on an icon for a desired +element or action, one of three possibilities occur: the element is +inserted (optionally with a closing element); an element dialog is +activated, allowing you to fill in the attributes in a dialog box; or, +lastly, an action is activated and does something nifty for your current +file or project. If you find yourself doing tedious and redundant typing +for a particular element, that is not in &quantaplus;, then you can add it. +See for more information. + + + +Configuring the toolbars and the elements on it can be done either by +using the context menu (right click on a toolbar), where you can +create a New Action, a New Toolbar, you can perform other actions like Remove Toolbar, Rename Toolbar or Configure Toolbars, which will get you the dialog where you can specify which actions should be visible on this or other toolbars. + + + By invoking the context menu on an action (icon) placed to a toolbar, aside of the above actions you will see the Remove Action and Edit Action entries, which speak for themselves. + + + The toolbars and the actions on them can be configured by using the SettingsConfigure Toolbars... and SettingsConfigure Actions.. menu entries. + + + About the user definable actions you can read in . + + + +A tag dialog looks just like the following: + + + + + +An example of a tag dialog. + + + + +The above image is the dialog for the anchor tag. If you know &HTML;/&XHTML;, +then you should have noticed that all the attributes that you can use, in +an anchor element, are available. Notice the tabs above for +Main, Core and i18n, +Events, and Focus, they hold +all of the other attributes, according to their purpose, available to the +anchor element. All you need do is: fill in the blanks for the attributes +you want in your anchor, omit the attributes you do not want, and click OK. +You now have a well formed anchor set down at the current cursor position. + + + +&quanta-projects; + + +Templates + + +Templates are basically skeleton documents, code snippets and files to +link to. &quantaplus; uses templates fundamentally as a standard file +system with enhanced organization and interfacing. You can copy, move or +link any repository currently on your system into the templates tree. +Think of &quantaplus; templates as having roughly the limitations to your +imagination that your file system has. + + + +Templates exist in nested folders. There is no limit to how deep you +can nest them, however, within any given folder &quantaplus; expects a +consistent action for the base template type described below. Additionally +templates allow for pre and post text to be concatenated to non document +type templates. This facilitates tag creation. The next update after the +introduction is scheduled to add the ability to pass variables to the text +such as image size information to assist in tag creation. + + + +Our goal with templates is to extend them to include multi file +concept templates useful for things like placing an order or +creating an about section. Ideally this will be a tool for making your +work more productive and dynamic. An eventual goal is to have a structural +template design mode to deal with site layout and structure which you +could use to design and interactively update your sites. If you would like +to be involved, check out our +help +wanted page. + + + + +Some of the templates that ship with &quantaplus; have conditions for +their usage. Please read carefully the usage statement of conditions at +the top of each template before you use it. + + + + +Template Types + + +There are various template types supported by &quantaplus;. +These are: + + + +Binary templates +Document templates +Text snippets +Site templates + + +Examples for these types are provided with &quantaplus;. + + + +Binary templates + + +Binaries are anything not identified purely in text. They can be any file, +except text, including images, &PDF;s, flash files, etc. Binary templates +are usually included in your document via links (&ie; images as +an img src=/src/url). +Some examples can be found in the Templates tree under Global Templates. +Please see for more information on the +Templates tree. + + + + + +Document templates + + +Documents can be any type of text document. You can create new documents +based on these templates. Generally you would want to nest +more specific or diverse documents in subfolders. Here you can make a +basic framework for what you do and deliver it to your work in an +organized fashion and realize much better efficiency. Some examples +can be found in the Templates tree under Global Templates. +Please see for more information on the +Templates tree. + + + + + +Text snippets + + +This type of template is useful when you don't want to create a new +document based on a template, but want to insert the same text area +over and over in your documents. They can contain anything, starting +with a comment and ending with a complete menu handling JavaScript +method or perl script. Some examples can be found in the Templates +tree under Global Templates. +Please see for more information on the +Templates tree. + + + + + +Site templates + + +As the name says these templates are useful to build a whole site +from a template. They are a collection of various documents which +can be organized in a directory structure, everything gathered in +a compressed tar archive. As of writing there are no example site +templates in &quantaplus;. + + + + + + + + +Template Scopes + + +Templates are accessible based upon their established +workspace in &quantaplus; + + + + + +Creating Templates + + +Creating document templates + +Create a document structure that you love (&XML;, &HTML;, DocBook, &etc;.) +and click on + +File +Save as Template +Save as Local/Project Template +. + + + +Once this is done, you will notice that (even if it is saved as a Project +template) the template does not show in the project +tab view. Look into the templates view to find your template under the +Project templates tab. + + + +Creating text snippets +Select some text in your document and click on + +File +Save as Template +Save Selection to Local/Project Template file +. +Alternatively you can just use drag and drop to drag the selection to the Templates treeview. + + + +Creating binary templates +Creation of a binary template is simple: just copy the file +into a template folder. You can use standard file management +functions to do it, like drag and drop or copy and paste from +Konqueror or the Files Tree. + + + +Creating site templates + +In the Files Tree or the Project Files +treeviews right click on a folder and select Create Site Template, +pick up a name for the template and save it. By default it will try +to save to the project template folder, but of course you can choose +to save it as a local or global template as well. + + + + + +Using Templates With Projects + + +Project templates allow you to be more tightly focused. You can create +headers, footers or go dynamic with &PHP; include files and link them. +Additionally there are some very cool things we took into consideration +when using templates in projects. + + + +When creating a project you can opt to copy to your local project, all the +existing global and user templates. Legacy project get default templating +abilities so nothing is lost You can choose where to locate your template +files so they can be in your server root and easy to upload or you can +make them secure to link to below server root which is a very cool trick. +When linking to a file not in the project templates you will be prompted +to copy the file to the project templates prior to linking. This will prevent +broken links on upload. You always have control where you place your +templates so you can choose to move them. However &quantaplus; does not +track this so you will need to change links. + + + + + +Managing Templates + + +Template structure on the template tab is based on the files found in + +$KDEDIR/share/apps/quanta/templates and + +$HOME/.kde/share/apps/quanta/templates. Each of +these folders is specified as one of four types of container as explained above. + + + +To set the behavior of each folder, &RMB; click in the template view on +the folder and choose Properties. The +following dialog will come up: + + + + + +Properties dialog. + + + + + +Type + + + +Drop down box with the three types discussed previously; files, text, +template. This box will be grayed out if you have the Inherit +parent attribute box checked. + + + + + +Inherit parent attribute (foo) + + +This is checked by default and is fine for all but the top level +folders in your templates tree. If the top level folder has this +checked, it will basically deactivate templates for that folder and all +that aren't explicitly set below it. If this is not a top level folder, +then the blah will say something like +Text snippet. If it says nothing, then chances are that +you are on a top level folder. + + + + +Use pre/post text + + +Enables pre and post text for templates in this folder. This could be a +common header/footer for all of your templates for a given project and +then you copy content templates into that folder and have a complete +page with the custom header/footer as a starting point. + + + + +Pre-text + + +The actual text to insert before your templates content. + + + + +Post-text + + +The actual text to insert after your templates content. + + + + + + +Additionally if you look at your options with the &RMB; you will see +complete file management tools for creating folders or copying and +pasting templates from one location to another. + + + + + + +<application>Visual Page Layout</application> + + +Nicolas +Deschildre + +
nicolasdchd@ifrance.com
+
+
+ + +Christopher +Hornbaker + +
chrishornbaker@earthlink.net
+
+Reviewer +
+ + + +
+
+ +<application>Visual Page Layout</application> + + +&VPL; Modes + + +The Visual Page Layout (&VPL;) editor (also known +as WYSIWYG (What You See Is What You Get)) allows you +to edit a &HTML; or &XHTML; document while seeing the changes on-the-fly. +Just like your favorite wordprocessor, you can click on your document and +a cursor will appear, thus enabling you to enter text, insert images, +apply text decorations, &etc;. &VPL;'s aim is to allow you to create great, +valid web pages without any knowledge of Internet markup languages. + + + +&quantaplus; offers two modes: &VPL; Editor and +&VPL; & Source Editors, which are accessible from +the View menu. The first replaces the Source +Editor with the &VPL; Editor, and the +second splits the editor window into two parts: the Source +Editor and the &VPL; Editor. + + + +The &VPL; Editor works like so: It loads a document +like a normal &HTML; or &XHTML; page and a cursor appears. Then you can +edit it, and switching back to Source Editor, you see +that the changes you made on the &VPL; Editor have +been merged in the Source Editor. + + + + +When working in the &VPL; Editor with a document that +contains &PHP;, you will see a small green icon representing the &PHP; +code. You cannot directly edit it with the &VPL; +Editor. To edit &PHP;, you will still need to use the +Source Editor. There are no plans to change this +functionality. + + + + +The second mode behaves exactly like the first, except that you instantly +see the impact that your changes have made, either in the Source +Editor or in the &VPL; Editor, and the +cursors of the source editor and of the &VPL; Editor +are synchronized. Pressing F9 loads this mode, but, if +it is already loaded, it will move the focus from one view to the other, +while keeping you at the same location of the document. + + + +The refresh intervals between the &VPL; Editor and +the Source Editor are configurable. Go to + +Settings +Configure Quanta... +. Select the &VPL; View tab. You can +choose whether you want to refresh a view only when you click on it or +automatically. If you choose automatically, then you can choose a refresh +interval. The general recommendation is: A smaller number for fast +computers and a bigger number for slower ones. + + + + + + +The &VPL; & Source Editors mode. + + + + +&VPL; Editing + + +The <guilabel>Document Properties</guilabel> Dialog + + +Now, let's say you want to edit the title of your web page. How do you do +it? Simply launch + +Tools +Document Properties +. This tool allows editing of invisible +tags when using the &VPL; Editor. The +Document Properties dialog is also launched when you +create a new document while in the &VPL; Editor. This +is in order to lessen the amount of hand coding you need to perform. With +it, you can edit: + + + + +Title + + +The title of the document. + + + + +Meta items + + +Meta tags allow you to store information about the document itself +⪚ keywords for the Internet search engines. You can add or remove +Meta items by pressing the two buttons below, +and edit them by clicking on the list ⪚ put keywords on +the name column and keyword1 keyword2 on the +content column. + + + + +CSS Rules + + +CSS Rules are the new way to tell your web browser +how to present the page. You can add or delete the CSS +Rules by pressing the buttons below. You can also fill the +fields like the Meta items. The editing of +CSS Rules is not yet supported. + + + + +Link CSS Stylesheet + + +You can also link an external CSS stylesheet. Simply click on the +Browse button and select your file. + + + + + + + + +The <guilabel>&VPL; Editor</guilabel> + + +You can use your cursor like you do in a wordprocessor, moving with the +arrows. There may come a time when the cursor does not want to go where you +want it to go (a pesky bug). Selection also works as usual. You can insert +text by typing and remove text by pressing the &Backspace; or Delete key. + + + +Now we come to tag insertion. You can insert images, applets, text +decorations such as bold and so on by using the same toolbars you use in +the source editor. Note that the insertion of tags does not remove previous +identical tags ⪚ if you insert an anchor tag around some text, then you +must remove any other anchor tag around it. + + + + +Some toolbar items will be disabled, such as the Table +Wizard or Quick List Wizard. They will +work later in &VPL;, but, for this release, you should use the +Tables or Lists toolbars. + + + + +To edit a tag (be it an image, an applet, or whatever), switch to the +Attribute Tree, accessible via + +View +Tool views +. Click on the tag you wish to edit, or, if you cannot access +it, click on an object contained by it. The Attribute +Tree will show the current tag name as well as a list of all its +parents and attributes. Currently &VPL; does not support, say, +&XHTML;+MathML, but you will see that you can edit +namespaces via this view. You can simply click on the +Value field and modify whatever you want. If you want +to access a parent of the current tag, then select it and the +Attribute Tree will load it. + + + +To delete a tag, we will use the Attribute Tree. Have +you noticed the two little red crosses at the top-right corner? The first one +deletes only the currently selected tag and, if the &HTML;/&XHTML; +specification does not allow some children of the deleted tag to be children of +the parent tag of the tag set to be deleted, then they are also deleted, +and so on. The second cross will delete the selected tag as well as all of +its children, so be careful! + + + + +
+
diff --git a/doc/xsldbg/Makefile.am b/doc/xsldbg/Makefile.am new file mode 100644 index 00000000..41691557 --- /dev/null +++ b/doc/xsldbg/Makefile.am @@ -0,0 +1,3 @@ +KDE_LANG = en +KDE_DOCS = AUTO + diff --git a/doc/xsldbg/commands.docbook b/doc/xsldbg/commands.docbook new file mode 100644 index 00000000..0c1e6735 --- /dev/null +++ b/doc/xsldbg/commands.docbook @@ -0,0 +1,801 @@ + + +Command Reference + +Addparam +Add a libxslt parameter ; equivalent to providing --param <QNAME>:<XPATH> via command line. + + +Addparam usage + +addparam <QNAME> <XPATH>    (The <XPATH> must not contain any spaces nor double quotation marks.) +addparam <QNAME> "<XPATH>"    (Must not contain double quotation marks in <XPATH>) + + +
+
+ +Addwatch +Add an expression to be watched. See showwatch for display watch values +Shortcut name: watch +Addwatch usage + +addwatch <XPATH> + + +
+
+ +Base +Print the base for this node +Base usage + + +base + + +
+
+ +Break +Break at a template, at a location in a stylesheet or xml file loaded by xsldbg, or at the current node. +New for xsldbg 3.1.4: When in gdb compatabilty mode orpaned breakpoints can be +set at a specific file and line number and be resolved to an active later on. +Shortcut name: bxsldbg will try to guess the complete URL given a + + +file name without a path specified. +a file name in the same directory as the "top" stylesheet loaded +a file name relative to the current working directory of xsldbg + + +Ie if you have loaded a stylesheet file of ../en/xsldoc.xsl you can do this + break -l xsldoc.xsl 26 +This command will match a partial or complete QNAME template and or mode name provided. Eg "template" will ma/tch any QNAME with a local part of "template" +Any name spaces in the provided QNAME will be expanded as specified +by the names spaces defined in the XSL SOURCE file. eg "xsl:test1" will be expanded to "http://www.w3.org/199/XSL/Transform:test1" +A requested breakpoint may need to be resolved to its associated URL and line number. This is done automaticly after +the first template has been seen by xsldbg. Breakpoints are re-validated shortly after the start of each run. +Automatic breakpoint validation is used when gdb mode is enabled - the default behaviour of xsldbg +Break usage + + +break -l <FILENAME> <LINENO>    (To set breakpoint at specified file, line number) +break -l <URI> <LINENO>    (To set breakpoint at specified URI, line number) +break <TEMPLATE_NAME>    (To break at named or matched template.) +break <TEMPLATE_NAME> <MODE_NAME>    (To break at named template with given mode.)> +break "" <MODE_NAME>    (To break at any template that has a given mode name) +break *    (To break at any template found.) +break \*    (To break at the "*" template. Other name that include '*' will not be treated specialy.) +break     (To break point at current node. Yes that includes xml data nodes!) + + +
+
+ +Bye +Exit processing stylesheet as soon as possible. +Bye usage + + +bye + + +
+
+ +Cat +Print the result of a xpath expression on relative current node. +Cat usage + + +Usage : cat <XPATH>    (To view a variable or parameter) +Usage : cat $<QNAME> + + +
+
+ +Cd +Change to the path specified by a xpath. +Cd usage + + +<< = preceding-sibling::node() +>> = following-sibling::node() +<- = ancestor::node() +-> = decendant::node() + +
+
+ +Chdir +Change the working directory +Chdir usage + + +chdir <PATH>    (A relative or absolute path for operating system) + + +
+
+ +Continue +Continue running stylesheet, stopping at any break points found. +Shortcut name: c +Contine usage + + +continue + + +
+
+ +Data +Switch to displaying the current node in xml data. Or change xml data used +Data usage + + +data    (Switch to the current document node.) +data <DATA>    (To change to a new xml data file. A leading "~" is replaced by the $HOME environment variable value. Will need to use "run" command to process it) + + +
+
+ +Delete +Delete a template breakpoint +Shortcut name: d +Delete usage + + +delete    (To delete breakpoint at current node) +delete <BREAKPOINT_ID>    (To delete breakpoint at specified break point number) +delete -l <FILENAME> <LINENO>    (Delete at specifed file, line number) +delete -l <URI> <LINENO>    (Delete at specifed URI, line number) +delete <TEMMPLATENAME>    (To delete break point at named template.) +delete *    (To delete all break points.) + + +
+
+ +Delparam +Delete a libxslt parameter +Delparam usage + + +delparam    (Delete all parameters present) +delparam <PARAM_ID> + + +
+
+ +Delwatch +Delete a watch expression or remove all watch expressions as displayed by "showwatch." command +Delwatch usage + + +delwatch <WATCHID>    (Delete a watch expression with given ID) +delwatch *    (Delete all watch expressions) + + +
+
+ +Dir +Print list of nodes in a similary way to the dir shell command. + +Dir usage + + +dir + + +
+
+ +Disable +Disable a breakpoint +Disable usage + + +disable    (To disable breakpoint at current node) +disable <BREAKPOINT_ID>    (To disable breakpoint at specified break point number +disable -l <FILENAME> <LINENO>    (Disable breakpoint at specifed file, line number) +disable -l <URI> <LINENO>    (Disable breakpoint at specifed URI, line number) + + +
+
+ +Du +Print a summary of child nodes in a tree format. +Du usage + + +du + + +
+
+ +Dump +Dump the gory details of this node +Dump usage + + +dump + + +
+
+ +Enable +Enable or disable a breakpoint (Toggle enable/disable/) +Shortcut name: e +Enable usage + + +enable    (To enable/disable breakpoint at current node) +enable <BREAKPOINT_ID>    (To enable/disable breakpoint at specified break point number +enable -l <FILENAME> <LINENO>    (Enable/disable breakpoint at specifed file, line number) +enable -l <URI> <LINENO>    (Enable/disable breakpoint at specifed URI, line number) + + +
+
+ +Entities +Print list of external General Parsed entities used data file (document) +Shortcut name : ent +Entities usage + + +entities + + +
+
+ +Exit +Exit processing stylesheet as soon as possible. +Exit usage + + +exit + + +
+
+ +Frame +Print the stack frame at a given depth +Shortcut name: f +Frame usage + + +frame <FRAME_DEPTH>    (Depth is a number from 0 to the current depth of call stack) + + +
+
+ +Free +Free stylesheet and data (Disabled see run) +Free usage + + +free + + +
+
+ +Globals +Print a list of global stylesheet variables or parameters. Print the value of a global variable +Globals usage + + +globals    (Print list of all globaly available variables) +globals -f    (Print list of all globaly available variables and thier values) +globals <QNAME>    (Print the value of variable specified) + + +
+
+ +Help +Display help on command or overiew +Shortcut name: h +Help usage + + +help     (Show overview of product) +help <COMMAND>     (Show help about a command) + + +
+
+ +Load +Load the xsldbg's options and user preferences from disk +Load usage + + +load + + +
+
+ +Locals +Print a list of local stylesheet variables or parameters. Print the value of a local variable +Locals usage + + +locals    (Print list of all locally available variables) +locals -f    (Print list of all locally available variables and thier values) +locals <QNAME>    (Print the value of variable specified) + + +
+
+ +Ls +List nodes in a brief format +Ls usage + + +ls + + +
+
+ +Next +Skip over an xsl:call-template or xsl:apply-templates. +This command has the same effect of entering the commands "step" and then "up" +Shortcut name: n +Next usage + + +next    (proceed to next sibling instruction) + + +
+
+ +Options +Print the values for xsldbg's option +Options usage + + +options + + +
+
+ +Output +Specify a local, writable file to be used for output of results +Shortcut name : o +Output usage + + +output <FILENAME>    (A local writable file name. Which can have a "~" prefix on *nix and CYGWIN platforms. Or environment variables under RISC OS) +output <URI>    (The <URI> must only use the "file://" protocol. This is then converted to a file name suitable for the operating system) +output -    ( Send to standard output. Must only be used when using xsldbg's command line prompt ) + + +
+
+ +Public +Print the value that a public ID maps via the current catalog +Shortcut name : pub +Public usage + + +public "<PublicID>" + + +
+
+ +Pwd +Print the current working directory. +Pwd usage + + +pwd + + +
+
+ +Quit +Exit processing stylesheet as soon as possible. +Shortcut name: q +Quit usage + + +quit + + +
+
+ +Run +Restart the stylesheet. +Shortcut name: r +Run usage + + +run + + +
+
+ +Save +Save the xsldbg's options and user preferences to disk +Save usage + + +save + + +
+
+ +Search +Search a dataBase of all information gathered from stylesheets loaded +All output files are stored in, value of the "searchresultspath" option if set, or the same directory as the provided stylesheet. searchresults.xml is normally transformed by search.xsl, but will be transformed using searchhtml.xsl if the "prefrehtml" option is set. +When the search command is issued a xml file (searchresults.xml) will be created. You can then process this file with your own stylesheet to present data in a other ways. If "preferhtml" option is not set +then searchresult.txt is printed to display. +Depending on the amount of data collected it might take a while to complete this command. + +Search usage + + +search <XPATH>    (See what xpath can be used see search.dtd. The deafault <XPATH> is '//search/*' ) +search -sort <XPATH>    (Tell search.xsl to sort the result before outputing it) + + +
+
+ +Set +Set the value of a variable +Set usage + + +set <VARIABLE_NAME> <XPATH> + + +
+
+ +Setoption +Set an option for execution of stylesheet +You will need to use run command to active changes +Setoption usage + + +setoption <OPTION_NAME> <INTEGER_VALUE> +Where <OPTION_NAME> can be either + + + + + debug    (If <INTEGER_VALUE> is true dump the tree of the result instead) + catalogs    (If <INTEGER_VALUE> is true use the catalogs from $SGML_CATALOG_FILES or SGML$CatalogFiles for risc operating system) + html    (If <INTEGER_VALUE> is true the input document is an HTML file) + docbook    (If <INTEGER_VALUE> is true and docbook is still supported by libxml the input document is SGML docbook) + xinclude    (If <INTEGER_VALUE> is true do XInclude processing on document intput) + preferhtml    (If <INTEGER_VALUE> is true the prefer html output for search results. : See search command) + autoencode    (If <INTEGER_VALUE> is true try to use the encoding from the stylesheet) + utf8input    (If <INTEGER_VALUE> is true All input from user is in UTF-8.This is normaly used when xsldbg is running as a thread) +      + gdb    (Run in gdb compatability mode) + + + + For a value of 1 this means + + + + Print lots more messages. Increase the frequency of printing "Breapoint at ..." + At most GDB_LINES_TO_PRINT lines will be printed when evalating expressions, followed by a "...". See options.h to change this value, the default is three lines of text + Both local and globals will be printed when the "locals" command is issued + When printing expresssions with cat/print. The evaluated value will be prefixed by "= " < EXPRESSION > + + + + + + For a value of 2 this means + + + + Print messages needed by KDbg as well as the output state above (when value is 1) + + + + + + + + + nonet    (If <INTEGER_VALUE> is true refuse to fetch DTDs or entities over network) + novalid    (If <INTEGER_VALUE> is true skip the DTD loading phase) + repeat    (If <INTEGER_VALUE> is true run the transformation 20 times) + profile    (If <INTEGER_VALUE> is true dump profiling informations) + timing    (If <INTEGER_VALUE> is true display the time used) + noout    (If <INTEGER_VALUE> is true do not dump the result) + + + + +Where value is true if it is NOT equal to zero +Where value is false if it IS equal to zero +stdout    Print all error messages to stdout. Normally error messages go to stderr. +setoption <OPTION_NAME> "<STRING_VALUE>"    (Must not contain double quotation marks in <STRING_VALUE>) +setoption <OPTION_NAME> <STRING_VALUE>    (Must not contain any spaces, nor double quotation marks in <STRING_VALUE>) +Where <OPTION_NAME> can be either + + + + + data    (Data file's URI) + source    (Source file's URI) + output    (Output file's SystemID ) + docspath    (Path to use when looking for documentation) + catalognames    (The names of the catalogs to use when the catalogs option is set. Value will be lost if set before setting catalogs option) + encoding    (What encoding to use for standard output) + searchresultspath    What path is to be used when storing the results of searching. If this is not set then xsldbg will use the path of the stylesheet + + + + + +
+
+ +Shell +Execute shell command +Shell usage + + +shell <TEXT>    (<TEXT> is the text to be passed to operating system for execution) + + +
+
+ +Showbreak +To display list of template break points. +Shortcut name: showIf a mode exists on a template breakpoint then it will + be appended to the end of template name for breakpoint. An example of the output is : + + + Breakpoint 3 enabled for template :"*" in file test1.xsl : line 105 + Breakpoint 2 enabled for template :"* testMode" in file test1.xsl : line 109 + Breakpoint 1 enabled for template :"* http://www.w3.org/1999/XSL/Transform:testMode" in file test1.xsl : line 113 + + Total of 3 breakpoints present + +Showbreak usage + + +showbreak + + +
+
+ +Showparam +Print the libxslt parameters present +Showparam usage + + +showparam + + +
+
+ +Showwatch +Show the current expression being watched +Shortcut name: watches +Showwatch usage + + +showwatch    (Show the currently selected watches and thier values) +showwatch 1    (Enable the automatic printing of watch expressions. This is used by default.) +showwatch 0    (Disable the automatic printing of watch expressions.) + + +
+
+ +Source +Switch to displaying the current node in stylesheet. Or change stylesheet used +Source usage + + +source    (Switch to the current node in stylesheet.) +source <SOURCE>    (To change to a new source file. A leading "~" is replaced by the $HOME environment variable value. Will need to use "run" command to execute it) + + +
+
+ +Step +Step until next stylesheet instruction. +Shortcut name: s +Step usage + + +step + + +
+
+ +Stepdown +Step down to a newer "call frame". +Shortcut name: down +Stepdown usage + + +stepdown     (step down one frame) +stepdown <NUMBER_OF_FRAMES>    (step down specified number of frames) + + +
+
+ +Stepup +Step up to a older "call frame". +Shortcut name: upThis is not an accurate command, xsldbg will stop as close as it can. +Stepup usage + + +stepup     (step up one frame) +stepup <NUMBER_OF_FRAMES>     (step up specified number of frames) + + +
+
+ +Stylesheets +Print out a list of stylesheets loaded +Shortcut name: style +Stylesheets usage + + +stylesheets + + +
+
+ + +System +Print the value that a system file maps via the current catalog +Shortcut name : sys +System usage + + +system "<SystemID>" + + +
+
+ +Templates +Print a list of available templates. Search for a template +Shortcut name: t +Templates usage + + +templates +templates <TEMPLATE>    (Print details of template named <TEMPLATE> if it can be found) + + +
+
+ +Trace +Trace one execution of the stylesheet printing the file and lines of +intermediate steps +Trace usage + + +trace + + +
+
+ +Tty +Open a terminal. Set the level of tty redirection. +Tty usage + + +tty <DEVICE_PATH>    (Where <DEVICE_PATH> is a valid terminal on the operating system. Just tries to open the terminal +tty <TTY_LEVEL>    (Set the level of tty redirection, where <TTY_LEVEL> is a valid level of input/output to use) + + + + Where level is + 0 = Default input/output + 1 = Terminal output of results of transformation, tracing and walking     (Default state when tty device has been opened. Not fully implemented yet.) + 2 = Full redirection to terminal    (Not implemented yet.) + All other integer values are assumed to mean level 0 + + + + + + + +
+
+ +Validate +Validate the output file generated by stylesheet (Disabled) +Validate usage + + +validate + + +
+
+ +Walk +Walk through code using a range of speeds +Walk usage + + +walk <SPEED>    (Use Ctrl-c to stop +execution, <SPEED> is a value between 0 and 9. Where 0 means stop, 1 is +very fast, 9 is very slow) + + +
+
+ +Where +Print a trace of templates calls (frame stack) and print the working directory. +Shortcut name: w +Where usage + + +where + + +
+
+ +Write +To be completed +Write usage + + +write + + +
+
+ + + + + +
diff --git a/doc/xsldbg/credits.docbook b/doc/xsldbg/credits.docbook new file mode 100644 index 00000000..89bdadc4 --- /dev/null +++ b/doc/xsldbg/credits.docbook @@ -0,0 +1,21 @@ + + +Credits and License + + +&xsldbg; + + +Program copyright 2004 Keith Isdale k_isdale tpg com au + + + +&underFDL; +&underGPL; + + +Thanks to + The writers the libxml and libxsl. +Johannes Sixt for helping with adding xsldbg support to KDbg + + diff --git a/doc/xsldbg/index.docbook b/doc/xsldbg/index.docbook new file mode 100644 index 00000000..4c211c10 --- /dev/null +++ b/doc/xsldbg/index.docbook @@ -0,0 +1,124 @@ + +xsldbg"> + + + + + + + + +]> + + + + + + + + + + + +The &xsldbg; Handbook + + + +Keith +Isdale + +
k_isdale@tpg.com.au
+
+
+ + + +
+ + +2002 +2003 +Keith Isdale + + +&FDLNotice; +2004-09-26 +1.01.00 + + + + +&xsldbg; is a tool intended to help understand stylesheets. +What makes it different to other stylesheet debuggers is the ability +to search for items of interest and trace stylesheet execution. + + + + +KDE +kdeutils +xsldbg +xsl +XML + + +
+ +&introduction-chapter; +&usage-chapter; +&commands-chapter; +&credits-chapter; + + + +Installation + + +How to obtain &xsldbg; + + +See the kxsldbg component of the kdewebdev module in &kde; SVN. + + +&install.intro.documentation; + + + + +Requirements + + +In order to successfully use &xsldbg;, you need &kde; libxslt, libexslt and +libxml installed which are available on a typical &kde; installation. + + + + +Compilation and Installation +&xsldbg; is usually compiled as part of the kxsldbg component in the kdewebdev module + + + +Configuration + +&xsldbg; is configured using arguments passed via the command line and its setoption command + + + + + +&documentation.index; +
+ + diff --git a/doc/xsldbg/introduction.docbook b/doc/xsldbg/introduction.docbook new file mode 100644 index 00000000..65879ce0 --- /dev/null +++ b/doc/xsldbg/introduction.docbook @@ -0,0 +1,20 @@ + + +Introduction + + +&xsldbg; is a text based tool to debug stylesheets (the eXtensible +Stylesheet Language) and has commands similar to the Unix/Linux debugger +gdb. It has three major modes of execution of stylesheets. + + + + + Run the whole stylesheet + Step to next xsl instruction + Continue until next break point is found, or stylesheet has restarted + + + + + diff --git a/doc/xsldbg/usage.docbook b/doc/xsldbg/usage.docbook new file mode 100644 index 00000000..5fe2fdc2 --- /dev/null +++ b/doc/xsldbg/usage.docbook @@ -0,0 +1,147 @@ + + +Using &xsldbg; + +xsldbg command arguments + +On systems with readline library available you can use the back/forward +keys to navigate the history of entered commands. +On all systems the last entered command can be repeated by just pressing +the <ENTER> key. + +If your operating system supports it file names will be expanded. + +Several commands take more that one argument. Quotes may be used to lead to +complex expressions being treated as one arument. eg break "* | @" would allow you to se a breakpoint on the + template with the name "* | @" + + + +Legend of terms +The following table describes the terms used in the subsiquent command guide + + + + TEMPLATE_NAME : A valid template name contains only ASCI + character codes 0x00 to 0x7F. And can be a fully qualified name ie + "xsl:templateName". + + FILENAME : A valid file name local to the system of the + user. It can have a "~" prefix on *nix and CYGWIN platforms. Or + environment variables under RISC OS + + URI : A Uniform Resource Identifiers as defined by RFC 2396 + MODE_NAME The mode of template which can be fully qualified name ie "xsl:modeName". + QNAME : A fully qualified name ie "xsl:localPart" + LINENO : A valid line number in associated <FILENAME> + NUMBER_OF_FRAMES : A valid line number frames to change position by + BREAKPOINT_ID : A valid break point number + WATCH_ID : A valid watch expression number as indicated by showwatch command + SPEED: speed to walk through code at, between 0 to 9 + +     (Comment): a + comment about command meaning or usage + + { opt1 | opt2 | opt2 .. etc} : Choose one of the opt's + XPATH : a xpath selection of node(s) + PARAM_ID : a valid parameter number as indicated by showparam command + + PATH : A path to change working directory to On some operating systems a + "~" prefix will be replaced by your home directory path + + + TEXT : Free form text     (no + restrictions) + + COMMAND : A valid command for the xsdbg + QNAME : A valid variable/parameter name + SOURCE : The stylesheet being/to be executed. See <FILENAME> and <URI> + + DATA : The xml data(document) being/to be processed by the + stylesheet. See <FILENAME> + and <URI> + + DEVICE_PATH : Is a valid terminal on the operating system + TTY_LEVEL : Is a valid level of input/output to use + + + + +Overview of available commands + + +Help related :help + + Running related : {bye|exit| + quit}, step, + stepup, stepdown, + next, + continue, + run, +trace, setoption, + options + + + Libxslt parameter related : addparam, + delparam, showparam, + output, setoption, + options + + + Template related : templates, + where, frame + + + Break point related : break, + showbreak, delete, + enable + + + Expression viewing(xpath) : cat + + + Node viewing : ls, dir, + du, cat, pwd + + + Variable viewing : globals, + locals, + cat, + addwatch + + + Variable setting: set + + + Node selection : source, + data, cd + + + Searching :search + + + Operating system related :chdir, + shell, tty +File related : output, + entities, system, + public + + + Disabled file commands: validate, + load, save, + write, free + + + + + + diff --git a/doc/xsldbg/xsldbghelp.xml b/doc/xsldbg/xsldbghelp.xml new file mode 100644 index 00000000..64d9b81b --- /dev/null +++ b/doc/xsldbg/xsldbghelp.xml @@ -0,0 +1,22 @@ + + + + + + +]> + + + + + + + +&introduction-chapter; +&usage-chapter; +&commands-chapter; + diff --git a/doc/xsldbg/xsldbghelp.xsl b/doc/xsldbg/xsldbghelp.xsl new file mode 100644 index 00000000..50e45ebd --- /dev/null +++ b/doc/xsldbg/xsldbghelp.xsl @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ==================== + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kdewebdev.lsm b/kdewebdev.lsm new file mode 100644 index 00000000..b8ceb975 --- /dev/null +++ b/kdewebdev.lsm @@ -0,0 +1,11 @@ +Begin4 +Title: kdewebdev +Version: 3.5.10 +Entered-date: 2008-08-26 +Description: Web Development Applications for the K Desktop Environment (KDE) +Keywords: KDE X11 desktop Qt +Author: http://bugs.kde.org/ (KDE Bugtracking System) +Primary-site: http://www.kde.org/download/ +Platforms: Unix, Qt +Copying-policy: GPL, Artistic +End diff --git a/kfilereplace/ChangeLog b/kfilereplace/ChangeLog new file mode 100644 index 00000000..9a9c507e --- /dev/null +++ b/kfilereplace/ChangeLog @@ -0,0 +1,211 @@ +2005-02-20: Andras Mantia + * Added the possibility to select the encoding of the files and a warning about + the possible damaged result if the wrong encoding is chosen + +2005-02-16: Andras Mantia + * Accept paths as command line arguments + +2005-01-29 Emiliano Gulmini + * Cleaning up. + +2005-01-23 Emiliano Gulmini + * Some clean up. + * Now the text 'captured text "blabla" at line...' etc. is substituted with + 'Line:xyz, Col:abc "blabla"' + * Fixed a bug in the string view, that cause KFR to crash if the string list is empty + and the user click on it with the mouse. + +2005-01-17 Emiliano Gulmini + * Now it should be possible to handle other characters encoding, like japanese. + * Added, but still buggy, a "replace confirmation" option. + * Now when open KFilereplace as standalone application it uses + this "*.c*;*.h*;*.sh;*.txt*;*.p*;*.java;*.log" string as default filter. + +2005-01-14 Andras Mantia + * Don't show the cannot open file dialogs for directories + * Don't create a backup for every scanned file, only for those that were modified + * Don't update the timestap for every scanned file + * Fix installation of the icons (they go to the part's data dir now) + +2005-01-13 Emiliano Gulmini + * I added some other infos to the docbook manual, I hope to complete it as soon as possible. + * I added a new command: [$mathexp:some_expression$]. It uses the bc calculator to + compute the result of an expression. + +2005-01-11 Emiliano Gulmini + * Fixed a bug in KAddStringDlg: now when we want edit a string the search-only mode and search-replace mode + don't merge. + * Modified KFR file format: I added the tag '' just after the root to allows + kfilereplace to recognize if the list to load is a list of only search strings. I added some lines of code + to permit users to load files that don't have this new tag. + * I'm writing docbook manual. + +2005-01-10 Emiliano Gulmini + * The KFilereplaceView widget has been modified. Now it change the layout of kfilereplace depending of the + value of m_option->m_searchOnlyMode. + * I fixed a bug in the backup file option. + +2004-12-13 Emiliano Gulmini + * I modified the way we can open files in quanta. Now we can select one or more entries + in the QListView that store the results, and open several files, at the same time. + For selecting more than one file, we must press CTRL button while clicking with mouse + on the entry we want open. + +2004-11-10 Emiliano Gulmini + * I added a graphical file counter. + * I added a semaphore to notify user about the state of the search. + * I improved a little the speed. + * I made some cleanup. + +2004-09-27 Emiliano Gulmini + * I fixed a bug that affect some strings in case of translation. + * I fixed a bug that affect "Create backup" option, I think that now this feature should work + properly. + +2004-09-26 Emiliano Gulmini + * I did some cleanup. + +2004-09-11 Emiliano Gulmini + * I added the class ResultViewEntry in configurationclasses.(h,cpp) to make the replace algorithm more clean. + * I make multiline text searching more useable. + * Now the file entries in the result view are shown with descriptive icons. + * I'm trying to write some documentation, in the meanwhile a tutorial is present. + +2004-08-13 Emiliano Gulmini + * I added CommandEngine class and Report class. + In fact I moved the code that do the report document and the + code that do commands feature from KFileREplaceLib to these two classes. + +2004-08-09 Emiliano Gulmini + * I fixed a bug that affected the method "void KFileReplaceView::slotStringsClear()" in kfilereplaceview.cpp file. + This bug caused the list of strings not to be correctly erased. + +2004-08-07 Emiliano Gulmini + * I modified the save-results system(thanks Luciano for the idea of using xml/css tecnology). + Now KFR creates a directory with name "NAME" that contains a xml file "NAME.xml" + and a css file "NAME.css". These two files are the new "report document" + that substitutes the xhtml file. To try it choose "Search/Replace|Results|Create Report File" menu option. + * I fixed a bug that causes Quanta to crash when we push Cancel button in new project + dialog. + * I finished the tutorial. + +2004-08-01 Emiliano Gulmini + * The line "if(::access(directory.local8Bit(), R_OK | X_OK) == -1)" has been removed, + and subtitued with "QFileInfo dirInfo(directory); " + "if(not(dirInfo.isReadable() and dirInfo.isExecutable())" + " or " + " not(dirInfo.isWritable())) " + in kfilereplacepart.cpp + +2004-07-30 Emiliano Gulmini + * The icons have been fixed!!! What a miracle!!! + +2004-07-24 Emiliano Gulmini + * I added a little feature. When KFR matches a string, it shows the row and the column + where that match is, by using a message like this: + /my/path/file + | + |__ string "xyz" found at line:40, column:2 + |__ string "xyz" found at line:18, column:57 + |__............. + Now if you use "Edit with Quanta" popup menu option, say, on the line: + "string "xyz" found at line:40, column:2" + of the result view, Quanta will open the file /my/path/file at row 40, column 2. + +2004-07-20 Emiliano Gulmini + * I fixed a bug that affects the generation of extension of + the backup files. + +2004-07-17 Emiliano Gulmini + * I fixed the bug that causes quanta to crash when KFR is active. + * I fixed (I hope!) the simulation feature. + * I reorganize the KOptionsDlg UI. + * I Added some tool tips. + * I' m tired and I go on bed ;-) + +2004-07-16 Emiliano Gulmini + * The KNewProjectDlg was modified, adding quick search/replace line edit objects + * A option in KOptionDlg was added, so that the files that don't + contain the strings we are searching for, will not be shown. + * Some code clean-up + * A bug with KAddStringDlg was fixed. + * I found a bug that makes quanta to crash when we close quanta with the x button... + I'm trying to fix it. + +2004-05-30 Emiliano Gulmini + * Well, KFR has been entirely (more or less :-)) rewrote. + the files: + apistruct.h + kernel.(cpp,h) + kexpression.(cpp,h) + kfilereplacedoc.(cpp,h) + kfilereplacepref.(cpp,h) + + were removed and these files are added: + + configurationclasses.h + + . the internal architecture was redesigned, to use QT/KDE tecnologies in particular: + . C-like code were removed (where possible). + . some system dependent functions were substituted with more portable code. + . the apistructs.h file were substituted with one class in configurationclasses.h. + . the UIs were modified in particular: + . new "add string" dialog were added. + . project dialog were modified. + . some new features were added in particular: + . the variable replace mechanism were modified. + . the result view shows the line and column where the string has been found. + . now the mechanism of search/replace with wildcards inherits from QT regular expression engine. + + * I wrote a little tutorial(TUTOR.txt), but a more exhaustive tutorial will be released soon. + Note: there some bugs to fix and some feature to implement, in particular: + . Simulation is not yet implemented. + . Some options are presents but disabled. + . I want to add more KFR variable commands. + + +2004-03-26 Emiliano Gulmini + * Added a feature. Now we can open a file from the result view of KFR in Quanta(thanks Andras). + +2004-03-14 Emiliano Gulmini + * Replaced two QLineEdit with two QSpinbox in knewprojectdlg.ui + * Fixed a bug in the new kfr (XML-based) file format. + +2004-03-12 Emiliano Gulmini + * Removed KresultView(.h,.cpp). Now KFileReplaceView is a QWidget that contains results and + strings view. + * Added whatthis.h that contains the "what's this" strings. + * Fixed a bug that generate a wrong XHTML result file. + +2004-03-06 Emiliano Gulmini + * Added kconfirmdlgs.ui. + * Fixed a bug in KOptionDlg, now when we select a option, the selection is shown correctly. + * Fixed a bug KNewProjectDlg. + +2004-02-26 Emiliano Gulmini + * I added a method 'editStrings' that fixes tha behaviour when a user + chooses edit string option instead of add string option. + * I modified the property textFormat of the QTextEdit widgets of + KAddstringDlg, from the value 'AutoText' to the value 'PlainText', + so the QTextEdit widgets will not try to render a string containing + html code. + +2004-02-24 Emiliano Gulmini + * kfilereplacepref.(h,cpp) were removed. + * kernel.(h,cpp) now are a singleton class. + * Some macros in kernel.h were replaced with integer constants. + * Methods in kernel.h file were renamed. + * Some superflous #include lines were removed. + * The filelib.(h,cpp) were subtituted with KFilereplaceLib singleton class. + * Now kfilereplace logo and icons in the result view appear. + +2004-02-18 Emiliano Gulmini + * The icons in toolbar directory were redrawn. + * Deleted the KFRHeader struct from apistruct.h. + * The mechanism of saving the string rules has been modified: now we can save the rules in a + file like this "a_file_name.kfr" that is an XML file. + * The file containing the results of the operations is now a XHTML file. + * Two new files UI added: now KOptionDlg inherits from KOptionDlgS and KAddstringDlg inherits + from KAddstringDlgS. + * The klistviewstring.(h,cpp) were removed. + * A lot of clean up has been made in all files. diff --git a/kfilereplace/Makefile.am b/kfilereplace/Makefile.am new file mode 100644 index 00000000..528a791e --- /dev/null +++ b/kfilereplace/Makefile.am @@ -0,0 +1,43 @@ +## Makefile.am for kfilereplace + +# set the include path for X, qt and KDE +INCLUDES = $(all_includes) + +# this has all of the subdirectories that make will recurse into. if +# there are none, comment this out +SUBDIRS = toolbar + +# these are the headers for your project +noinst_HEADERS = kaddstringdlg.h kfilereplaceiface.h kfilereplacelib.h \ + knewprojectdlg.h kfilereplaceview.h koptionsdlg.h report.h commandengine.h \ + configurationclasses.h kfilereplace.h + +# let automoc handle all of the meta source files (moc) +METASOURCES = AUTO + +kde_module_LTLIBRARIES = libkfilereplacepart.la +libkfilereplacepart_la_SOURCES = kfilereplacepart.cpp kfilereplaceview.cpp \ + kfilereplaceviewwdg.ui kaddstringdlg.cpp kaddstringdlgs.ui knewprojectdlg.cpp \ + knewprojectdlgs.ui koptionsdlg.cpp koptionsdlgs.ui kfilereplacelib.cpp report.cpp \ + commandengine.cpp configurationclasses.cpp + +libkfilereplacepart_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) +libkfilereplacepart_la_LIBADD = $(LIB_KFILE) $(LIB_KPARTS) $(LIB_KHTML) + +messages: rc.cpp + $(XGETTEXT) *.cpp *.h -o $(podir)/kfilereplace.pot + +KDE_ICON = AUTO +kde_services_DATA = kfilereplacepart.desktop +xdg_apps_DATA = kfilereplace.desktop + +# this is where the XML-GUI resource file goes +partrcdir = $(kde_datadir)/kfilereplacepart +partrc_DATA = kfilereplacepartui.rc + +shellrcdir = $(kde_datadir)/kfilereplace +shellrc_DATA = kfilereplaceui.rc +bin_PROGRAMS = kfilereplace +kfilereplace_LDFLAGS = $(KDE_RPATH) $(all_libraries) +kfilereplace_LDADD = $(LIB_KPARTS) +kfilereplace_SOURCES = kfilereplace.cpp main.cpp diff --git a/kfilereplace/commandengine.cpp b/kfilereplace/commandengine.cpp new file mode 100644 index 00000000..56cc50b1 --- /dev/null +++ b/kfilereplace/commandengine.cpp @@ -0,0 +1,213 @@ +/*************************************************************************** + commandengine.cpp - kfr commands feature class + ------------------- + begin : fri aug 13 15:29:46 CEST 2004 + + copyright : (C) 2004 Emiliano Gulmini + email : emi_barbarossa@yahoo.it + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +// QT +#include +#include +#include +#include + +// KDE +#include +#include +#include + +// local +#include "commandengine.h" + +QString CommandEngine::datetime(const QString& opt, const QString& arg) +{ + Q_UNUSED(arg); + if(opt == "iso") + return QDateTime::currentDateTime(Qt::LocalTime).toString(Qt::ISODate); + if(opt == "local") + return QDateTime::currentDateTime(Qt::LocalTime).toString(Qt::LocalDate); + return QString::null; +} + +QString CommandEngine::user(const QString& opt, const QString& arg) +{ + Q_UNUSED(arg); + KUser u; + if(opt == "uid") + return QString::number(u.uid(),10); + if(opt == "gid") + return QString::number(u.gid(),10); + if(opt == "loginname") + return u.loginName(); + if(opt == "fullname") + return u.fullName(); + if(opt == "homedir") + return u.homeDir(); + if(opt == "shell") + return u.shell(); + return QString::null; +} + +QString CommandEngine::loadfile(const QString& opt, const QString& arg) +{ + Q_UNUSED(arg); + + QFile f(opt); + if(!f.open(IO_ReadOnly)) return QString::null; + + QTextStream t(&f); + + QString s = t.read(); + + f.close(); + + return s; +} + +QString CommandEngine::empty(const QString& opt, const QString& arg) +{ + Q_UNUSED(opt); + Q_UNUSED(arg); + return ""; +} + +QString CommandEngine::mathexp(const QString& opt, const QString& arg) +{ + /* We will use bc 1.06 by Philip A. Nelson */ + //Q_UNUSED(opt); + Q_UNUSED(arg); + + QString tempOpt = opt; + tempOpt.replace("ln","l"); + tempOpt.replace("sin","s"); + tempOpt.replace("cos","c"); + tempOpt.replace("arctan","a"); + tempOpt.replace("exp","e"); + + QString program = "var=("+tempOpt+");print var"; + QString script = "echo '"+program+"' | bc -l;"; + + KProcess* proc = new KProcess(); + + proc->setUseShell(true); + + *(proc) << script; + + connect(proc, SIGNAL(receivedStdout(KProcess*,char*,int)), this, SLOT(slotGetScriptOutput(KProcess*,char*,int))); + connect(proc, SIGNAL(receivedStderr(KProcess*,char*,int)), this, SLOT(slotGetScriptError(KProcess*,char*,int))); + connect(proc, SIGNAL(processExited(KProcess*)), this, SLOT(slotProcessExited(KProcess*))); + + //Through slotGetScriptOutput, m_processOutput contains the result of the KProcess call + if(!proc->start(KProcess::Block, KProcess::All)) + { + return QString::null; + } + else + { + proc->wait(); + } + if(proc) + delete proc; + + QString tempbuf = m_processOutput; + m_processOutput = QString::null; + + return tempbuf; + +} + +QString CommandEngine::random(const QString& opt, const QString& arg) +{ + Q_UNUSED(arg); + long seed; + if(opt.isEmpty()) + { + QDateTime dt; + seed = dt.toTime_t(); + } + else + seed = opt.toLong(); + + KRandomSequence seq(seed); + return QString::number(seq.getLong(1000000),10); +} + +QString CommandEngine::stringmanip(const QString& opt, const QString& arg) +{ + Q_UNUSED(opt); + Q_UNUSED(arg); + return ""; +} + +QString CommandEngine::variableValue(const QString &variable) +{ + QString s = variable; + + s.remove("[$").remove("$]").remove(" "); + + if(s.contains(":") == 0) + return variable; + else + { + QString leftValue = s.section(":",0,0), + midValue = s.section(":",1,1), + rightValue = s.section(":",2,2); + + QString opt = midValue; + QString arg = rightValue; + + if(leftValue == "stringmanip") + return stringmanip(opt, arg); + if(leftValue == "datetime") + return datetime(opt, arg); + if(leftValue == "user") + return user(opt, arg); + if(leftValue == "loadfile") + return loadfile(opt, arg); + if(leftValue == "empty") + return empty(opt, arg); + if(leftValue == "mathexp") + return mathexp(opt, arg); + if(leftValue == "random") + return random(opt, arg); + + return variable; + } +} + +//SLOTS +void CommandEngine::slotGetScriptError(KProcess* proc, char* s, int i) +{ + Q_UNUSED(proc); + Q_UNUSED(proc); + QCString temp(s,i+1); + if(temp.isEmpty() || temp == "\n") return; +} + +void CommandEngine::slotGetScriptOutput(KProcess* proc, char* s, int i) +{ + Q_UNUSED(proc); + QCString temp(s,i+1); + + if(temp.isEmpty() || temp == "\n") return; + + m_processOutput += QString::fromLocal8Bit(temp); +} + +void CommandEngine::slotProcessExited(KProcess* proc) +{ + Q_UNUSED(proc); +} + +#include "commandengine.moc" diff --git a/kfilereplace/commandengine.h b/kfilereplace/commandengine.h new file mode 100644 index 00000000..cff15b29 --- /dev/null +++ b/kfilereplace/commandengine.h @@ -0,0 +1,57 @@ +/*************************************************************************** + commandengine.h - kfr commands feature class + ------------------- + begin : fri aug 13 15:29:46 CEST 2004 + + copyright : (C) 2004 Emiliano Gulmini + email : emi_barbarossa@yahoo.it + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef COMMANDENGINE_H +#define COMMANDENGINE_H + +// QT +class QString; +#include + +//KDE +class KProcess; + +class CommandEngine : public QObject +{ + Q_OBJECT + private: + QString m_processOutput; + public: + CommandEngine() {} + + public: + + /** + These functions implement the KFR commands + */ + QString datetime(const QString& opt, const QString& arg); + QString user(const QString& opt, const QString& arg); + QString loadfile(const QString& opt, const QString& arg); + QString empty(const QString& opt, const QString& arg); + QString mathexp(const QString& opt, const QString& arg); + QString random(const QString& opt, const QString& arg); + QString stringmanip(const QString& opt, const QString& arg); + QString variableValue(const QString &variable); + + private slots: + void slotGetScriptOutput(KProcess*,char*,int); + void slotGetScriptError(KProcess*,char*,int); + void slotProcessExited(KProcess*); +}; + +#endif // COMMANDENGINE_H diff --git a/kfilereplace/configurationclasses.cpp b/kfilereplace/configurationclasses.cpp new file mode 100644 index 00000000..848eafdc --- /dev/null +++ b/kfilereplace/configurationclasses.cpp @@ -0,0 +1,188 @@ +/*************************************************************************** + configurationclasses.cpp - description + ------------------- + begin : Sat Sep 11 2004 + copyright : (C) 2004 Emiliano Gulmini + email : emi_barbarossa@yahoo.it + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +// QT + +// KDE + +// local +#include "configurationclasses.h" +#include "whatthis.h" + +using namespace whatthisNameSpace; + +//RCOptions Class +RCOptions::RCOptions() +{ + m_searchingOnlyMode = false; +} + +RCOptions& RCOptions::operator=(const RCOptions& ci) +{ + //m_callResetActions = ci.m_callResetActions; + + m_directories = ci.m_directories; + m_filters = ci.m_filters; + m_currentDirectory = ci.m_currentDirectory; + m_minSize = ci.m_minSize; + m_maxSize = ci.m_maxSize; + + m_dateAccess = ci.m_dateAccess; + m_minDate = ci.m_minDate; + m_maxDate = ci.m_maxDate; + + m_caseSensitive = ci.m_caseSensitive; + m_recursive = ci.m_recursive; + m_followSymLinks = ci.m_followSymLinks; + m_allStringsMustBeFound = ci.m_allStringsMustBeFound; + m_backup = ci.m_backup; + m_backupExtension = ci.m_backupExtension; + m_ignoreFiles = ci.m_ignoreFiles; + m_regularExpressions = ci.m_regularExpressions; + + m_variables = ci.m_variables; + m_haltOnFirstOccur = ci.m_haltOnFirstOccur; + m_ignoreHidden = ci.m_ignoreHidden; + m_simulation = ci.m_simulation; + m_searchingOnlyMode = ci.m_searchingOnlyMode; + + m_ownerUserIsChecked = ci.m_ownerUserIsChecked; + m_ownerGroupIsChecked = ci.m_ownerGroupIsChecked; + + m_ownerUserBool = ci.m_ownerUserBool; + m_ownerGroupBool = ci.m_ownerGroupBool; + + m_ownerUserType = ci.m_ownerUserType; + m_ownerGroupType = ci.m_ownerGroupType; + + m_ownerUserValue = ci.m_ownerUserValue; + m_ownerGroupValue = ci.m_ownerGroupValue; + + m_mapStringsView = ci.m_mapStringsView; + + m_quickSearchString = ci.m_quickSearchString; + m_quickReplaceString = ci.m_quickReplaceString; + + m_recentStringFileList = ci.m_recentStringFileList; + + m_notifyOnErrors = ci.m_notifyOnErrors; + + return (*this); +} + +//ResultViewEntry Class +ResultViewEntry::ResultViewEntry(QString nkey, QString ndata, bool regexp, bool caseSensitive) +{ + m_caseSensitive = caseSensitive; + m_regexp = regexp; + + if(regexp) + { + m_rxKey = QRegExp("("+nkey+")", caseSensitive, false); + } + else + { + m_key = nkey; + } + m_data = ndata; + m_matchedStringsOccurrence = 0; + m_pos = 0; +} + +int ResultViewEntry::lineNumber(const QString& line) const +{ + return line.mid(0,m_pos).contains('\n')+1; +} + +int ResultViewEntry::columnNumber(const QString& line) const +{ + return(m_pos - line.findRev('\n',m_pos)); +} + +void ResultViewEntry::incOccurrences() +{ + m_matchedStringsOccurrence++; +} + +int ResultViewEntry::occurrences() const +{ + return m_matchedStringsOccurrence; +} + +bool ResultViewEntry::regexp()const +{ + return m_regexp; +} + +int ResultViewEntry::pos(const QString& line) +{ + if(m_regexp) + m_pos = m_rxKey.search(line,m_pos); + else + m_pos = line.find(m_key, m_pos, m_caseSensitive); + + return m_pos; +} + +void ResultViewEntry::incPos() +{ + int kl = keyLength(), + dl = dataLength(); + + if(kl < dl) + m_pos += kl; + else + m_pos += dl; + +} + +QString ResultViewEntry::capturedText(const QString& line) +{ + QString cap; + + if(m_regexp) + cap = m_rxKey.cap(1); + else + cap =line.mid(m_pos,m_key.length()); + + return cap; +} + +QString ResultViewEntry::message(const QString& capturedText, int x, int y) const +{ + QString data = m_data; + //return i18n(" captured text \"%1\" replaced with \"%2\" at line: %3, column: %4 ").arg(capturedText).arg(data).arg(QString::number(x,10)).arg(QString::number(y,10)); + return i18n(" Line:%3,Col:%4 - \"%1\" -> \"%2\"").arg(capturedText).arg(data).arg(QString::number(x,10)).arg(QString::number(y,10)); +} + +int ResultViewEntry::keyLength() const +{ + if(m_regexp) + return m_rxKey.matchedLength(); + else + return m_key.length(); +} + +int ResultViewEntry::dataLength() const +{ + return m_data.length(); +} + +void ResultViewEntry::updateLine(QString& line) +{ + line.insert(m_pos, m_data); + line.remove(m_pos + dataLength(), keyLength()); +} diff --git a/kfilereplace/configurationclasses.h b/kfilereplace/configurationclasses.h new file mode 100644 index 00000000..82bff991 --- /dev/null +++ b/kfilereplace/configurationclasses.h @@ -0,0 +1,165 @@ +/*************************************************************************** + configurationclasses.h - description + ------------------- + begin : Sat Apr 17 2004 + copyright : (C) 2004 Emiliano Gulmini + email : + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +#ifndef CONFIGURATIONCLASSES_H +#define CONFIGURATIONCLASSES_H + +// QT +#include +#include +#include +#include +#include + +typedef QMap KeyValueMap; +// entry strings in the kfilereplacerc file +const QString rcDirectoriesList = "Directories list"; +const QString rcFiltersList = "Filters list"; +const QString rcRecentFiles = "Recent files"; +const QString rcAllStringsMustBeFound = "All strings must be found"; +const QString rcEncoding = "Encoding"; +const QString rcCaseSensitive = "Case sensitive"; +const QString rcConfirmStrings = "Confirm strings"; +const QString rcConfirmFiles = "Confirm files"; +const QString rcConfirmDirs = "Confirm directories"; +const QString rcFollowSymLinks = "Follow symbolic links"; +const QString rcHaltOnFirstOccur = "Halt on first occurrence"; +const QString rcIgnoreHidden = "Ignore hidden files"; +const QString rcRecursive = "Search/replace in sub folders"; +const QString rcVariables = "Enable variables"; +const QString rcRegularExpressions = "Enable regular expressions"; +const QString rcMinFileSize = "Minimum file size"; +const QString rcMaxFileSize = "Maximum file size"; +const QString rcValidAccessDate = "Access mode"; +const QString rcMinDate = "Minimum access date"; +const QString rcMaxDate = "Maximum access date"; +const QString rcOwnerUser = "Owner user filters"; +const QString rcOwnerGroup = "Owner group filters"; +const QString rcSearchMode = "Search only mode"; +const QString rcBackupExtension = "Backup file extension"; +const QString rcIgnoreFiles = "Ignore files if there is no match"; +const QString rcNotifyOnErrors = "NotifyOnErrors"; +const QString rcAskConfirmReplace = "Ask confirmation on replace"; +const QString rcDontAskAgain = "Dont ask again"; +// Default configuration options +const QString EncodingOption = "utf8"; +const bool RecursiveOption = true; +const bool CaseSensitiveOption = false; +const bool FollowSymbolicLinksOption = false; +const bool RegularExpressionsOption = false; +const bool VariablesOption = false; +const bool StopWhenFirstOccurenceOption = false; +const bool IgnoreHiddenOption = false; +const int FileSizeOption = -1; +const QString AccessDateOption="unknown"; +const QString ValidAccessDateOption="unknown"; +const QString OwnerOption="false,Name,Equals To"; +const bool SearchModeOption=true; +const QString BackupExtensionOption="false,~"; +const bool IgnoreFilesOption = true; +const bool NotifyOnErrorsOption = false; +const bool AskConfirmReplaceOption = false; + +// This class store configuration informations +class RCOptions +{ + public: + bool m_callResetActions; + + bool m_askConfirmReplace, + m_dontAskAgain; + + QStringList m_directories; + QStringList m_filters; + QString m_currentDirectory; + + int m_minSize, + m_maxSize; + + QString m_dateAccess, + m_minDate, + m_maxDate; + + QString m_encoding; + + bool m_caseSensitive, + m_recursive, + m_followSymLinks, + m_allStringsMustBeFound, + m_backup, + m_regularExpressions; + + bool m_variables, + m_haltOnFirstOccur, + m_ignoreHidden, + m_simulation, + m_searchingOnlyMode; + + bool m_ownerUserIsChecked, + m_ownerGroupIsChecked; + + QString m_ownerUserType, + m_ownerGroupType, + m_ownerUserValue, + m_ownerGroupValue, + m_ownerUserBool, + m_ownerGroupBool; + + QString m_backupExtension; + + bool m_ignoreFiles; + + KeyValueMap m_mapStringsView; + + QString m_quickSearchString, + m_quickReplaceString; + + QStringList m_recentStringFileList; + + bool m_notifyOnErrors; + + public: + RCOptions(); + RCOptions& operator=(const RCOptions& ci); +}; + +class ResultViewEntry +{ + private: + QString m_key; + QString m_data; + QRegExp m_rxKey; + bool m_regexp; + bool m_caseSensitive; + int m_pos; + int m_matchedStringsOccurrence; + + public: + ResultViewEntry(QString nkey, QString ndata, bool regexp, bool caseSensitive); + int lineNumber(const QString& line) const ; + int columnNumber(const QString& line) const ; + void incOccurrences(); + int occurrences() const ; + bool regexp()const ; + int pos(const QString& line) ; + void incPos(); + QString capturedText(const QString& line) ; + QString message(const QString& capturedText, int x, int y) const; + int keyLength() const; + int dataLength() const; + void updateLine(QString& line); +}; +#endif diff --git a/kfilereplace/configure.in.in b/kfilereplace/configure.in.in new file mode 100644 index 00000000..a7f9ec22 --- /dev/null +++ b/kfilereplace/configure.in.in @@ -0,0 +1,12 @@ +#MIN_CONFIG + +AM_INIT_AUTOMAKE(kfilereplace, 0.8.0) + +dnl These are common macros that you might or might not want to use + +dnl Checks for header files. +AC_HEADER_DIRENT +AC_HEADER_STDC +AC_HEADER_TIME +AC_CHECK_HEADERS(fcntl.h sys/time.h unistd.h stdlib.h paths.h) +AC_CHECK_FUNCS(usleep) diff --git a/kfilereplace/hi22-app-kfilereplace.png b/kfilereplace/hi22-app-kfilereplace.png new file mode 100644 index 00000000..429a3984 Binary files /dev/null and b/kfilereplace/hi22-app-kfilereplace.png differ diff --git a/kfilereplace/hi32-app-kfilereplace.png b/kfilereplace/hi32-app-kfilereplace.png new file mode 100644 index 00000000..8dff2abb Binary files /dev/null and b/kfilereplace/hi32-app-kfilereplace.png differ diff --git a/kfilereplace/hi48-app-kfilereplace.png b/kfilereplace/hi48-app-kfilereplace.png new file mode 100644 index 00000000..c11f34ba Binary files /dev/null and b/kfilereplace/hi48-app-kfilereplace.png differ diff --git a/kfilereplace/kaddstringdlg.cpp b/kfilereplace/kaddstringdlg.cpp new file mode 100644 index 00000000..44b51f30 --- /dev/null +++ b/kfilereplace/kaddstringdlg.cpp @@ -0,0 +1,273 @@ +/*************************************************************************** + KAddStringDlg.cpp - description + ------------------- + begin : Sat Oct 16 1999 + copyright : (C) 1999 by François Dupoux + (C) 2004 Emiliano Gulmini + email : dupoux@dupoux.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +// QT +#include +#include +#include +#include +#include +#include +#include + +// KDE +#include +#include +#include +#include +#include + +// local +#include "kaddstringdlg.h" +#include "whatthis.h" + +using namespace whatthisNameSpace; + +KAddStringDlg::KAddStringDlg(RCOptions* info, bool wantEdit, QWidget *parent, const char *name) : KAddStringDlgS(parent,name,true) +{ + m_option = info; + m_wantEdit = wantEdit; + m_currentMap = m_option->m_mapStringsView; + + initGUI(); + + connect(m_pbOK, SIGNAL(clicked()), this, SLOT(slotOK())); + connect(m_rbSearchOnly, SIGNAL(pressed()), this, SLOT(slotSearchOnly())); + connect(m_rbSearchReplace, SIGNAL(pressed()), this, SLOT(slotSearchReplace())); + connect(m_pbAdd, SIGNAL(clicked()), this, SLOT(slotAddStringToView())); + connect(m_pbDel, SIGNAL(clicked()), this, SLOT(slotDeleteStringFromView())); + connect(m_pbHelp, SIGNAL(clicked()), this ,SLOT(slotHelp())); + + whatsThis(); +} + +//PRIVATE +void KAddStringDlg::initGUI() +{ + m_pbAdd->setIconSet(SmallIconSet(QString::fromLatin1("forward"))); + m_pbDel->setIconSet(SmallIconSet(QString::fromLatin1("back"))); + + m_stack->addWidget(m_stringView); + m_stack->addWidget(m_stringView_2); + + + if(m_option->m_searchingOnlyMode) + { + if(m_wantEdit) + m_rbSearchReplace->setEnabled(false); + m_rbSearchOnly->setChecked(true); + m_edSearch->setEnabled(true); + m_edReplace->setEnabled(false); + m_tlSearch->setEnabled(true); + m_tlReplace->setEnabled(false); + } + else + { + if(m_wantEdit) + m_rbSearchOnly->setEnabled(false); + m_rbSearchReplace->setChecked(true); + m_edSearch->setEnabled(true); + m_edReplace->setEnabled(true); + m_tlSearch->setEnabled(true); + m_tlReplace->setEnabled(true); + } + + raiseView(); + + if(m_wantEdit) + loadMapIntoView(); +} + +void KAddStringDlg::eraseViewItems() +{ + QListViewItem* item = m_sv->firstChild(); + if(item == 0) + return; + else + { + while(item) + { + QListViewItem* tempItem = item; + item = item->nextSibling(); + delete tempItem; + } + } +} + +void KAddStringDlg::raiseView() +{ + if(m_option->m_searchingOnlyMode) + m_sv = m_stringView_2; + else + m_sv = m_stringView; + + m_stack->raiseWidget(m_sv); +} + +bool KAddStringDlg::columnContains(QListView* lv,const QString& s, int column) +{ + QListViewItem* i = lv->firstChild(); + while (i != 0) + { + if(i->text(column) == s) + return true; + i = i->nextSibling(); + } + return false; +} + +void KAddStringDlg::saveViewContentIntoMap() +{ + QListViewItem* i = m_sv->firstChild(); + while(i != 0) + { + if(m_option->m_searchingOnlyMode) + m_currentMap[i->text(0)] = QString::null; + else + m_currentMap[i->text(0)] = i->text(1); + i = i->nextSibling(); + } +} + +void KAddStringDlg::loadMapIntoView() +{ + KeyValueMap::Iterator itMap; + + for (itMap = m_currentMap.begin(); itMap != m_currentMap.end(); ++itMap) + { + QListViewItem* temp = new QListViewItem(m_sv); + temp->setText(0,itMap.key()); + if(!m_option->m_searchingOnlyMode) + temp->setText(1,itMap.data()); + } +} + +void KAddStringDlg::whatsThis() +{ + QWhatsThis::add(m_rbSearchOnly, rbSearchOnlyWhatthis); + QWhatsThis::add(m_rbSearchReplace, rbSearchReplaceWhatthis); + QWhatsThis::add(m_edSearch, edSearchWhatthis); + QWhatsThis::add(m_edReplace, edReplaceWhatthis); +} + +//PRIVATE SLOTS +void KAddStringDlg::slotOK() +{ + m_option->m_mapStringsView = m_currentMap; + + accept(); +} + +void KAddStringDlg::slotSearchOnly() +{ + m_option->m_searchingOnlyMode = true; + + m_rbSearchOnly->setChecked(true); + m_edSearch->setEnabled(true); + m_edReplace->setEnabled(false); + m_tlSearch->setEnabled(true); + m_tlReplace->setEnabled(false); + + //sets the right view appearance + raiseView(); + //empties the view content + eraseViewItems(); +} + +void KAddStringDlg::slotSearchReplace() +{ + m_option->m_searchingOnlyMode = false; + + m_rbSearchReplace->setChecked(true); + m_edSearch->setEnabled(true); + m_edReplace->setEnabled(true); + m_tlSearch->setEnabled(true); + m_tlReplace->setEnabled(true); + + //sets the right view appearance + raiseView(); + //empties the view content + eraseViewItems(); +} + +void KAddStringDlg::slotAddStringToView() +{ + if(m_option->m_searchingOnlyMode) + { + QString text = m_edSearch->text(); + if(!(text.isEmpty() || columnContains(m_sv, text, 0))) + { + QListViewItem* lvi = new QListViewItem(m_sv); + lvi->setMultiLinesEnabled(true); + lvi->setText(0,text); + m_currentMap[text] = QString::null; + m_edSearch->clear(); + } + } + else + { + QString searchText = m_edSearch->text(), + replaceText = m_edReplace->text(); + + if(!(searchText.isEmpty() || replaceText.isEmpty() || columnContains(m_sv,searchText,0) || columnContains(m_sv,replaceText,1))) + { + QListViewItem* lvi = new QListViewItem(m_sv); + lvi->setMultiLinesEnabled(true); + lvi->setText(0,searchText); + m_edSearch->clear(); + lvi->setText(1,replaceText); + m_currentMap[searchText] = replaceText; + m_edReplace->clear(); + } + } +} + +void KAddStringDlg::slotDeleteStringFromView() +{ + // Choose current item or selected item + QListViewItem* currentItem = m_sv->currentItem(); + + // Do nothing if list is empty + if(currentItem == 0) + return; + + m_currentMap.remove(currentItem->text(0)); + + if(m_option->m_searchingOnlyMode) + { + m_edSearch->setText(currentItem->text(0)); + m_edReplace->clear(); + //currentItem->setText(1,m_edReplace->text()); + } + else + { + m_edSearch->setText(currentItem->text(0)); + m_edReplace->setText(currentItem->text(1)); + } + + delete currentItem; + + currentItem = 0; +} + +void KAddStringDlg::slotHelp() +{ + kapp->invokeHelp(QString::null, "kfilereplace"); +} + +#include "kaddstringdlg.moc" + diff --git a/kfilereplace/kaddstringdlg.h b/kfilereplace/kaddstringdlg.h new file mode 100644 index 00000000..f51e7f77 --- /dev/null +++ b/kfilereplace/kaddstringdlg.h @@ -0,0 +1,75 @@ +/*************************************************************************** + KAddStringDlg.h - description + ------------------- + begin : Sat Oct 16 1999 + copyright : (C) 1999 by François Dupoux + (C) 2004 Emiliano Gulmini + email : dupoux@dupoux.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KADDSTRINGDLG_H +#define KADDSTRINGDLG_H + +// local +#include "kaddstringdlgs.h" +#include "configurationclasses.h" +/** + * This is the dialog used to add a list of searching/replacing strings + */ +class KAddStringDlg : public KAddStringDlgS +{ + Q_OBJECT + private: + RCOptions* m_option; + QListView* m_sv; + KeyValueMap m_currentMap; + bool m_wantEdit; + + public: //Constructors + KAddStringDlg(RCOptions* info, bool wantEdit, QWidget *parent=0, const char *name=0); + + private slots: + void slotOK(); + void slotSearchOnly(); + void slotSearchReplace(); + void slotAddStringToView(); + void slotDeleteStringFromView(); + void slotHelp(); + + private: + /** + * inits... the GUI :-) + */ + void initGUI(); + /** + * Deletes all the items of the view + */ + void eraseViewItems(); + /** + * Deletes all the items of the map + */ + void clearMap() { KeyValueMap m; m_option->m_mapStringsView = m; } + /** + * The view is actually a stack widget that contains two different views widget + */ + void raiseView(); + /** + * Verifies whether 'lv' contains 's' + */ + bool columnContains(QListView* lv,const QString& s, int column); + void saveViewContentIntoMap(); + void loadMapIntoView(); + void whatsThis(); +}; + +#endif // KADDSTRINGDLG_H + diff --git a/kfilereplace/kaddstringdlgs.ui b/kfilereplace/kaddstringdlgs.ui new file mode 100644 index 00000000..6685e92f --- /dev/null +++ b/kfilereplace/kaddstringdlgs.ui @@ -0,0 +1,426 @@ + +KAddStringDlgS + + + KAddStringDlgS + + + + 0 + 0 + 586 + 347 + + + + Insert Searching/Replacing Strings + + + true + + + + unnamed + + + + layout14 + + + + unnamed + + + + bgChoose + + + Choose String Adding Mode + + + true + + + + unnamed + + + + m_rbSearchReplace + + + Search and replace mode + + + + + + + + m_rbSearchOnly + + + Search only mode + + + true + + + + + + + frame4 + + + StyledPanel + + + Raised + + + + unnamed + + + + layout11 + + + + unnamed + + + + layout13 + + + + unnamed + + + + m_tlSearch + + + Search for: + + + + + m_edSearch + + + PlainText + + + + + + + layout14 + + + + unnamed + + + + m_tlReplace + + + false + + + Replace with: + + + + + m_edReplace + + + false + + + PlainText + + + AutoAll + + + + + + + + + layout16 + + + + unnamed + + + + spacer8 + + + Vertical + + + Expanding + + + + 20 + 90 + + + + + + layout15 + + + + unnamed + + + + m_pbDel + + + + 30 + 32767 + + + + + + + + + m_pbAdd + + + + 30 + 32767 + + + + + + + false + + + + + + + spacer9 + + + Vertical + + + Expanding + + + + 20 + 90 + + + + + + + + m_stack + + + + 7 + 7 + 0 + 0 + + + + + WStackPage + + + 0 + + + + unnamed + + + 0 + + + + + Search For + + + true + + + true + + + + m_stringView_2 + + + true + + + false + + + AllColumns + + + + + + + WStackPage + + + 1 + + + + unnamed + + + 0 + + + + + Search For + + + true + + + true + + + + + Replace With + + + true + + + true + + + + m_stringView + + + true + + + false + + + AllColumns + + + + + + + + + + layout2 + + + + unnamed + + + + m_pbHelp + + + true + + + &Help + + + + + spacer1 + + + Horizontal + + + Expanding + + + + 90 + 20 + + + + + + layout1 + + + + unnamed + + + + m_pbOK + + + &OK + + + + + m_pbCancel + + + &Cancel + + + + + + + + + + + + + m_pbCancel + clicked() + KAddStringDlgS + reject() + + + + diff --git a/kfilereplace/kfilereplace.cpp b/kfilereplace/kfilereplace.cpp new file mode 100644 index 00000000..a6ade0fe --- /dev/null +++ b/kfilereplace/kfilereplace.cpp @@ -0,0 +1,111 @@ +/*************************************************************************** + kfilereplace.cpp - KFileReplace shell implementation + ------------------- + begin : Thu Sep 16 14:14:09 2004 + copyright : (C) 2004 by Andras Mantia + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +//kde includes +#include +#include +#include +#include +#include + +//app includes +#include "kfilereplace.h" + +KFileReplace::KFileReplace() + : KParts::MainWindow(0L, "KFileReplace") +{ + KLibFactory *factory = KLibLoader::self()->factory("libkfilereplacepart"); + if (factory) + { + m_part = static_cast(factory->create(this, + "kfilereplace_part", "KParts::ReadOnlyPart" )); + + if (m_part) + { + setCentralWidget(m_part->widget()); + KStdAction::quit(this, SLOT(close()), actionCollection()); + KStdAction::keyBindings(this, SLOT(slotConfigureKeys()), actionCollection()); + KStdAction::configureToolbars(this, SLOT(slotConfigureToolbars()), actionCollection()); + setStandardToolBarMenuEnabled(true); + createGUI(m_part); + removeDuplicatedActions(); + } + } + else + { + KMessageBox::error(this, i18n("Could not find the KFileReplace part.")); + close(); + return; + } +} + + +KFileReplace::~KFileReplace() +{ +} + +void KFileReplace::openURL(const KURL &url) +{ + m_part->openURL(url); +} + +void KFileReplace::slotConfigureKeys() +{ + KKeyDialog dlg( false, this ); + QPtrList clients = guiFactory()->clients(); + for( QPtrListIterator it( clients ); + it.current(); ++it ) + { + dlg.insert( (*it)->actionCollection() ); + } + dlg.configure(); +} + +void KFileReplace::slotConfigureToolbars() +{ + saveMainWindowSettings(KGlobal::config(), autoSaveGroup()); + KEditToolbar dlg(factory()); + connect(&dlg, SIGNAL(newToolbarConfig()), + this, SLOT(applyNewToolbarConfig())); + dlg.exec(); +} + +void KFileReplace::applyNewToolbarConfig() +{ + applyMainWindowSettings(KGlobal::config(), autoSaveGroup()); +} + + +void KFileReplace::removeDuplicatedActions() +{ + KActionCollection* part_action_collection = m_part->actionCollection(); + KAction* part_about_action = part_action_collection->action("help_about_kfilereplace"); + KAction* part_report_action = part_action_collection->action("report_bug"); + KAction* part_help_action= part_action_collection->action("help_kfilereplace"); + + if (!part_about_action || !part_report_action || !part_help_action || !part_action_collection) + return; + + QWidget* container = part_about_action->container(0); + part_about_action->unplug(container); + part_report_action->unplug(container); + part_help_action->unplug(container); + part_action_collection->remove(part_about_action); + part_action_collection->remove(part_report_action); + part_action_collection->remove(part_help_action); +} + +#include "kfilereplace.moc" diff --git a/kfilereplace/kfilereplace.desktop b/kfilereplace/kfilereplace.desktop new file mode 100644 index 00000000..0e01c478 --- /dev/null +++ b/kfilereplace/kfilereplace.desktop @@ -0,0 +1,55 @@ +[Desktop Entry] +Name=KFileReplace +Name[hi]=कà‡-à¤Ğà¤ĵà¤à¤‡à¤²-à¤°à¤żà¤Şàà¤²à‡à¤¸ +Name[ne]=à¤Ĵà¤Ĥलàà¤¨à‡ कà‡à¤Ħà€à¤ˆ à¤Ğà¤à¤‡à¤² +Name[pa]=ਕà݇-à¨Ğà¨à¨‡à¨²-à¨Ĵà¨Ĥਲàİ‹ +Name[sk]=KFile zameniĊ +Name[sv]=Kfilereplace +Name[ta]=Kà•àŻ‹àŞàŻàŞàŻ à‡àŸàààħàŻàħàŻ +Name[tg]=K¤°ığр Ò·ı³Ñƒ·Ñ€ ş°Ñ€´°½ +Name[tr]=K Dosya DeğiĊŸtirme +Exec=kfilereplace %i %m -caption "%c" +Icon=kfilereplace +Type=Application +DocPath=kfilereplace/index.html +Terminal=false +GenericName=Search & Replace Tool +GenericName[bg]=˘ÑŠÑ€Ñµ½µ ¸ ·°ĵя½° +GenericName[br]=Ostilh klask hag erlec'hiaħ +GenericName[ca]=Eina cerca i substitueix +GenericName[cs]=NĦstroj pro vyhledĦn­ a nahrazen­ +GenericName[da]=S¸g og erstat-vĤrkt¸j +GenericName[de]=Suchen & Ersetzen Werkzeug +GenericName[el]=ΕργÎħÎğείο ÎħνÎħÎĥÎτησης & ÎħντÎıÎşÎħτÎĴστÎħσης +GenericName[es]=Herramienta de bşsqueda y reemplazo +GenericName[et]=Otsimise ja asendamise tĥĥriist +GenericName[eu]=Bilaketa eta ordezkapen tresna +GenericName[fa]=Ĝ§Ĝ¨Ĝ²Ĝ§Ĝħ ĜĴĜ³ĜŞĜĴو و ĜĴĜ§ÛŒÚŻĜ²ÛŒÙ†ÛŒ +GenericName[fi]=Etsi & korvaa tyĥkalu +GenericName[fr]=Outil de recherche et de remplacement +GenericName[gl]=Ferramenta de busca e reemprazo +GenericName[hu]=FĦjlkeresĊ‘ +GenericName[is]=T³l til a° leita a° texta og skipta şt +GenericName[it]=Strumento di ricerca e sostituzione +GenericName[ja]=ĉ¤œç´˘Š‚ˆ³ç½ĉ›ƒ„ƒĵƒĞ +GenericName[ka]=áƒĞიებიáƒĦ და áƒİანაცვლებიáƒĦ áƒáƒ”ლáƒĦაáƒĴყო +GenericName[lt]=PaieĊĦkos ir keitimo ÄŻrankis +GenericName[ms]=Alatan Cari & Ganti +GenericName[nds]=Sĥĥk- un Utwesselwarktĵĵch +GenericName[ne]=खà‹à¤œà€ गरàà¤¨à‡ र à¤Ĵà¤Ĥलàà¤¨à‡ à¤‰à¤Şà¤°à¤•à¤°à¤£ +GenericName[nl]=Gereedschap voor zoeken en vervangen +GenericName[pa]=ਖà݋ਜ ਅਤà݇ ਤà¨Ĵà¨Ĥà݀ਲ ਸàİ°à¨Ĥ +GenericName[pl]=Narzędzie do wyszukiwania i zamiany +GenericName[pt]=Ferramenta de Procura e Substitui§£o +GenericName[pt_BR]=Ferramenta de Procura & Substitui§£o +GenericName[ru]=Ÿ¸Ñş ¸ ·°ĵµ½° +GenericName[sk]=NĦjsĊ a zameniĊ +GenericName[sl]=Orodje za iskanje in zamenjavo +GenericName[sr]=ğ°Ñ‚ ·° żÑ€µÑ‚Ñ€°³Ñƒ ¸ ·°ĵµ½Ñƒ +GenericName[sr@Latn]=Alat za pretragu i zamenu +GenericName[sv]=Sĥk- och ers¤ttningsverktyg +GenericName[uk]=—°ÑÑ–ħ żÑˆÑƒşÑƒ т° ·°ĵі½¸ +GenericName[zh_CN]=ĉœç´˘ĉ›żĉ˘ċ·ċ…· +GenericName[zh_HK]=ĉœċ°‹ċŠċ–äğ£ċ·ċ…· +GenericName[zh_TW]=ĉœċ°‹ċŠċ–äğ£ċ·ċ…· +Categories=Qt;KDE;Utility;X-KDE-Utilities-File; diff --git a/kfilereplace/kfilereplace.h b/kfilereplace/kfilereplace.h new file mode 100644 index 00000000..2d65d0ed --- /dev/null +++ b/kfilereplace/kfilereplace.h @@ -0,0 +1,45 @@ +/*************************************************************************** + kfilereplace.h - KFileReplace header + ------------------- + begin : Thu Sep 16 14:14:09 2004 + copyright : (C) 2004 by Andras Mantia + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +#ifndef KFILEREPLACE_H +#define KFILEREPLACE_H + +#include + +/** +Shell application for the KFileReplace part. + +@author Andras Mantia +*/ +class KFileReplace : public KParts::MainWindow +{ + Q_OBJECT +public: + KFileReplace(); + ~KFileReplace(); + void openURL(const KURL &url); + +private slots: + void slotConfigureKeys(); + void slotConfigureToolbars(); + void applyNewToolbarConfig(); + +private: + void removeDuplicatedActions(); + + KParts::ReadOnlyPart *m_part; +}; + +#endif diff --git a/kfilereplace/kfilereplace.kdevelop b/kfilereplace/kfilereplace.kdevelop new file mode 100644 index 00000000..96834aae --- /dev/null +++ b/kfilereplace/kfilereplace.kdevelop @@ -0,0 +1,190 @@ + + + + + + $VERSION$ + KDevKDEAutoProject + C++ + + Qt + KDE + + . + false + + + + kdevcvsservice + + + + + + + + + false + false + + + false + false + *.o,*.lo,CVS + + + + + ada + ada_bugs_gcc + bash + bash_bugs + clanlib + fortran_bugs_gcc + gnome1 + gnustep + gtk + gtk_bugs + haskell + haskell_bugs_ghc + java_bugs_gcc + java_bugs_sun + opengl + pascal_bugs_fp + php + php_bugs + perl + perl_bugs + python + python_bugs + ruby + ruby_bugs + sdl + stl + sw + w3c-dom-level2-html + w3c-svg + w3c-uaag10 + wxwidgets_bugs + + + qmake User Guide + + + + + libtool + + + + + + true + false + false + + + false + true + 10 + + + + + + + + + + + + + + + + + true + 1 + false + + 0 + + + build + / + kfilereplace/kfilereplace + + false + true + + + + default + kfilereplace + + + + + + + --enable-debug=full --prefix=/opt/kde3 --enable-editors + /home/andris/development/build/kde-head/kdewebdev + /home/andris/development/sources/kde-head/kdewebdev + -DKDE_NO_COMPAT -DQT_NO_COMPAT -DDEBUG_PARSER + + kdevgccoptions + kdevgppoptions + kdevpgf77options + + + + + + + + + + + + .h + .cpp + + + + + true + true + true + false + true + true + true + 250 + 400 + 250 + + + + + set + m_,_ + theValue + true + true + + + + + + + + + + + true + true + true + true + -C + + diff --git a/kfilereplace/kfilereplaceiface.h b/kfilereplace/kfilereplaceiface.h new file mode 100644 index 00000000..ab7348d2 --- /dev/null +++ b/kfilereplace/kfilereplaceiface.h @@ -0,0 +1,30 @@ +/*************************************************************************** + kfilereplaceif.h - description + ------------------- + copyright : (C) 1999 by François Dupoux + (C) 2003 Andras Mantia + email : dupoux@dupoux.com, amantia@kde.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +#ifndef KFILEREPLACEIFACE_H +#define KFILEREPLACEIFACE_H + +#include + +class KFileReplaceIface : virtual public DCOPObject +{ + K_DCOP + +k_dcop: + virtual void openURL(const QString& url) = 0; +}; + +#endif // KFILEREPLACEIFACE_H diff --git a/kfilereplace/kfilereplacelib.cpp b/kfilereplace/kfilereplacelib.cpp new file mode 100644 index 00000000..e57a3a84 --- /dev/null +++ b/kfilereplace/kfilereplacelib.cpp @@ -0,0 +1,381 @@ +/*************************************************************************** + kfilereplacelib.cpp - File library + ------------------- + begin : lun mai 3 20:19:52 CEST 1999 + + copyright : (C) 1999 by François Dupoux + (C) 2003 Andras Mantia + (C) 2004 Emiliano Gulmini + email : dupoux@dupoux.com + + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +//QT +#include +#include +#include +#include + +//KDE +#include +#include +#include +#include + +//needed for malloc/free +#include + +// local +#include "kfilereplacelib.h" + +const double kilo = 1024.0; +const double mega = 1048576.0;//1024^2 +const double giga = 1073741824.0;//1024^3 +const double tera = 1099511627776.0;//1024^4 + +/** + Format a path, from a path and a filename, or another sub-path (avoid double '/' risks) + Parameters::.....* basePath: fist path (can be "/" if root, or "/usr/bin/" or "/usr/bin" for example) + .................* fileName: second path (can be "/doc/html/", or "doc/html/" or "doc/html/index.html" for example) + Return values:...* Full valid path (without double "/") +*/ +QString KFileReplaceLib::formatFullPath(const QString& basePath, const QString &fileName) +{ + QString fullPath = basePath; + QString fname = fileName; + + if (fname.startsWith("/")) // skip beginning '/' + fname = fname.remove(0,1); + + if (fullPath.endsWith("/")) + fullPath.append(fname); + else + fullPath.append("/"+fname); + + return fullPath; +} + +/** + Add an extension to a filename, or a filepath + Parameters::.....* fileName: filename or filepath (it can have already the extension) + .................* extension: extension to add without "." (ex: "html", "kfr") + Return values:...* Filename / Filepath with the extension +*/ +QString KFileReplaceLib::addExtension(const QString& fileName, const QString& extension) +{ + QString fullExtension = "."; + QString fname = fileName; + + fullExtension.append(extension); + + // filename cannot contain ".ext" ==> Add it + if(fname.length() <= fullExtension.length()) + fname.append(fullExtension); + else // filename can contain ".ext" + { + if (fname.right(fullExtension.length()) != fullExtension) + fname.append(fullExtension); + } + + return fname; +} + +QString KFileReplaceLib::formatFileSize(double size) +{ + QString stringSize; + + if(size < kilo) + { + const int asInt = (int) size; + stringSize = i18n("1 byte", "%n bytes", asInt); + } + else + if(size >= kilo && size < mega) + { + double d = size / kilo; + stringSize = i18n("%1 KB").arg(QString::number(d,'f',2)); + } + else + if(size >= mega && size < giga) + { + double d = size / mega; + stringSize = i18n("%1 MB").arg(QString::number(d,'f',2)); + } + else + if(size >= giga) + { + double d = size / giga; + stringSize = i18n("%1 GB").arg(QString::number(d,'f',2)); + } + return stringSize; +} + +void KFileReplaceLib::convertOldToNewKFRFormat(const QString& fileName, KListView* stringView) +{ + //this method convert old format in new XML-based format + typedef struct + { + char pgm[13]; // Must be "KFileReplace" : like MZ for EXE files + int stringNumber; // Number of strings in file + char reserved[64]; // Reserved for future use + } KFRHeader; + + KFRHeader head; + + FILE* f = fopen(fileName.ascii(),"rb"); + int err = fread(&head, sizeof(KFRHeader), 1, f); + QString pgm(head.pgm); + + if(!f || (err != 1) || (pgm != "KFileReplace")) + { + KMessageBox::error(0, i18n("Cannot open the file %1 and load the string list. This file seems not to be a valid old kfr file or it is broken.").arg(fileName)); + return ; + } + + stringView->clear(); + + int oldTextSize, + newTextSize, + errors = 0, + stringSize; + QStringList l; + + int i ; + for (i=0; i < head.stringNumber; i++) + { + errors += (fread(&oldTextSize, sizeof(int), 1, f)) != 1; + errors += (fread(&newTextSize, sizeof(int), 1, f)) != 1; + if(errors > 0) + KMessageBox::error(0, i18n("Cannot read data.")); + else + { + stringSize = ((oldTextSize > newTextSize) ? oldTextSize : newTextSize) + 2; + char* oldString = (char*) malloc(stringSize+10), + * newString = (char*) malloc(stringSize+10); + memset(oldString, 0, stringSize); + memset(newString,0, stringSize); + if (oldString == 0 || newString == 0) + KMessageBox::error(0, i18n("Out of memory.")); + else + { + if (fread(oldString, oldTextSize, 1, f) != 1) + KMessageBox::error(0, i18n("Cannot read data.")); + else + { + if (newTextSize > 0) // If there is a Replace text + { + if (fread(newString, newTextSize, 1, f) != 1) + KMessageBox::error(0, i18n("Cannot read data.")); + else + { + QListViewItem* lvi = new QListViewItem(stringView); + lvi->setText(0,oldString); + lvi->setText(1,newString); + + if(newString) + free(newString); + if(oldString) + free(oldString); + } + } + } + } + } + } + fclose(f); + return ; + } + +bool KFileReplaceLib::isAnAccessibleFile(const QString& filePath, const QString& fileName, RCOptions* info) +{ + QString bkExt = info->m_backupExtension; + if(fileName == ".." || fileName == "." || (!bkExt.isEmpty() && fileName.right(bkExt.length()) == bkExt)) + return false; + + QFileInfo fi; + if(filePath.isEmpty()) + fi.setFile(fileName); + else + fi.setFile(filePath+"/"+fileName); + + if(fi.isDir()) + return true; + + int minSize = info->m_minSize, + maxSize = info->m_maxSize; + QString minDate = info->m_minDate, + maxDate = info->m_maxDate, + dateAccess = info->m_dateAccess; + + // Avoid files that not match access date requirements + QString last = "unknown"; + if(dateAccess == "Last Writing Access") + last = fi.lastModified().toString(Qt::ISODate); + if(dateAccess == "Last Reading Access") + last = fi.lastRead().toString(Qt::ISODate); + + if(last != "unknown") + { + if(minDate != "unknown" && maxDate != "unknown") + { //If out of range then exit + if((minDate > last) || (maxDate < last)) + return false; + } + else + { + if(minDate != "unknown") + { //If out of range then exit + if(minDate > last) + return false; + } + else + { + if(maxDate != "unknown") + //If out of range then exit + if(maxDate < last) + return false; + } + } + } + // Avoid files that not match size requirements + int size = fi.size(); + if(maxSize != FileSizeOption && minSize != FileSizeOption) + if(size > (maxSize*1024) || size < (minSize*1024)) + return false; + + // Avoid files that not match ownership requirements + if(info->m_ownerUserIsChecked) + { + QString fileOwnerUser; + if(info->m_ownerUserType == "Name") + fileOwnerUser = fi.owner(); + else + fileOwnerUser = QString::number(fi.ownerId(),10); + + if(info->m_ownerUserBool == "Equals To") + { + if(info->m_ownerUserValue != fileOwnerUser) + return false; + } + else + { + if(info->m_ownerUserValue == fileOwnerUser) + return false; + } + } + + if(info->m_ownerGroupIsChecked) + { + QString fileOwnerGroup; + if(info->m_ownerGroupType == "Name") + fileOwnerGroup = fi.group(); + else + fileOwnerGroup = QString::number(fi.groupId(),10); + if(info->m_ownerGroupBool == "Equals To") + { + if(info->m_ownerGroupValue != fileOwnerGroup) + return false; + } + else + { + if(info->m_ownerGroupValue == fileOwnerGroup) + return false; + } + } + + //If we are here then all requirements have been verified + return true; +} + +void KFileReplaceLib::setIconForFileEntry(QListViewItem* item, QString path) +{ + QFileInfo fi(path); + QString extension = fi.extension(), + baseName = fi.baseName(); + + KeyValueMap extensionMap; + + extensionMap["a"] = "binary"; + extensionMap["am"] = "shellscript"; + extensionMap["bz"] = "zip"; + extensionMap["bz2"] = "zip"; + extensionMap["c"] = "source_c"; + extensionMap["cc"] = "source_cpp"; + extensionMap["cpp"] = "source_cpp"; + extensionMap["eml"] = "message"; + extensionMap["exe"] = "exec_wine"; + extensionMap["gz"] = "zip"; + extensionMap["h"] = "source_h"; + extensionMap["htm"] = "html"; + extensionMap["html"] = "html"; + extensionMap["in"] = "shellscript"; + extensionMap["java"] = "source_java"; + extensionMap["jpg"] = "image"; + extensionMap["kfr"] = "html"; + extensionMap["kmdr"] = "widget_doc"; + extensionMap["kwd"] = "kword_kwd"; + extensionMap["log"] = "log"; + extensionMap["moc"] = "source_moc"; + extensionMap["mp3"] = "sound"; + extensionMap["o"] = "source_o"; + extensionMap["pdf"] = "pdf"; + extensionMap["php"] = "source_php"; + extensionMap["py"] = "source_py"; + extensionMap["pl"] = "source_pl"; + extensionMap["p"] = "source_p"; + extensionMap["ps"] = "postscript"; + extensionMap["png"] = "image"; + extensionMap["sa"] = "binary"; + extensionMap["sh"] = "shellscript"; + extensionMap["so"] = "binary"; + extensionMap["tar"] = "tar"; + extensionMap["tex"] = "tex"; + extensionMap["tgz"] = "tgz"; + extensionMap["txt"] = "txt"; + extensionMap["ui"] = "widget_doc"; + extensionMap["uml"] = "umbrellofile"; + extensionMap["wav"] = "sound"; + extensionMap["xml"] = "html"; + extensionMap["xpm"] = "image"; + + KeyValueMap::Iterator itExtensionMap; + + for(itExtensionMap = extensionMap.begin(); itExtensionMap != extensionMap.end(); ++itExtensionMap) + { + if(extension == itExtensionMap.key()) + { + item->setPixmap(0,SmallIcon(itExtensionMap.data())); + return; + } + } + + KeyValueMap baseNameMap; + + baseNameMap["configure"] = "shellscript"; + baseNameMap["core"] = "core"; + baseNameMap["makefile"] = "make"; + baseNameMap["readme"] = "readme"; + baseNameMap["README"] = "readme"; + baseNameMap["Readme"] = "readme"; + baseNameMap["TODO"] = "txt"; + + KeyValueMap::Iterator itBaseNameMap; + + for(itBaseNameMap = baseNameMap.begin(); itBaseNameMap != baseNameMap.end(); ++itBaseNameMap) + { + if(baseName == itBaseNameMap.key()) + { + item->setPixmap(0,SmallIcon(itBaseNameMap.data())); + return; + } + } +} diff --git a/kfilereplace/kfilereplacelib.h b/kfilereplace/kfilereplacelib.h new file mode 100644 index 00000000..e5c14c72 --- /dev/null +++ b/kfilereplace/kfilereplacelib.h @@ -0,0 +1,65 @@ +/*************************************************************************** + kfilereplacelib.h - File library, derived from filelib.h + ------------------- + begin : lun mai 3 20:19:52 CEST 1999 + + copyright : (C) 1999 by François Dupoux + (C) 2003 Andras Mantia + (C) 2004 Emiliano Gulmini + email : dupoux@dupoux.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KFILEREPLACELIB_H +#define KFILEREPLACELIB_H + +// KDE +#include +class KlistView; + +// local +#include "configurationclasses.h" + +class KFileReplaceLib +{ + public: + + /** + Format a path, from a path and a filename, or another sub-path (avoid double '/' risks) + Parameters::.....* basePath: fist path (can be "/" if root, or "/usr/bin/" or "/usr/bin" for example) + .................* filename: second path (can be "/doc/html/", or "doc/html/" or "doc/html/index.html" for example) + Return values:...* Full valid path (without double "/") + */ + static QString formatFullPath(const QString& basePath, const QString& fileName); + + /** + Add an extension to a filename, or a filepath + Parameters::.....* filename: filename or filepath (it can have already the extension) + .................* extension: extension to add without "." (ex: "html", "kfr") + Return values:...* Filename / Filepath with the extension + */ + static QString addExtension(const QString& fileName, const QString& extension); + + static QString formatFileSize(double size); + + /** + converts the old kfr format file in the new xml-based format. + */ + static void convertOldToNewKFRFormat(const QString& fileName, KListView* stringView); + /** + Verifies that files, which we are scanning, respect some + conditions + */ + static bool isAnAccessibleFile(const QString& filePath, const QString& fileName, RCOptions* info); + + static void setIconForFileEntry(QListViewItem* item, QString path); +}; +#endif // KFILEREPLACEFILELIB_H diff --git a/kfilereplace/kfilereplacepart.cpp b/kfilereplace/kfilereplacepart.cpp new file mode 100644 index 00000000..9e0be192 --- /dev/null +++ b/kfilereplace/kfilereplacepart.cpp @@ -0,0 +1,1679 @@ +// +// +// C++ Implementation: kfilereplacepart +// +// Description: +// +// +// Author: Andras Mantia , (C) 2003 +// Maintainer: Emiliano Gulmini , (C) 2004 +// +// Copyright: GPL v2. See COPYING file that comes with this distribution +// +// + +// QT +#include +#include +#include +#include +#include + +// KDE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// local +#include "kfilereplacelib.h" +#include "kfilereplacepart.h" +#include "kfilereplaceview.h" +#include "koptionsdlg.h" +#include "knewprojectdlg.h" +#include "report.h" +#include "commandengine.h" +#include "whatthis.h" + +using namespace whatthisNameSpace; + +//PUBLIC CONSTRUCTORS +// Factory code for KDE 3 +typedef KParts::GenericFactory FileReplaceFactory; + +K_EXPORT_COMPONENT_FACTORY( libkfilereplacepart, FileReplaceFactory ) + +KFileReplacePart::KFileReplacePart(QWidget* parentWidget, const char* , QObject* parent, const char* name, const QStringList & ) : KParts::ReadOnlyPart(parent,name) +{ + setInstance(FileReplaceFactory::instance()); + KGlobal::locale()->insertCatalogue("kfilereplace"); + m_parentWidget = parentWidget; + m_config = new KConfig("kfilereplacerc"); + m_aboutDlg = 0; + m_stop = false; + m_optionMask = QDir::Files; + m_w = widget(); + m_option = 0; + + loadOptionsFromRC(); + initView(); + initGUI(); + + whatsThis(); +} + +KFileReplacePart::~KFileReplacePart() +{ + m_view = 0; //it's already deleted, so set it to NULL + + saveOptionsToRC(); + + delete m_aboutDlg; + m_aboutDlg = 0; + delete m_config; + m_config = 0; + delete m_w; + m_w = 0; + delete m_option; +} + +//PRIVATE SLOTS +void KFileReplacePart::slotSetNewParameters() +{ + launchNewProjectDialog(KURL()); + m_view->changeView(m_option->m_searchingOnlyMode); + emit setStatusBarText(i18n("Ready.")); +} + +void KFileReplacePart::slotSearchingOperation() +{ + if(!checkBeforeOperation()) + return; + + KListView* rv = m_view->getResultsView(); + + rv->clear(); + + rv->setSorting(-1); + + // show wait cursor + QApplication::setOverrideCursor( Qt::waitCursor ); + + freezeActions(); + + setOptionMask(); + + QString currentDirectory = m_option->m_directories[0], + currentFilter = m_option->m_filters[0]; + + //m_currentDir = currentDirectory; + + m_view->showSemaphore("red"); + + uint filesNumber = 0; + + if(m_option->m_recursive) + recursiveFileSearch(currentDirectory, currentFilter, filesNumber); + else + fileSearch(currentDirectory, currentFilter); + + m_view->showSemaphore("yellow"); + + kapp->processEvents(); + + //disabling and enabling sorting... don't ask me why, but it works! + rv->setSorting(0); + rv->sort(); + rv->setSorting(-1); + + // restore false status for stop button + m_stop = false; + + QApplication::restoreOverrideCursor(); + + emit setStatusBarText(i18n("Search completed.")); + + m_option->m_searchingOnlyMode = true; + + resetActions(); + + m_searchingOperation = true; + + m_view->showSemaphore("green"); +} + +void KFileReplacePart::slotReplacingOperation() +{ + if (KMessageBox::warningContinueCancel(m_w, i18n("You have selected %1 as the encoding of the files.
Selecting the correct encoding is very important as if you have files that have some other encoding than the selected one, after a replace you may damage those files.

In case you do not know the encoding of your files, select utf8 and enable the creation of backup files. This setting will autodetect utf8 and utf16 files, but the changed files will be converted to utf8.
").arg(m_option->m_encoding), i18n("File Encoding Warning"), KStdGuiItem::cont(), "ShowEncodingWarning") == KMessageBox::Cancel) + return; + if(!checkBeforeOperation()) + return; + + KListView* rv = m_view->getResultsView(); + + if(m_option->m_simulation) + { + emit setStatusBarText(i18n("Replacing files (simulation)...")); + rv->setColumnText(4,i18n("Replaced strings (simulation)")); + } + else + { + emit setStatusBarText(i18n("Replacing files...")); + rv->setColumnText(4,i18n("Replaced strings")); + } + // show wait cursor + QApplication::setOverrideCursor( Qt::waitCursor ); + + freezeActions(); + + setOptionMask(); + + rv->setSorting(-1); + + m_view->showSemaphore("green"); + + QString currentDirectory = m_option->m_directories[0]; + + m_view->showSemaphore("red"); + + if(m_option->m_recursive) + { + int filesNumber = 0; + recursiveFileReplace(currentDirectory, filesNumber); + } + else + { + fileReplace(); + } + + rv->setSorting(0); + rv->sort(); + rv->setSorting(-1); + + // restore false status for stop button + m_stop = false; + + QApplication::restoreOverrideCursor(); + + m_option->m_searchingOnlyMode = false; + + resetActions(); + + m_searchingOperation = false; + + m_view->showSemaphore("green"); +} + +void KFileReplacePart::slotSimulatingOperation() +{ + m_option->m_simulation = true; + slotReplacingOperation(); + m_option->m_simulation = false; +} + +void KFileReplacePart::slotStop() +{ + emit setStatusBarText(i18n("Stopping...")); + m_stop = true; + QApplication::restoreOverrideCursor(); + resetActions(); +} + +void KFileReplacePart::slotCreateReport() +{ + // Check there are results + KListView* rv = m_view->getResultsView(), + * sv = m_view->getStringsView(); + + if(rv->firstChild() == 0) + { + KMessageBox::error(m_w, i18n("There are no results to save: the result list is empty.")); + return ; + } + // Select the file where results will be saved + QString documentName = KFileDialog::getSaveFileName(QString::null, "*.xml|XML " + i18n("Files") + " (*.xml)", m_w, i18n("Save Report")); + if (documentName.isEmpty()) + return ; + + // delete a spourious extension + documentName.truncate(documentName.length()-4); + + QFileInfo fileInfo(documentName); + if(fileInfo.exists()) + { + KMessageBox::error(m_w, i18n("A folder or a file named %1 already exists.").arg(documentName)); + return ; + } + + QDir directoryName; + + if(!directoryName.mkdir(documentName, true)) + { + KMessageBox::error(m_w, i18n("Cannot create the %1 folder.").arg(documentName)); + return ; + } + + directoryName.cd(documentName); + + QString documentPath = documentName+"/"+directoryName.dirName(); + + Report report(m_option, rv, sv); + report.createDocument(documentPath); + + //resetActions(); +} + +void KFileReplacePart::slotStringsAdd() +{ + m_view->slotStringsAdd(); + resetActions(); +} + +void KFileReplacePart::slotQuickStringsAdd() +{ + //this slot handles a pair of strings that come from project dialog, + //if the control character 'N' is found at the position 0 of the two strings, + //then we start the search now. + QString qs = m_option->m_quickSearchString; + QStringList map; + + map.append(qs.left(1)); + map.append(qs.right(qs.length()-1)); + //in this case there is no string to search for, so return + if(map[1].isEmpty()) + return; + + //in this one instead, we must search for a string + qs = m_option->m_quickReplaceString; + map.append(qs.left(1)); + map.append(qs.right(qs.length()-1)); + + m_view->updateOptions(m_option); + + m_view->slotQuickStringsAdd(map[1],map[3]); + + //if search-only mode == true and search-now mode == true then + //search string + if(map[0] == "N") + if(m_option->m_searchingOnlyMode) + slotSearchingOperation(); + else + slotReplacingOperation(); +} + +void KFileReplacePart::slotStringsDeleteItem() +{ + m_view->slotStringsDeleteItem(); + resetActions(); +} + +void KFileReplacePart::slotStringsEmpty() +{ + m_view->slotStringsEmpty(); + resetActions(); +} + +void KFileReplacePart::slotStringsEdit() +{ + m_view->slotStringsEdit(); + resetActions(); +} + +void KFileReplacePart::slotStringsSave() +{ + m_view->slotStringsSave(); +} + +void KFileReplacePart::slotStringsLoad() +{ + // Selects the file to load from + QString menu = "*.kfr|" + i18n("KFileReplace strings") + " (*.kfr)\n*|"+i18n("All Files") + " (*)"; + QString fileName = KFileDialog::getOpenFileName(QString::null, menu, m_w, i18n("Load Strings From File")); + + if(!fileName.isEmpty()) + loadRulesFile(fileName); + + resetActions(); +} + +void KFileReplacePart::slotStringsInvertCur() +{ + m_view->stringsInvert(false); + resetActions(); +} + +void KFileReplacePart::slotStringsInvertAll() +{ + m_view->stringsInvert(true); + resetActions(); +} + +void KFileReplacePart::slotOpenRecentStringFile(const KURL& urlFile) +{ + QString fileName; + + // Downloads file if need (if url is "http://...") + if (!(KIO::NetAccess::download(urlFile, fileName, 0))) + return; + + // Checks it's not a directory + QFileInfo fileInfo; + fileInfo.setFile(fileName); + if(fileInfo.isDir()) + { + KMessageBox::error(m_w, i18n("Cannot open folders.")); + return; + } + + loadRulesFile(fileName); + resetActions(); +} + +void KFileReplacePart::slotOptionRecursive() +{ + m_option->m_recursive = !m_option->m_recursive; + resetActions(); +} + +void KFileReplacePart::slotOptionBackup() +{ + m_option->m_backup = !m_option->m_backup; + resetActions(); +} + +void KFileReplacePart::slotOptionCaseSensitive() +{ + m_option->m_caseSensitive = !m_option->m_caseSensitive; + resetActions(); +} + +void KFileReplacePart::slotOptionVariables() +{ + m_option->m_variables = !m_option->m_variables; + resetActions(); +} + +void KFileReplacePart::slotOptionRegularExpressions() +{ + m_option->m_regularExpressions = !m_option->m_regularExpressions; + resetActions(); +} + +void KFileReplacePart::slotOptionPreferences() +{ + KOptionsDlg dlg(m_option, m_w, 0); + + if(!dlg.exec()) + return; + + //updating m_view + m_view->updateOptions(m_option); + + resetActions(); +} + +void KFileReplacePart::showAboutApplication() +{ + m_aboutDlg = new KAboutApplication(createAboutData(), (QWidget *)0, (const char *)0, false); + if(m_aboutDlg == 0) + return; + + if(!m_aboutDlg->isVisible()) + m_aboutDlg->show(); + else + m_aboutDlg->raise(); +} + +void KFileReplacePart::appHelpActivated() +{ + kapp->invokeHelp(QString::null, "kfilereplace"); +} + +void KFileReplacePart::reportBug() +{ + KBugReport dlg(m_w, true, createAboutData()); + dlg.exec(); +} + +void KFileReplacePart::resetActions() +{ + KListView* rv = m_view->getResultsView(), + * sv = m_view->getStringsView(); + + bool hasItems = (sv->firstChild() != 0), + searchOnlyMode = m_option->m_searchingOnlyMode; + + // File + actionCollection()->action("new_project")->setEnabled(true); + actionCollection()->action("search")->setEnabled(hasItems && searchOnlyMode); + actionCollection()->action("file_simulate")->setEnabled(hasItems && !searchOnlyMode); + actionCollection()->action("replace")->setEnabled(hasItems && !searchOnlyMode); + actionCollection()->action("save_results")->setEnabled(hasItems); + actionCollection()->action("stop")->setEnabled(false); + + // Strings + actionCollection()->action("strings_add")->setEnabled(true); + actionCollection()->action("strings_del")->setEnabled(hasItems); + actionCollection()->action("strings_empty")->setEnabled(hasItems); + actionCollection()->action("strings_edit")->setEnabled(hasItems); + actionCollection()->action("strings_save")->setEnabled(hasItems); + actionCollection()->action("strings_load")->setEnabled(true); + actionCollection()->action("strings_invert")->setEnabled(hasItems && !searchOnlyMode); + actionCollection()->action("strings_invert_all")->setEnabled(hasItems && !searchOnlyMode); + + // Options + actionCollection()->action("options_recursive")->setEnabled(true); + actionCollection()->action("options_backup")->setEnabled(!searchOnlyMode); + actionCollection()->action("options_case")->setEnabled(true); + actionCollection()->action("options_var")->setEnabled(!searchOnlyMode); + actionCollection()->action("options_regularexpressions")->setEnabled(true); + actionCollection()->action("configure_kfilereplace")->setEnabled(true); + + hasItems = (rv->firstChild() != 0); + + // Results + actionCollection()->action("results_infos")->setEnabled(hasItems); + actionCollection()->action("results_openfile")->setEnabled(hasItems); + if (actionCollection()->action("results_editfile")) + actionCollection()->action("results_editfile")->setEnabled(hasItems); + actionCollection()->action("results_opendir")->setEnabled(hasItems); + actionCollection()->action("results_delete")->setEnabled(hasItems); + actionCollection()->action("results_treeexpand")->setEnabled(hasItems); + actionCollection()->action("results_treereduce")->setEnabled(hasItems); + + // Updates menus and toolbar + ((KToggleAction* ) actionCollection()->action("options_recursive"))->setChecked(m_option->m_recursive); + ((KToggleAction* ) actionCollection()->action("options_backup"))->setChecked(m_option->m_backup && !searchOnlyMode); + ((KToggleAction* ) actionCollection()->action("options_case"))->setChecked(m_option->m_caseSensitive); + ((KToggleAction* ) actionCollection()->action("options_var"))->setChecked(m_option->m_variables && !searchOnlyMode); + ((KToggleAction* ) actionCollection()->action("options_regularexpressions"))->setChecked(m_option->m_regularExpressions); +} + +//PUBLIC METHODS +KAboutData* KFileReplacePart::createAboutData() +{ + KAboutData * aboutData = new KAboutData("kfilereplacepart", + I18N_NOOP("KFileReplacePart"), + KFR_VERSION, + I18N_NOOP( "Batch search and replace tool."), + KAboutData::License_GPL_V2, + "(C) 1999-2002 Franïż½is Dupoux\n(C) 2003-2004 Andras Mantia\n(C) 2004 Emiliano Gulmini", I18N_NOOP("Part of the KDEWebDev module."), "http://www.kdewebdev.org"); + aboutData->addAuthor("Franïż½is Dupoux", + I18N_NOOP("Original author of the KFileReplace tool"), + "dupoux@dupoux.com"); + aboutData->addAuthor("Emiliano Gulmini", + I18N_NOOP("Current maintainer, code cleaner and rewriter"), + "emi_barbarossa@yahoo.it"); + aboutData->addAuthor("Andras Mantia", + I18N_NOOP("Co-maintainer, KPart creator"), + "amantia@kde.org"); + aboutData->addCredit("Heiko Goller", + I18N_NOOP("Original german translator"), + "heiko.goller@tuebingen.mpg.de"); + return aboutData; +} + +//PROTECTED METHODS +bool KFileReplacePart::openURL(const KURL &url) +{ + if(!url.isEmpty() && (url.protocol() != "file")) + { + KMessageBox::sorry(m_w, i18n("Sorry, currently the KFileReplace part works only for local files."), i18n("Non Local File")); + emit canceled(""); + return false; + } + if(!url.isEmpty()) + return launchNewProjectDialog(url); + else + { + resetActions(); + return true; + } +} + +//PRIVATE METHODS +void KFileReplacePart::initGUI() +{ + setXMLFile("kfilereplacepartui.rc"); + + actionCollection()->setHighlightingEnabled(true); + + DCOPClient *client = kapp->dcopClient(); + QCStringList appList = client->registeredApplications(); + bool quantaFound = false; + for(QCStringList::Iterator it = appList.begin(); it != appList.end(); ++it) + { + if((*it).left(6) == "quanta") + { + quantaFound = true; + break; + } + } + // File + (void)new KAction(i18n("Customize Search/Replace Session..."), "projectopen", 0, this, SLOT(slotSetNewParameters()), actionCollection(), "new_project"); + (void)new KAction(i18n("&Search"), "filesearch", 0, this, SLOT(slotSearchingOperation()), actionCollection(), "search"); + (void)new KAction(i18n("S&imulate"), "filesimulate", 0, this, SLOT(slotSimulatingOperation()), actionCollection(), "file_simulate"); + (void)new KAction(i18n("&Replace"), "filereplace", 0, this, SLOT(slotReplacingOperation()), actionCollection(), "replace"); + (void)new KAction(i18n("Sto&p"), "stop", 0, this, SLOT(slotStop()), actionCollection(), "stop"); + (void)new KAction(i18n("Cre&ate Report File..."), "filesaveas", 0, this, SLOT(slotCreateReport()), actionCollection(), "save_results"); + + // Strings + (void)new KAction(i18n("&Add String..."), "editadd", 0, this, SLOT(slotStringsAdd()), actionCollection(), "strings_add"); + + (void)new KAction(i18n("&Delete String"), "editremove", 0, this, SLOT(slotStringsDeleteItem()), actionCollection(), "strings_del"); + (void)new KAction(i18n("&Empty Strings List"), "editdelete", 0, this, SLOT(slotStringsEmpty()), actionCollection(), "strings_empty"); + (void)new KAction(i18n("Edit Selected String..."), "edit", 0, this, SLOT(slotStringsEdit()), actionCollection(), "strings_edit"); + (void)new KAction(i18n("&Save Strings List to File..."), "filesaveas", 0, this, SLOT(slotStringsSave()), actionCollection(), "strings_save"); + (void)new KAction(i18n("&Load Strings List From File..."), "unsortedList", 0, this, SLOT(slotStringsLoad()), actionCollection(), "strings_load"); + (void)new KRecentFilesAction(i18n("&Load Recent Strings Files"), "fileopen", 0, this, SLOT(slotOpenRecentStringFile(const KURL&)), actionCollection(),"strings_load_recent"); + (void)new KAction(i18n("&Invert Current String (search <--> replace)"), "invert", 0, this, SLOT(slotStringsInvertCur()), actionCollection(), "strings_invert"); + (void)new KAction(i18n("&Invert All Strings (search <--> replace)"), "invert", 0, this, SLOT(slotStringsInvertAll()), actionCollection(), "strings_invert_all"); + + // Options + (void)new KToggleAction(i18n("&Include Sub-Folders"), "recursive_option", 0, this, SLOT(slotOptionRecursive()), actionCollection(), "options_recursive"); + (void)new KToggleAction(i18n("Create &Backup Files"), "backup_option", 0, this, SLOT(slotOptionBackup()), actionCollection(), "options_backup"); + (void)new KToggleAction(i18n("Case &Sensitive"), "casesensitive_option", 0, this, SLOT(slotOptionCaseSensitive()), actionCollection(), "options_case"); + (void)new KToggleAction(i18n("Enable Commands &in Replace String: [$command:option$]"), "command_option", 0, this, SLOT(slotOptionVariables()), actionCollection(), "options_var"); + (void)new KToggleAction(i18n("Enable &Regular Expressions"), "regularexpression_option", 0, this, SLOT(slotOptionRegularExpressions()), actionCollection(), "options_regularexpressions"); + (void)new KAction(i18n("Configure &KFileReplace..."), "configure", 0, this, SLOT(slotOptionPreferences()), actionCollection(), "configure_kfilereplace"); + + // Results + (void)new KAction(i18n("&Properties"), "informations", 0, m_view, SLOT(slotResultProperties()), actionCollection(), "results_infos"); + (void)new KAction(i18n("&Open"), "filenew", 0, m_view, SLOT(slotResultOpen()), actionCollection(), "results_openfile"); + + if(quantaFound) + { + (void)new KAction(i18n("&Edit in Quanta"), "quanta", 0, m_view, SLOT(slotResultEdit()), actionCollection(), "results_editfile"); + } + (void)new KAction(i18n("Open Parent &Folder"), "fileopen", 0, m_view, SLOT(slotResultDirOpen()), actionCollection(), "results_opendir"); + (void)new KAction(i18n("&Delete"), "editdelete", 0, m_view, SLOT(slotResultDelete()), actionCollection(), "results_delete"); + (void)new KAction(i18n("E&xpand Tree"), 0, m_view, SLOT(slotResultTreeExpand()), actionCollection(), "results_treeexpand"); + (void)new KAction(i18n("&Reduce Tree"), 0, m_view, SLOT(slotResultTreeReduce()), actionCollection(), "results_treereduce"); + (void)new KAction(i18n("&About KFileReplace"), "kfilereplace", 0, this, SLOT(showAboutApplication()), actionCollection(), "help_about_kfilereplace"); + (void)new KAction(i18n("KFileReplace &Handbook"), "help", 0, this, SLOT(appHelpActivated()), actionCollection(), "help_kfilereplace"); + (void)new KAction(i18n("&Report Bug"), 0, 0, this, SLOT(reportBug()), actionCollection(), "report_bug"); + +} + +void KFileReplacePart::initView() +{ + m_view = new KFileReplaceView(m_option, m_parentWidget, "view"); + + setWidget(m_view); + + m_view->setAcceptDrops(false); + + m_view->showSemaphore("green"); +} + +void KFileReplacePart::freezeActions() +{ + //Disables actions during search/replace operation + actionCollection()->action("new_project")->setEnabled(false); + actionCollection()->action("stop")->setEnabled(true); + + actionCollection()->action("file_simulate")->setEnabled(false); + actionCollection()->action("replace")->setEnabled(false); + actionCollection()->action("search")->setEnabled(false); + actionCollection()->action("strings_add")->setEnabled(false); + actionCollection()->action("strings_del")->setEnabled(false); + actionCollection()->action("strings_empty")->setEnabled(false); + actionCollection()->action("strings_edit")->setEnabled(false); + actionCollection()->action("strings_save")->setEnabled(false); + actionCollection()->action("strings_load")->setEnabled(false); + actionCollection()->action("strings_invert")->setEnabled(false); + actionCollection()->action("strings_invert_all")->setEnabled(false); + actionCollection()->action("options_recursive")->setEnabled(false); + actionCollection()->action("options_backup")->setEnabled(false); + actionCollection()->action("options_case")->setEnabled(false); + actionCollection()->action("options_var")->setEnabled(false); + actionCollection()->action("options_regularexpressions")->setEnabled(false); + actionCollection()->action("configure_kfilereplace")->setEnabled(false); + actionCollection()->action("results_infos")->setEnabled(false); + actionCollection()->action("results_openfile")->setEnabled(false); + if (actionCollection()->action("results_editfile")) + actionCollection()->action("results_editfile")->setEnabled(false); + actionCollection()->action("results_opendir")->setEnabled(false); + actionCollection()->action("results_delete")->setEnabled(false); + actionCollection()->action("results_treeexpand")->setEnabled(false); + actionCollection()->action("results_treereduce")->setEnabled(false); + ((KToggleAction* ) actionCollection()->action("options_recursive"))->setChecked(false); + ((KToggleAction* ) actionCollection()->action("options_backup"))->setChecked(false); + ((KToggleAction* ) actionCollection()->action("options_case"))->setChecked(false); + ((KToggleAction* ) actionCollection()->action("options_var"))->setChecked(false); + ((KToggleAction* ) actionCollection()->action("options_regularexpressions"))->setChecked(false); +} + +void KFileReplacePart::loadOptionsFromRC() +{ + m_option = new RCOptions(); + + loadOptions(); + loadFileSizeOptions(); + loadDateAccessOptions(); + loadOwnerOptions(); + loadLocationsList(); + loadFiltersList(); + loadBackupExtensionOptions(); +} + +void KFileReplacePart::loadOptions() +{ + m_config->setGroup("General Options"); + + m_option->m_recentStringFileList = m_config->readListEntry(rcRecentFiles); + + m_option->m_searchingOnlyMode = m_config->readBoolEntry(rcSearchMode,SearchModeOption); + + m_config->setGroup("Options"); + + m_option->m_encoding = m_config->readEntry(rcEncoding, EncodingOption); + m_option->m_recursive = m_config->readBoolEntry(rcRecursive, RecursiveOption); + + m_option->m_caseSensitive = m_config->readBoolEntry(rcCaseSensitive, CaseSensitiveOption); + m_option->m_variables = m_config->readBoolEntry(rcVariables, VariablesOption); + m_option->m_regularExpressions = m_config->readBoolEntry(rcRegularExpressions, RegularExpressionsOption); + m_option->m_followSymLinks = m_config->readBoolEntry(rcFollowSymLinks, FollowSymbolicLinksOption); + + m_option->m_haltOnFirstOccur = m_config->readBoolEntry(rcHaltOnFirstOccur, StopWhenFirstOccurenceOption); + + m_option->m_ignoreHidden = m_config->readBoolEntry(rcIgnoreHidden, IgnoreHiddenOption); + m_option->m_ignoreFiles = m_config->readBoolEntry(rcIgnoreFiles, IgnoreFilesOption); + + m_config->setGroup("Notification Messages"); + + m_option->m_notifyOnErrors = m_config->readBoolEntry(rcNotifyOnErrors, true); + + m_option->m_askConfirmReplace = m_config->readBoolEntry(rcAskConfirmReplace, AskConfirmReplaceOption); + + QString dontAskAgain = m_config->readEntry(rcDontAskAgain, "no"); + + if(dontAskAgain == "yes") + m_option->m_askConfirmReplace = false; +} + +void KFileReplacePart::loadFileSizeOptions() +{ + m_config->setGroup("Size options"); + + m_option->m_minSize = m_config->readNumEntry(rcMinFileSize, FileSizeOption); + m_option->m_maxSize = m_config->readNumEntry(rcMaxFileSize, FileSizeOption); +} + +void KFileReplacePart::loadDateAccessOptions() +{ + m_config->setGroup("Access options"); + + m_option->m_dateAccess = m_config->readEntry(rcValidAccessDate, ValidAccessDateOption); + m_option->m_minDate = m_config->readEntry(rcMinDate, AccessDateOption); + m_option->m_maxDate = m_config->readEntry(rcMaxDate, AccessDateOption); +} + +void KFileReplacePart::loadOwnerOptions() +{ + m_config->setGroup("Owner options"); + + QStringList ownerList = QStringList::split(',',m_config->readEntry(rcOwnerUser, OwnerOption),true); + if(ownerList[0] == "true") + m_option->m_ownerUserIsChecked = true; + else + m_option->m_ownerUserIsChecked = false; + + m_option->m_ownerUserType = ownerList[1]; + m_option->m_ownerUserBool = ownerList[2]; + m_option->m_ownerUserValue = ownerList[3]; + + ownerList = QStringList::split(',',m_config->readEntry(rcOwnerGroup, OwnerOption),true); + + if(ownerList[0] == "true") + m_option->m_ownerGroupIsChecked = true; + else + m_option->m_ownerGroupIsChecked = false; + + m_option->m_ownerGroupType = ownerList[1]; + m_option->m_ownerGroupBool = ownerList[2]; + m_option->m_ownerGroupValue = ownerList[3]; +} + +void KFileReplacePart::loadLocationsList() +{ + m_config->setGroup("Directories"); + QStringList locationsEntryList; + #if KDE_IS_VERSION(3,1,3) + locationsEntryList = m_config->readPathListEntry(rcDirectoriesList); + #else + locationsEntryList = m_config->readListEntry(rcDirectoriesList); + #endif + + if(locationsEntryList.isEmpty()) + locationsEntryList.append(QDir::current().path()); + + m_option->m_directories = locationsEntryList; +} + +void KFileReplacePart::loadFiltersList() +{ + QStringList filtersEntryList; + + m_config->setGroup("Filters"); + #if KDE_IS_VERSION(3,1,3) + filtersEntryList = m_config->readPathListEntry(rcFiltersList); + #else + filtersEntryList = m_config->readListEntry(rcFiltersList); + #endif + + if(filtersEntryList.isEmpty()) + filtersEntryList.append("*.htm;*.html;*.xml;*.xhtml;*.css;*.js;*.php"); + + m_option->m_filters = filtersEntryList; +} + +void KFileReplacePart::loadBackupExtensionOptions() +{ + m_config->setGroup("Options"); + QStringList bkList = QStringList::split(',', + m_config->readEntry(rcBackupExtension, BackupExtensionOption), + true); + if(bkList[0] == "true") + m_option->m_backup = true; + else + m_option->m_backup = false; + + m_option->m_backupExtension = bkList[1]; +} + +void KFileReplacePart::saveOptionsToRC() +{ + saveOptions(); + saveFileSizeOptions(); + saveDateAccessOptions(); + saveOwnerOptions(); + saveLocationsList(); + saveFiltersList(); + saveBackupExtensionOptions(); +} + +void KFileReplacePart::saveOptions() +{ + m_config->setGroup("General Options"); + + m_config->writeEntry(rcRecentFiles, m_option->m_recentStringFileList); + m_config->writeEntry(rcSearchMode,m_option->m_searchingOnlyMode); + + m_config->setGroup("Options"); + + m_config->writeEntry(rcEncoding, m_option->m_encoding); + m_config->writeEntry(rcRecursive, m_option->m_recursive); + m_config->writeEntry(rcCaseSensitive, m_option->m_caseSensitive); + m_config->writeEntry(rcVariables, m_option->m_variables); + m_config->writeEntry(rcRegularExpressions, m_option->m_regularExpressions); + + m_config->writeEntry(rcFollowSymLinks, m_option->m_followSymLinks); + m_config->writeEntry(rcHaltOnFirstOccur, m_option->m_haltOnFirstOccur); + + m_config->writeEntry(rcIgnoreHidden, m_option->m_ignoreHidden); + m_config->writeEntry(rcIgnoreFiles, m_option->m_ignoreFiles); + + m_config->setGroup("Notification Messages"); + m_config->writeEntry(rcNotifyOnErrors, m_option->m_notifyOnErrors); + if(m_config->readEntry(rcDontAskAgain,"no") == "yes") + m_config->writeEntry(rcAskConfirmReplace, false); + else + m_config->writeEntry(rcAskConfirmReplace, m_option->m_askConfirmReplace); + + m_config->sync(); +} + +void KFileReplacePart::saveFileSizeOptions() +{ + m_config->setGroup("Size options"); + + m_config->writeEntry(rcMaxFileSize, m_option->m_maxSize); + m_config->writeEntry(rcMinFileSize, m_option->m_minSize); + + m_config->sync(); +} + +void KFileReplacePart::saveDateAccessOptions() +{ + m_config->setGroup("Access options"); + + m_config->writeEntry(rcValidAccessDate, m_option->m_dateAccess); + m_config->writeEntry(rcMinDate, m_option->m_minDate); + m_config->writeEntry(rcMaxDate, m_option->m_maxDate); + + m_config->sync(); +} + +void KFileReplacePart::saveOwnerOptions() +{ + m_config->setGroup("Owner options"); + + QString list; + if(m_option->m_ownerUserIsChecked) + list = "true,"; + else + list = "false,"; + + list += m_option->m_ownerUserType + + "," + + m_option->m_ownerUserBool; + if(!m_option->m_ownerUserValue.isEmpty()) + list += "," + m_option->m_ownerUserValue; + + m_config->writeEntry(rcOwnerUser,list); + + if(m_option->m_ownerGroupIsChecked) + list = "true,"; + else + list = "false,"; + + list += m_option->m_ownerGroupType + + "," + + m_option->m_ownerGroupBool; + if(!m_option->m_ownerGroupValue.isEmpty()) + list += "," + m_option->m_ownerGroupValue; + + m_config->writeEntry(rcOwnerGroup,list); + m_config->sync(); +} + +void KFileReplacePart::saveLocationsList() +{ + m_config->setGroup("Directories"); + #if KDE_IS_VERSION(3,1,3) + m_config->writePathEntry(rcDirectoriesList, m_option->m_directories); + #else + m_config->writeEntry(rcDirectoriesList, m_option->m_directories); + #endif + m_config->sync(); +} + +void KFileReplacePart::saveFiltersList() +{ + m_config->setGroup("Filters"); + m_config->writeEntry(rcFiltersList, m_option->m_filters); + m_config->sync(); +} + +void KFileReplacePart::saveBackupExtensionOptions() +{ + m_config->setGroup("Options"); + QString bkOptions; + if(m_option->m_backup) + bkOptions = "true," + m_option->m_backupExtension; + else + bkOptions = "false," + m_option->m_backupExtension; + + m_config->writeEntry(rcBackupExtension, bkOptions); + m_config->sync(); +} + +void KFileReplacePart::fileReplace() +{ + QString directoryName = m_option->m_directories[0]; + QDir d(directoryName); + d.setMatchAllDirs(true); + d.setFilter(m_optionMask); + + QString currentFilter = m_option->m_filters[0]; + QStringList filesList = d.entryList(currentFilter); + QStringList::iterator filesIt; + int filesNumber = 0; + + m_view->displayScannedFiles(filesNumber); + + for (filesIt = filesList.begin(); filesIt != filesList.end() ; ++filesIt) + { + QString fileName = (*filesIt); + + // m_stop == true means that we pushed the stop button + if(m_stop) + break; + + // Avoids files that not match requirements + if(!KFileReplaceLib::isAnAccessibleFile(d.canonicalPath(), fileName, m_option)) + continue; + kapp->processEvents(); + if(m_option->m_backup) + replaceAndBackup(d.canonicalPath(), fileName); + else + replaceAndOverwrite(d.canonicalPath(), fileName); + + filesNumber++; + m_view->displayScannedFiles(filesNumber); + } +} + +void KFileReplacePart::recursiveFileReplace(const QString& directoryName, int& filesNumber) +{ + //if m_stop == true then interrupts recursion + if(m_stop) + return; + else + { + QDir d(directoryName); + + d.setMatchAllDirs(true); + d.setFilter(m_optionMask); + + QString currentFilter = m_option->m_filters[0]; + QStringList filesList = d.entryList(currentFilter); + QStringList::iterator filesIt; + + for(filesIt = filesList.begin(); filesIt != filesList.end(); ++filesIt) + { + //if m_stop == true then end for-loop + if(m_stop) + break; + + QString fileName = (*filesIt); + + // Avoids files that not match requirements + if(!KFileReplaceLib::isAnAccessibleFile(d.canonicalPath(),fileName, m_option)) + continue; + + QString filePath = d.canonicalPath()+"/"+fileName; + + QFileInfo qi(filePath); + + m_view->displayScannedFiles(filesNumber); + + //if filePath is a directory then recursion + if(qi.isDir()) + recursiveFileReplace(filePath, filesNumber); + else + { + kapp->processEvents(); + if(m_option->m_backup) + replaceAndBackup(d.canonicalPath(), fileName); + else + replaceAndOverwrite(d.canonicalPath(), fileName); + + filesNumber++; + m_view->displayScannedFiles(filesNumber); + } + } + } +} + +void KFileReplacePart::replaceAndBackup(const QString& currentDir, const QString& oldFileName) +{ + //Creates a path string + QString oldPathString = currentDir+"/"+oldFileName; + + QFile currentFile(oldPathString); + if(!currentFile.open(IO_ReadOnly)) + { + KMessageBox::information(m_w, i18n("Cannot open file %1 for reading.").arg(oldFileName),QString::null, rcNotifyOnErrors); + return ; + } + QTextStream currentStream(¤tFile); + if (m_option->m_encoding == "utf8") + currentStream.setEncoding(QTextStream::UnicodeUTF8); + else + currentStream.setCodec(QTextCodec::codecForName(m_option->m_encoding)); + QString line = currentStream.read(), + backupLine = line; + + QString backupSize = KFileReplaceLib::formatFileSize(currentFile.size()); + + currentFile.close(); + + QString backupExtension = m_option->m_backupExtension; + + bool atLeastOneStringFound = false; + KListViewItem *item = 0; + int occurrence = 0; + + replacingLoop(line, &item, atLeastOneStringFound, occurrence, m_option->m_regularExpressions, m_option->m_askConfirmReplace); + + //If we are not performing a simulation creates a backup file + if(!m_option->m_simulation) + { + if(atLeastOneStringFound) + { + KIO::NetAccess::file_copy(KURL::fromPathOrURL(oldPathString), KURL::fromPathOrURL(oldPathString + backupExtension), -1, true); + } + } + + if(!m_option->m_simulation) + { + if(atLeastOneStringFound) + { + QFile newFile(oldPathString); + if(!newFile.open(IO_WriteOnly)) + { + KMessageBox::information(m_w, i18n("Cannot open file %1 for writing.").arg(oldFileName),QString::null, rcNotifyOnErrors); + return ; + } + QTextStream newStream(&newFile); + if (m_option->m_encoding == "utf8") + newStream.setEncoding(QTextStream::UnicodeUTF8); + else + newStream.setCodec(QTextCodec::codecForName(m_option->m_encoding)); + newStream << line; + newFile.close(); + } + } + + if(!m_option->m_ignoreFiles) + atLeastOneStringFound = true; + + QFileInfo oldFileInfo(oldPathString); + + if(atLeastOneStringFound && item/* && atLeastOneStringConfirmed*/) + { + KFileReplaceLib::setIconForFileEntry(item,currentDir+"/"+oldFileName); + item->setText(0,oldFileName); + item->setText(1,currentDir); + QString newSize = KFileReplaceLib::formatFileSize(oldFileInfo.size()); + if(!m_option->m_simulation) + { + item->setText(2, backupSize); + item->setText(3, newSize); + } + else + { + item->setText(2, backupSize); + item->setText(3, "-"); + } + + item->setText(4,QString::number(occurrence,10)); + item->setText(5,QString("%1[%2]").arg(oldFileInfo.owner()).arg(oldFileInfo.ownerId())); + item->setText(6,QString("%1[%2]").arg(oldFileInfo.group()).arg(oldFileInfo.groupId())); + } +} + +void KFileReplacePart::replaceAndOverwrite(const QString& currentDir, const QString& oldFileName) +{ + QString oldPathString = currentDir+"/"+oldFileName; + QFile oldFile(oldPathString); + QFileInfo oldFileInfo(oldPathString); + + if (!oldFile.open(IO_ReadOnly)) + { + KMessageBox::information(m_w, i18n("Cannot open file %1 for reading.").arg(oldFile.name()),QString::null, rcNotifyOnErrors); + return ; + } + + QString fileSizeBeforeReplacing = KFileReplaceLib::formatFileSize(oldFileInfo.size()); + KListViewItem *item = 0; + + QTextStream oldStream( &oldFile ); + if (m_option->m_encoding == "utf8") + oldStream.setEncoding(QTextStream::UnicodeUTF8); + else + oldStream.setCodec(QTextCodec::codecForName(m_option->m_encoding)); + QString line = oldStream.read(); + + oldFile.close(); + + bool atLeastOneStringFound = false; + int occurrence = 0; + + replacingLoop(line, &item, atLeastOneStringFound, occurrence, m_option->m_regularExpressions, m_option->m_askConfirmReplace); + + + if(!m_option->m_simulation) + { + if(atLeastOneStringFound) + { + QFile newFile(oldPathString); + if(!newFile.open(IO_WriteOnly)) + { + KMessageBox::information(m_w, i18n("Cannot open file %1 for writing.").arg(newFile.name()),QString::null, rcNotifyOnErrors); + return ; + } + QTextStream newStream( &newFile ); + if (m_option->m_encoding == "utf8") + newStream.setEncoding(QTextStream::UnicodeUTF8); + else + newStream.setCodec(QTextCodec::codecForName(m_option->m_encoding)); + newStream << line; + newFile.close(); + } + } + + QFileInfo nf(oldPathString); + QString fileSizeAfterReplacing = KFileReplaceLib::formatFileSize(nf.size()); + + //if ignoreFiles == false then every files must be show + if(!m_option->m_ignoreFiles) + atLeastOneStringFound = true; + + if(atLeastOneStringFound && item/*&& atLeastOneStringConfirmed*/) + { + KFileReplaceLib::setIconForFileEntry(item,currentDir+"/"+oldFileName); + item->setText(0,oldFileName); + item->setText(1,currentDir); + item->setText(2,fileSizeBeforeReplacing); + if(!m_option->m_simulation) + item->setText(3,fileSizeAfterReplacing); + else + item->setText(3,"-"); + + item->setText(4,QString::number(occurrence,10)); + item->setText(5,QString("%1[%2]").arg(oldFileInfo.owner()).arg(oldFileInfo.ownerId())); + item->setText(6,QString("%1[%2]").arg(oldFileInfo.group()).arg(oldFileInfo.groupId())); + } +} + +void KFileReplacePart::replacingLoop(QString& line, KListViewItem** item, bool& atLeastOneStringFound, int& occur, bool regularExpression, bool& askConfirmReplace) +{ + KeyValueMap tempMap = m_replacementMap; + KeyValueMap::Iterator it; + KListView* rv = m_view->getResultsView(); + + for(it = tempMap.begin(); it != tempMap.end(); ++it) + { + if(m_stop) + break; + + ResultViewEntry entry(it.key(), it.data(), regularExpression, m_option->m_caseSensitive); + while(entry.pos(line) != -1) + { + if(m_stop) + break; + + if(askConfirmReplace) + { + int answer = KMessageBox::questionYesNo(0, + i18n("Do you want to replace the string %1 with the string %2?").arg(it.key()).arg(it.data()), + i18n("Confirm Replace"), + i18n("Replace"), + i18n("Do Not Replace"), + rcDontAskAgain); + if(answer == KMessageBox::Yes) + { + atLeastOneStringFound = true; + QString msg = entry.message(entry.capturedText(line), + entry.lineNumber(line), + entry.columnNumber(line)); + + if(!*item) + *item = new KListViewItem(rv); + KListViewItem* tempItem = new KListViewItem(*item); + tempItem->setMultiLinesEnabled(true); + tempItem->setText(0,msg); + occur ++; + entry.updateLine(line); + entry.incPos(); + } + else + { + entry.incPos(); + } + if(dontAskAgain()) askConfirmReplace = false; + } + else + { + atLeastOneStringFound = true; + QString msg = entry.message(entry.capturedText(line), + entry.lineNumber(line), + entry.columnNumber(line)); + + if(!*item) + *item = new KListViewItem(rv); + KListViewItem* tempItem = new KListViewItem(*item); + tempItem->setMultiLinesEnabled(true); + tempItem->setText(0,msg); + occur ++; + entry.updateLine(line); + entry.incPos(); + } + + } + } +} + +void KFileReplacePart::fileSearch(const QString& directoryName, const QString& filters) +{ + QDir d(directoryName); + + d.setMatchAllDirs(true); + d.setFilter(m_optionMask); + + QStringList filesList = d.entryList(filters); + QString filePath = d.canonicalPath(); + QStringList::iterator filesIt; + uint filesNumber = 0; + + m_view->displayScannedFiles(filesNumber); + + for (filesIt = filesList.begin(); filesIt != filesList.end() ; ++filesIt) + { + // We pushed stop button + if(m_stop) + break; + + QString fileName = (*filesIt); + + // Avoids files that not match + if(!KFileReplaceLib::isAnAccessibleFile(filePath, fileName, m_option)) + continue; + + QFileInfo fileInfo(filePath+"/"+fileName); + if(fileInfo.isDir()) + continue; + kapp->processEvents(); + search(filePath, fileName); + filesNumber++; + m_view->displayScannedFiles(filesNumber); + } +} + +void KFileReplacePart::recursiveFileSearch(const QString& directoryName, const QString& filters, uint& filesNumber) +{ + // if m_stop == true then interrupt recursion + if(m_stop) + return; + else + { + QDir d(directoryName); + + d.setMatchAllDirs(true); + d.setFilter(m_optionMask); + + QStringList filesList = d.entryList(filters); + QString filePath = d.canonicalPath(); + QStringList::iterator filesIt; + + for(filesIt = filesList.begin(); filesIt != filesList.end(); ++filesIt) + { + // stop polling + if(m_stop) + break; + + QString fileName = (*filesIt); + // Avoids files that not match + if(!KFileReplaceLib::isAnAccessibleFile(filePath, fileName, m_option)) + continue; + + // Composes file path string + QFileInfo fileInfo(filePath+"/"+fileName); + + m_view->displayScannedFiles(filesNumber); + + // Searchs recursively if "filePath" is a directory + if(fileInfo.isDir()) + recursiveFileSearch(filePath+"/"+fileName, filters, filesNumber); + else + { + kapp->processEvents(); + search(filePath, fileName); + filesNumber++; + m_view->displayScannedFiles(filesNumber); + } + } + } +} + +void KFileReplacePart::search(const QString& currentDir, const QString& fileName) +{ + QFile file(currentDir+"/"+fileName); + + if(!file.open(IO_ReadOnly)) + { + KMessageBox::information(m_w, i18n("Cannot open file %1 for reading.").arg(fileName), QString::null, rcNotifyOnErrors); + return ; + } + // Creates a stream with the file + QTextStream stream( &file ); + if (m_option->m_encoding == "utf8") + stream.setEncoding(QTextStream::UnicodeUTF8); + else + stream.setCodec(QTextCodec::codecForName(m_option->m_encoding)); + QString line = stream.read(); + file.close(); + + QFileInfo fileInfo(currentDir+"/"+fileName); + + KListViewItem *item = 0; + + //Counts occurrences + int occurrence = 0; + + //This map contains strings to search + KeyValueMap tempMap = m_replacementMap; + //If no strings has been found, then no lines will be added to the result view + bool atLeastOneStringFound = false; + + KeyValueMap::Iterator it = tempMap.begin(); + + KListView* rv = m_view->getResultsView(); + + while(it != tempMap.end()) + { + //stop polling + if(m_stop) + break; + + QString key = it.key(); + QString strKey; + QRegExp rxKey; + + if(m_option->m_regularExpressions) + rxKey = QRegExp("("+key+")", m_option->m_caseSensitive, false); + else + strKey = key; + /* If this option is true then for any string in + * the map we search for the first match*/ + if(m_option->m_haltOnFirstOccur) + { + int pos; + + if(m_option->m_regularExpressions) + pos = line.find(rxKey); + else + pos = line.find(strKey, 0 ,m_option->m_caseSensitive); + + if(pos != -1) + { + atLeastOneStringFound = true; + int lineNumber = line.mid(0,pos).contains('\n')+1; + int columnNumber = pos - line.findRev('\n',pos); + + if (!item) + item = new KListViewItem(rv); + + KListViewItem* tempItem= new KListViewItem(item); + QString msg, + capturedText; + + if(m_option->m_regularExpressions) + capturedText = rxKey.cap(1); + else + capturedText = line.mid(pos,strKey.length()); + + msg = i18n(" Line:%2, Col:%3 - \"%1\"").arg(capturedText).arg(QString::number(lineNumber,10)).arg(QString::number(columnNumber,10)); + tempItem->setMultiLinesEnabled(true); + tempItem->setText(0,msg); + occurrence = 1; + } + }// ends m_option->m_haltOnFirstOccur if-block + else + { + /* This point of the code is reached when we must search for all + * occurrences of all the strings*/ + + int pos = 0; + if(m_option->m_regularExpressions) + pos = rxKey.search(line,pos); + else + pos = line.find(strKey, pos ,m_option->m_caseSensitive); + + while(pos != -1) + { + //stop polling + if(m_stop) + break; + + atLeastOneStringFound = true; + QString msg, + capturedText; + int lineNumber = line.mid(0,pos).contains('\n')+1; + int columnNumber = pos - line.findRev('\n',pos); + + if(m_option->m_regularExpressions) + { + capturedText = rxKey.cap(1); + pos = rxKey.search(line, pos+rxKey.matchedLength()); + } + else + { + capturedText = line.mid(pos,strKey.length()); + pos = line.find(strKey,pos+strKey.length()); + } + + msg = i18n(" Line:%2, Col:%3 - \"%1\"").arg(capturedText).arg(QString::number(lineNumber,10)).arg(QString::number(columnNumber,10)); + + if(!item) + item = new KListViewItem(rv); + KListViewItem* tempItem = new KListViewItem(item); + tempItem->setMultiLinesEnabled(true); + tempItem->setText(0,msg); + occurrence++; + //we push stop button + if(m_stop) + break; + } + } + //Advances of one position in the strings map + ++it; + + //we push stop button + if(m_stop) + break; + } + + //if ignoreFiles == false then every files must be show + if(!m_option->m_ignoreFiles) + atLeastOneStringFound = true; + + if(atLeastOneStringFound && item) + { + KFileReplaceLib::setIconForFileEntry(item,currentDir+"/"+fileName); + item->setText(0,fileName); + item->setText(1,currentDir); + item->setText(2,KFileReplaceLib::formatFileSize(fileInfo.size())); + item->setText(3,QString::number(occurrence,10)); + item->setText(4,QString("%1[%2]").arg(fileInfo.owner()).arg(fileInfo.ownerId())); + item->setText(5,QString("%1[%2]").arg(fileInfo.group()).arg(fileInfo.groupId())); + } +} + +void KFileReplacePart::loadViewContent() +{ + /* Maps the content of the strings view to a QMap */ + KeyValueMap tempMap; + CommandEngine command; + + QListViewItemIterator itlv(m_view->getStringsView()); + while(itlv.current()) + { + QListViewItem *item = itlv.current(); + if(m_option->m_variables) + tempMap[item->text(0)] = command.variableValue(item->text(1)); + else + tempMap[item->text(0)] = item->text(1); + ++itlv; + } + m_replacementMap = tempMap; +} + +void KFileReplacePart::loadRulesFile(const QString& fileName) +{ + /* Loads a file with kfr extension. + * creates a xml document and browses it*/ + QDomDocument doc("mydocument"); + QFile file(fileName); + KListView* sv = m_view->getStringsView(); + + if(!file.open(IO_ReadOnly)) + { + KMessageBox::error(m_w, i18n("Cannot open the file %1 and load the string list.").arg(fileName)); + return ; + } + + if(!doc.setContent(&file)) + { + file.close(); + + KMessageBox::information(m_w, i18n("File %1 seems not to be written in new kfr format. Remember that the old kfr format will be soon abandoned. You can convert your old rules files by simply saving them with kfilereplace.").arg(fileName),i18n("Warning")); + + KFileReplaceLib::convertOldToNewKFRFormat(fileName, sv); + + return; + } + else + file.close(); + + //clears view + sv->clear(); + + QDomElement docElem = doc.documentElement(); + QDomNode n = docElem.firstChild(); + QString searchAttribute = n.toElement().attribute("search").latin1(); + + KeyValueMap docMap; + + if(searchAttribute.isNull() || searchAttribute.isEmpty()) + { + int answer = KMessageBox::warningYesNo(m_w, i18n("The format of kfr files has been changed; attempting to load %1. Please see the KFilereplace manual for details. Do you want to load a search-and-replace list of strings?").arg(fileName),i18n("Warning"),i18n("Load"),i18n("Do Not Load")); + + if(answer == KMessageBox::Yes) + searchAttribute = "false"; + else + searchAttribute = "true"; + } + //Verifies the search mode + if(searchAttribute == "true") + m_option->m_searchingOnlyMode = true; + else + m_option->m_searchingOnlyMode = false; + + //Refreshes the view appearances + m_view->changeView(m_option->m_searchingOnlyMode); + //Goes to next tag + n = n.nextSibling(); + //Reads the string list + while(!n.isNull()) + { + QDomElement e = n.toElement(); // tries to convert the node to an element. + if(!e.isNull()) + { + QString oldString = e.firstChild().toElement().text(), + newString = e.lastChild().toElement().text(); + docMap[oldString] = newString; + } + n = n.nextSibling(); + } + + // Adds file to "load strings form file" menu + QStringList fileList = m_option->m_recentStringFileList; + if(!fileList.contains(fileName)) + { + fileList.append(fileName); + ((KRecentFilesAction* ) actionCollection()->action("strings_load_recent"))->setItems(fileList); + m_option->m_recentStringFileList = fileList; + } + + m_view->changeView(m_option->m_searchingOnlyMode); + + m_view->loadMap(docMap); + + //resetActions(); +} + +bool KFileReplacePart::launchNewProjectDialog(const KURL & startURL) +{ + if(!startURL.isEmpty()) + m_option->m_directories.prepend(startURL.path()); + + /* This dlg reads options from m_option, then execs, finally returns options.*/ + KNewProjectDlg dlg(m_option); + + if(!dlg.exec()) + return false; + + dlg.saveRCOptions(); + + m_config->sync(); + + slotQuickStringsAdd(); + + m_view->updateOptions(m_option); + + resetActions(); + + return true; +} + +void KFileReplacePart::setOptionMask() +{ + m_optionMask |= QDir::Dirs; + + if(!m_option->m_ignoreHidden) + m_optionMask |= QDir::Hidden; + + if(!m_option->m_followSymLinks) + m_optionMask |= QDir::NoSymLinks; +} + +bool KFileReplacePart::checkBeforeOperation() +{ + loadViewContent(); + KListView* sv = m_view->getStringsView(); + + // Checks if there are strings to replace (not need in search operation) + if (sv->childCount() == 0) + { + KMessageBox::error(m_w, i18n("There are no strings to search and replace.")); + return false; + } + + // Checks if the main directory can be accessed + QString currentDirectory = m_option->m_directories[0]; + QDir dir; + + dir.setPath(currentDirectory); + QString directory = dir.absPath(); + + if(!dir.exists()) + { + KMessageBox::error(m_w, i18n("The main folder of the project %1 does not exist.").arg(directory)); + return false; + } + + QFileInfo dirInfo(directory); + if(!(dirInfo.isReadable() && dirInfo.isExecutable()) + || (!m_option->m_searchingOnlyMode && !m_option->m_simulation && !(dirInfo.isWritable()))) + { + KMessageBox::error(m_w, i18n("Access denied in the main folder of the project:
%1
").arg(directory)); + return false; + } + + // Clears the list view + m_view->getResultsView()->clear(); + + return true; +} + +bool KFileReplacePart::dontAskAgain() +{ + m_config->setGroup("Notification Messages"); + QString dontAskAgain = m_config->readEntry(rcDontAskAgain, "no"); + if(dontAskAgain == "yes") + return true; + else + return false; +} + +void KFileReplacePart::whatsThis() +{ + actionCollection()->action("options_backup")->setWhatsThis(optionsBackupWhatthis); + actionCollection()->action("options_case")->setWhatsThis(optionsCaseWhatthis); + actionCollection()->action("options_var")->setWhatsThis(optionsVarWhatthis); + actionCollection()->action("options_recursive")->setWhatsThis(optionsRecursiveWhatthis); + actionCollection()->action("options_regularexpressions")->setWhatsThis(optionsRegularExpressionsWhatthis); +} + +#include "kfilereplacepart.moc" diff --git a/kfilereplace/kfilereplacepart.desktop b/kfilereplace/kfilereplacepart.desktop new file mode 100644 index 00000000..388f6579 --- /dev/null +++ b/kfilereplace/kfilereplacepart.desktop @@ -0,0 +1,95 @@ +[Desktop Entry] +Type=Service +MimeType=inode/directory +Icon=kfilereplace.png +ServiceTypes=KParts/ReadOnlyPart +X-KDE-Library=libkfilereplacepart +Comment=A batch search and replace tool +Comment[bg]=˘ÑŠÑ€Ñµ½µ ¸ ·°ĵя½° ²ÑŠ² ф½² рµĥ¸ĵ +Comment[ca]=Una eina per a la cerca i substituci³ per lots +Comment[cs]=DĦvkov½ nĦstroj pro hledĦn­ a nahrazovĦn­ +Comment[da]=S¸g- og erstat-gruppek¸rselsvĤrkt¸j +Comment[de]=Ein Werkzeug zum Suchen und Ersetzen im Stapelbetrieb +Comment[el]= ΕργÎħÎğείο Ï€ÎżÎğÎğÎħπÎğÎς ÎħνÎħÎĥÎτησης ÎşÎħÎı ÎħντÎıÎşÎħτÎĴστÎħσης +Comment[es]=Una herramienta de bşsqueda y reemplazo por lotes +Comment[et]=Otsimise ja asendamise tĥĥriist +Comment[eu]=Bilaketa eta ordezkapen tresna +Comment[fa]=Ĝ§Ĝ¨Ĝ²Ĝ§Ĝħ ĜĴĜ³ĜŞĜĴو و ĜĴĜ§ÛŒÚŻĜ²ÛŒÙ†ÛŒ ĜŻĜ³ĜŞÙ‡â€ŒĜ§ÛŒ +Comment[fi]=Batchien etsint¤- ja korvaustyĥkalu +Comment[fr]=Un outil de recherche et de remplacement de texte en sİrie. +Comment[gl]=Unha utilidade de busca e reemprazo por lotes +Comment[hi]=एक खà‹à¤œ तà¤à¤ à¤Ĵà¤Ĥल à¤‰à¤Şà¤•à¤°à¤£ +Comment[hu]=Sok fĦjl kezelİsİre alkalmas keresĊ‘- İs cserİlĊ‘program +Comment[is]=T³l til a° leita a° texta og skipta şt +Comment[it]=Uno strumento per la ricerca e la sostituzione in sequenza +Comment[ja]=ƒƒƒƒĉ¤œç´˘Š‚ˆ³ç½ĉ›ƒ„ƒĵƒĞ +Comment[ka]=áƒŻáƒ’áƒ£áƒ¤áƒ£áƒ áƒ˜ áƒĞიებიáƒĦ და áƒİანაცვლებიáƒĦ áƒáƒ”ლáƒĦაáƒĴყო +Comment[lt]=Paketinis paieĊĦkos ir keitimo ÄŻrankis +Comment[ms]=Gugusan alatan cari dan ganti +Comment[nds]=En Sĥĥk- un Utwesselwarktĵĵch fĥr Stapelbedrief +Comment[ne]=एउटठसà¤à‚à¤ı खà‹à¤œà€ गरàà¤¨à‡ र à¤Ĵà¤Ĥलàà¤¨à‡ à¤‰à¤Şà¤•à¤°à¤£ +Comment[nl]=Een gereedschap voor zoeken en vervangen +Comment[pl]=Narzędzie do wyszukiwania i zamiany +Comment[pt]=Uma ferramenta de procura e substitui§£o por atacado +Comment[pt_BR]=Uma ferramenta de substitui§£o e pesquisa batch +Comment[ru]=Ÿ°şµÑ‚½Ñ‹ı ż¸Ñş ¸ ·°ĵµ½° +Comment[sk]=DĦvkovac­ nĦstroj pre nĦjsĊ a zameniĊ +Comment[sl]=Orodje serijskega iskanja in zamenjevanja +Comment[sr]=ğ°Ñ‚ ·° ż°şµÑ‚½Ñƒ żÑ€µÑ‚Ñ€°³Ñƒ ¸ ·°ĵµ½Ñƒ +Comment[sr@Latn]=Alat za paketnu pretragu i zamenu +Comment[sv]=Ett sĥk- och ers¤ttningsverktyg +Comment[ta]=à¤àŻŠà•àŻà¤àż à¤àŻ‡àŸà²àŻ ààħàŻàħàŻààŻ à•à°àŻàµàż à‡àŸàààħàŻàħà²àŻ +Comment[tg]=ÒĥÑƒÑÑ‚ÑƒÒ·ÓŻ¸ ż°şµÑ‚ ²° ¸²°·¸ °Ñħħ +Comment[tr]=Bir toplu arama ve değiĊŸtirme aracÄħ +Comment[uk]=—°ÑÑ–ħ ż°şµÑ‚½³ żÑˆÑƒşÑƒ т° ·°ĵі½¸ +Comment[zh_CN]=ĉ‰ı量ĉœç´˘ĉ›żĉ˘ċ·ċ…· +Comment[zh_HK]=ĉ‰ıĉĴĦĉœċ°‹ċŠċ–äğ£ċ·ċ…· +Comment[zh_TW]=ĉ‰ıĉĴĦĉœċ°‹ċŠċ–äğ£ċ·ċ…· +Name=KFileReplace +Name[hi]=कà‡-à¤Ğà¤ĵà¤à¤‡à¤²-à¤°à¤żà¤Şàà¤²à‡à¤¸ +Name[ne]=à¤Ĵà¤Ĥलàà¤¨à‡ कà‡à¤Ħà€à¤ˆ à¤Ğà¤à¤‡à¤² +Name[pa]=ਕà݇-à¨Ğà¨à¨‡à¨²-à¨Ĵà¨Ĥਲàİ‹ +Name[sk]=KFile zameniĊ +Name[sv]=Kfilereplace +Name[ta]=Kà•àŻ‹àŞàŻàŞàŻ à‡àŸàààħàŻàħàŻ +Name[tg]=K¤°ığр Ò·ı³Ñƒ·Ñ€ ş°Ñ€´°½ +Name[tr]=K Dosya DeğiĊŸtirme +GenericName=File Replace View +GenericName[bg]=ŸÑ€µ³ğµ´ ½° ф°ığ²µÑ‚µ ·° ·°ĵя½° +GenericName[ca]=Vista per a substituir fitxers +GenericName[cs]=Nahrazen­ souborĊŻ +GenericName[da]=Filerstatningsvisning +GenericName[de]=KFileReplace +GenericName[el]=Î ÏÎżÎ²ÎżÎğÎ ÎħντÎıÎşÎħτÎĴστÎħσης ÎħÏÏ‡ÎµÎŻÎżÏ… +GenericName[es]=Vista de reemplazo de archivo +GenericName[et]=Failide asendamise vaade +GenericName[eu]=Fitxategi ordezkapen ikuspegia +GenericName[fa]=نمĜ§ÛŒ ĜĴĜ§ÛŒÚŻĜ²ÛŒÙ†ÛŒ ÙĜħونĜŻÙ‡ +GenericName[fi]=Tiedoston korvausn¤yttĥ +GenericName[fr]=Remplacement de fichiers +GenericName[gl]=Vista de reemprazo de ficheiro +GenericName[hu]=FĦjlcserİlĊ‘ nİzet +GenericName[is]=Texta ştskiptingars½n +GenericName[it]=Vista di sostituzione file +GenericName[ja]=ƒ•‚Ħ‚¤ƒĞç½ĉ›ƒ“ƒƒĵ +GenericName[ka]=ფაილიáƒĦ áƒİანაცვლებიáƒĦ áƒáƒ”დი +GenericName[lt]=KeitimĊ³ bylose vaizdas +GenericName[ms]=Paparan Ganti Fail +GenericName[nds]=Datei-Utwesselansicht +GenericName[ne]=à¤Ğà¤à¤‡à¤² à¤Ĵà¤Ĥलàà¤¨à‡ à¤Ĥàƒà¤ĥàà¤Ż +GenericName[nl]=Weergave van bestanden vervangen +GenericName[pa]=à¨Ğà¨à¨‡à¨² ਤà¨Ĵà¨Ĥà݀ਲ ਝਲਕ +GenericName[pl]=Widok zamiany w plikach +GenericName[pt]=Vista de Substitui§£o de Ficheiros +GenericName[pt_BR]=Vis£o de Substitui§£o de Arquivos +GenericName[ru]=Ħрµ´ÑÑ‚² ż¸Ñş° ¸ ·°ĵµ½Ñ‹ ² ф°ığ°Ñ… +GenericName[sk]=PohÄad zĦmeny sşboru +GenericName[sl]=Prikaz zamenjave datotek +GenericName[sr]=ŸÑ€¸ş°· ·°ĵµ½° у ф°Ñ˜ğ²¸ĵ° +GenericName[sr@Latn]=Prikaz zamena u fajlovima +GenericName[sv]=Filers¤ttningsvy +GenericName[ta]=à•àŻ‹àŞàŻàŞàŻ à‡àŸàààħàŻàħàŻ à•ààŸàŻàšàż +GenericName[uk]=ŸµÑ€µ³ğя´ ·°ĵі½¸ ² ф°ığ°Ñ… +GenericName[zh_CN]=ĉ–‡äğĥĉ›żĉ˘è§†ċ› +GenericName[zh_HK]=ĉŞ”ĉĦˆċ–äğ£ĉŞ˘èĤ–ĉ¨Ħċĵ +GenericName[zh_TW]=ĉŞ”ĉĦˆċ–äğ£ĉŞ˘èĤ– diff --git a/kfilereplace/kfilereplacepart.h b/kfilereplace/kfilereplacepart.h new file mode 100644 index 00000000..1c133cb5 --- /dev/null +++ b/kfilereplace/kfilereplacepart.h @@ -0,0 +1,159 @@ +// +// +// C++ Interface: kfilereplacepart +// +// Description: +// +// +// Author: Andras Mantia , (C) 2003 +// Maintainer: Emiliano Gulmini , (C) 2004 +// +// Copyright: GPL v2. See COPYING file that comes with this distribution +// +// + +#ifndef KFILEREPLACEPART_H +#define KFILEREPLACEPART_H + +// QT + +// KDE +#include +class KAboutApplication; +class KAboutData; +class KConfig; + +// local +#include "configurationclasses.h" +class KFileReplaceView; + +#define KFR_VERSION "0.8.1" + +class KFileReplacePart: public KParts::ReadOnlyPart +{ + Q_OBJECT + + private: //MEMBERS + KFileReplaceView* m_view; + QWidget* m_parentWidget, + * m_w; + KConfig* m_config; + KAboutApplication* m_aboutDlg; + KeyValueMap m_replacementMap; + RCOptions* m_option; + bool m_stop, + m_searchingOperation; + int m_optionMask; + + public://Constructors + KFileReplacePart(QWidget *parentWidget, + const char *widgetName, + QObject *parent, + const char *name, + const QStringList &args); + ~KFileReplacePart(); + + //SLOTS + private slots: + void slotSetNewParameters(); + void slotSearchingOperation(); + void slotReplacingOperation(); + void slotSimulatingOperation(); + void slotStop(); + void slotCreateReport(); + void slotStringsAdd(); + void slotQuickStringsAdd(); + void slotStringsDeleteItem(); + void slotStringsEmpty(); + void slotStringsEdit(); + void slotStringsSave(); + void slotStringsLoad(); + void slotStringsInvertCur(); + void slotStringsInvertAll(); + void slotOpenRecentStringFile(const KURL& urlFile); + void slotOptionRecursive(); + void slotOptionBackup(); + void slotOptionCaseSensitive(); + void slotOptionVariables(); + void slotOptionRegularExpressions(); + void slotOptionPreferences(); + void showAboutApplication(void); + void appHelpActivated(); + void reportBug(); + void resetActions(); + void slotSearchMode(bool b){ m_option->m_searchingOnlyMode = b; } + + //METHODS + public: + static KAboutData* createAboutData(); + KConfig *config(){ return m_config; } + + protected: + virtual bool openFile() { return false; } + virtual bool openURL (const KURL &url); + + private: + /** + * Initialization methods + */ + void initGUI(); + void initView(); + + /** + * This method freezes the GUI of kfilereplace during searching + */ + void freezeActions(); + + /** + * These methods load the resources from kfilereplacerc + */ + void loadOptionsFromRC(); + void loadOptions(); + void loadFileSizeOptions(); + void loadDateAccessOptions(); + void loadOwnerOptions(); + void loadLocationsList(); + void loadFiltersList(); + void loadBackupExtensionOptions(); + + /** + * These methods save the resources to kfilereplacerc + */ + void saveOptionsToRC(); + void saveOptions(); + void saveFileSizeOptions(); + void saveDateAccessOptions(); + void saveOwnerOptions(); + void saveLocationsList(); + void saveFiltersList(); + void saveBackupExtensionOptions(); + + /** + * Replacing methods + */ + void fileReplace(); + void recursiveFileReplace(const QString& dirName, int& filesNumber); + void replaceAndBackup(const QString& currentDir, const QString& oldFileName); + void replaceAndOverwrite(const QString& currentDir, const QString& oldFileName); + void replacingLoop(QString& line, KListViewItem** item, bool& atLeastOneStringFound, int& occur, bool regularExpression, bool& askConfirmReplace); + + /** + * Searching methods + */ + void fileSearch(const QString& dirName, const QString& filters); + void recursiveFileSearch(const QString& dirName, const QString& filters, uint& filesNumber); + void search(const QString& currentDir, const QString& fileName); + + /** + * Others methods + */ + void loadViewContent(); + void loadRulesFile(const QString& fileName); + bool launchNewProjectDialog(const KURL& startURL); + void setOptionMask(); + bool checkBeforeOperation(); + bool dontAskAgain(); + void whatsThis(); +}; + +#endif// KFileReplacePart diff --git a/kfilereplace/kfilereplacepartui.rc b/kfilereplace/kfilereplacepartui.rc new file mode 100644 index 00000000..66946878 --- /dev/null +++ b/kfilereplace/kfilereplacepartui.rc @@ -0,0 +1,75 @@ + + + + Search/&Replace + + + + + + + &Strings + + + + + + + + + + + + + &Results + + + + + + + + + + + + &Options + + + + + + + + &Settings + + + &Help + + + + + + + +KFileReplace Main Toolbar + + + + + + + + + + + + + + + + + + + + diff --git a/kfilereplace/kfilereplaceui.rc b/kfilereplace/kfilereplaceui.rc new file mode 100644 index 00000000..2f645413 --- /dev/null +++ b/kfilereplace/kfilereplaceui.rc @@ -0,0 +1,10 @@ + + + + &File + + + Search/&Replace + + + diff --git a/kfilereplace/kfilereplaceview.cpp b/kfilereplace/kfilereplaceview.cpp new file mode 100644 index 00000000..16ca82da --- /dev/null +++ b/kfilereplace/kfilereplaceview.cpp @@ -0,0 +1,672 @@ +/***************************************************************************** + kfilereplaceview.cpp - description + ------------------- + begin : sam oct 16 15:28:00 CEST 1999 + copyright : (C) 1999 by Franïż½is Dupoux + (C) 2004 Emiliano Gulmini +*****************************************************************************/ + +/***************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + *****************************************************************************/ + +// Qt +#include +#include +#include + +// KDE +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include + +// local +#include "kfilereplaceview.h" +#include "kfilereplacelib.h" +#include "kaddstringdlg.h" +#include "whatthis.h" + +using namespace whatthisNameSpace; + +KFileReplaceView::KFileReplaceView(RCOptions* info, QWidget *parent,const char *name):KFileReplaceViewWdg(parent,name) +{ + m_option = info; + + initGUI(); + + // connect events + connect(m_lvResults, SIGNAL(mouseButtonClicked(int, QListViewItem *, const QPoint &, int)), this, SLOT(slotMouseButtonClicked(int, QListViewItem *, const QPoint &))); + connect(m_lvResults_2, SIGNAL(mouseButtonClicked(int, QListViewItem *, const QPoint &, int)), this, SLOT(slotMouseButtonClicked(int, QListViewItem *, const QPoint &))); + connect(m_lvStrings, SIGNAL(doubleClicked(QListViewItem *)), this, SLOT(slotStringsEdit())); + connect(m_lvStrings_2, SIGNAL(doubleClicked(QListViewItem *)), this, SLOT(slotStringsEdit())); + + whatsThis(); +} + +QString KFileReplaceView::currentPath() +{ + QListViewItem *lvi; + + if(! m_lviCurrent) lvi = m_rv->currentItem(); + else lvi = (QListViewItem*) m_lviCurrent; + + while (lvi->parent()) + lvi = lvi->parent(); + + return QString(lvi->text(1)+"/"+lvi->text(0)); +} + +void KFileReplaceView::showSemaphore(QString s) +{ + if(s == "green") + { + m_ledGo->setState(KLed::On); + m_ledWait->setState(KLed::Off); + m_ledStop->setState(KLed::Off); + } + else + if(s == "yellow") + { + m_ledGo->setState(KLed::Off); + m_ledWait->setState(KLed::On); + m_ledStop->setState(KLed::Off); + } + else + if(s == "red") + { + m_ledGo->setState(KLed::Off); + m_ledWait->setState(KLed::Off); + m_ledStop->setState(KLed::On); + } +} + +void KFileReplaceView::stringsInvert(bool invertAll) +{ + QListViewItem* lviCurItem, + * lviFirst; + KListView* sv = getStringsView(); + + if(invertAll) + lviCurItem = lviFirst = sv->firstChild(); + else + lviCurItem = lviFirst = sv->currentItem(); + + if(lviCurItem == 0) + return ; + + do + { + QString searchText = lviCurItem->text(0), + replaceText = lviCurItem->text(1); + + // Cannot invert the string when search string is empty + if (replaceText.isEmpty()) + { + KMessageBox::error(0, i18n("Cannot invert string %1, because the search string would be empty.").arg(searchText)); + return; + } + + lviCurItem->setText(0, replaceText); + lviCurItem->setText(1, searchText); + + lviCurItem = lviCurItem->nextSibling(); + if(!invertAll) + break; + } while(lviCurItem && lviCurItem != lviFirst); + setCurrentStringsViewMap(); +} + +void KFileReplaceView::changeView(bool searchingOnlyMode) +{ + if(searchingOnlyMode) + { + m_stackResults->raiseWidget(m_lvResults_2); + m_stackStrings->raiseWidget(m_lvStrings_2); + m_rv = m_lvResults_2; + m_sv = m_lvStrings_2; + } + else + { + m_stackResults->raiseWidget(m_lvResults); + m_stackStrings->raiseWidget(m_lvStrings); + m_rv = m_lvResults; + m_sv = m_lvStrings; + } +} + +KListView* KFileReplaceView::getResultsView() +{ + if(m_option->m_searchingOnlyMode) + m_rv = m_lvResults_2; + else + m_rv = m_lvResults; + + return m_rv; +} + +KListView* KFileReplaceView::getStringsView() +{ + if(m_option->m_searchingOnlyMode) + m_sv = m_lvStrings_2; + else + m_sv = m_lvStrings; + return m_sv; +} + +//PUBLIC SLOTS +void KFileReplaceView::slotMouseButtonClicked (int button, QListViewItem *lvi, const QPoint &pos) +{ + if (lvi == 0) // No item selected + return; + + // RIGHT BUTTON + if (button == QMouseEvent::RightButton) + { + m_lviCurrent = static_cast(lvi); + m_menuResult->popup(pos); + } +} + +void KFileReplaceView::slotResultProperties() +{ + QString currItem = currentPath(); + if(! currItem.isEmpty()) + { + KURL url(currItem); + (void) new KPropertiesDialog(url); + m_lviCurrent = 0; + } +} + +void KFileReplaceView::slotResultOpen() +{ + QString currItem = currentPath(); + if(!currItem.isEmpty()) + { + (void) new KRun(KURL(currItem), 0, true, true); + m_lviCurrent = 0; + } +} + +void KFileReplaceView::slotResultOpenWith() +{ + QString currItem = currentPath(); + if(!currItem.isEmpty()) + { + KURL::List kurls; + kurls.append(KURL(currItem)); + KRun::displayOpenWithDialog(kurls); + m_lviCurrent = 0; + } +} + +void KFileReplaceView::slotResultDirOpen() +{ + QString currItem = currentPath(); + if(!currItem.isEmpty()) + { + QFileInfo fi; + fi.setFile(currItem); + (void) new KRun (KURL::fromPathOrURL(fi.dirPath()), 0, true, true); + m_lviCurrent = 0; + } +} + +void KFileReplaceView::slotResultEdit() +{ + QListViewItem *lvi = m_rv->firstChild(); + + while (lvi) + { + DCOPClient *client = kapp->dcopClient(); + DCOPRef quanta(client->appId(),"WindowManagerIf"); + QString path = QString(lvi->text(1)+"/"+lvi->text(0)); + QListViewItem *lviChild = lvi; + + while(lviChild) + { + if(lviChild->isSelected()) + { + coord c; + if(lviChild == lvi) + { + c.line = 0; + c.column = 0; + } + else + { + c= extractWordCoordinates(lviChild); + } + bool success = quanta.send("openFile", path, c.line, c.column); + + if(!success) + { + QString message = i18n("File %1 cannot be opened. Might be a DCOP problem.").arg(path); + KMessageBox::error(parentWidget(), message); + } + } + if (lviChild == lvi) + lviChild = lviChild->firstChild(); + else + lviChild = lviChild->nextSibling(); + } + + lvi = lvi->nextSibling(); + } + + m_lviCurrent = 0; +} + +void KFileReplaceView::slotResultDelete() +{ + QString currItem = currentPath(); + if (!currItem.isEmpty()) + { + QFile fi; + int answer = KMessageBox::warningContinueCancel(this, i18n("Do you really want to delete %1?").arg(currItem), + QString::null,KStdGuiItem::del()); + + if(answer == KMessageBox::Continue) + { + fi.setName(currItem); + fi.remove(); + + delete m_lviCurrent; + m_lviCurrent = 0; + } + } +} + +void KFileReplaceView::slotResultTreeExpand() +{ + QListViewItem *lviRoot = getResultsView()->firstChild(); + + if(lviRoot) + expand(lviRoot, true); +} + +void KFileReplaceView::slotResultTreeReduce() +{ + QListViewItem *lviRoot = getResultsView()->firstChild(); + + if(lviRoot) + expand(lviRoot, false); +} + +void KFileReplaceView::slotStringsAdd() +{ + KeyValueMap oldMap(m_option->m_mapStringsView); + + KAddStringDlg addStringDlg(m_option, false); + + if(!addStringDlg.exec()) + return; + + KeyValueMap addedStringsMap(m_option->m_mapStringsView); + KeyValueMap::Iterator itMap; + + for(itMap = oldMap.begin(); itMap != oldMap.end(); ++itMap) + addedStringsMap.insert(itMap.key(),itMap.data()); + + m_option->m_mapStringsView = addedStringsMap; + + raiseResultsView(); + raiseStringsView(); + + loadMapIntoView(addedStringsMap); +} + +void KFileReplaceView::slotQuickStringsAdd(const QString& quickSearch, const QString& quickReplace) +{ + if(!quickSearch.isEmpty()) + { + KeyValueMap map; + if(quickReplace.isEmpty()) + { + map[quickSearch] = QString::null; + m_option->m_searchingOnlyMode = true; + } + else + { + map[quickSearch] = quickReplace; + m_option->m_searchingOnlyMode = false; + } + + m_option->m_mapStringsView = map; + + raiseResultsView(); + raiseStringsView(); + + loadMapIntoView(map); + } +} + +void KFileReplaceView::slotStringsEdit() +{ + KeyValueMap oldMap(m_option->m_mapStringsView); + if(oldMap.isEmpty()) return; + bool oldSearchFlagValue = m_option->m_searchingOnlyMode; + + oldMap.remove(m_sv->currentItem()->text(0)); + + m_option->m_mapStringsView.clear(); + + m_option->m_mapStringsView.insert(m_sv->currentItem()->text(0), m_sv->currentItem()->text(1)); + + KAddStringDlg addStringDlg(m_option, true); + + if(!addStringDlg.exec()) + return; + + KeyValueMap newMap(m_option->m_mapStringsView); + if(oldSearchFlagValue == m_option->m_searchingOnlyMode) + { + KeyValueMap::Iterator itMap; + + //merges the two maps + for(itMap = oldMap.begin(); itMap != oldMap.end(); ++itMap) + newMap.insert(itMap.key(),itMap.data()); + } + + m_option->m_mapStringsView = newMap; + + raiseResultsView(); + raiseStringsView(); + + loadMapIntoView(newMap); +} + +void KFileReplaceView::slotStringsSave() +{ + // Check there are strings in the list + KListView* sv = getStringsView(); + + if (sv->firstChild() == 0) + { + KMessageBox::error(0, i18n("No strings to save as the list is empty.")); + return ; + } + + QString header("\n"), + footer("\n"), + body; + if(m_option->m_searchingOnlyMode) + header += "\n\t"; + else + header += "\n\t"; + + QListViewItem* lvi = sv->firstChild(); + + while( lvi ) + { + body += QString("\n\t" + "\n\t\t" + "\n\t\t" + "\n\t").arg(lvi->text(0)).arg(lvi->text(1)); + lvi = lvi->nextSibling(); + } + + // Selects the file where strings will be saved + QString menu = "*.kfr|" + i18n("KFileReplace Strings") + " (*.kfr)\n*|" + i18n("All Files") + " (*)"; + QString fileName = KFileDialog::getSaveFileName(QString::null, menu, 0, i18n("Save Strings to File")); + if (fileName.isEmpty()) + return; + + // Forces the extension to be "kfr" == KFileReplace extension + + fileName = KFileReplaceLib::addExtension(fileName, "kfr"); + + QFile file( fileName ); + if(!file.open( IO_WriteOnly )) + { + KMessageBox::error(0, i18n("File %1 cannot be saved.").arg(fileName)); + return ; + } + QTextStream oTStream( &file ); + oTStream.setEncoding(QTextStream::UnicodeUTF8); + oTStream << header + << body + << footer; + file.close(); +} + +void KFileReplaceView::slotStringsDeleteItem() +{ + QListViewItem* item = m_sv->currentItem(); + if(item != 0) + { + KeyValueMap m = m_option->m_mapStringsView; + m.remove(item->text(0)); + m_option->m_mapStringsView = m; + delete item; + } +} + +void KFileReplaceView::slotStringsEmpty() +{ + QListViewItem * myChild = m_sv->firstChild(); + while( myChild ) + { + QListViewItem* item = myChild; + myChild = myChild->nextSibling(); + delete item; + } + KeyValueMap m; + m_option->m_mapStringsView = m; +} + +//PRIVATE +void KFileReplaceView::initGUI() +{ + m_option->m_searchingOnlyMode = true; + + m_stackResults->addWidget(m_lvResults); + m_stackResults->addWidget(m_lvResults_2); + m_stackStrings->addWidget(m_lvStrings); + m_stackStrings->addWidget(m_lvStrings_2); + + DCOPClient *client = kapp->dcopClient(); + QCStringList appList = client->registeredApplications(); + bool quantaFound = false; + + + for(QCStringList::Iterator it = appList.begin(); it != appList.end(); ++it) + { + if((*it).left(6) == "quanta") + { + quantaFound = true; + break; + } + } + + m_menuResult = new KPopupMenu(this, "ResultPopup"); + + + + m_menuResult->insertItem(SmallIconSet(QString::fromLatin1("fileopen")), + i18n("&Open"), + this, + SLOT(slotResultOpen())); + if(!quantaFound) + { + m_menuResult->insertItem(i18n("Open &With..."), + this, + SLOT(slotResultOpenWith())); + } + + if(quantaFound) + { + m_menuResult->insertItem(SmallIconSet("quanta"), + i18n("&Edit in Quanta"), + this, + SLOT(slotResultEdit())); + } + + m_menuResult->insertItem(SmallIconSet(QString::fromLatin1("up")), + i18n("Open Parent &Folder"), + this, + SLOT(slotResultDirOpen())); + m_menuResult->insertItem(SmallIconSet(QString::fromLatin1("editdelete")), + i18n("&Delete"), + this, + SLOT(slotResultDelete())); + m_menuResult->insertSeparator(); + m_menuResult->insertItem(SmallIconSet(QString::fromLatin1("info")), + i18n("&Properties"), + this, + SLOT(slotResultProperties())); + raiseResultsView(); + raiseStringsView(); +} + +void KFileReplaceView::raiseStringsView() +{ + if(m_option->m_searchingOnlyMode) + m_sv = m_lvStrings_2; + else + m_sv = m_lvStrings; + + m_stackStrings->raiseWidget(m_sv); +} + +void KFileReplaceView::raiseResultsView() +{ + if(m_option->m_searchingOnlyMode) + m_rv = m_lvResults_2; + else + m_rv = m_lvResults; + + m_stackResults->raiseWidget(m_rv); +} + +coord KFileReplaceView::extractWordCoordinates(QListViewItem* lvi) +{ + //get coordinates of the first string of the current selected file + coord c; + c.line = 0; + c.column = 0; + QString s = lvi->text(0); + //qWarning("WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW=%s",s.latin1()); + /* if(lvi->parent()) s = lvi->text(0); + else return c;*/ + + QString temp; + int i = 0; + + //extracts line and column from lvi->text(0) + //FIXME: Don't get the line and column number from the text as it's translated and it will + //fail for non-English languages! + + //EMILIANO: This is not a good fixing but for now it should reduce the problems + while(true) + { + if(s[i] < '0' || s[i] > '9') + i++; + else + break; + } + while(true) + { + if(s[i] >= '0' && s[i] <= '9') + { + temp += s[i]; + i++; + } + else + break; + } + c.line = temp.toInt(); + temp = QString::null; + + while(true) + { + if(s[i] < '0' || s[i] > '9') + i++; + else + break; + } + while(true) + { + if(s[i] >= '0' && s[i] <= '9') + { + temp += s[i]; + i++; + } + else + break; + } + c.column = temp.toInt(); + + if(c.line > 0) c.line--; + if(c.column > 0) c.column--; + + return c; +} + +void KFileReplaceView::expand(QListViewItem *lviCurrent, bool b) +{ + // current item + lviCurrent->setOpen(b); + + // recursivity + while((lviCurrent = lviCurrent->nextSibling()) != 0) + { + lviCurrent->setOpen(b); + + if (lviCurrent->firstChild()) + expand(lviCurrent->firstChild(), b); + } +} + +void KFileReplaceView::setMap() +{ + KeyValueMap map; + QListViewItem* i = m_sv->firstChild(); + while(i != 0) + { + if(m_option->m_searchingOnlyMode) + map[i->text(0)] = QString::null; + else + map[i->text(0)] = i->text(1); + i = i->nextSibling(); + } + m_option->m_mapStringsView = map; +} + +void KFileReplaceView::loadMapIntoView(KeyValueMap map) +{ + m_sv->clear(); + KeyValueMap::Iterator itMap; + + for(itMap = map.begin(); itMap != map.end(); ++itMap) + { + QListViewItem* lvi = new QListViewItem(m_sv); + lvi->setMultiLinesEnabled(true); + lvi->setText(0,itMap.key()); + if(!m_option->m_searchingOnlyMode) + lvi->setText(1,itMap.data()); + } + +} + +void KFileReplaceView::whatsThis() +{ + QWhatsThis::add(getResultsView(), lvResultWhatthis); + QWhatsThis::add(getStringsView(), lvStringsWhatthis); +} +#include "kfilereplaceview.moc" diff --git a/kfilereplace/kfilereplaceview.h b/kfilereplace/kfilereplaceview.h new file mode 100644 index 00000000..21ac6a29 --- /dev/null +++ b/kfilereplace/kfilereplaceview.h @@ -0,0 +1,116 @@ +/*************************************************************************** + kfilereplaceview.h - description + ------------------- + begin : sam oct 16 15:28:00 CEST 1999 + copyright : (C) 1999 by François Dupoux + (C) 2004 Emiliano Gulmini + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KFILEREPLACEVIEW_H +#define KFILEREPLACEVIEW_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +//QT +#include +#include +class QPixMap; + +//KDE +class KPopupMenu; +class KListView; + +//local +#include "kfilereplaceviewwdg.h" +#include "configurationclasses.h" + +class coord +{ + public: + int line, + column; + public: + coord(){ line = 1; + column = 1;} + coord(const coord& c) { line = c.line; + column = c.column;} + coord operator=(const coord& c) { line = c.line; + column = c.column; + return (*this);} +}; + + +/** + * The view of KFilereplace. + */ +class KFileReplaceView : public KFileReplaceViewWdg +{ + Q_OBJECT + private: + KPopupMenu* m_menuResult; + RCOptions* m_option; + KListViewItem* m_lviCurrent; + KListView* m_rv, + * m_sv; + + public://Constructors + KFileReplaceView(RCOptions* info, QWidget *parent,const char *name); + + public: + QString currentPath(); + void showSemaphore(QString s); + void displayScannedFiles(int filesNumber) { m_lcdFilesNumber->display(QString::number(filesNumber,10)); } + void stringsInvert(bool invertAll); + void changeView(bool searchingOnlyMode); + KListView* getResultsView(); + KListView* getStringsView(); + void updateOptions(RCOptions* info) { m_option = info; } + void loadMap(KeyValueMap extMap){ loadMapIntoView(extMap); } + KeyValueMap getStringsViewMap()const { return m_option->m_mapStringsView;} + void setCurrentStringsViewMap(){ setMap(); } + //void emitSearchingOnlyMode(bool b) { emit searchingOnlyMode(b); } + + public slots: + void slotMouseButtonClicked (int button, QListViewItem *lvi, const QPoint &pos); + void slotResultProperties(); + void slotResultOpen(); + void slotResultOpenWith(); + void slotResultDirOpen(); + void slotResultEdit(); + void slotResultDelete(); + void slotResultTreeExpand(); + void slotResultTreeReduce(); + void slotStringsAdd(); + void slotQuickStringsAdd(const QString& quickSearch, const QString& quickReplace); + void slotStringsDeleteItem(); + void slotStringsEmpty(); + void slotStringsEdit(); + void slotStringsSave(); + + private: + void initGUI(); + void raiseStringsView(); + void raiseResultsView(); + coord extractWordCoordinates(QListViewItem* lvi); + void expand(QListViewItem *lviCurrent, bool b); + void setMap(); + void loadMapIntoView(KeyValueMap map); + void whatsThis(); + + /*signals: + void resetActions(); + void searchingOnlyMode(bool);*/ +}; + +#endif // KFILEREPLACEVIEW_H diff --git a/kfilereplace/kfilereplaceviewwdg.ui b/kfilereplace/kfilereplaceviewwdg.ui new file mode 100644 index 00000000..17be7441 --- /dev/null +++ b/kfilereplace/kfilereplaceviewwdg.ui @@ -0,0 +1,555 @@ + +KFileReplaceViewWdg + + + KFileReplaceViewWdg + + + + 0 + 0 + 635 + 370 + + + + + unnamed + + + 0 + + + + splitter3 + + + Vertical + + + + m_stackResults + + + + 7 + 7 + 0 + 0 + + + + + WStackPage + + + 0 + + + + unnamed + + + 0 + + + + + Name + + + true + + + true + + + + + Folder + + + true + + + true + + + + + Old Size + + + true + + + true + + + + + New Size + + + true + + + true + + + + + Replaced Strings + + + true + + + true + + + + + Owner User + + + true + + + true + + + + + Owner Group + + + true + + + true + + + + m_lvResults + + + Extended + + + true + + + true + + + true + + + LastColumn + + + false + + + + 238 + 246 + 255 + + + + + + + + WStackPage + + + 1 + + + + unnamed + + + 0 + + + + + Name + + + true + + + true + + + + + Folder + + + true + + + true + + + + + Size + + + true + + + true + + + + + Found Strings + + + true + + + true + + + + + Owner User + + + true + + + true + + + + + Owner Group + + + true + + + true + + + + m_lvResults_2 + + + Extended + + + true + + + true + + + true + + + LastColumn + + + false + + + + 238 + 246 + 255 + + + + + + + + + m_stackStrings + + + + 7 + 7 + 0 + 0 + + + + + WStackPage + + + 0 + + + + unnamed + + + 0 + + + + + Search For + + + true + + + true + + + + + Replace With + + + true + + + true + + + + m_lvStrings + + + true + + + false + + + AllColumns + + + false + + + + + + + WStackPage + + + 1 + + + + unnamed + + + 0 + + + + + Search For + + + true + + + true + + + + m_lvStrings_2 + + + true + + + false + + + AllColumns + + + false + + + + + + + + + layout7 + + + + unnamed + + + + layout6 + + + + unnamed + + + + m_ledGo + + + + 20 + 20 + + + + On + + + + 170 + 255 + 0 + + + + Green means ready + + + Ready + + + + + m_ledWait + + + + 20 + 20 + + + + On + + + + 255 + 255 + 0 + + + + Yellow means wait while sorting list + + + Please wait while sorting list + + + + + m_ledStop + + + + 20 + 20 + + + + + 255 + 0 + 0 + + + + Red means scanning files + + + + + + + spacer1 + + + Horizontal + + + Expanding + + + + 354 + 20 + + + + + + layout1 + + + + unnamed + + + + m_tlFilesNumber + + + Scanned files: + + + + + m_lcdFilesNumber + + + LineEditPanel + + + Raised + + + 7 + + + Dec + + + Flat + + + 0 + + + + + + + + + + + klistview.h + klistview.h + klistview.h + klistview.h + kled.h + kled.h + kled.h + + diff --git a/kfilereplace/knewprojectdlg.cpp b/kfilereplace/knewprojectdlg.cpp new file mode 100644 index 00000000..5428473b --- /dev/null +++ b/kfilereplace/knewprojectdlg.cpp @@ -0,0 +1,531 @@ +/*************************************************************************** + knewprojectdlg.cpp - description + ------------------- + begin : Tue Dec 28 1999 + copyright : (C) 1999 by Franïż½is Dupoux + (C) 2004 Emiliano Gulmini + email : dupoux@dupoux.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + + +//QT +#include +#include +#include +#include +#include +#include +#include +#include + +//KDE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// local +#include "knewprojectdlg.h" +#include "whatthis.h" + +using namespace whatthisNameSpace; + + +KNewProjectDlg::KNewProjectDlg(RCOptions* info, QWidget *parent, const char *name) : KNewProjectDlgS(parent, name) +{ + m_searchNowFlag = ""; + m_option = info; + + initGUI(); + + connect(m_pbLocation, SIGNAL(clicked()), this, SLOT(slotDir())); + connect(m_pbCancel, SIGNAL(clicked()), this, SLOT(slotReject())); + connect(m_pbSearchNow, SIGNAL(clicked()), this, SLOT(slotSearchNow())); + connect(m_pbSearchLater, SIGNAL(clicked()), this, SLOT(slotSearchLater())); + connect(m_leSearch, SIGNAL(textChanged(const QString&)), this, SLOT(slotSearchLineEdit(const QString&))); + connect(m_chbSizeMin, SIGNAL(toggled(bool)), this, SLOT(slotEnableSpinboxSizeMin(bool))); + connect(m_chbSizeMax, SIGNAL(toggled(bool)), this, SLOT(slotEnableSpinboxSizeMax(bool))); + connect(m_chbDateMin, SIGNAL(toggled(bool)), m_dedDateMin, SLOT(setEnabled(bool))); + connect(m_chbDateMax, SIGNAL(toggled(bool)), m_dedDateMax, SLOT(setEnabled(bool))); + connect(m_chbDateMin,SIGNAL(toggled(bool)),this, SLOT(slotEnableCbValidDate(bool))); + connect(m_chbDateMax,SIGNAL(toggled(bool)),this, SLOT(slotEnableCbValidDate(bool))); + connect(m_chbOwnerUser, SIGNAL(toggled(bool)), this, SLOT(slotEnableChbUser(bool))); + connect(m_chbOwnerGroup, SIGNAL(toggled(bool)), this, SLOT(slotEnableChbGroup(bool))); + connect(m_chbBackup, SIGNAL(toggled(bool)), this, SLOT(slotEnableChbBackup(bool))); + connect(m_pbHelp, SIGNAL(clicked()), this, SLOT(slotHelp())); + + whatsThis(); +} + +KNewProjectDlg::~KNewProjectDlg() +{ +} + +void KNewProjectDlg::saveRCOptions() +{ + saveOptions(); + saveFileSizeOptions(); + saveDateAccessOptions(); + saveOwnerOptions(); + saveLocationsList(); + saveFiltersList(); + saveBackupExtensionOptions(); +} + +void KNewProjectDlg::slotDir() +{ + QString directoryString = KFileDialog::getExistingDirectory(QString::null, this, i18n("Project Directory")); + if(!directoryString.isEmpty()) + m_cbLocation->setEditText(directoryString); +} + +void KNewProjectDlg::slotOK() +{ + // Check that Search text and Filter are not empty + m_option->m_directories = m_cbLocation->currentText(); + m_option->m_filters = m_cbFilter->currentText(); + if(!m_leSearch->text().isEmpty()) + { + if(m_leReplace->text().isEmpty()) + m_option->m_searchingOnlyMode = true; + else + m_option->m_searchingOnlyMode = false; + } + m_option->m_quickSearchString = m_searchNowFlag + m_leSearch->text(); + m_option->m_quickReplaceString = m_searchNowFlag + m_leReplace->text(); + + if (m_option->m_directories.isEmpty() || m_option->m_filters.isEmpty()) + { + KMessageBox::error(this, i18n("You must fill the combo boxes (location and filter) before continuing.")); + return; + } + + // OWNER OPTIONS + if ((m_chbOwnerUser->isChecked() && m_edOwnerUser->text().isEmpty()) || + (m_chbOwnerGroup->isChecked() && m_edOwnerGroup->text().isEmpty())) + { + KMessageBox::error(this, i18n("Some edit boxes are empty in the Owner page.")); + return ; + } + + // Check option "Size Min/Max": check MinSize is not greater than MaxSize + int minSize = m_spbSizeMin->value(), + maxSize = m_spbSizeMax->value(); + if ((minSize != FileSizeOption) && (maxSize != FileSizeOption)) + if (minSize > maxSize) + { + KMessageBox::error(this, i18n("The minimum size is greater than the maximum size.")); + return ; + } + + accept(); +} + +void KNewProjectDlg::slotReject() +{ + m_option->m_quickSearchString = m_searchNowFlag; + m_option->m_quickReplaceString = m_searchNowFlag; + + reject(); +} + +void KNewProjectDlg::slotSearchNow() +{ //Add a 'N' to represent the status search-now + m_searchNowFlag = "N"; + slotOK(); +} + +void KNewProjectDlg::slotSearchLater() +{ //Add a 'L' to represent the status search-later + m_searchNowFlag = "L"; + slotOK(); +} + +void KNewProjectDlg::slotSearchLineEdit(const QString& t) +{ + m_pbSearchNow->setEnabled(!t.isEmpty()); +} + +void KNewProjectDlg::slotEnableSpinboxSizeMin(bool b) +{ + m_spbSizeMin->setEnabled(b); +} + +void KNewProjectDlg::slotEnableSpinboxSizeMax(bool b) +{ + m_spbSizeMax->setEnabled(b); +} + +void KNewProjectDlg::slotEnableCbValidDate(bool b) +{ + Q_UNUSED(b); + m_cbDateValid->setEnabled(m_chbDateMax->isChecked() || m_chbDateMin->isChecked()); +} + +void KNewProjectDlg::slotEnableChbUser(bool b) +{ + m_cbOwnerUserType->setEnabled(b); + m_cbOwnerUserBool->setEnabled(b); + m_edOwnerUser->setEnabled(b); +} + +void KNewProjectDlg::slotEnableChbGroup(bool b) +{ + m_cbOwnerGroupType->setEnabled(b); + m_cbOwnerGroupBool->setEnabled(b); + m_edOwnerGroup->setEnabled(b); +} + +void KNewProjectDlg::slotEnableChbBackup(bool b) +{ + m_leBackup->setEnabled(b); + m_tlBackup->setEnabled(b); +} + +//PRIVATE +void KNewProjectDlg::initGUI() +{ + QIconSet iconSet = SmallIconSet("fileopen"); + QPixmap pixMap = iconSet.pixmap( QIconSet::Small, QIconSet::Normal ); + + m_pbLocation->setIconSet(iconSet); + m_pbLocation->setFixedSize(pixMap.width() + 8, pixMap.height() + 8); + + m_pbSearchNow->setEnabled(false); + + loadOptions(); + loadFileSizeOptions(); + loadDateAccessOptions(); + loadOwnerOptions(); + loadBackupExtensionOptions(); + loadLocationsList(); + loadFiltersList(); +} + +void KNewProjectDlg::loadOptions() +{ + QStringList availableEncodingNames(KGlobal::charsets()->availableEncodingNames()); + m_cbEncoding->insertStringList(availableEncodingNames); + int idx = -1; + int utf8Idx = -1; + for (uint i = 0; i < availableEncodingNames.count(); i++) + { + if (availableEncodingNames[i] == m_option->m_encoding) + { + idx = i; + break; + } + if (availableEncodingNames[i] == "utf8") + { + utf8Idx = i; + } + } + if (idx != -1) + m_cbEncoding->setCurrentItem(idx); + else + m_cbEncoding->setCurrentItem(utf8Idx); + + m_chbIncludeSubfolders->setChecked(m_option->m_recursive); + m_chbCaseSensitive->setChecked(m_option->m_caseSensitive); + m_chbEnableVariables->setChecked(m_option->m_variables); + m_chbRegularExpressions->setChecked(m_option->m_regularExpressions); +} + +void KNewProjectDlg::loadFileSizeOptions() +{ + int size = m_option->m_minSize; + if(size == FileSizeOption) + { + m_chbSizeMin->setChecked(false); + m_spbSizeMin->setEnabled(false); + m_spbSizeMin->setValue(0); + } + else + { + m_chbSizeMin->setChecked(true); + m_spbSizeMin->setEnabled(true); + m_spbSizeMin->setValue(size); + } + + size = m_option->m_maxSize; + if(size == FileSizeOption) + { + m_chbSizeMax->setChecked(false); + m_spbSizeMax->setEnabled(false); + m_spbSizeMax->setValue(0); + } + else + { + m_chbSizeMax->setChecked(true); + m_spbSizeMax->setEnabled(true); + m_spbSizeMax->setValue(size); + } +} + +void KNewProjectDlg::loadDateAccessOptions() +{ + // ================== DATE OPTIONS ======================== + + QString date = m_option->m_minDate; + if(date == AccessDateOption) + { + m_chbDateMin->setChecked(false); + m_dedDateMin->setDate(m_dedDateMin->minValue()); + m_dedDateMin->setEnabled(false); + } + else + { + m_chbDateMin->setChecked(true); + m_dedDateMin->setDate(QDate::fromString(date,Qt::ISODate)); + m_dedDateMin->setEnabled(true); + } + + date = m_option->m_maxDate; + if(date == AccessDateOption) + { + m_chbDateMax->setChecked(false); + m_dedDateMax->setDate(m_dedDateMax->maxValue()); + m_dedDateMax->setEnabled(false); + } + else + { + m_chbDateMax->setChecked(true); + m_dedDateMax->setDate(QDate::fromString(date,Qt::ISODate)); + m_dedDateMax->setEnabled(true); + } + + m_cbDateValid->setEnabled(m_chbDateMax->isChecked() || m_chbDateMin->isChecked()); + +} + +void KNewProjectDlg::loadOwnerOptions() +{ + bool enableOwner = m_option->m_ownerUserIsChecked; + + m_chbOwnerUser->setChecked(enableOwner); + m_cbOwnerUserType->setEnabled(enableOwner); + m_cbOwnerUserBool->setEnabled(enableOwner); + m_edOwnerUser->setEnabled(enableOwner); + + m_cbOwnerUserType->setCurrentText(m_option->m_ownerUserType); + m_cbOwnerUserBool->setCurrentText(m_option->m_ownerUserBool); + + m_edOwnerUser->setText(m_option->m_ownerUserValue); + + enableOwner = m_option->m_ownerGroupIsChecked; + + m_chbOwnerGroup->setChecked(enableOwner); + m_cbOwnerGroupType->setEnabled(enableOwner); + m_cbOwnerGroupBool->setEnabled(enableOwner); + m_edOwnerGroup->setEnabled(enableOwner); + + m_cbOwnerGroupType->setCurrentText(m_option->m_ownerGroupType); + m_cbOwnerGroupBool->setCurrentText(m_option->m_ownerGroupBool); + m_edOwnerGroup->setText(m_option->m_ownerGroupValue); +} + +void KNewProjectDlg::loadLocationsList() +{ + m_cbLocation->insertStringList(m_option->m_directories); +} + +void KNewProjectDlg::loadFiltersList() +{ + m_cbFilter->insertStringList(m_option->m_filters); +} + +void KNewProjectDlg::loadBackupExtensionOptions() +{ + bool enableBackup = m_option->m_backup; + + m_chbBackup->setChecked(enableBackup); + m_leBackup->setEnabled(enableBackup); + m_tlBackup->setEnabled(enableBackup); + m_leBackup->setText(m_option->m_backupExtension); +} + +void KNewProjectDlg::saveOptions() +{ + m_option->m_encoding = m_cbEncoding->currentText(); + m_option->m_recursive = m_chbIncludeSubfolders->isChecked(); + m_option->m_caseSensitive = m_chbCaseSensitive->isChecked(); + m_option->m_variables = m_chbEnableVariables->isChecked(); + m_option->m_regularExpressions = m_chbRegularExpressions->isChecked(); +} + +void KNewProjectDlg::saveFileSizeOptions() +{ + if(m_chbSizeMax->isChecked()) + m_option->m_maxSize = m_spbSizeMax->value(); + else + m_option->m_maxSize = FileSizeOption; + + if(m_chbSizeMin->isChecked()) + m_option->m_minSize = m_spbSizeMin->value(); + else + m_option->m_minSize = FileSizeOption; +} + +void KNewProjectDlg::saveDateAccessOptions() +{ + if(m_chbDateMin->isChecked() || m_chbDateMax->isChecked()) + m_option->m_dateAccess = m_cbDateValid->currentText(); + else + m_option->m_dateAccess = ValidAccessDateOption; + + if(m_chbDateMin->isChecked()) + { + QString date = m_dedDateMin->date().toString(Qt::ISODate); + m_option->m_minDate = date; + } + else + m_option->m_minDate = AccessDateOption; + + if(m_chbDateMax->isChecked()) + { + QString date = m_dedDateMax->date().toString(Qt::ISODate); + m_option->m_maxDate = date; + } + else + m_option->m_maxDate = AccessDateOption; +} + +void KNewProjectDlg::saveOwnerOptions() +{ + bool isChecked = m_chbOwnerUser->isChecked(); + if(isChecked) + { + m_option->m_ownerUserIsChecked = true; + m_option->m_ownerUserType = m_cbOwnerUserType->currentText(); + m_option->m_ownerUserBool = m_cbOwnerUserBool->currentText(); + m_option->m_ownerUserValue = m_edOwnerUser->text(); + } + else + { + m_option->m_ownerUserIsChecked = false; + m_option->m_ownerUserType = "Name"; + m_option->m_ownerUserBool = "Equals To"; + m_option->m_ownerUserValue = ""; + } + + isChecked = m_chbOwnerGroup->isChecked(); + if(isChecked) + { + m_option->m_ownerGroupIsChecked = true; + m_option->m_ownerGroupType = m_cbOwnerGroupType->currentText(); + m_option->m_ownerGroupBool = m_cbOwnerGroupBool->currentText(); + m_option->m_ownerGroupValue = m_edOwnerGroup->text(); + } + else + { + m_option->m_ownerGroupIsChecked = false; + m_option->m_ownerGroupType = "Name"; + m_option->m_ownerGroupBool = "Equals To"; + m_option->m_ownerGroupValue = ""; + } +} + +void KNewProjectDlg::saveLocationsList() +{ + QString current = m_cbLocation->currentText(); + QStringList list = current; + + int count = m_cbLocation->listBox()->count(), + i; + for(i = 0; i < count; i++) + { + QString text = m_cbLocation->listBox()->item(i)->text(); + if(text != current) + list.append(text); + } + m_option->m_directories = list; +} + +void KNewProjectDlg::saveFiltersList() +{ + QString current = m_cbFilter->currentText(); + QStringList list = current; + + int count = m_cbFilter->listBox()->count(), + i; + for(i = 0; i < count; i++) + { + QString text = m_cbFilter->listBox()->item(i)->text(); + if(text != current) + list.append(text); + } + m_option->m_filters = list; +} + +void KNewProjectDlg::saveBackupExtensionOptions() +{ + QString backupExt = m_leBackup->text(); + m_option->m_backup = (m_chbBackup->isChecked() && !backupExt.isEmpty()); + m_option->m_backupExtension = backupExt; +} + +void KNewProjectDlg::setDatas(const QString& directoryString, const QString& filterString) +{ + if (!directoryString.isEmpty()) + m_cbLocation->setEditText(directoryString); + + if (!filterString.isEmpty()) + m_cbFilter->setEditText(filterString); +} + +bool KNewProjectDlg::contains(QListView* lv,const QString& s, int column) +{ + QListViewItem* i = lv->firstChild(); + while (i != 0) + { + if(i->text(column) == s) + return true; + i = i->nextSibling(); + } + return false; +} + +void KNewProjectDlg::whatsThis() +{ + QWhatsThis::add(m_cbLocation, cbLocationWhatthis); + QWhatsThis::add(m_cbFilter, cbFilterWhatthis); + + QWhatsThis::add(m_spbSizeMin, edSizeMinWhatthis); + QWhatsThis::add(m_spbSizeMax, edSizeMaxWhatthis); + + QWhatsThis::add(m_cbDateValid, cbDateValidWhatthis); + QWhatsThis::add(m_chbDateMin, chbDateMinWhatthis); + QWhatsThis::add(m_chbDateMax, chbDateMaxWhatthis); + + QWhatsThis::add(m_chbIncludeSubfolders, chbRecursiveWhatthis); + QWhatsThis::add(m_chbRegularExpressions, chbRegularExpressionsWhatthis); + QWhatsThis::add(m_chbEnableVariables, chbVariablesWhatthis); + QWhatsThis::add(m_chbCaseSensitive, chbCaseSensitiveWhatthis); + QWhatsThis::add(m_chbBackup, chbBackupWhatthis); + QWhatsThis::add(m_leBackup, chbBackupWhatthis); + QWhatsThis::add(m_leSearch, leSearchWhatthis); + QWhatsThis::add(m_leReplace, leReplaceWhatthis); +} + +#include "knewprojectdlg.moc" + diff --git a/kfilereplace/knewprojectdlg.h b/kfilereplace/knewprojectdlg.h new file mode 100644 index 00000000..e4852cb8 --- /dev/null +++ b/kfilereplace/knewprojectdlg.h @@ -0,0 +1,84 @@ +/*************************************************************************** + knewprojectdlg.h - description + ------------------- + begin : Tue Dec 28 1999 + copyright : (C) 1999 by François Dupoux + (C) 2004 Emiliano Gulmini + email : dupoux@dupoux.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KNEWPROJECTDLG_H +#define KNEWPROJECTDLG_H + +//KDE +class KConfig; + +//local +#include "knewprojectdlgs.h" +#include "configurationclasses.h" + +class KNewProjectDlg : public KNewProjectDlgS +{ + Q_OBJECT + + private: + QString m_searchNowFlag; + RCOptions* m_option; + + public: + KNewProjectDlg(RCOptions* info, QWidget *parent=0, const char *name=0); + ~KNewProjectDlg(); + + public: + //void updateOptions(const RCOptions& info); + void saveRCOptions(); + + protected slots: + void slotDir(); + void slotOK(); + void slotReject(); + void slotSearchNow(); + void slotSearchLater(); + void slotSearchLineEdit(const QString& t); + void slotEnableSpinboxSizeMin(bool b); + void slotEnableSpinboxSizeMax(bool b); + void slotEnableCbValidDate(bool b); + void slotEnableChbUser(bool b); + void slotEnableChbGroup(bool b); + void slotEnableChbBackup(bool b); + void slotHelp(){ kapp->invokeHelp(QString::null, "kfilereplace"); } + + private: + void initGUI(); + + void loadOptions(); + void loadFileSizeOptions(); + void loadDateAccessOptions(); + void loadOwnerOptions(); + void loadLocationsList(); + void loadFiltersList(); + void loadBackupExtensionOptions(); + + void saveOptions(); + void saveFileSizeOptions(); + void saveDateAccessOptions(); + void saveOwnerOptions(); + void saveLocationsList(); + void saveFiltersList(); + void saveBackupExtensionOptions(); + + bool contains(QListView* lv,const QString& s, int column); + void setDatas(const QString& directoryString, const QString& filterString); + void whatsThis(); +}; + +#endif // KNewProjectDlg diff --git a/kfilereplace/knewprojectdlgs.ui b/kfilereplace/knewprojectdlgs.ui new file mode 100644 index 00000000..238a003f --- /dev/null +++ b/kfilereplace/knewprojectdlgs.ui @@ -0,0 +1,898 @@ + +KNewProjectDlgS + + + KNewProjectDlgS + + + + 0 + 0 + 568 + 609 + + + + Search & Replace in Files + + + true + + + true + + + + unnamed + + + + layout28 + + + + unnamed + + + + m_pbHelp + + + true + + + + 3 + 1 + 0 + 0 + + + + + 0 + 0 + + + + + 70 + 32767 + + + + &Help + + + + + spacer7 + + + Horizontal + + + Expanding + + + + 150 + 20 + + + + + + m_pbSearchNow + + + Search Now + + + + + + true + + + + + m_pbSearchLater + + + Search Later + + + + + + + + m_pbCancel + + + + 3 + 1 + 0 + 0 + + + + + 70 + 32767 + + + + &Cancel + + + + + + + tabWidget2 + + + + tab + + + &General + + + + unnamed + + + + groupBox5 + + + Startup Folder Options + + + + unnamed + + + + m_tlFilter + + + Filter: + + + cbFilter + + + + + m_tlLocation + + + Location: + + + AutoText + + + cbLocation + + + + + m_cbLocation + + + + 3 + 0 + 0 + 0 + + + + true + + + 20 + + + 10 + + + AtTop + + + false + + + Insert a search path here. You can use the search path button. + + + + + m_pbLocation + + + + + + + + + + + m_cbFilter + + + + 3 + 0 + 0 + 0 + + + + true + + + 20 + + + 10 + + + AtTop + + + false + + + + + + + + m_chbIncludeSubfolders + + + &Include subfolders + + + true + + + + + + + groupBox6 + + + Search/Replace Strings + + + + unnamed + + + + m_leSearch + + + + + m_leReplace + + + + + m_tlSearch + + + Search: + + + + + m_tlReplace + + + Replace: + + + + + + + groupBox4 + + + General Options + + + + unnamed + + + + m_chbRegularExpressions + + + true + + + Enable &regular expressions + + + + + m_chbBackup + + + Do &backup copy instead of overwrite + + + + + m_chbCaseSensitive + + + &Case sensitive + + + + + m_chbEnableVariables + + + Enable co&mmands in the replace string + + + + + m_tlBackup + + + Backup copy suffix: + + + + + m_leBackup + + + + + + + + m_cbEncoding + + + + 3 + 0 + 0 + 0 + + + + + + textLabel1 + + + Encoding of the files: + + + + + + + + + tab + + + &Advanced + + + + unnamed + + + + gbOwnership + + + Ownership Filtering + + + + unnamed + + + + m_chbOwnerUser + + + User: + + + + + + Name + + + + + ID (Number) + + + + m_cbOwnerUserType + + + false + + + 2 + + + 2 + + + true + + + + + + Equals To + + + + + Is Not + + + + m_cbOwnerUserBool + + + false + + + 2 + + + 2 + + + false + + + + + + Equals To + + + + + Is Not + + + + m_cbOwnerGroupBool + + + false + + + 2 + + + 2 + + + false + + + + + + Name + + + + + ID (Number) + + + + m_cbOwnerGroupType + + + false + + + 2 + + + 2 + + + false + + + + + m_chbOwnerGroup + + + Group: + + + + + m_edOwnerUser + + + false + + + + + m_edOwnerGroup + + + false + + + + + + + gbAccessDate + + + Access Date Filtering + + + + unnamed + + + + layout8 + + + + unnamed + + + + layout18 + + + + unnamed + + + + m_tlDateValid + + + Dates valid for: + + + + + m_chbDateMin + + + Accessed after: + + + + + m_chbDateMax + + + Accessed before: + + + + + + + layout19 + + + + unnamed + + + + + Last Writing Access + + + + + Last Reading Access + + + + m_cbDateValid + + + 2 + + + 2 + + + false + + + + + m_dedDateMin + + + false + + + + 2000 + 1 + 1 + + + + true + + + + 2100 + 12 + 31 + + + + + 1900 + 12 + 31 + + + + + + m_dedDateMax + + + false + + + + 2000 + 1 + 1 + + + + true + + + + 2100 + 12 + 31 + + + + + 1900 + 9 + 14 + + + + + + + + spacer3 + + + Horizontal + + + Expanding + + + + 190 + 16 + + + + + + + + + + gbSize + + + Size Filtering + + + + unnamed + + + + layout32 + + + + unnamed + + + + layout31 + + + + unnamed + + + + m_chbSizeMin + + + Minimum si&ze: + + + + + m_chbSizeMax + + + Maximum size: + + + + + + + layout30 + + + + unnamed + + + + m_spbSizeMin + + + 4000000 + + + 0 + + + + + m_spbSizeMax + + + 4000000 + + + 0 + + + + + + + layout31 + + + + unnamed + + + + m_tlSizeMin + + + KB + + + + + m_tlSizeMax + + + KB + + + + + + + spacer2 + + + Horizontal + + + Expanding + + + + 330 + 16 + + + + + + + + + + + + + + tabWidget2 + m_leSearch + m_leReplace + m_cbLocation + m_pbLocation + m_cbFilter + m_chbIncludeSubfolders + m_cbEncoding + m_chbCaseSensitive + m_chbRegularExpressions + m_chbEnableVariables + m_chbBackup + m_leBackup + m_pbSearchNow + m_pbSearchLater + m_pbCancel + m_pbHelp + m_chbSizeMin + m_spbSizeMin + m_chbSizeMax + m_spbSizeMax + m_cbDateValid + m_chbDateMin + m_chbDateMax + m_chbOwnerUser + m_cbOwnerUserType + m_cbOwnerUserBool + m_edOwnerUser + m_chbOwnerGroup + m_cbOwnerGroupType + m_cbOwnerGroupBool + m_edOwnerGroup + m_dedDateMin + m_dedDateMax + + + diff --git a/kfilereplace/koptionsdlg.cpp b/kfilereplace/koptionsdlg.cpp new file mode 100644 index 00000000..3980a7a6 --- /dev/null +++ b/kfilereplace/koptionsdlg.cpp @@ -0,0 +1,236 @@ +/*************************************************************************** + koptionsdlg.cpp - description + ------------------- + begin : Tue Dec 28 1999 + copyright : (C) 1999 by Franïż½is Dupoux + (C) 2004 Emiliano Gulmini + email : dupoux@dupoux.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +// QT +#include +#include +#include +#include +#include +#include + +// KDE +#include +#include +#include +#include +#include +#include +//#include + +// local +#include "whatthis.h" +#include "koptionsdlg.h" + + +using namespace whatthisNameSpace; + + +KOptionsDlg::KOptionsDlg(RCOptions* info, QWidget *parent, const char *name) : KOptionsDlgS(parent,name,true) +{ + m_config = new KConfig("kfilereplacerc"); + m_option = info; + + initGUI(); + + connect(m_pbOK, SIGNAL(clicked()), this, SLOT(slotOK())); + connect(m_pbDefault, SIGNAL(clicked()),this,SLOT(slotDefaults())); + connect(m_chbBackup, SIGNAL(toggled(bool)), this, SLOT(slotChbBackup(bool))); + connect(m_pbHelp, SIGNAL(clicked()), this, SLOT(slotHelp())); + connect(m_chbConfirmStrings, SIGNAL(toggled(bool)), this, SLOT(slotChbConfirmStrings(bool))); + connect(m_chbShowConfirmDialog, SIGNAL(toggled(bool)), this, SLOT(slotChbShowConfirmDialog(bool))); + + whatsThis(); +} + +KOptionsDlg::~KOptionsDlg() +{ +} + +//PRIVATE SLOTS +void KOptionsDlg::slotOK() +{ + saveRCOptions(); + accept(); +} + +/** Set defaults values for all options of the dialog */ +void KOptionsDlg::slotDefaults() +{ + m_chbCaseSensitive->setChecked(CaseSensitiveOption); + m_chbRecursive->setChecked(RecursiveOption); + m_chbHaltOnFirstOccurrence->setChecked(StopWhenFirstOccurenceOption); + + m_chbFollowSymLinks->setChecked(FollowSymbolicLinksOption); + m_chbIgnoreHidden->setChecked(IgnoreHiddenOption); + m_chbRegularExpressions->setChecked(RegularExpressionsOption); + m_chbIgnoreFiles->setChecked(IgnoreFilesOption); + m_chbConfirmStrings->setChecked(AskConfirmReplaceOption); + + QStringList bkList = QStringList::split(",",BackupExtensionOption,true); + + bool enableBackup = (bkList[0] == "true" ? true : false); + + m_chbBackup->setChecked(enableBackup); + m_leBackup->setEnabled(enableBackup); + m_tlBackup->setEnabled(enableBackup); + + m_leBackup->setText(bkList[1]); + + m_chbVariables->setChecked(VariablesOption); + + m_chbNotifyOnErrors->setChecked(NotifyOnErrorsOption); +} + +void KOptionsDlg::slotChbBackup(bool b) +{ + m_leBackup->setEnabled(b); + m_tlBackup->setEnabled(b); +} + +void KOptionsDlg::slotChbConfirmStrings(bool b) +{ + if(b) + { + m_chbShowConfirmDialog->setEnabled(true); + m_chbShowConfirmDialog->setChecked(true); + m_config->setGroup("Notification Messages"); + m_config->writeEntry(rcDontAskAgain,"no"); + } + else + { + m_chbShowConfirmDialog->setEnabled(false); + m_chbShowConfirmDialog->setChecked(false); + m_config->setGroup("Notification Messages"); + m_config->writeEntry(rcDontAskAgain,"yes"); + } +} + +void KOptionsDlg::slotChbShowConfirmDialog(bool b) +{ + m_config->setGroup("Notification Messages"); + if(b) + { + m_config->writeEntry(rcDontAskAgain,"no"); + } + else + { + m_config->writeEntry(rcDontAskAgain,"yes"); + } +} + +//PRIVATE +void KOptionsDlg::initGUI() +{ + m_config->sync(); + m_config->setGroup("Notification Messages"); + m_option->m_notifyOnErrors = m_config->readBoolEntry(rcNotifyOnErrors, true); + + QString dontAskAgain = m_config->readEntry(rcDontAskAgain,"no"); + + m_chbConfirmStrings->setChecked(m_option->m_askConfirmReplace); + + if(m_chbConfirmStrings->isChecked()) + { + if(dontAskAgain == "yes") + m_chbShowConfirmDialog->setChecked(false); + else + m_chbShowConfirmDialog->setChecked(true); + } + + QStringList availableEncodingNames(KGlobal::charsets()->availableEncodingNames()); + m_cbEncoding->insertStringList( availableEncodingNames ); + int idx = -1; + int utf8Idx = -1; + for (uint i = 0; i < availableEncodingNames.count(); i++) + { + if (availableEncodingNames[i] == m_option->m_encoding) + { + idx = i; + break; + } + if (availableEncodingNames[i] == "utf8") + { + utf8Idx = i; + } + } + if (idx != -1) + m_cbEncoding->setCurrentItem(idx); + else + m_cbEncoding->setCurrentItem(utf8Idx); + + m_chbCaseSensitive->setChecked(m_option->m_caseSensitive); + m_chbRecursive->setChecked(m_option->m_recursive); + + bool enableBackup = m_option->m_backup; + + m_chbBackup->setChecked(enableBackup); + m_leBackup->setEnabled(enableBackup); + m_tlBackup->setEnabled(enableBackup); + + m_leBackup->setText(m_option->m_backupExtension); + + m_chbVariables->setChecked(m_option->m_variables); + m_chbRegularExpressions->setChecked(m_option->m_regularExpressions); + m_chbHaltOnFirstOccurrence->setChecked(m_option->m_haltOnFirstOccur); + m_chbFollowSymLinks->setChecked(m_option->m_followSymLinks); + m_chbIgnoreHidden->setChecked(m_option->m_ignoreHidden); + m_chbIgnoreFiles->setChecked(m_option->m_ignoreFiles); + + m_chbNotifyOnErrors->setChecked(m_option->m_notifyOnErrors); +} + +void KOptionsDlg::saveRCOptions() +{ + m_option->m_encoding = m_cbEncoding->currentText(); + m_option->m_caseSensitive = m_chbCaseSensitive->isChecked(); + m_option->m_recursive = m_chbRecursive->isChecked(); + QString backupExt = m_leBackup->text(); + m_option->m_backup = (m_chbBackup->isChecked() && !backupExt.isEmpty()); + m_option->m_backupExtension = backupExt; + m_option->m_variables = m_chbVariables->isChecked(); + m_option->m_regularExpressions = m_chbRegularExpressions->isChecked(); + m_option->m_haltOnFirstOccur = m_chbHaltOnFirstOccurrence->isChecked(); + m_option->m_followSymLinks = m_chbFollowSymLinks->isChecked(); + m_option->m_ignoreHidden = m_chbIgnoreHidden->isChecked(); + m_option->m_ignoreFiles = m_chbIgnoreFiles->isChecked(); + m_option->m_askConfirmReplace = m_chbConfirmStrings->isChecked(); + m_option->m_notifyOnErrors = m_chbNotifyOnErrors->isChecked(); + + m_config->setGroup("Notification Messages"); + m_config->writeEntry(rcNotifyOnErrors, m_option->m_notifyOnErrors); + + m_config->sync(); +} + +void KOptionsDlg::whatsThis() +{ + // Create help QWhatsThis + QWhatsThis::add(m_chbCaseSensitive, chbCaseSensitiveWhatthis); + QWhatsThis::add(m_chbRecursive, chbRecursiveWhatthis); + QWhatsThis::add(m_chbHaltOnFirstOccurrence, chbHaltOnFirstOccurrenceWhatthis); + QWhatsThis::add(m_chbFollowSymLinks, chbFollowSymLinksWhatthis); + QWhatsThis::add(m_chbIgnoreHidden, chbIgnoreHiddenWhatthis); + QWhatsThis::add(m_chbIgnoreFiles, chbIgnoreFilesWhatthis); + QWhatsThis::add(m_chbRegularExpressions, chbRegularExpressionsWhatthis); + QWhatsThis::add(m_chbVariables, chbVariablesWhatthis); + QWhatsThis::add(m_chbBackup, chbBackupWhatthis); + QWhatsThis::add(m_chbConfirmStrings, chbConfirmStringsWhatthis); +} + +#include "koptionsdlg.moc" diff --git a/kfilereplace/koptionsdlg.h b/kfilereplace/koptionsdlg.h new file mode 100644 index 00000000..993f2c7d --- /dev/null +++ b/kfilereplace/koptionsdlg.h @@ -0,0 +1,58 @@ +/*************************************************************************** + koptionsdlg.h - description + ------------------- + begin : Tue Dec 28 1999 + copyright : (C) 1999 by François Dupoux + (C) 2004 Emiliano Gulmini + email : dupoux@dupoux.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KOPTIONSDLG_H +#define KOPTIONSDLG_H + +// KDE +class KConfig; + +//local +#include "configurationclasses.h" +#include "koptionsdlgs.h" + +/** + *@author François Dupoux + */ + +class KOptionsDlg : public KOptionsDlgS +{ + Q_OBJECT + public: + KOptionsDlg(RCOptions* info, QWidget *parent, const char *name); + ~KOptionsDlg(); + + private: + RCOptions* m_option; + KConfig *m_config; + + private slots: + void slotOK(); + void slotDefaults(); + void slotChbBackup(bool b); + void slotChbConfirmStrings(bool b); + void slotChbShowConfirmDialog(bool b); + void slotHelp(){ kapp->invokeHelp(QString::null, "kfilereplace"); } + + private: + void initGUI(); + void saveRCOptions(); + void whatsThis(); +}; + +#endif // KOPTIONSDLG_H diff --git a/kfilereplace/koptionsdlgs.ui b/kfilereplace/koptionsdlgs.ui new file mode 100644 index 00000000..88f0d8f8 --- /dev/null +++ b/kfilereplace/koptionsdlgs.ui @@ -0,0 +1,347 @@ + +KOptionsDlgS + + + KOptionsDlgS + + + + 0 + 0 + 572 + 420 + + + + Options + + + true + + + + unnamed + + + + tabWidget2 + + + + tab1 + + + General + + + + unnamed + + + + groupBox7 + + + General Options + + + + unnamed + + + + m_chbVariables + + + Enable commands in replace strings + + + + + + + + m_tlBackup + + + Backup copy suffix: + + + + + m_leBackup + + + + + + + + m_chbNotifyOnErrors + + + Notif&y on errors + + + + + m_chbCaseSensitive + + + Case sensitive + + + + + + + + m_chbRecursive + + + Recursive (search/replace in all sub folders) + + + + + + + + m_chbRegularExpressions + + + true + + + Enable regular e&xpressions + + + + + m_chbBackup + + + Do &backup copy + + + + + textLabel1 + + + Encoding of the files: + + + + + m_cbEncoding + + + + 3 + 0 + 0 + 0 + + + + + + + + + + Tab3 + + + &Advanced + + + + unnamed + + + + gbxConfirm + + + Advanced Options + + + + unnamed + + + + m_chbIgnoreHidden + + + Ignore hidden files and folders + + + + + m_chbFollowSymLinks + + + Follow s&ymbolic links + + + + + m_chbHaltOnFirstOccurrence + + + When searching, stop on first string found (faster but no details) + + + + + m_chbIgnoreFiles + + + true + + + Do not show file if no strings are found or replaced + + + + + layout9 + + + + unnamed + + + + spacer2 + + + Horizontal + + + Fixed + + + + 16 + 20 + + + + + + m_chbShowConfirmDialog + + + false + + + Show confirmation dialog + + + + + + + m_chbConfirmStrings + + + false + + + Confirm before replace each string + + + + + + + + + + m_pbHelp + + + true + + + &Help + + + + + spacer1 + + + Horizontal + + + Expanding + + + + 202 + 20 + + + + + + m_pbDefault + + + &Default Values + + + + + m_pbOK + + + &OK + + + + + m_pbCancel + + + &Cancel + + + + + + + m_pbCancel + clicked() + KOptionsDlgS + reject() + + + + tabWidget2 + m_cbEncoding + m_chbCaseSensitive + m_chbRecursive + m_chbRegularExpressions + m_chbVariables + m_chbNotifyOnErrors + m_chbBackup + m_leBackup + m_pbDefault + m_pbOK + m_pbCancel + m_pbHelp + m_chbConfirmStrings + m_chbShowConfirmDialog + m_chbIgnoreFiles + m_chbHaltOnFirstOccurrence + m_chbFollowSymLinks + m_chbIgnoreHidden + + + diff --git a/kfilereplace/main.cpp b/kfilereplace/main.cpp new file mode 100644 index 00000000..4ce9b742 --- /dev/null +++ b/kfilereplace/main.cpp @@ -0,0 +1,77 @@ +/*************************************************************************** + main.cpp - Main file for the KFileReplace shell + ------------------- + begin : Thu Sep 16 14:14:09 2004 + copyright : (C) 2004 by Andras Mantia + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kfilereplace.h" + +#include +#include +#include +#include + +static const char description[] = + I18N_NOOP("Batch search and replace tool"); + +static const char version[] = "0.1"; + +static KCmdLineOptions options[] = + { + { "+[PATH]", I18N_NOOP( "Starting folder" ), 0 }, + KCmdLineLastOption + }; + +int main(int argc, char *argv[]) +{ + KAboutData about("kfilereplace", I18N_NOOP("KFileReplace"), version, description, + KAboutData::License_GPL_V2, "(C) 2004-2005 Andras Mantia\n(C) 2004-2005 Emiliano Gulmini\n(C) 1999-2002 Francois Dupoux", I18N_NOOP("Part of the KDEWebDev module."), + "http://www.kdewebdev.org"); + + about.addAuthor("Andras Mantia", I18N_NOOP("Shell author, KPart creator, co-maintainer"), "amantia@kde.org"); + about.addAuthor("Emiliano Gulmini", I18N_NOOP("Current maintainer, code cleaner and rewriter"),"emi_barbarossa@yahoo.it"); + about.addAuthor("Francois Dupou", + I18N_NOOP("Original author of the KFileReplace tool"), + "dupoux@dupoux.com"); + + KCmdLineArgs::init(argc, argv, &about); + KCmdLineArgs::addCmdLineOptions( options ); + + KApplication app; + + // see if we are starting with session management + if (app.isRestored()) + { + RESTORE(KFileReplace); + } + else + { + // no session.. just start up normally + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + + KFileReplace *kfr = new KFileReplace; + kfr->show(); + + if (args->count() == 0) + { + kfr->openURL(KURL()); + } + else + { + kfr->openURL(args->url(0)); + } + args->clear(); + } + + return app.exec(); +} diff --git a/kfilereplace/report.cpp b/kfilereplace/report.cpp new file mode 100644 index 00000000..cae0dfe4 --- /dev/null +++ b/kfilereplace/report.cpp @@ -0,0 +1,282 @@ +/*************************************************************************** + report.cpp - Report document class + ------------------- + begin : fri aug 13 15:29:46 CEST 2004 + + copyright : (C) 2004 Emiliano Gulmini + email : emi_barbarossa@yahoo.it + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +// QT +#include +#include + +// KDE +#include +#include +#include + +// local +#include "report.h" +#include "configurationclasses.h" + +void Report::createReportFile() +{ + QString xmlFileName = m_docPath + ".xml", + cssFileName = m_docPath + ".css"; + + // Generates a report file + // a) Open the file + QFile report(xmlFileName); + if (!report.open( IO_WriteOnly )) + { + KMessageBox::error(0, i18n("Cannot open the file %1.").arg(xmlFileName)); + return ; + } + + // b) Write the header of the XML file + + QDateTime datetime = QDateTime::currentDateTime(Qt::LocalTime); + QString dateString = datetime.toString(Qt::LocalDate); + KUser user; + QString columnTextFour, + columnReplaceWith; + if(!m_isSearchFlag) + { + columnTextFour = i18n("Replaced Strings"); + columnReplaceWith = i18n("Replace with"); + } + else + { + columnTextFour = i18n("Total number occurrences"); + columnReplaceWith = i18n("-"); + } + + QString css = cssFileName.mid(cssFileName.findRev("/")+1,cssFileName.length()-(cssFileName.findRev("/")+1)); + QTextStream oTStream( &report ); + oTStream << "\n" + "" + "\n" + " "+i18n("KFileReplace Report")+" \n" + " "+user.fullName()+"("+user.loginName()+")"+"\n" + " "+dateString+"\n" + "
\n" + " \n" + " "+i18n("Searching/Replacing Strings Table")+" \n" + "
\n" + " \n" + " "+i18n("Search for")+"\n"; + + if(!m_isSearchFlag) + oTStream<< " "+columnReplaceWith+"\n"; + + oTStream<< " \n" + "
\n"; + // c) Write the strings list + QListViewItem *lviCurItem, + *lviFirst; + + lviCurItem = lviFirst = m_stringsView->firstChild(); + + if(lviCurItem == 0) + return ; + + QString rowType="a1"; + + do + { QString rowTag = "\n" + " text(0)+"]]>\n" + " text(1)+"]]>\n" + "\n"; + + oTStream << rowTag; + + rowType = ((rowType == "a1") ? "a2" : "a1"); + + lviCurItem = lviCurItem->nextSibling(); + } while(lviCurItem && lviCurItem != lviFirst); + + oTStream<< "
\n"; + + oTStream<< "\n" + " \n" + " "+i18n("Results Table")+ " " + "
\n" + " \n" + " "+i18n("Name")+"\n" + " "+i18n("Folder")+"\n"; + if(m_isSearchFlag) + { + oTStream<< " "+i18n("Size")+"\n"; + } + else + { + oTStream<< " "+i18n("Old Size")+"\n" + " "+i18n("New Size")+"\n"; + } + oTStream<< " "+columnTextFour+"\n" + " "+i18n("Owner User")+"\n" + " "+i18n("Owner Group")+"\n" + " \n" + "
\n"; + + // d) Write the result list + + lviCurItem = lviFirst = m_resultsView->firstChild(); + + if(lviCurItem == 0) + return ; + + unsigned int totalOccurrences = 0; + + rowType="a1"; + + do + { QString rowTag = " \n" + " text(0)+"]]>\n" + " text(1)+"]]>\n"; + if(m_isSearchFlag) + { + rowTag += " text(2)+"]]>\n" + " text(3)+"]]>\n" + " text(4)+"]]>\n" + " text(5)+"]]>\n" + " \n"; + } + else + { + rowTag += " text(2)+"]]>\n" + " text(3)+"]]>\n" + " text(4)+"]]>\n" + " text(5)+"]]>\n" + " text(6)+"]]>\n" + " \n"; + } + + oTStream << rowTag; + + rowType = ((rowType == "a1") ? "a2" : "a1"); + + if(m_isSearchFlag) + totalOccurrences += lviCurItem->text(3).toInt(); + else + totalOccurrences += lviCurItem->text(4).toInt(); + + lviCurItem = lviCurItem->nextSibling(); + } while(lviCurItem && lviCurItem != lviFirst); + + + // e) Write the end of the file + + oTStream<< "
\n" + "" + << totalOccurrences + << "\n" + "
\n"; + + report.close(); +} + +void Report::createStyleSheet() +{ + QString cssFileName = m_docPath +".css"; + QFile styleSheet(cssFileName); + if (!styleSheet.open( IO_WriteOnly )) + { + KMessageBox::error(0, i18n("Cannot open the file %1.").arg(cssFileName)); + return ; + } + + QTextStream oTStream( &styleSheet ); + + QString css = "title { display:block;font:40px bold sans-serif; }\n\n" + "createdby:before { content :\""+i18n("Created by")+": \"; }\n" + "createdby { display:inline; }\n\n" + "date:before { content :\"-"+i18n("date")+": \"; }\n" + "date { display:inline; }\n\n" + "totaloccurrences:before { content :\""+i18n("Total occurrences")+": \"; }\n" + "totaloccurrences { display:block;text-align:right; font-weight:bold;margin-top:5px;margin-right:5px;}\n" + "tablecaption {display:table-caption;font:20px bold sans-serif;}\n\n" + "hr {display:block;background:black;height:1px;margin:5px 0px 5px;}\n" + "whiteline {display:block;height:16px;}\n\n" + "searchfor {\n" + " display:table-cell;\n" + " border:1px solid black;\n" + " padding:0 7px 0; }\n\n"; + + if(!m_isSearchFlag) + { + css += "replacewith {\n" + " display:table-cell;\n" + " border:1px solid black;\n" + " padding:0 7px 0; }\n\n"; + } + + css += "folder {\n" + " display:table-cell;\n" + " border:1px solid black;\n" + " padding:0 7px 0; }\n\n" + "header { display: table-header-group; }\n\n" + "name {\n" + " display:table-cell;\n" + " border:1px solid black;\n" + " padding:0 7px 0; }\n\n" + "newsize {\n" + " display:table-cell;\n" + " border:1px solid black;\n" + " padding:0 7px 0;\n" + " text-align:right; }\n\n" + "oldsize {\n" + " display:table-cell;\n" + " border:1px solid black;\n" + " padding:0 7px 0;\n" + " text-align:right; }\n\n" + "ownergroup {\n" + " display:table-cell;\n" + " border:1px solid black;\n" + " padding:0 7px 0; }\n\n" + "owneruser {\n" + " display:table-cell;\n" + " border:1px solid black;\n" + " padding:0 7px 0; }\n\n" + "replacedstrings {\n" + " text-align:right;\n" + " display:table-cell;\n" + " border:1px solid black;\n" + " padding:0 7px 0; }\n\n" + "*[class~=header] {\n" + " background : lightgray;\n" + " text-align : center; }\n\n" + "row { display : table-row; }\n\n" + "table {\n" + " display:table;\n" + " border-collapse: collapse; }\n\n" + "*[class~=a1] {\n" + " background-color:aliceblue;\n" + " font-weight : bold;font-size:15px; }\n\n" + "*[class~=a2] {\n" + " background-color:khaki;\n" + " font-weight : bold;\n" + " font-size:15px; }\n\n"; + + oTStream << css; + + styleSheet.close(); +} + +void Report::createDocument(const QString& docPath) +{ + m_docPath = docPath; + + createStyleSheet(); + createReportFile(); +} + diff --git a/kfilereplace/report.h b/kfilereplace/report.h new file mode 100644 index 00000000..98996f92 --- /dev/null +++ b/kfilereplace/report.h @@ -0,0 +1,58 @@ +/*************************************************************************** + report.h - Report document class + ------------------- + begin : fri aug 13 15:29:46 CEST 2004 + + copyright : (C) 2004 Emiliano Gulmini + email : emi_barbarossa@yahoo.it + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef REPORT_H +#define REPORT_H + +// QT +class QString; + +// KDE +#include +#include "configurationclasses.h" +class KListView; + +/** Report class is used to create a pair of files (a xml and a css file) which are + * a short statistical report of the operations. + */ + +class Report +{ + private: + KListView* m_stringsView, + * m_resultsView; + QString m_docPath; + bool m_isSearchFlag; + RCOptions* m_option; + + public: + Report(RCOptions* info, KListView* rv, KListView* sv) { m_option = info; + m_resultsView = rv; + m_stringsView = sv; + m_isSearchFlag = m_option->m_searchingOnlyMode; + } + ~Report() { m_option = 0; } + private: + void createReportFile(); + void createStyleSheet(); + + public: + void createDocument(const QString& docPath); +}; + +#endif // REPORT_H diff --git a/kfilereplace/toolbar/Makefile.am b/kfilereplace/toolbar/Makefile.am new file mode 100644 index 00000000..1b5627ad --- /dev/null +++ b/kfilereplace/toolbar/Makefile.am @@ -0,0 +1,3 @@ +appdir = $(kde_datadir)/kfilereplacepart/icons +app_ICON = AUTO + diff --git a/kfilereplace/toolbar/cr22-action-back.png b/kfilereplace/toolbar/cr22-action-back.png new file mode 100644 index 00000000..3e8f12fe Binary files /dev/null and b/kfilereplace/toolbar/cr22-action-back.png differ diff --git a/kfilereplace/toolbar/cr22-action-backup_option.png b/kfilereplace/toolbar/cr22-action-backup_option.png new file mode 100644 index 00000000..a0e1e02f Binary files /dev/null and b/kfilereplace/toolbar/cr22-action-backup_option.png differ diff --git a/kfilereplace/toolbar/cr22-action-casesensitive_option.png b/kfilereplace/toolbar/cr22-action-casesensitive_option.png new file mode 100644 index 00000000..6302c0f2 Binary files /dev/null and b/kfilereplace/toolbar/cr22-action-casesensitive_option.png differ diff --git a/kfilereplace/toolbar/cr22-action-command_option.png b/kfilereplace/toolbar/cr22-action-command_option.png new file mode 100644 index 00000000..1da3688b Binary files /dev/null and b/kfilereplace/toolbar/cr22-action-command_option.png differ diff --git a/kfilereplace/toolbar/cr22-action-editadd.png b/kfilereplace/toolbar/cr22-action-editadd.png new file mode 100644 index 00000000..5eb6f503 Binary files /dev/null and b/kfilereplace/toolbar/cr22-action-editadd.png differ diff --git a/kfilereplace/toolbar/cr22-action-editremove.png b/kfilereplace/toolbar/cr22-action-editremove.png new file mode 100644 index 00000000..50117f6d Binary files /dev/null and b/kfilereplace/toolbar/cr22-action-editremove.png differ diff --git a/kfilereplace/toolbar/cr22-action-filereplace.png b/kfilereplace/toolbar/cr22-action-filereplace.png new file mode 100644 index 00000000..c3692e11 Binary files /dev/null and b/kfilereplace/toolbar/cr22-action-filereplace.png differ diff --git a/kfilereplace/toolbar/cr22-action-filesearch.png b/kfilereplace/toolbar/cr22-action-filesearch.png new file mode 100644 index 00000000..1be59c49 Binary files /dev/null and b/kfilereplace/toolbar/cr22-action-filesearch.png differ diff --git a/kfilereplace/toolbar/cr22-action-filesimulate.png b/kfilereplace/toolbar/cr22-action-filesimulate.png new file mode 100644 index 00000000..7cc5b284 Binary files /dev/null and b/kfilereplace/toolbar/cr22-action-filesimulate.png differ diff --git a/kfilereplace/toolbar/cr22-action-informations.png b/kfilereplace/toolbar/cr22-action-informations.png new file mode 100644 index 00000000..daeb5b80 Binary files /dev/null and b/kfilereplace/toolbar/cr22-action-informations.png differ diff --git a/kfilereplace/toolbar/cr22-action-invert.png b/kfilereplace/toolbar/cr22-action-invert.png new file mode 100644 index 00000000..f3ab8be6 Binary files /dev/null and b/kfilereplace/toolbar/cr22-action-invert.png differ diff --git a/kfilereplace/toolbar/cr22-action-next.png b/kfilereplace/toolbar/cr22-action-next.png new file mode 100644 index 00000000..cfab7cfb Binary files /dev/null and b/kfilereplace/toolbar/cr22-action-next.png differ diff --git a/kfilereplace/toolbar/cr22-action-projectopen.png b/kfilereplace/toolbar/cr22-action-projectopen.png new file mode 100644 index 00000000..607e6aa8 Binary files /dev/null and b/kfilereplace/toolbar/cr22-action-projectopen.png differ diff --git a/kfilereplace/toolbar/cr22-action-recursive_option.png b/kfilereplace/toolbar/cr22-action-recursive_option.png new file mode 100644 index 00000000..bc98df90 Binary files /dev/null and b/kfilereplace/toolbar/cr22-action-recursive_option.png differ diff --git a/kfilereplace/toolbar/cr22-action-regularexpression_option.png b/kfilereplace/toolbar/cr22-action-regularexpression_option.png new file mode 100644 index 00000000..f74c7b56 Binary files /dev/null and b/kfilereplace/toolbar/cr22-action-regularexpression_option.png differ diff --git a/kfilereplace/toolbar/cr22-action-unsortedList.png b/kfilereplace/toolbar/cr22-action-unsortedList.png new file mode 100644 index 00000000..bed281f1 Binary files /dev/null and b/kfilereplace/toolbar/cr22-action-unsortedList.png differ diff --git a/kfilereplace/tutorial.kwd b/kfilereplace/tutorial.kwd new file mode 100644 index 00000000..2183e53b Binary files /dev/null and b/kfilereplace/tutorial.kwd differ diff --git a/kfilereplace/whatthis.h b/kfilereplace/whatthis.h new file mode 100644 index 00000000..c91356dd --- /dev/null +++ b/kfilereplace/whatthis.h @@ -0,0 +1,101 @@ +/*************************************************************************** + whatthis.h - description + ------------------- + begin : fri 12 march CEST 2004 + copyright : (C) 2004 Emiliano Gulmini + email : + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +#ifndef WHATTHIS_H +#define WHATTHIS_H + +// QT +#include + +// KDE +#include + +namespace whatthisNameSpace +{ + //KFileReplaceView messages + const QString lvResultWhatthis = i18n("Shows the statistics of your operations. Note that the columns content changes depending on what kind of operation you are performing."); + + const QString lvStringsWhatthis = i18n("Shows a list of strings to search for (and if you specified it, a list of strings to replace with). Use the \"add strings\" dialog to edit your string list or double click on a string."); + + //KNewProjectDlg messages + const QString cbLocationWhatthis = i18n("Base folder for operations of search/replace. Insert path string here by hand or use the search button."); + + const QString cbFilterWhatthis = i18n("Shell-like wildcards. Example: \"*.html;*.txt;*.xml\"."); + + const QString edSizeMinWhatthis = i18n("Insert the minimum file size you want to search, or leave it unchecked if you don't want minimum size limit."); + + const QString edSizeMaxWhatthis = i18n("Insert the maximum file size you want to search, or leave it unchecked if you don't want maximum size limit."); + + const QString edDateMinWhatthis = i18n("Insert the minimum value for file access date that you want to search, or leave it unchecked if you don't a minimum limit."); + + const QString edDateMaxWhatthis = i18n("Insert the maximum value for file access date that you want to search, or leave it unchecked if you don't a maximum limit."); + + const QString cbDateValidWhatthis = i18n("Select \"writing\" if you want to use the date of the last modification, or \"reading\" to use the the date of the last access."); + + const QString chbDateMinWhatthis = i18n("Minimum value for access date."); + + const QString chbDateMaxWhatthis = i18n("Maximum value for access date."); + + const QString leSearchWhatthis = i18n("Insert here the string to search for."); + + const QString leReplaceWhatthis = i18n("Insert here the string to replace with."); + + //KOptionsDlg messages + const QString chbCaseSensitiveWhatthis = i18n("Enable this option if your search is case sensitive."); + + const QString chbRecursiveWhatthis = i18n("Enable this option to search in sub folders too."); + + const QString chbHaltOnFirstOccurrenceWhatthis = i18n("Enable this option when you are searching for a string and you are only interested to know if the string is present or not in the current file."); + + const QString chbIgnoreWhitespacesWhatthis =""; + + const QString chbFollowSymLinksWhatthis = i18n("If kfilereplace encounters a symbolic link treats it like a normal folder or file."); + + const QString chbIgnoreHiddenWhatthis = i18n("Enable this option to ignore hidden files or folders."); + + const QString chbIgnoreFilesWhatthis = i18n("If this option is enabled, KFR will show even the names of the files in which no string has been found or replaced."); + + const QString chbRegularExpressionsWhatthis = i18n("Allows you to apply QT-like regular expressions on the search string. Note that a complex regular expression could affect speed performance"); + + const QString chbVariablesWhatthis = i18n("Enable \"commands\". For example: if search string is \"user\" and replace string is the command \"[$user:uid$]\", KFR will substitute \"user\" with the uid of the user."); + + const QString chbBackupWhatthis = i18n("Enable this option if you want leave original files untouched."); + + const QString chbConfirmStringsWhatthis = i18n("Enable this option if you want to be asked for single string replacement confirmation."); + + //KFileReplacePart + const QString fileSimulateWhatthis = i18n("Enable this option to perform replacing as a simulation, i.e. without make any changes in files."); + + const QString optionsRegularExpressionsWhatthis = chbRegularExpressionsWhatthis; + + const QString optionsBackupWhatthis = chbBackupWhatthis; + + const QString optionsCaseWhatthis = chbCaseSensitiveWhatthis; + + const QString optionsVarWhatthis = chbVariablesWhatthis; + + const QString optionsRecursiveWhatthis = chbRecursiveWhatthis; + + //KAddStringDlg + const QString rbSearchOnlyWhatthis = i18n("Select search-only mode."); + + const QString rbSearchReplaceWhatthis = i18n("Select search-and-replace mode."); + + const QString edSearchWhatthis = i18n("Insert here a string you want search for."); + + const QString edReplaceWhatthis = i18n("Insert here the string that KFR will use to replace the search string."); +} +#endif diff --git a/kimagemapeditor/AUTHORS b/kimagemapeditor/AUTHORS new file mode 100644 index 00000000..7aee7c48 --- /dev/null +++ b/kimagemapeditor/AUTHORS @@ -0,0 +1 @@ +Jan Schäfer diff --git a/kimagemapeditor/COPYING b/kimagemapeditor/COPYING new file mode 100644 index 00000000..c7aea189 --- /dev/null +++ b/kimagemapeditor/COPYING @@ -0,0 +1,280 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/kimagemapeditor/ChangeLog b/kimagemapeditor/ChangeLog new file mode 100644 index 00000000..55983873 --- /dev/null +++ b/kimagemapeditor/ChangeLog @@ -0,0 +1,105 @@ +1.0 : +- New features : + * French translation - Thanks to Germain Chazot + - KImageMapEditor is now translated to 4 languages : + German, spanish, french and dutch + * Improved session management + * Made it possible to start with the last opened document + * The ImageMapChoosDialog is only shown, if there are more then one map to choose. +- Bug fixes : + * Fixed the bug that prevents from dropping html or image files + * Fixed another Mandrake compilation problem + * The area preview image size can now be changed by the properties dialog + * The highlight and show alt tag settings are now saved when used within Quanta. + * Completed spanish translation - Thanks to Antonio Crevillén + +1.0b3 : +- New features : + * Added dutch translation - Thanks to Fabrice Mous +- Bug fixes : + * added namespace to cout : std::cout to solve the compilation problem under Mandrake + * saveAs works now + * made the KPart readwrite only to work within Quanta correctly + +1.0b2 : +- Bug fixes : + * Opening of an image over the toolbar or the menu entry file->open add + the image now correctly to the image list. + * The command line option --stdout works again. + +1.0b : +- Note : Because of various internal modifications, this is intended to be a beta + release. So it's possible that KImageMapEditor may crash and/or + the content of the currently editing html file could be corrupted + or be lost at all. + KImageMapEditor therefore creates a backup file everytime you + save an html file. It ends with a ~. + Please only delete this file if you are sure that the original file + isn't corrupted. +- New features : + * Converted the program to the KPart architecture, it can now be used as a + imagemap viewer plugin in Konqueror or as an edit plugin in Quanta. + * It's now possible to really edit a html file instead of creating always + a new one with only one imagemap. + * Added a listview of all imagemaps of the current editing html files. + It's now possible to switch between the different maps, to delete maps and + to add new maps to the html file. + * Added a listview of all images that are contained in the current html file. + It's now possible to switch between these images. + * Spanish translation - Thanks to Antonio Crevillén +- Bug fixes : + * When KImageMapEditor was not properly installed with make install and + the required image files couldn't be found, KImageMapEditor now shows + an error message and exit(1), instead of crashing. + +0.9.5 : +- New features : + * Tool for adding and removing points to/from a polygon with the mouse + * Freehand tool for drawing polygons + * German translation + * More zoom modes +- Bug fixes : + * Some undo bugs which results in a crash -> fixed + * When switching from non-highlight mode to highlight mode the areas + weren't highlighted correctly -> fixed + * Crash when moving an area outside the drawing zone -> fixed + +0.9.4 : +- New features : + * Areas can be highlighted + * Alt. text can be shown + * PHP-files can be read + * Property dialog extended + * New action : close file + +0.9.3 : +- New features : + * Multiselection + * Keyboard can be used better + * New mouse cursors + * New Action : delete + * other new Actions + +0.9.2 : +- New features : + * Undo / Redo for almost all actions + * Middle mouse click opens the properties dialog + * Possiblity of enable / disable the default area + +- Bug fixes : + * It's now possible to save to a file without an *.html,*.htm extension + * Creating a rectangle with a negative size ( and a following crash ) is no longer possible. + +0.9.1 : +- New features : + * Better way of editing the area coordinates manually + - Possibility of adding and removing points to a polygon + * Cursor shape changes to indicate moving or resizing + * Circle drawing is now perfekt + * Possibility of changing the order of the areas + +- Bug fixes : + * When saving to an HTML file the ending tag is no longer missing. + * When adding an area and pressing cancel the area will not be added. + * Restoring the window size works now + diff --git a/kimagemapeditor/INSTALL b/kimagemapeditor/INSTALL new file mode 100644 index 00000000..02a4a074 --- /dev/null +++ b/kimagemapeditor/INSTALL @@ -0,0 +1,167 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes a while. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Type `make install' to install the programs and any data files and + documentation. + + 4. You can remove the program binaries and object files from the + source code directory by typing `make clean'. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. + diff --git a/kimagemapeditor/Makefile.am b/kimagemapeditor/Makefile.am new file mode 100644 index 00000000..3f2ed486 --- /dev/null +++ b/kimagemapeditor/Makefile.am @@ -0,0 +1,63 @@ +SUBDIRS = pics + +bin_PROGRAMS = kimagemapeditor +kde_module_LTLIBRARIES = libkimagemapeditor.la + +METASOURCES = AUTO + +noinst_LTLIBRARIES = libkimagemapeditorcommon.la + +libkimagemapeditorcommon_la_SOURCES = \ + qextfileinfo.cpp \ + areacreator.cpp \ + kimearea.cpp \ + kimecommands.cpp \ + kimedialogs.cpp \ + kimagemapeditor.cpp \ + drawzone.cpp \ + arealistview.cpp \ + imageslistview.cpp \ + mapslistview.cpp + +libkimagemapeditor_la_SOURCES = \ + dummy.cpp + +kimagemapeditor_SOURCES = \ + main.cpp \ + kimeshell.cpp + + +noinst_HEADERS = \ + qextfileinfo.h \ + areacreator.h \ + kimearea.h \ + kimecommands.h \ + kimedialogs.h \ + kimagemapeditor.h \ + drawzone.h \ + kimeshell.h + + +libkimagemapeditor_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) +libkimagemapeditor_la_LIBADD = libkimagemapeditorcommon.la $(LIB_KFILE) $(LIB_KPARTS) $(LIB_KHTML) + +kimagemapeditor_LDFLAGS = $(all_libraries) $(KDE_RPATH) +kimagemapeditor_LDADD = libkimagemapeditorcommon.la $(LIB_KFILE) $(LIB_KPARTS) $(LIB_KHTML) + +# set the include path for X, qt and KDE +INCLUDES= $(all_includes) + +xdg_apps_DATA = kimagemapeditor.desktop + +rcdir = $(kde_datadir)/kimagemapeditor +rc_DATA = kimagemapeditorui.rc \ + kimagemapeditorpartui.rc + +kde_services_DATA = kimagemapeditorpart.desktop + +messages: rc.cpp + LIST=`find . -name \*.h -o -name \*.hh -o -name \*.H -o -name \*.hxx -o -name \*.hpp -o -name \*.cpp -o -name \*.cc -o -name \*.cxx -o -name \*.ecpp -o -name \*.C`; \ + if test -n "$$LIST"; then \ + $(XGETTEXT) $$LIST -o $(podir)/kimagemapeditor.pot; \ + fi + diff --git a/kimagemapeditor/NEWS b/kimagemapeditor/NEWS new file mode 100644 index 00000000..3957e33d --- /dev/null +++ b/kimagemapeditor/NEWS @@ -0,0 +1,13 @@ +1.0 : +- New features : + * French translation - Thanks to Germain Chazot + - KImageMapEditor is now translated to 4 languages : + German, spanish, french and dutch + * Session management + * Made it possible to start with the last opened document +- Bug fixes : + * Fixed the bug that prevents from dropping html or image files + * Fixed another Mandrake compilation problem + * The area preview image size can now be changed by the properties dialog + * The highlight and show alt tag settings are now saved when used within Quanta. + * Completed spanish translation - Thanks to Antonio Crevillén diff --git a/kimagemapeditor/README b/kimagemapeditor/README new file mode 100644 index 00000000..b04c6794 --- /dev/null +++ b/kimagemapeditor/README @@ -0,0 +1,12 @@ + + --------------------------------- + + KImageMapEditor + + An HTML image map editor + + Jan Schäfer + + janschaefer@users.sourceforge.net + + --------------------------------- diff --git a/kimagemapeditor/TODO b/kimagemapeditor/TODO new file mode 100644 index 00000000..c629ca1d --- /dev/null +++ b/kimagemapeditor/TODO @@ -0,0 +1,5 @@ +- Create a handbook +- Add Tip Of The Day +- Translate to more languages ( help would be really appreciated ) +- Have fun with it ;-) + diff --git a/kimagemapeditor/VERSION b/kimagemapeditor/VERSION new file mode 100644 index 00000000..51164aba --- /dev/null +++ b/kimagemapeditor/VERSION @@ -0,0 +1 @@ +KImageMapEditor v1.0.1 diff --git a/kimagemapeditor/areacreator.cpp b/kimagemapeditor/areacreator.cpp new file mode 100644 index 00000000..739409fc --- /dev/null +++ b/kimagemapeditor/areacreator.cpp @@ -0,0 +1,44 @@ +/*************************************************************************** + areacreator.cpp - description + ------------------- + begin : Wed Apr 3 2002 + copyright : (C) 2002 by Jan Schäfer + email : janschaefer@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "areacreator.h" + + + +Area* AreaCreator::create( Area::ShapeType type) +{ + switch ( type ) { + case Area::Rectangle : return new RectArea(); + case Area::Circle : return new CircleArea(); + case Area::Polygon : return new PolyArea(); + case Area::Default : return new DefaultArea(); + case Area::Selection : return new AreaSelection(); + default : return new Area(); + } +} + + +Area* AreaCreator::create( KImageMapEditor::ToolType type) +{ + switch ( type ) { + case KImageMapEditor::Rectangle : return new RectArea(); + case KImageMapEditor::Circle : return new CircleArea(); + case KImageMapEditor::Polygon : return new PolyArea(); + case KImageMapEditor::Freehand : return new PolyArea(); + default : return new Area(); + } +} diff --git a/kimagemapeditor/areacreator.h b/kimagemapeditor/areacreator.h new file mode 100644 index 00000000..c232d4f3 --- /dev/null +++ b/kimagemapeditor/areacreator.h @@ -0,0 +1,35 @@ +/*************************************************************************** + areacreator.h - description + ------------------- + begin : Wed Apr 3 2002 + copyright : (C) 2002 by Jan Schäfer + email : janschaefer@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef AREACREATOR_H +#define AREACREATOR_H + + +#include "kimagemapeditor.h" + +/** + * A small creator class which follows the + * factory method pattern + */ +class AreaCreator +{ + public : + static Area* create( Area::ShapeType ); + static Area* create( KImageMapEditor::ToolType); +}; + +#endif diff --git a/kimagemapeditor/arealistview.cpp b/kimagemapeditor/arealistview.cpp new file mode 100644 index 00000000..80cd3265 --- /dev/null +++ b/kimagemapeditor/arealistview.cpp @@ -0,0 +1,67 @@ +/*************************************************************************** + arealistview.cpp - description + ------------------- + begin : Weg Feb 26 2003 + copyright : (C) 2003 by Jan Schäfer + email : janschaefer@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +// QT +#include +#include +#include +#include +#include + +// KDE +#include +#include + +// local +#include "kimearea.h" +#include "arealistview.h" + + +AreaListView::AreaListView(QWidget *parent, const char *name) + : QVBox(parent, name) +{ + listView = new KListView(this); + listView->addColumn(i18n("Areas")); + listView->addColumn(i18n("Preview")); + + listView->setMultiSelection(true); + listView->setSelectionMode( QListView::Extended ); + listView->setSorting(-1); // The user can't sort by clicking on the header + listView->setFullWidth(true); + + + QWhatsThis::add( listView, i18n("

Area List

The area list shows you all areas of the map.
" + "The left column shows the link associated with the area; the right " + "column shows the part of the image that is covered by the area.
" + "The maximum size of the preview images can be configured.")); + QToolTip::add( listView, i18n("A list of all areas")); + + QHBox *hbox= new QHBox(this); + upBtn= new QPushButton("",hbox); + upBtn->setIconSet(SmallIconSet("up")); + + downBtn= new QPushButton("",hbox); + downBtn->setIconSet(SmallIconSet("down")); + +} + + +AreaListView::~AreaListView() +{ +} + +#include "arealistview.moc" diff --git a/kimagemapeditor/arealistview.h b/kimagemapeditor/arealistview.h new file mode 100644 index 00000000..6037f5ee --- /dev/null +++ b/kimagemapeditor/arealistview.h @@ -0,0 +1,47 @@ +/*************************************************************************** + arealistview.h - description + ------------------- + begin : Weg Feb 26 2003 + copyright : (C) 2003 by Jan Schäfer + email : janschaefer@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef _AREALISTVIEW_H_ +#define _AREALISTVIEW_H_ + +#include +#include + +class KListView; +class QPushButton; +class Area; + +/** + * This class consists of a ListView and two arrow buttons on the bottom. + * It shows all Areas of the current map. + * Jan Schaefer + **/ +class AreaListView : public QVBox +{ + Q_OBJECT + +public: + AreaListView(QWidget *parent, const char *name); + ~AreaListView(); + + KListView* listView; + QPushButton *upBtn; + QPushButton *downBtn; + +}; + +#endif diff --git a/kimagemapeditor/configure.in.in b/kimagemapeditor/configure.in.in new file mode 100644 index 00000000..f9c208de --- /dev/null +++ b/kimagemapeditor/configure.in.in @@ -0,0 +1,6 @@ +#MIN_CONFIG + +AM_INIT_AUTOMAKE(kimagemapeditor, 1.0) +AC_C_BIGENDIAN +AC_CHECK_KDEMAXPATHLEN + diff --git a/kimagemapeditor/drawzone.cpp b/kimagemapeditor/drawzone.cpp new file mode 100644 index 00000000..a5bf5612 --- /dev/null +++ b/kimagemapeditor/drawzone.cpp @@ -0,0 +1,896 @@ +/*************************************************************************** + drawzone.cpp - description + ------------------- + begin : Wed Apr 4 2001 + copyright : (C) 2001 by Jan Schïż½er + email : j_schaef@informatik.uni-kl.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +// QT +#include +#include +#include +#include + +// KDE +#include +#include +#include +#include +#include +#include + +// Local +#include "drawzone.h" +#include "kimagemapeditor.h" +#include "kimecommands.h" +#include "areacreator.h" + +#include "kimecommon.h" + +DrawZone::DrawZone(QWidget *parent,KImageMapEditor* _imageMapEditor) + : QScrollView(parent) +{ + imageMapEditor=_imageMapEditor; +// setPicture(QImage()); + currentAction=None; + currentArea=0L; + oldArea=0L; + _zoom=1; + if (imageMapEditor->isReadWrite()) { + viewport()->setMouseTracking(true); + viewport()->setAcceptDrops(true); + this->setAcceptDrops(true); + } + else + viewport()->setMouseTracking(false); + + setDragAutoScroll(true); + + // The cross rectangle cursor + QBitmap b(32,32,true); + QBitmap b2(32,32,true); + QPainter p(&b); + // the cross + p.drawLine(0,8,6,8); + p.drawLine(10,8,16,8); + p.drawLine(8,0,8,6); + p.drawLine(8,10,8,16); + // the rectangle + p.drawRect(17,17,8,6); + + p.end(); + + p.begin(&b2); + // the cross black lines + p.drawLine(0,8,6,8); + p.drawLine(10,8,16,8); + p.drawLine(8,0,8,6); + p.drawLine(8,10,8,16); + + // the cross white lines + p.drawLine(0,7,6,7); + p.drawLine(10,7,16,7); + p.drawLine(7,0,7,6); + p.drawLine(7,10,7,16); + + // the cross white lines + p.drawLine(0,9,6,9); + p.drawLine(10,9,16,9); + p.drawLine(9,0,9,6); + p.drawLine(9,10,9,16); + + // the rectangles + p.drawRect(17,17,8,6); // black + p.drawRect(18,18,6,4); // white + p.drawRect(16,16,10,8); // white + + p.end(); + + RectangleCursor = QCursor(b,b2,8,8); + + + // The cross circle cursor + b = QBitmap(32,32,true); + b2 = QBitmap(32,32,true); + p.begin(&b); + // the cross + p.drawLine(0,8,6,8); + p.drawLine(10,8,16,8); + p.drawLine(8,0,8,6); + p.drawLine(8,10,8,16); + // the circle + p.drawEllipse(17,17,8,8); + + p.end(); + + p.begin(&b2); + // the cross black lines + p.drawLine(0,8,6,8); + p.drawLine(10,8,16,8); + p.drawLine(8,0,8,6); + p.drawLine(8,10,8,16); + + // the cross white lines + p.drawLine(0,7,6,7); + p.drawLine(10,7,16,7); + p.drawLine(7,0,7,6); + p.drawLine(7,10,7,16); + + // the cross white lines + p.drawLine(0,9,6,9); + p.drawLine(10,9,16,9); + p.drawLine(9,0,9,6); + p.drawLine(9,10,9,16); + + // the circles + p.drawEllipse(17,17,8,8); // black + p.drawEllipse(16,16,10,10); // white + p.drawEllipse(18,18,6,6); // white + + p.end(); + + CircleCursor = QCursor(b,b2,8,8); + + QString path = KGlobal::dirs()->findResourceDir( "data", "kimagemapeditor/polygoncursor.png" ) + "kimagemapeditor/polygoncursor.png"; + PolygonCursor = QCursor(QPixmap(path),8,8); + + path = KGlobal::dirs()->findResourceDir( "data", "kimagemapeditor/freehandcursor.png" ) + "kimagemapeditor/freehandcursor.png"; + FreehandCursor = QCursor(QPixmap(path),8,8); + + path = KGlobal::dirs()->findResourceDir( "data", "kimagemapeditor/addpointcursor.png" ) + "kimagemapeditor/addpointcursor.png"; + AddPointCursor = QCursor(QPixmap(path),8,8); + + path = KGlobal::dirs()->findResourceDir( "data", "kimagemapeditor/removepointcursor.png" ) + "kimagemapeditor/removepointcursor.png"; + RemovePointCursor = QCursor(QPixmap(path),8,8); +} + +DrawZone::~DrawZone(){ +} + +void DrawZone::setPicture(const QImage &_image) { + image=_image; +//- zoomedImage.convertFromImage(image); + setZoom(_zoom); +} + +void DrawZone::setZoom(double z) +{ + _zoom=z; + imageRect.setHeight(myround(image.height()*_zoom)); + imageRect.setWidth(myround(image.width()*_zoom)); + zoomedImage=QPixmap(imageRect.width(),imageRect.height()); + QPainter p(&zoomedImage); + p.scale(z,z); + QPixmap pix; + pix.convertFromImage(image); + // if the picture has transparent areas, + // fill them with Gimp like background + if (pix.mask()) { + QPixmap backPix(32,32); + QPainter p2(&backPix); + p2.fillRect(0,0,32,32,QColor(156,149,156)); + p2.fillRect(0,16,16,16,QColor(98,105,98)); + p2.fillRect(16,0,16,16,QColor(98,105,98)); + p2.flush(); + p.setPen(QPen()); + p.fillRect(imageRect.left(),imageRect.top(),imageRect.width(),imageRect.height(),QBrush(QColor("black"),backPix)); + } + p.drawPixmap(imageRect.left(),imageRect.top(),pix); + p.flush(); + resizeContents(visibleWidth()>imageRect.width() ? visibleWidth() : imageRect.width(), + visibleHeight()>imageRect.height() ? visibleHeight() : imageRect.height()); + repaintContents(0,0,contentsWidth(),contentsHeight(),true); +} + +QPoint DrawZone::translateFromZoom(const QPoint & p) const { + return QPoint((int)(p.x()/_zoom),(int)(p.y()/_zoom)); +} + +QRect DrawZone::translateFromZoom(const QRect & p) const { + return QRect((int)(p.x()/_zoom),(int) (p.y()/_zoom), + (int)(p.width()/_zoom),(int)(p.height()/_zoom)); +} + +QPoint DrawZone::translateToZoom(const QPoint & p) const { + return QPoint(myround(p.x()*_zoom),myround(p.y()*_zoom)); +} + +QRect DrawZone::translateToZoom(const QRect & r) const { +// return QRect(round(r.x()*_zoom),round(r.y()*_zoom), +// round(r.width()*_zoom),round(r.height()*_zoom)); + return QRect((int)(r.x()*_zoom),(int)(r.y()*_zoom), + (int)(r.width()*_zoom+2),(int)(r.height()*_zoom+2)); +} + +void DrawZone::contentsMouseDoubleClickEvent(QMouseEvent* e) { + if ( ! imageMapEditor->isReadWrite()) + return; + + QPoint point=e->pos(); + point-=imageRect.topLeft(); + point=translateFromZoom(point); + if ( currentAction==None && + (currentArea=imageMapEditor->onArea(point))) + { + imageMapEditor->deselectAll(); + imageMapEditor->select(currentArea); + currentArea=imageMapEditor->selected(); + imageMapEditor->showTagEditor(imageMapEditor->selected()); + } + +} + +void DrawZone::contentsMousePressEvent(QMouseEvent* e) +{ + if ( ! imageMapEditor->isReadWrite()) + return; + + drawStart=e->pos(); + // Check if it's on picture if not + // move it to the picture's border + if (!imageRect.contains(drawStart)) { + if (drawStart.x()>imageRect.right()) + drawStart.setX(imageRect.right()); + if (drawStart.x()imageRect.bottom()) + drawStart.setY(imageRect.bottom()); + if (drawStart.y()clone(); + } + + if ( currentAction==None ) { + if (e->button()==RightButton) + { + if ( (currentArea=imageMapEditor->onArea(drawStart)) ) + { + if ( ! currentArea->isSelected()) + { + imageMapEditor->deselectAll(); + imageMapEditor->select(currentArea); + } + currentArea=imageMapEditor->selected(); + } + + imageMapEditor->slotShowMainPopupMenu(e->globalPos()); + + } + else + if (e->button()==MidButton) { + contentsMouseDoubleClickEvent(e); + } + else // LeftClick on selectionpoint + if ((currentArea=imageMapEditor->selected()) && + (currentSelectionPoint=currentArea->onSelectionPoint(zoomedPoint,_zoom))) + { + oldArea=currentArea->clone(); + + if ( (imageMapEditor->currentToolType() == KImageMapEditor::RemovePoint) && + (imageMapEditor->selected()->selectionPoints()->count()>3) ) + { + currentAction=RemovePoint; + } + else + { + currentAction=MoveSelectionPoint; + currentArea->setMoving(true); + } + + } else // leftclick not on selectionpoint but on area + if ((currentArea=imageMapEditor->onArea(drawStart))) + { + if ( imageMapEditor->currentToolType() == KImageMapEditor::AddPoint ) + { + currentAction=AddPoint; + viewport()->setCursor(AddPointCursor); + oldArea=currentArea->clone(); + } + else + { + currentAction=MoveArea; + viewport()->setCursor(sizeAllCursor); + + if ( currentArea->isSelected() ) { + if ( (e->state() & ControlButton) ) + imageMapEditor->deselect(currentArea); + } else + { + if ( (e->state() & ControlButton) ) + imageMapEditor->select( currentArea ); + else { + imageMapEditor->deselectAll(); + imageMapEditor->select( currentArea ); + } + } + + currentArea = imageMapEditor->selected(); + currentArea->setMoving(true); + + oldArea=currentArea->clone(); + } + } + else // leftclick on the background + if ( (imageMapEditor->currentToolType()==KImageMapEditor::Rectangle) || + (imageMapEditor->currentToolType()==KImageMapEditor::Circle) || + (imageMapEditor->currentToolType()==KImageMapEditor::Polygon) || + (imageMapEditor->currentToolType()==KImageMapEditor::Freehand)) + { + currentArea=AreaCreator::create(imageMapEditor->currentToolType()); + + currentArea->setRect(QRect(drawStart,drawStart)); + currentArea->setSelected(false); + imageMapEditor->deselectAll(); + + switch (imageMapEditor->currentToolType()) { + case KImageMapEditor::Rectangle : currentAction=DrawRectangle; break; + case KImageMapEditor::Circle : currentAction=DrawCircle; break; + case KImageMapEditor::Polygon : + currentAction=DrawPolygon; + currentArea->addCoord(drawStart); + currentSelectionPoint=currentArea->selectionPoints()->last(); + break; + case KImageMapEditor::Freehand : + currentAction=DrawFreehand; + //currentArea->addCoord(drawStart); + currentArea->setFinished(false); + break; + default: break; + } + } + else + // leftclicked with the arrow at an areafree position + if (imageMapEditor->currentToolType()==KImageMapEditor::Selection) + { + currentArea=0L; + imageMapEditor->deselectAll(); + // Start drawing a selection rectangle + currentAction=DoSelect; + oldSelectionRect = imageRect; + } + } else + if ( currentAction==DrawPolygon) { + + } + + QRect r; + if (oldArea) + r=oldArea->selectionRect(); + if (currentArea) { + r= r | currentArea->selectionRect(); + repaintContents(translateToZoom(r),false); + } + + +} + +void DrawZone::contentsMouseReleaseEvent(QMouseEvent *e) { + if ( ! imageMapEditor->isReadWrite()) + return; + + QPoint drawEnd=e->pos(); + + // Check if it's on picture if not + // move it to the picture's border + if (!imageRect.contains(drawEnd)) { + if (drawEnd.x()>imageRect.right()) + drawEnd.setX(imageRect.right()); + if (drawEnd.x()imageRect.bottom()) + drawEnd.setY(imageRect.bottom()); + if (drawEnd.y()commandHistory()->addCommand( + new CreateCommand( imageMapEditor, currentArea ), true); + } else + if (currentAction==DrawPolygon) { + // If the number of Polygonpoints is more than 2 + // and clicked on the first PolygonPoint or + // the right Button was pressed the Polygon is finished + if ((currentArea->selectionPoints()->count()>2) + && (currentArea->selectionPoints()->first()->contains(drawEnd) + || (e->button()==RightButton))) + { + currentArea->setFinished(true); + currentAction=None; + imageMapEditor->commandHistory()->addCommand( + new CreateCommand( imageMapEditor, currentArea ), true); + } else + { + currentArea->insertCoord(currentArea->countSelectionPoints()-1, drawEnd); + currentSelectionPoint=currentArea->selectionPoints()->last(); + } + } else + if (currentAction==DrawFreehand) + { + currentArea->setFinished(true); + currentArea->simplifyCoords(); + currentAction=None; + imageMapEditor->commandHistory()->addCommand( + new CreateCommand( imageMapEditor, currentArea ), true); + } else + if (currentAction==MoveArea) { + QPoint p1 = oldArea->rect().topLeft(); + QPoint p2 = imageMapEditor->selected()->rect().topLeft(); + + if (p1 != p2) + { + imageMapEditor->commandHistory()->addCommand( + new MoveCommand( imageMapEditor, imageMapEditor->selected(), oldArea->rect().topLeft()),true); + imageMapEditor->slotAreaChanged(currentArea); + } else + imageMapEditor->updateSelection(); + + currentAction=None; + } else + if (currentAction==MoveSelectionPoint) { + imageMapEditor->commandHistory()->addCommand( + new ResizeCommand( imageMapEditor, imageMapEditor->selected(), oldArea),true); + imageMapEditor->slotAreaChanged(currentArea); + currentAction=None; + } else + if (currentAction==RemovePoint) { + if (currentSelectionPoint==currentArea->onSelectionPoint(zoomedPoint,_zoom)) + { + currentArea->removeSelectionPoint(currentSelectionPoint); + + imageMapEditor->commandHistory()->addCommand( + new RemovePointCommand( imageMapEditor, imageMapEditor->selected(), oldArea),true); + imageMapEditor->slotAreaChanged(currentArea); + } + currentAction=None; + } else + if (currentAction==AddPoint) + { + if (currentArea==imageMapEditor->onArea(drawEnd)) + { + imageMapEditor->commandHistory()->addCommand( + new AddPointCommand( imageMapEditor, imageMapEditor->selected(), drawEnd),true); + imageMapEditor->slotAreaChanged(currentArea); + } + currentAction=None; + } else + if (currentAction==DoSelect) { + currentAction=None; + + QRect r(drawStart.x(),drawStart.y(),drawCurrent.x()-drawStart.x(),drawCurrent.y()-drawStart.y()); + r = r.normalize(); + + AreaListIterator it=imageMapEditor->areaList(); + for ( ; it.current() != 0L ; ++it ) { + if ( it.current()->rect().intersects(r) ) + { + if (!it.current()->isSelected() ) + imageMapEditor->selectWithoutUpdate( it.current() ); + } + else + if (it.current()->isSelected()) + imageMapEditor->deselectWithoutUpdate( it.current() ); + } + + imageMapEditor->updateActionAccess(); + imageMapEditor->updateSelection(); + repaintContents(imageRect,false); + } else { + currentAction=None; + } + imageMapEditor->slotChangeStatusCoords(drawEnd.x(),drawEnd.y()); + if (currentArea) + { + currentArea->setMoving(false); + repaintArea(*currentArea); + } + delete oldArea; + oldArea=0L; +// repaintContents(0,0,contentsWidth(),contentsHeight(),false); + imageMapEditor->slotUpdateSelectionCoords(); +} + + +void DrawZone::contentsMouseMoveEvent(QMouseEvent *e) +{ + if ( ! imageMapEditor->isReadWrite()) + return; + + + drawCurrent=e->pos(); + + // If outside the image + // set it to the border + if (!imageRect.contains(drawCurrent)) { + if (drawCurrent.x()>imageRect.right()) + drawCurrent.setX(imageRect.right()); + if (drawCurrent.x()imageRect.bottom()) + drawCurrent.setY(imageRect.bottom()); + if (drawCurrent.y()rect()); + currentArea->setRect(QRect(drawStart,drawCurrent).normalize()); + QRect newRect=translateToZoom(currentArea->selectionRect()); + QRect r=oldRect | newRect; + repaintContents(r,false); + imageMapEditor->slotUpdateSelectionCoords( currentArea->rect() ); + } else + if (currentAction==DrawCircle) { + QRect oldRect=translateToZoom(currentArea->rect()); + + // We don't want ellipses + int maxDistance=myabs(drawStart.x()-drawCurrent.x()) > + myabs(drawStart.y()-drawCurrent.y()) ? + myabs(drawStart.x()-drawCurrent.x()) : + myabs(drawStart.y()-drawCurrent.y()) ; + + int xDiff=maxDistance; + int yDiff=maxDistance; + + if ( drawStart.x()-drawCurrent.x() > 0) + xDiff=-xDiff; + + if ( drawStart.y()-drawCurrent.y() > 0) + yDiff=-yDiff; + + QPoint endPoint( drawStart.x()+xDiff, drawStart.y()+yDiff); + + currentArea->setRect(QRect(drawStart,endPoint).normalize()); + QRect newRect=translateToZoom(currentArea->rect()); + QRect r=oldRect | newRect; + repaintContents(r,false); + imageMapEditor->slotUpdateSelectionCoords( currentArea->rect() ); + } else + if ( currentAction==DrawPolygon ) { + QRect oldRect=translateToZoom(currentArea->rect()); + currentArea->moveSelectionPoint(currentSelectionPoint,drawCurrent); + QRect newRect=translateToZoom(currentArea->rect()); + QRect r=oldRect | newRect; + repaintContents(r,false); + } else + if ( currentAction==DrawFreehand) { + QRect oldRect=translateToZoom(currentArea->rect()); + currentArea->insertCoord(currentArea->countSelectionPoints(), drawCurrent); + QRect newRect=translateToZoom(currentArea->rect()); + QRect r=oldRect | newRect; + repaintContents(r,false); + } else + if ( currentAction==MoveArea ) { + QRect oldRect=translateToZoom(currentArea->selectionRect()); + currentArea->moveBy((drawCurrent-drawStart).x(),(drawCurrent-drawStart).y()); + QRect newRect=translateToZoom(currentArea->selectionRect()); + QRect r=oldRect | newRect; + currentArea->setMoving(true); + repaintContents(r,false); + drawStart=drawCurrent; + imageMapEditor->slotUpdateSelectionCoords(); + } else + if ( currentAction==MoveSelectionPoint ) { + QRect oldRect=translateToZoom(currentArea->selectionRect()); + currentArea->moveSelectionPoint(currentSelectionPoint,drawCurrent); + QRect newRect=translateToZoom(currentArea->selectionRect()); + QRect r=oldRect | newRect; + repaintContents(r,false); + imageMapEditor->slotUpdateSelectionCoords(); + } else + if (currentAction==DoSelect) { + + QRect r(drawStart.x(),drawStart.y(),drawCurrent.x()-drawStart.x(),drawCurrent.y()-drawStart.y()); + r = r.normalize(); +// r = translateFromZoom(r); +/* + AreaListIterator it=imageMapEditor->areaList(); + for ( ; it.current() != 0L ; ++it ) { + if ( it.current()->rect().intersects(r) ) + { + if (!it.current()->isSelected() ) + imageMapEditor->selectWithoutUpdate( it.current() ); + } + else + if (it.current()->isSelected()) + imageMapEditor->deselectWithoutUpdate( it.current() ); + } +*/ + // We don't have to repaint the hole selection rectangle + // only the borders have to be repainted. + // So we have to create 4 rectangles for every rectangle + // which represent the borders and then repaint them. + + QRect lb,rb,tb,bb; + createBorderRectangles(translateToZoom(r),lb,rb,tb,bb); + repaintContents(lb,false); + repaintContents(rb,false); + repaintContents(tb,false); + repaintContents(bb,false); + + createBorderRectangles(translateToZoom(oldSelectionRect),lb,rb,tb,bb); + repaintContents(lb,false); + repaintContents(rb,false); + repaintContents(tb,false); + repaintContents(bb,false); + +// repaintContents(oldSelectionRect | r,false); + oldSelectionRect = r; +// repaintContents(translateToZoom(r),false); +//+ imageMapEditor->updateSelection(); + + +// QRect r(drawStart.x(),drawStart.y(),drawCurrent.x()-drawStart.x(),drawCurrent.y()-drawStart.y()); +// r = r.normalize(); +// QRect r2(drawStart.x(),drawStart.y(),drawOld.x()-drawStart.x(),drawOld.y()-drawStart.y()); +// r2 = r2.normalize(); +// r = translateToZoom(r | r2); +// repaintContents(r,false); + } else + if ( currentAction==None ) + { + if ( imageMapEditor->selected() && + imageMapEditor->selected()->onSelectionPoint(zoomedPoint,_zoom )) + { + if (imageMapEditor->selected()->type()==Area::Polygon) + { + if ((imageMapEditor->currentToolType()==KImageMapEditor::RemovePoint) && + (imageMapEditor->selected()->selectionPoints()->count()>3) ) + { + viewport()->setCursor(RemovePointCursor); + } + else + { + viewport()->setCursor(pointingHandCursor); + } + } + else + { + QPoint center=imageMapEditor->selected()->rect().center(); + if (drawCurrent.x() < center.x()) { + if (drawCurrent.y() < center.y()) + viewport()->setCursor(sizeFDiagCursor); + else + viewport()->setCursor(sizeBDiagCursor); + } + else { + if (drawCurrent.y() < center.y()) + viewport()->setCursor(sizeBDiagCursor); + else + viewport()->setCursor(sizeFDiagCursor); + } + } + } else + if ( imageMapEditor->onArea(drawCurrent) ) + { + if (imageMapEditor->currentToolType()==KImageMapEditor::AddPoint) + { + viewport()->setCursor(AddPointCursor); + } + else + { + viewport()->setCursor(sizeAllCursor); + } + } + else + if (imageMapEditor->currentToolType()==KImageMapEditor::Rectangle) { + viewport()->setCursor(RectangleCursor); +// kdDebug() << "KImageMapEditor::DrawZone: viewport()->setCursor to Rectangle" << endl; + } + else + if (imageMapEditor->currentToolType()==KImageMapEditor::Circle) + viewport()->setCursor(CircleCursor); + else + if (imageMapEditor->currentToolType()==KImageMapEditor::Polygon) + viewport()->setCursor(PolygonCursor); + else + if (imageMapEditor->currentToolType()==KImageMapEditor::Freehand) + viewport()->setCursor(FreehandCursor); + else + viewport()->setCursor(arrowCursor); + + } + imageMapEditor->slotChangeStatusCoords(drawCurrent.x(),drawCurrent.y()); +} + +void DrawZone::createBorderRectangles(const QRect & r,QRect & rb,QRect & lb,QRect & tb,QRect & bb) +{ + int bw; + bw = (int) (2+2*_zoom); // Border width + + rb.setX(r.x()+r.width()-bw); + rb.setY(r.y()); + rb.setWidth(bw+1); + rb.setHeight(r.height()); + + lb.setX(r.x()); + lb.setY(r.y()); + lb.setWidth(bw); + lb.setHeight(r.height()); + + tb.setX(r.x()); + tb.setY(r.y()); + tb.setWidth(r.width()); + tb.setHeight(bw); + + bb.setX(r.x()); + bb.setY(r.y()+r.height()-bw); + bb.setWidth(r.width()); + bb.setHeight(bw+1); +} + + +void DrawZone::resizeEvent(QResizeEvent* e) { + QScrollView::resizeEvent(e); + int width=(int) (image.width()*_zoom); + int height=(int) (image.height()*_zoom); + if (visibleWidth()>width) + width=visibleWidth(); + if (visibleHeight()>height) + height=visibleHeight(); + + resizeContents(width,height); + + imageRect.setLeft(0); + imageRect.setTop(0); + imageRect.setHeight((int)(image.height()*_zoom)); + imageRect.setWidth((int)(image.width()*_zoom)); + +} + +void DrawZone::cancelDrawing() +{ + if ( (currentAction == DrawPolygon ) + || (currentAction == DrawRectangle ) + || (currentAction == DrawCircle ) + ) + { + currentAction = None; + QRect r = translateToZoom(currentArea->selectionRect()); + delete currentArea; + currentArea = 0L; + repaintContents(r,false); + imageMapEditor->slotUpdateSelectionCoords(); + } +} + +void DrawZone::repaintArea(const Area & a) { + repaintContents(translateToZoom(a.selectionRect()),false); +} + +void DrawZone::repaintRect(const QRect & r) { + repaintContents(translateToZoom(r),false); +} + +void DrawZone::drawContents(QPainter* p,int clipx,int clipy,int clipw,int cliph) +{ + +// Erase background without flicker + QRect updateRect(clipx,clipy,clipw,cliph); + + // Pixmap for double-buffering + QPixmap doubleBuffer(updateRect.size()); + if (doubleBuffer.isNull()) + return; + + QPainter p2(&doubleBuffer); + p2.drawPixmap(0,0,zoomedImage,clipx,clipy,clipw,cliph); + p2.setBackgroundColor(p->backgroundColor()); + + if (zoomedImage.width() < (clipw+clipx) ) { + int eraseWidth = clipw+clipx - zoomedImage.width(); + p2.eraseRect( QRect(clipw-eraseWidth,0,eraseWidth,cliph) ); + } + + if (zoomedImage.height() < (cliph+clipy) ) { + int eraseHeight = cliph+clipy - zoomedImage.height(); + p2.eraseRect( QRect(0,cliph-eraseHeight,clipw,eraseHeight) ); + } + + p2.translate(-clipx, -clipy); + p2.scale(_zoom,_zoom); + + QRect areaUpdateRect; + areaUpdateRect.setX(myround(clipx/_zoom)-1); + areaUpdateRect.setY(myround(clipy/_zoom)-1); + areaUpdateRect.setWidth(myround(clipw/_zoom)+2); + areaUpdateRect.setHeight(myround(cliph/_zoom)+2); + + AreaListIterator it=imageMapEditor->areaList(); + for ( it.toLast();it.current() != 0L; --it) + { + if (it.current()->rect().intersects(areaUpdateRect)) + it.current()->draw(p2); + } + + // Draw the current drawing Area + if (currentAction != MoveArea && + currentAction != MoveSelectionPoint && + currentAction != None && + currentAction != DoSelect) + { + currentArea->draw(p2); + } + + if (currentAction == DoSelect ) + { + QPen pen = QPen(QColor("white"),1); + p2.setRasterOp(Qt::XorROP); + pen.setStyle(Qt::DotLine); + p2.setPen(pen); + + QRect r( drawStart.x(),drawStart.y(),drawCurrent.x()-drawStart.x(),drawCurrent.y()-drawStart.y()); + r = r.normalize(); + p2.drawRect(r); + } + + + + p2.end(); + + // Copy the double buffer into the widget + p->drawPixmap(clipx,clipy,doubleBuffer); + + +} + +void DrawZone::contentsDragEnterEvent(QDragEnterEvent*e) { + if (!KURLDrag::canDecode(e)) + return; + +// bool accept = false; + KURL::List uris; + KURLDrag::decode(e,uris); + KMimeType::Ptr ptr = KMimeType::findByURL(uris.first()); +// kdDebug() << "***** " << ptr.data()->name() << endl; + if ((ptr.data()->name() == "text/html") + || (ptr.data()->name().left(6) == "image/")) + e->accept(); +} + +void DrawZone::contentsDropEvent( QDropEvent* e) { + viewportDropEvent(e); +} + + + +void DrawZone::viewportDropEvent( QDropEvent* e) { + KURL::List urlList; + // A file from konqueror was dropped + if (KURLDrag::decode(e,urlList)) { + imageMapEditor->openFile(urlList.first()); + } +} diff --git a/kimagemapeditor/drawzone.h b/kimagemapeditor/drawzone.h new file mode 100644 index 00000000..764e6951 --- /dev/null +++ b/kimagemapeditor/drawzone.h @@ -0,0 +1,122 @@ +/*************************************************************************** + imagemap.h - description + ------------------- + begin : Wed Apr 4 2001 + copyright : (C) 2001 by Jan Schäfer + email : janschaefer@users.sourceforge.net +***************************************************************************/ + +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#ifndef IMAGEMAP_H +#define IMAGEMAP_H + +#include +#include +#include +#include +#include + +#include "kdeversion.h" + +class KImageMapEditor; +class Area; + +/** + *@short Draws the image and areas and handle the draw actions + *@author Jan Schäfer + *@internal + *@see Area + */ +class DrawZone : public QScrollView { +public: + + DrawZone(QWidget *parent,KImageMapEditor* _imageMapEditor); + ~DrawZone(); + + QImage picture() const; + void repaintArea(const Area & a); + void repaintRect(const QRect & r); + void cancelDrawing(); + + void setPicture(const QImage &_image); + void setZoom(double z); + + QPoint translateFromZoom(const QPoint & p) const; + QRect translateFromZoom(const QRect & p) const; + QPoint translateToZoom(const QPoint & p) const; + QRect translateToZoom(const QRect & p) const; + + QRect getImageRect() const { return image.rect(); } + + +protected: + + virtual void contentsMouseDoubleClickEvent(QMouseEvent*); + virtual void contentsMousePressEvent(QMouseEvent*); + virtual void contentsMouseReleaseEvent(QMouseEvent*); + virtual void contentsMouseMoveEvent(QMouseEvent*); + virtual void resizeEvent(QResizeEvent*); + virtual void drawContents(QPainter*,int,int,int,int); + virtual void viewportDropEvent(QDropEvent*); + virtual void contentsDragEnterEvent(QDragEnterEvent*); + virtual void contentsDropEvent(QDropEvent*); + + /** + * Represents whats currently going on + * @li None : Nothing + * @li DrawCircle : The user is drawing a circle + * @li DrawRectangle : The user is drawing a rectangle + * @li MoveSelectionPoint : The user is resizing an @ref Area or moving a polygon point + * @li MoveArea : The user is moving an @ref Area + * @li DoSelect : The user makes a selection rectangle + */ + enum DrawAction { None, DrawCircle, DrawRectangle, DrawPolygon, DrawFreehand, MoveSelectionPoint, MoveArea, DoSelect, RemovePoint, AddPoint }; + + void createBorderRectangles(const QRect & r,QRect & rb,QRect & lb,QRect & tb,QRect & bb); + +private: + + DrawAction currentAction; + // The currently drawing area + Area *currentArea; + // Needed when moving selectionpoints + QRect *currentSelectionPoint; + // The point where the user clicked the mouse + QPoint drawStart; + QPoint drawCurrent; + // The original image + QImage image; + KImageMapEditor *imageMapEditor; + // Only the rect of the zoomed image, perhaps redundant + QRect imageRect; + // Only for repaint issues + Area *oldArea; + + QRect oldSelectionRect; + // Holds the zoomed image for efficiency reasons + QPixmap zoomedImage; + // The current zoom-factor + double _zoom; + + QCursor RectangleCursor; + QCursor CircleCursor; + QCursor PolygonCursor; + QCursor FreehandCursor; + QCursor AddPointCursor; + QCursor RemovePointCursor; +}; + +inline QImage DrawZone::picture() const { + return image; +} + + +#endif diff --git a/kimagemapeditor/dummy.cpp b/kimagemapeditor/dummy.cpp new file mode 100644 index 00000000..e69de29b diff --git a/kimagemapeditor/imagemap.cpp b/kimagemapeditor/imagemap.cpp new file mode 100644 index 00000000..665ef000 --- /dev/null +++ b/kimagemapeditor/imagemap.cpp @@ -0,0 +1,395 @@ +/*************************************************************************** + imagemap.cpp - description + ------------------- + begin : Wed Apr 4 2001 + copyright : (C) 2001 by Jan Schäfer + email : j_schaef@informatik.uni-kl.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "imagemap.h" +#include "kimagemapeditor.h" +#include "qpainter.h" +#include "kdebug.h" +#include + +int round(double d) { + if ( (d-((int) d)) < 0.5 ) + return (int) d; + else + return ((int) d)+1; +} + +ImageMap::ImageMap(QWidget *parent,KImageMapEditor* _imageMapEditor) + : QScrollView(parent) +{ + imageMapEditor=_imageMapEditor; +// setPicture(QImage()); + currentAction=None; + currentArea=0L; + eraseOldArea=false; + oldArea=0L; + _zoom=1; + viewport()->setMouseTracking(true); + + +} + +ImageMap::~ImageMap(){ +} + +void ImageMap::setPicture(const QImage &_image) { + image=_image; + zoomedImage.convertFromImage(image); + setZoom(_zoom); +} + +void ImageMap::setZoom(double z) { + _zoom=z; + imageRect.setHeight(image.height()*_zoom); + imageRect.setWidth(image.width()*_zoom); + zoomedImage=QPixmap(imageRect.width(),imageRect.height()); + QPainter p(&zoomedImage); + p.scale(z,z); + QPixmap pix; + pix.convertFromImage(image); + // if the picture has transparent areas, + // fill them with Gimp like background + if (pix.mask()) { + QPixmap backPix(32,32); + QPainter p2(&backPix); + p2.fillRect(0,0,32,32,QColor(156,149,156)); + p2.fillRect(0,16,16,16,QColor(98,105,98)); + p2.fillRect(16,0,16,16,QColor(98,105,98)); + p2.flush(); + p.setPen(QPen()); + p.fillRect(imageRect.left(),imageRect.top(),imageRect.width(),imageRect.height(),QBrush(QColor("black"),backPix)); + } + p.drawPixmap(imageRect.left(),imageRect.top(),pix); + p.flush(); + resizeContents(visibleWidth()>imageRect.width() ? visibleWidth() : imageRect.width(), + visibleHeight()>imageRect.height() ? visibleHeight() : imageRect.height()); + repaintContents(0,0,contentsWidth(),contentsHeight(),true); +} + +QPoint ImageMap::translateFromZoom(const QPoint & p) const { + return QPoint(p.x()/_zoom,p.y()/_zoom); +} + +QPoint ImageMap::translateToZoom(const QPoint & p) const { + return QPoint(round(p.x()*_zoom),round(p.y()*_zoom)); +} + +QRect ImageMap::translateToZoom(const QRect & r) const { + return QRect(round(r.x()*_zoom),round(r.y()*_zoom), + round(r.width()*_zoom),round(r.height()*_zoom)); +} + +void ImageMap::contentsMouseDoubleClickEvent(QMouseEvent* e) { + QPoint point=e->pos(); + point-=imageRect.topLeft(); + point=translateFromZoom(point); + if ( currentAction==None && + (currentArea=imageMapEditor->onArea(point))) + imageMapEditor->showTagEditor(currentArea); + +} + +void ImageMap::contentsMousePressEvent(QMouseEvent* e) { + drawStart=e->pos(); + // Check if it's on picture if not + // move it to the picture's border + if (!imageRect.contains(drawStart)) { + if (drawStart.x()>imageRect.right()) + drawStart.setX(imageRect.right()); + if (drawStart.x()imageRect.bottom()) + drawStart.setY(imageRect.bottom()); + if (drawStart.y()button()==RightButton) { + currentArea=imageMapEditor->onArea(drawStart); + imageMapEditor->select(currentArea); + imageMapEditor->slotShowPopupMenu(e->globalPos()); + } else + if ((currentArea=imageMapEditor->selected()) && + (currentSelectionPoint=currentArea->onSelectionPoint(drawStart))) + { + currentAction=MoveSelectionPoint; + } else + if ((currentArea=imageMapEditor->onArea(drawStart))) { + currentAction=MoveArea; + imageMapEditor->select(currentArea); + } else + if (imageMapEditor->currentShapeType()!=Area::None) { + currentArea=new Area(imageMapEditor->currentShapeType()); + currentArea->setRect(QRect(drawStart,drawStart)); + currentArea->setSelected(false); + if (imageMapEditor->selected()) + imageMapEditor->selected()->setSelected(false); + switch (currentArea->type()) { + case Area::Rectangle : currentAction=DrawRectangle; break; + case Area::Circle : currentAction=DrawCircle; break; + case Area::Polygon : + currentAction=DrawPolygon; + currentArea->addCoord(drawStart); + currentSelectionPoint=currentArea->selectionPoints()->last(); + + break; + default: break; + } + } + // Clicked with the arrow at an areafree position + else { + currentArea=0L; + imageMapEditor->deselectAll(); + } + } else + if ( currentAction==DrawPolygon) { + + } + + QRect r; + if (oldArea) + r=oldArea->selectionRect(); + if (currentArea) { + r= r | currentArea->selectionRect(); + repaintContents(translateToZoom(r),false); + } + +} + +void ImageMap::contentsMouseReleaseEvent(QMouseEvent *e) { + drawEnd=e->pos(); + + // Check if it's on picture if not + // move it to the picture's border + if (!imageRect.contains(drawEnd)) { + if (drawEnd.x()>imageRect.right()) + drawEnd.setX(imageRect.right()); + if (drawEnd.x()imageRect.bottom()) + drawEnd.setY(imageRect.bottom()); + if (drawEnd.y()addArea(currentArea); + imageMapEditor->select(currentArea); + //imageMapEditor->slotAreaChanged(currentArea); + currentAction=None; + } else + if (currentAction==DrawPolygon) { + // If the number of Polygonpoints is more than 2 + // and clicked on the first PolygonPoint or + // the right Button was pressed the Polygon is finished + if ((currentArea->selectionPoints()->count()>2) + && (currentArea->selectionPoints()->first()->contains(drawEnd) + || (e->button()==RightButton))) + { + currentArea->setFinished(true); + imageMapEditor->addArea(currentArea); + currentAction=None; + } else + { + currentArea->addCoord(drawEnd); + currentSelectionPoint=currentArea->selectionPoints()->last(); + } + +// currentArea->addCoord(drawEnd); +// currentSelectionPoint=currentArea->selectionPoints()->last(); + } else + if (currentAction==MoveArea || currentAction==MoveSelectionPoint) { + imageMapEditor->slotAreaChanged(currentArea); + currentAction=None; + } + else { + currentAction=None; + } + imageMapEditor->slotChangeStatusCoords(drawEnd.x(),drawEnd.y()); + imageMapEditor->slotUpdateSelectionCoords(); + + if (currentArea) + repaintArea(*currentArea); +// repaintContents(0,0,contentsWidth(),contentsHeight(),false); +} + + +void ImageMap::contentsMouseMoveEvent(QMouseEvent *e) { + drawCurrent=e->pos(); + + // If outside the image + // set it to the border + if (!imageRect.contains(drawCurrent)) { + if (drawCurrent.x()>imageRect.right()) + drawCurrent.setX(imageRect.right()); + if (drawCurrent.x()imageRect.bottom()) + drawCurrent.setY(imageRect.bottom()); + if (drawCurrent.y()rect()); + currentArea->setRect(QRect(drawStart,drawCurrent).normalize()); + QRect newRect=translateToZoom(currentArea->rect()); + QRect r=oldRect | newRect; + repaintContents(r,false); + imageMapEditor->slotUpdateSelectionCoords(currentArea->rect()); + } else + if (currentAction==DrawCircle) { + QRect oldRect=translateToZoom(currentArea->rect()); + currentArea->setRect(QRect(drawStart,drawCurrent).normalize()); + QRect newRect=translateToZoom(currentArea->rect()); + QRect r=oldRect | newRect; + repaintContents(r,false); + imageMapEditor->slotUpdateSelectionCoords(currentArea->rect()); + } else + if ( currentAction==DrawPolygon ) { + QRect oldRect=translateToZoom(currentArea->rect()); + currentArea->moveSelectionPoint(currentSelectionPoint,drawCurrent); + QRect newRect=translateToZoom(currentArea->rect()); + QRect r=oldRect | newRect; + repaintContents(r,false); + imageMapEditor->slotUpdateSelectionCoords(currentArea->rect()); + } else + if ( currentAction==MoveArea ) { + QRect oldRect=translateToZoom(currentArea->selectionRect()); + currentArea->moveBy((drawCurrent-drawStart).x(),(drawCurrent-drawStart).y()); + QRect newRect=translateToZoom(currentArea->selectionRect()); + QRect r=oldRect | newRect; + repaintContents(r,false); + drawStart=drawCurrent; + imageMapEditor->slotUpdateSelectionCoords(); + } else + if ( currentAction==MoveSelectionPoint ) { + QRect oldRect=translateToZoom(currentArea->selectionRect()); + currentArea->moveSelectionPoint(currentSelectionPoint,drawCurrent); + QRect newRect=translateToZoom(currentArea->selectionRect()); + QRect r=oldRect | newRect; + repaintContents(r,false); + imageMapEditor->slotUpdateSelectionCoords(); + } + imageMapEditor->slotChangeStatusCoords(drawCurrent.x(),drawCurrent.y()); +} + +void ImageMap::resizeEvent(QResizeEvent* e) { + QScrollView::resizeEvent(e); + int width=(int) (image.width()*_zoom); + int height=(int) (image.height()*_zoom); + if (visibleWidth()>width) + width=visibleWidth(); + if (visibleHeight()>height) + height=visibleHeight(); + + resizeContents(width,height); + + imageRect.setLeft(0); + imageRect.setTop(0); + imageRect.setHeight(image.height()*_zoom); + imageRect.setWidth(image.width()*_zoom); + +} + +void ImageMap::repaintArea(const Area & a) { + repaintContents(translateToZoom(a.selectionRect()),false); +} + +void ImageMap::drawContents(QPainter* p,int clipx,int clipy,int clipw,int cliph) { +// kdDebug() << "drawing\n" << endl; +// p.scale(rect.width()*2,rect.height()*2); +// if (e->rect()!=rect()) { +// p.setClipping(true); +// p.setClipRect(e->rect()); +// } else +/* if (currentAction==DrawRectangle) { + p->setClipping(true); + QRect r(currentArea->rect()); + r.moveBy(imageRect.left()-5,imageRect.top()-5); + r.setSize(r.size()+QSize(10,10)); + p->setClipRegion(r); + } +*/ + + QRect updateRect(clipx,clipy,clipw,cliph); + QPixmap doubleBuffer(updateRect.size()); // Pixmap for double-buffering + QPainter p2(&doubleBuffer); + p2.drawPixmap(0,0,zoomedImage,clipx,clipy,clipw,cliph); + p2.translate(-updateRect.x(), -updateRect.y()); + p2.scale(_zoom,_zoom); + + AreaList *list=imageMapEditor->areaList(); + for (Area* s=list->first();s != 0L; s=list->next()) + s->draw(p2); + + // Draw the current drawing Area + if (currentAction != MoveArea && + currentAction != MoveSelectionPoint && + currentAction != None) + { + currentArea->draw(p2); + } + + p2.end(); + + // Copy the double buffer into the widget + p->drawPixmap(clipx,clipy,doubleBuffer); + // Erase background without flicker + QRegion region(contentsX(),contentsY(),visibleWidth(),visibleHeight()); + region=region.subtract(QRegion(imageRect)); + for (int i=0;ieraseRect(region.rects()[i]); + } + + + // Draw our picture +// p->drawPixmap(imageRect.left(),imageRect.top(),zoomedImage); +// +// +// p->scale(_zoom,_zoom); +// p->translate(imageRect.left(),imageRect.top()); +// +// AreaList *list=imageMapEditor->areaList(); +// for (Area* s=list->first();s != 0L; s=list->next()) +// s->draw(*p); +// +// // Draw the current drawing Area +// if (currentAction != MoveArea && +// currentAction != MoveSelectionPoint && +// currentAction != None) +// { +// currentArea->draw(*p); +// } + + +} diff --git a/kimagemapeditor/imagemap.h b/kimagemapeditor/imagemap.h new file mode 100644 index 00000000..7576baa0 --- /dev/null +++ b/kimagemapeditor/imagemap.h @@ -0,0 +1,77 @@ +/*************************************************************************** + imagemap.h - description + ------------------- + begin : Wed Apr 4 2001 + copyright : (C) 2001 by Jan Schäfer + email : janschaefer@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef IMAGEMAP_H +#define IMAGEMAP_H + +#include +#include +#include +#include + +#include "kdeversion.h" + +/** + *@author Jan Schäfer + */ +class KImageMapEditor; +class Area; + +class ImageMap : public QScrollView { +public: + enum DrawAction { None, DrawCircle, DrawRectangle, DrawPolygon, MoveSelectionPoint, MoveArea }; +private: + QRect imageRect; + QPoint drawStart; + QPoint drawCurrent; + QPoint drawEnd; + bool eraseOldArea; + Area *oldArea; + // Holds the original image + QImage image; + // Holds the zoomed image for efficiency reasons + QPixmap zoomedImage; + Area *currentArea; + DrawAction currentAction; + QRect *currentSelectionPoint; + KImageMapEditor *imageMapEditor; + double _zoom; +public: + ImageMap(QWidget *parent,KImageMapEditor* _imageMapEditor); + ~ImageMap(); + void setZoom(double z); + void setPicture(const QImage &_image); + void repaintArea(const Area & a); + QImage picture() const; + QPoint translateFromZoom(const QPoint & p) const; + QPoint translateToZoom(const QPoint & p) const; + QRect translateToZoom(const QRect & p) const; +protected: + virtual void contentsMousePressEvent(QMouseEvent* e); + virtual void contentsMouseDoubleClickEvent(QMouseEvent* e); + virtual void contentsMouseReleaseEvent(QMouseEvent *e); + virtual void contentsMouseMoveEvent(QMouseEvent *e); + virtual void resizeEvent(QResizeEvent* e); + virtual void drawContents(QPainter* p,int clipx,int clipy,int clipw,int cliph); +}; + +inline QImage ImageMap::picture() const { + return image; +} + + +#endif diff --git a/kimagemapeditor/imageslistview.cpp b/kimagemapeditor/imageslistview.cpp new file mode 100644 index 00000000..55992101 --- /dev/null +++ b/kimagemapeditor/imageslistview.cpp @@ -0,0 +1,157 @@ +/*************************************************************************** + imageslistview.cpp - description + ------------------- + begin : Weg Feb 26 2003 + copyright : (C) 2003 by Jan Schäfer + email : janschaefer@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +// QT +#include + + +// KDE +#include +#include + +// locale +#include "imageslistview.h" + +ImagesListViewItem::ImagesListViewItem(ImagesListView* parent, ImageTag* tag) + : QListViewItem(parent) +{ + _imageTag = tag; + update(); +} + + +void ImagesListViewItem::update() { + QString src=""; + QString usemap=""; + if (_imageTag->find("src")) + src=*_imageTag->find("src"); + if (_imageTag->find("usemap")) + usemap=*_imageTag->find("usemap"); + + setText(0,src); + setText(1,usemap); +} + +ImageTag* ImagesListViewItem::imageTag() { + return _imageTag; +} + + +ImagesListView::ImagesListView(QWidget *parent, const char *name) + : KListView(parent, name) +{ + addColumn(i18n("Images")); + addColumn(i18n("Usemap")); + //addColumn(i18n("Preview")); + setFullWidth(true); + + + connect( this, SIGNAL( selectionChanged(QListViewItem*)), + this, SLOT( slotSelectionChanged(QListViewItem*))); +} + + +ImagesListView::~ImagesListView() +{ +} + +void ImagesListView::addImage(ImageTag* tag) +{ + if (!tag) { + kdDebug() << "ImageListView::addImage: Parameter is null !" << endl; + return; + } + + new ImagesListViewItem(this, tag); +} + +void ImagesListView::addImages(QPtrList * images) +{ + for (ImageTag *tag = images->first(); tag!=0L; tag=images->next()) { + addImage(tag); + } +} + +void ImagesListView::clear() { + QListView::clear(); +} + +void ImagesListView::removeImage(ImageTag* tag) { + ImagesListViewItem *item = findListViewItem(tag); + if (item) { + takeItem(item); + setSelected(currentItem(),true); + } + else { + kdDebug() << "ImageListView::removeImage: ListViewItem was not found !" << endl; + } +} + +void ImagesListView::updateImage(ImageTag* tag) { + ImagesListViewItem *item = findListViewItem(tag); + if (item) + item->update(); + else { + kdDebug() << "ImageListView::updateImage: ListViewItem was not found !" << endl; + } +} + +ImagesListViewItem* ImagesListView::findListViewItem(ImageTag* tag) { + + kdDebug() << "ImageListView::findListViewItem: start searching ... " << endl; + + for (QListViewItem* item = firstChild(); item ; item = item->nextSibling()) { + ImagesListViewItem *imageItem = static_cast(item); + if (imageItem->imageTag() == tag) { + kdDebug() << "ImageListView::findListViewItem: found it " << endl; + + return imageItem; + } + } + + kdDebug() << "ImageListView::findListViewItem: found nothing " << endl; + return 0L; + +} + +void ImagesListView::slotSelectionChanged(QListViewItem* item) { + QString src = item->text(0); + + emit imageSelected(KURL(_baseUrl,src)); +} + +ImageTag* ImagesListView::selectedImage() { + ImagesListViewItem* item = static_cast(selectedItem()); + if ( ! item) { + kdDebug() << "ImagesListView::selectedImage: No Image is selected !" << endl; + return 0L; + } + + return item->imageTag(); + + +} + +void ImagesListView::selectImage(ImageTag* tag) { + ImagesListViewItem* item = findListViewItem(tag); + if (item) { + setSelected(item, true); + } +} + +#include "imageslistview.moc" + diff --git a/kimagemapeditor/imageslistview.h b/kimagemapeditor/imageslistview.h new file mode 100644 index 00000000..55680405 --- /dev/null +++ b/kimagemapeditor/imageslistview.h @@ -0,0 +1,111 @@ +/*************************************************************************** + imageslistview.h - description + ------------------- + begin : Weg Feb 26 2003 + copyright : (C) 2003 by Jan Schäfer + email : janschaefer@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef _IMAGESLISTVIEW_H_ +#define _IMAGESLISTVIEW_H_ + +#include +#include + +#include "kimagemapeditor.h" + +class ImagesListView; + +class ImagesListViewItem : public QListViewItem +{ + public: + ImagesListViewItem(ImagesListView*, ImageTag*); + ImageTag* imageTag(); + + /** + * Re-reads the contents of the ImageTag and updates + * itself accordingly + */ + void update(); + protected: + ImageTag* _imageTag; +}; + +/** + * Simple class that shows a list of imagenames with a preview + * Jan Schaefer + **/ +class ImagesListView : public KListView +{ + Q_OBJECT + +public: + ImagesListView(QWidget *parent, const char *name); + virtual ~ImagesListView(); + + /** + * Adds an image + */ + void addImage(ImageTag*); + + /** + * Adds images + */ + void addImages(QPtrList *); + + /** + * Removes the given image from the list + */ + void removeImage(ImageTag*); + + /** + * Updates the listview item with the given ImageTag + */ + void updateImage(ImageTag*); + + /** + * Removes all images + */ + void clear(); + + /** + * Returns the filename of the current selected Image + */ + ImageTag* selectedImage(); + + /** + * Selects the given image + */ + void selectImage(ImageTag*); + + /** + * Sets the base URL of all images + */ + void setBaseUrl(const KURL & url) { _baseUrl = url; }; + +protected slots: + void slotSelectionChanged(QListViewItem*); + +signals: + void imageSelected(const KURL &); + +protected: + KURL _baseUrl; + + /** + * Finds the first ImageListViewItem with the given ImageTag + * Returns 0L if no item was found + */ + ImagesListViewItem* findListViewItem(ImageTag*); +}; + +#endif diff --git a/kimagemapeditor/kimagemapeditor.cpp b/kimagemapeditor/kimagemapeditor.cpp new file mode 100644 index 00000000..ebfb0c7f --- /dev/null +++ b/kimagemapeditor/kimagemapeditor.cpp @@ -0,0 +1,2819 @@ +/*************************************************************************** + imagemapeditor.cpp - description + ------------------- + begin : Wed Apr 4 2001 + copyright : (C) 2001 by Jan Schïż½er + email : j_schaef@informatik.uni-kl.de +***************************************************************************/ + +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#include +#include + +// QT +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// KDE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if KDE_IS_VERSION(3,1,90) +#include +#else +#include +#endif + +// local +#include "kimagemapeditor.h" +#include "kimagemapeditor.moc" +#include "drawzone.h" +#include "kimedialogs.h" +#include "kimecommands.h" +#include "qextfileinfo.h" +#include "areacreator.h" +#include "arealistview.h" +#include "imageslistview.h" +#include "mapslistview.h" +#include "kimecommon.h" + +#include +#include + +// Factory code for KDE 3 +typedef KParts::GenericFactory KimeFactory; +K_EXPORT_COMPONENT_FACTORY( libkimagemapeditor , KimeFactory ) + +KImageMapEditor::KImageMapEditor(QWidget *parentWidget, const char *, + QObject *parent, const char *name, const QStringList & ) + : KParts::ReadWritePart(parent,name) +{ + setInstance( KimeFactory::instance() ); + +// KDockMainWindow* mainWidget; + + // Test if the MainWindow can handle DockWindows, if so create DockWidgets + // instead of a Splitter + mainDock = dynamic_cast(parent) ; + QSplitter * splitter = 0L; + tabWidget = 0L; + + if (mainDock) { +// kdDebug() << "KImageMapEditor: We got a KDockMainWindow !" << endl; + + KDockWidget* parentDock = mainDock->getMainDockWidget(); + areaDock = mainDock->createDockWidget( "Areas", 0L, 0L, i18n("Areas"), i18n("Areas")); + mapsDock = mainDock->createDockWidget( "Maps", 0L, 0L, i18n("Maps"), i18n("Maps")); + imagesDock = mainDock->createDockWidget( "Images", 0L, 0L, i18n("Images"), i18n("Images")); + + areaListView = new AreaListView(areaDock,"AreaListView"); + mapsListView = new MapsListView(mapsDock, "MapsListView"); + imagesListView = new ImagesListView(imagesDock, "ImagesListView"); + + areaDock->setWidget(areaListView); + mapsDock->setWidget(mapsListView); + imagesDock->setWidget(imagesListView); + + areaDock->manualDock( (KDockWidget*) parentDock, KDockWidget::DockLeft, 30); + mapsDock->manualDock( (KDockWidget*) areaDock, KDockWidget::DockCenter); + imagesDock->manualDock( (KDockWidget*) mapsDock, KDockWidget::DockCenter); + + connect( mainDock->manager(), SIGNAL(change()), this, SLOT(dockingStateChanged())); + } + else + { + areaDock = 0L; + mapsDock = 0L; + imagesDock = 0L; + splitter = new QSplitter(parentWidget); + tabWidget = new QTabWidget(splitter); + areaListView = new AreaListView(tabWidget,"AreaListView"); + mapsListView = new MapsListView(tabWidget, "MapsListView"); + imagesListView = new ImagesListView(tabWidget, "ImagesListView"); + + tabWidget->addTab(areaListView,i18n("Areas")); + tabWidget->addTab(mapsListView,i18n("Maps")); + tabWidget->addTab(imagesListView,i18n("Images")); + } + + + connect( areaListView->listView, SIGNAL(selectionChanged()), this, SLOT(slotSelectionChanged())); + connect( areaListView->listView, SIGNAL(doubleClicked(QListViewItem*)), this, SLOT(showTagEditor(QListViewItem*))); + connect( areaListView->listView, SIGNAL(rightButtonPressed(QListViewItem*,const QPoint &,int)), this, + SLOT(slotShowPopupMenu(QListViewItem*,const QPoint &))); + + connect( mapsListView, SIGNAL( mapSelected(const QString &)), + this, SLOT( setMap(const QString &))); + + connect( mapsListView, SIGNAL( mapRenamed(const QString &)), + this, SLOT( setMapName(const QString &))); + + connect( mapsListView->listView(), SIGNAL(rightButtonPressed(QListViewItem*,const QPoint &,int)), this, + SLOT(slotShowMapPopupMenu(QListViewItem*,const QPoint &))); + + connect( imagesListView, SIGNAL( imageSelected(const KURL &)), + this, SLOT( setPicture(const KURL &))); + + connect( imagesListView, SIGNAL(rightButtonPressed(QListViewItem*,const QPoint &,int)), this, + SLOT(slotShowImagePopupMenu(QListViewItem*,const QPoint &))); + + // Shows the text: + // "Drop an image or html file" +/* QString path = KGlobal::dirs()->findResourceDir( "data", "kimagemapeditor/dropimage.png" ) + "kimagemapeditor/dropimage.png"; + if ( ! QFileInfo(path).exists() ) { + kdError() << "Couldn't find needed dropimage.png file in " + "the data directory of KImageMapEditor.\n" + "Perhaps you have forgotten to do a make install !" << endl; + exit(1); + } +*/ + + if (splitter) { + drawZone = new DrawZone(splitter,this); + splitter->setResizeMode(drawZone,QSplitter::Stretch); + splitter->setResizeMode(tabWidget,QSplitter::KeepSize); + setWidget(splitter); + } else { + drawZone = new DrawZone(parentWidget,this); + setWidget(drawZone); + } + + + areas = new AreaList(); + currentSelected= new AreaSelection(); + _currentToolType=KImageMapEditor::Selection; + copyArea=0L; + defaultArea=0L; + currentMapElement = 0L; + + setupActions(); + setupStatusBar(); + + setXMLFile("kimagemapeditorpartui.rc"); + + setPicture(getBackgroundImage()); + _htmlContent.setAutoDelete(true); + + init(); + readConfig(); +} + +KImageMapEditor::~KImageMapEditor() { + writeConfig(); + + #if KDE_VERSION < 300 + delete accel; + #endif + delete areas; + + delete currentSelected; + delete copyArea; + delete defaultArea; + + // Delete our DockWidgets + if (areaDock) { + areaDock->hide(); + mapsDock->hide(); + imagesDock->hide(); + + delete areaDock; + delete mapsDock; + delete imagesDock; + } + +} + +MapTag::MapTag() { + modified = false; + name = QString::null; +} + +void KImageMapEditor::init() +{ + _htmlContent.clear(); + _imageUrl = QString::null; + m_url = QString::null; + HtmlElement* el = new HtmlElement("\n"); + _htmlContent.append(el); + el = new HtmlElement("\n"); + _htmlContent.append(el); + el = new HtmlElement("\n"); + _htmlContent.append(el); + el = new HtmlElement("\n"); + _htmlContent.append(el); + + addMap(i18n("unnamed")); + + el = new HtmlElement("\n"); + _htmlContent.append(el); + el = new HtmlElement("\n"); + _htmlContent.append(el); + + setImageActionsEnabled(false); +} + +KAboutData* KImageMapEditor::createAboutData() +{ + KAboutData* aboutData = + new KAboutData( "kimagemapeditor", I18N_NOOP("KImageMapEditor"), + "1.0", I18N_NOOP( "An HTML imagemap editor" ), + KAboutData::License_GPL, + "(c) 2001-2003 Jan Schäfer "); + return aboutData; +} + + +void KImageMapEditor::setReadWrite(bool) +{ + + // For now it doesn't matter if its readwrite or readonly + // it is always readwrite, because Quanta only supports ReadOnlyParts + // at this moment and in that case it should be readwrite, too. + ReadWritePart::setReadWrite(true); + /* + if (rw) + ; + else + { + actionCollection()->remove(arrowAction); + actionCollection()->remove(circleAction); + actionCollection()->remove(rectangleAction); + actionCollection()->remove(polygonAction); + actionCollection()->remove(freehandAction); + actionCollection()->remove(addPointAction); + actionCollection()->remove(removePointAction); + + actionCollection()->remove(cutAction); + actionCollection()->remove(deleteAction); + actionCollection()->remove(copyAction); + actionCollection()->remove(pasteAction); + + actionCollection()->remove(mapNewAction); + actionCollection()->remove(mapDeleteAction); + actionCollection()->remove(mapNameAction); + actionCollection()->remove(mapDefaultAreaAction); + + actionCollection()->remove(areaPropertiesAction); + + actionCollection()->remove(moveLeftAction); + actionCollection()->remove(moveRightAction); + actionCollection()->remove(moveUpAction); + actionCollection()->remove(moveDownAction); + + actionCollection()->remove(increaseWidthAction); + actionCollection()->remove(decreaseWidthAction); + actionCollection()->remove(increaseHeightAction); + actionCollection()->remove(decreaseHeightAction); + + actionCollection()->remove(toFrontAction); + actionCollection()->remove(toBackAction); + actionCollection()->remove(forwardOneAction); + actionCollection()->remove(backOneAction); + + actionCollection()->remove(imageRemoveAction); + actionCollection()->remove(imageAddAction); + actionCollection()->remove(imageUsemapAction); + + } + */ + +} + +void KImageMapEditor::setModified(bool modified) +{ + // get a handle on our Save action and make sure it is valid + KAction *save = actionCollection()->action(KStdAction::stdName(KStdAction::Save)); + if (!save) + return; + + // if so, we either enable or disable it based on the current + // state + if (modified) + save->setEnabled(true); + else + save->setEnabled(false); + + // in any event, we want our parent to do it's thing + ReadWritePart::setModified(modified); +} + + +KConfig *KImageMapEditor::config() +{ + return KimeFactory::instance()->config(); +} + +void KImageMapEditor::readConfig(KConfig* config) { + recentFilesAction->loadEntries(config,"Data"); +} + +void KImageMapEditor::writeConfig(KConfig* config) { + config->writeEntry("highlightareas",highlightAreasAction->isChecked()); + config->writeEntry("showalt",showAltAction->isChecked()); + recentFilesAction->saveEntries(config,"Data"); + saveLastURL(config); + +} + +void KImageMapEditor::readConfig() { + config()->setGroup("General Options"); + readConfig(config()); + slotConfigChanged(); +} + +void KImageMapEditor::writeConfig() { + config()->setGroup("General Options"); + writeConfig(config()); + config()->sync(); +} + + +void KImageMapEditor::saveProperties(KConfig *config) +{ + saveLastURL(config); +} + +void KImageMapEditor::readProperties(KConfig * config) +{ + openLastURL(config); +} + +void KImageMapEditor::slotConfigChanged() +{ + config()->setGroup("Appearance"); + int newHeight=config()->readNumEntry("maximum-preview-height",50); + config()->setGroup("General Options"); + _commandHistory->setUndoLimit(config()->readNumEntry("undo-level",20)); + _commandHistory->setRedoLimit(config()->readNumEntry("redo-level",20)); + Area::highlightArea = config()->readBoolEntry("highlightareas",true); + highlightAreasAction->setChecked(Area::highlightArea); + Area::showAlt = config()->readBoolEntry("showalt",true); + showAltAction->setChecked(Area::showAlt); + + // if the image preview size changed update all images + if (maxAreaPreviewHeight!=newHeight) { + maxAreaPreviewHeight=newHeight; + } + + updateAllAreas(); + drawZone->viewport()->repaint(); +} + +void KImageMapEditor::openLastURL(KConfig* config) { + KURL lastURL ( config->readPathEntry("lastopenurl") ); + QString lastMap = config->readEntry("lastactivemap"); + QString lastImage = config->readPathEntry("lastactiveimage"); + + +// kdDebug() << "loading from group : " << config->group() << endl; + +// kdDebug() << "loading entry lastopenurl : " << lastURL.path() << endl; +// KMessageBox::information(0L, config->group()+" "+lastURL.path()); + if (!lastURL.isEmpty()) { +// kdDebug() << "opening HTML file with map " << lastMap << " and image " << lastImage << endl; + if ( openHTMLFile(lastURL, lastMap, lastImage) ) + m_url = lastURL; + else + m_url = QString::null; + } +} + +void KImageMapEditor::saveLastURL(KConfig* config) { + config->writePathEntry("lastopenurl",url().path()); + config->writeEntry("lastactivemap",mapName()); + config->writePathEntry("lastactiveimage",_imageUrl.path()); +// kdDebug() << "writing entry lastopenurl : " << url().path() << endl; +// kdDebug() << "writing entry lastactivemap : " << mapName() << endl; +// kdDebug() << "writing entry lastactiveimage : " << _imageUrl.path() << endl; + //KMessageBox::information(0L, QString("Group: %1 Saving ... %2").arg(config->group()).arg(url().path())); +} + +void KImageMapEditor::setupActions() +{ + // File Open + KAction *temp=KStdAction::open(this, SLOT(fileOpen()), actionCollection()); + QMimeSourceFactory::defaultFactory()->setPixmap( "openimage", SmallIcon("fileopen") ); + temp->setWhatsThis(i18n("

Open File

Click this to open a new picture or HTML file.")); + temp->setToolTip(i18n("Open new picture or HTML file")); + + // File Open Recent + recentFilesAction = KStdAction::openRecent(this, SLOT(openURL(const KURL&)), + actionCollection()); + // File Save + temp =KStdAction::save(this, SLOT(fileSave()), actionCollection()); + QMimeSourceFactory::defaultFactory()->setPixmap( "saveimage", SmallIcon("filesave") ); + temp->setWhatsThis(i18n("

Save File

Click this to save the changes to the HTML file.")); + temp->setToolTip(i18n("Save HTML file")); + + + // File Save As + (void)KStdAction::saveAs(this, SLOT(fileSaveAs()), actionCollection()); + + // File Close + temp=KStdAction::close(this, SLOT(fileClose()), actionCollection()); + QMimeSourceFactory::defaultFactory()->setPixmap( "closeimage", SmallIcon("fileclose") ); + temp->setWhatsThis(i18n("

Close File

Click this to close the currently open HTML file.")); + temp->setToolTip(i18n("Close HTML file")); + + // Edit Copy + copyAction=KStdAction::copy(this, SLOT(slotCopy()), actionCollection()); + QMimeSourceFactory::defaultFactory()->setPixmap( "editcopyimage", SmallIcon("editcopy") ); + copyAction->setWhatsThis(i18n("

Copy

" + "Click this to copy the selected area.")); + copyAction->setEnabled(false); + + // Edit Cut + cutAction=KStdAction::cut(this, SLOT(slotCut()), actionCollection()); + QMimeSourceFactory::defaultFactory()->setPixmap( "editcutimage", SmallIcon("editcut") ); + cutAction->setWhatsThis(i18n("

Cut

" + "Click this to cut the selected area.")); + cutAction->setEnabled(false); + + // Edit Paste + pasteAction=KStdAction::paste(this, SLOT(slotPaste()), actionCollection()); + QMimeSourceFactory::defaultFactory()->setPixmap( "editpasteimage", SmallIcon("editpaste") ); + pasteAction->setWhatsThis(i18n("

Paste

" + "Click this to paste the copied area.")); + pasteAction->setEnabled(false); + + + // Edit Delete + deleteAction=new KAction(i18n("&Delete"), "editdelete", + Key_Delete,this,SLOT (slotDelete()),actionCollection(), "edit_delete"); + QMimeSourceFactory::defaultFactory()->setPixmap( "editdeleteimage", SmallIcon("editdelete") ); + deleteAction->setWhatsThis(i18n("

Delete

" + "Click this to delete the selected area.")); + deleteAction->setEnabled(false); + + // Edit Undo/Redo + _commandHistory = new KCommandHistory( actionCollection(), true); + + // Edit Properties + areaPropertiesAction= new KAction(i18n("Pr&operties"),0,this,SLOT(showTagEditor()), + actionCollection(), "edit_properties"); + areaPropertiesAction->setEnabled(false); + + // View Zoom In + zoomInAction=KStdAction::zoomIn(this, SLOT(slotZoomIn()), actionCollection()); + // View Zoom Out + zoomOutAction=KStdAction::zoomOut(this, SLOT(slotZoomOut()), actionCollection()); + + // View Zoom + zoomAction=new KSelectAction(i18n("Zoom"), 0,this,SLOT (slotZoom()), + actionCollection(), "view_zoom"); + zoomAction->setWhatsThis(i18n("

Zoom

" + "Choose the desired zoom level.")); + zoomAction->setItems(QStringList() + << i18n("25%") + << i18n("50%") + << i18n("100%") + << i18n("150%") + << i18n("200%") + << i18n("250%") + << i18n("300%") + << i18n("500%") + << i18n("750%") + << i18n("1000%")); + + zoomAction->setCurrentItem(2); + + highlightAreasAction = new KToggleAction(i18n("Highlight Areas"),0, this, SLOT (slotHightlightAreas()), + actionCollection(), "view_highlightareas"); + + showAltAction = new KToggleAction(i18n("Show Alt Tag"),0, this, SLOT (slotShowAltTag()), + actionCollection(), "view_showalt"); +#if KDE_IS_VERSION(3,2,90) + showAltAction->setCheckedState(i18n("Hide Alt Tag")); +#endif + + mapNameAction= new KAction(i18n("Map &Name..."),0,this,SLOT(mapEditName()), + actionCollection(), "map_name"); + + mapNewAction = new KAction(i18n("Ne&w Map..."),0,this,SLOT(mapNew()), + actionCollection(), "map_new"); + mapNewAction->setToolTip(i18n("Create a new map")); + + mapDeleteAction = new KAction(i18n("D&elete Map"),0,this,SLOT(mapDelete()), + actionCollection(), "map_delete"); + mapDeleteAction->setToolTip(i18n("Delete the current active map")); + + mapDefaultAreaAction = new KAction(i18n("Edit &Default Area..."),0,this,SLOT(mapDefaultArea()), + actionCollection(), "map_defaultarea"); + mapDefaultAreaAction->setToolTip(i18n("Edit the default area of the current active map")); + + temp = new KAction(i18n("&Preview"),0,this,SLOT(mapPreview()), + actionCollection(), "map_preview"); + temp->setToolTip(i18n("Show a preview")); + + // IMAGE + i18n("&Image"); + + imageAddAction = new KAction(i18n("Add Image..."),0,this,SLOT(imageAdd()), + actionCollection(), "image_add"); + imageAddAction->setToolTip(i18n("Add a new image")); + + imageRemoveAction = new KAction(i18n("Remove Image"),0,this,SLOT(imageRemove()), + actionCollection(), "image_remove"); + imageRemoveAction->setToolTip(i18n("Remove the current visible image")); + + imageUsemapAction = new KAction(i18n("Edit Usemap..."),0,this,SLOT(imageUsemap()), + actionCollection(), "image_usemap"); + imageUsemapAction->setToolTip(i18n("Edit the usemap tag of the current visible image")); + + temp= new KAction(i18n("Show &HTML"),0,this,SLOT(mapShowHTML()), + actionCollection(), "map_showhtml"); + + + // Selection Tool + arrowAction=new KRadioAction(i18n("&Selection"), "arrow", + 0,this,SLOT (slotDrawArrow()), + actionCollection(), "tool_arrow"); + QMimeSourceFactory::defaultFactory()->setPixmap( "arrowimage", SmallIcon("arrow") ); + arrowAction->setWhatsThis(i18n("

Selection

" + "Click this to select areas.")); + arrowAction->setExclusiveGroup("drawing"); + arrowAction->setChecked(true); + + // Circle + circleAction=new KRadioAction(i18n("&Circle"), "circle", + 0,this,SLOT (slotDrawCircle()), + actionCollection(), "tool_circle"); + QMimeSourceFactory::defaultFactory()->setPixmap( "circleimage", SmallIcon("drawcircle") ); + circleAction->setWhatsThis(i18n("

Circle

" + "Click this to start drawing a circle.")); + circleAction->setExclusiveGroup("drawing"); + + // Rectangle + rectangleAction=new KRadioAction(i18n("&Rectangle"), "rectangle", + 0,this,SLOT (slotDrawRectangle()), + actionCollection(), "tool_rectangle"); + QMimeSourceFactory::defaultFactory()->setPixmap( "rectangleimage", SmallIcon("drawrectangle") ); + rectangleAction->setWhatsThis(i18n("

Rectangle

" + "Click this to start drawing a rectangle.")); + rectangleAction->setExclusiveGroup("drawing"); + + // Polygon + polygonAction=new KRadioAction(i18n("&Polygon"), "polygon", + 0,this,SLOT (slotDrawPolygon()), + actionCollection(), "tool_polygon"); + QMimeSourceFactory::defaultFactory()->setPixmap( "polygonimage", SmallIcon("drawpolygon") ); + polygonAction->setWhatsThis(i18n("

Polygon

" + "Click this to start drawing a polygon.")); + polygonAction->setExclusiveGroup("drawing"); + + // Freehand + freehandAction=new KRadioAction(i18n("&Freehand Polygon"), "freehand", + 0,this,SLOT (slotDrawFreehand()), + actionCollection(), "tool_freehand"); + QMimeSourceFactory::defaultFactory()->setPixmap( "freehandimage", SmallIcon("freehand") ); + freehandAction->setWhatsThis(i18n("

Freehandpolygon

" + "Click this to start drawing a freehand polygon.")); + freehandAction->setExclusiveGroup("drawing"); + + // Add Point + addPointAction=new KRadioAction(i18n("&Add Point"), "addpoint", + 0,this,SLOT (slotDrawAddPoint()), + actionCollection(), "tool_addpoint"); + QMimeSourceFactory::defaultFactory()->setPixmap( "addpointimage", SmallIcon("addpoint") ); + addPointAction->setWhatsThis(i18n("

Add Point

" + "Click this to add points to a polygon.")); + addPointAction->setExclusiveGroup("drawing"); + + // Remove Point + removePointAction=new KRadioAction(i18n("&Remove Point"), "removepoint", + 0,this,SLOT (slotDrawRemovePoint()), + actionCollection(), "tool_removepoint"); + QMimeSourceFactory::defaultFactory()->setPixmap( "removepointimage", SmallIcon("removepoint") ); + removePointAction->setWhatsThis(i18n("

Remove Point

" + "Click this to remove points from a polygon.")); + removePointAction->setExclusiveGroup("drawing"); + +#if KDE_VERSION < 300 + KAction *cancelAction = +#endif + new KAction(i18n("Cancel Drawing"), Key_Escape, this, SLOT( slotCancelDrawing() ), + actionCollection(), "canceldrawing" ); + + moveLeftAction = new KAction(i18n("Move Left"), Key_Left, this, SLOT( slotMoveLeft() ), + actionCollection() , "moveleft" ); + + moveRightAction = new KAction(i18n("Move Right"), Key_Right, this, SLOT( slotMoveRight() ), + actionCollection() , "moveright" ); + + moveUpAction = new KAction(i18n("Move Up"), Key_Up, this, SLOT( slotMoveUp() ), + actionCollection() , "moveup" ); + + moveDownAction = new KAction(i18n("Move Down"), Key_Down, this, SLOT( slotMoveDown() ), + actionCollection() , "movedown" ); + + increaseWidthAction = new KAction(i18n("Increase Width"), Key_Right + SHIFT, this, SLOT( slotIncreaseWidth() ), + actionCollection() , "increasewidth" ); + + decreaseWidthAction = new KAction(i18n("Decrease Width"), Key_Left + SHIFT, this, SLOT( slotDecreaseWidth() ), + actionCollection() , "decreasewidth" ); + + increaseHeightAction = new KAction(i18n("Increase Height"), Key_Up + SHIFT, this, SLOT( slotIncreaseHeight() ), + actionCollection() , "increaseheight" ); + + decreaseHeightAction = new KAction(i18n("Decrease Height"), Key_Down + SHIFT, this, SLOT( slotDecreaseHeight() ), + actionCollection() , "decreaseheight" ); +#if KDE_VERSION < 300 + accel = new KAccel(widget()); + cancelAction->plugAccel(accel, true); + moveLeftAction->plugAccel(accel, true); + moveRightAction->plugAccel(accel, true); + moveUpAction->plugAccel(accel, true); + moveDownAction->plugAccel(accel, true); + increaseWidthAction->plugAccel(accel, true); + decreaseWidthAction->plugAccel(accel, true); + increaseHeightAction->plugAccel(accel, true); + decreaseHeightAction->plugAccel(accel, true); +#endif + + toFrontAction = new KAction(i18n("Bring to Front"), 0 , this, SLOT( slotToFront() ), + actionCollection() , "tofront" ); + + toBackAction = new KAction(i18n("Send to Back"), 0 , this, SLOT( slotToBack() ), + actionCollection() , "toback" ); + + forwardOneAction = new KAction(i18n("Bring Forward One"), "raise" ,0, this, SLOT( slotForwardOne() ), + actionCollection() , "forwardone" ); + backOneAction = new KAction(i18n("Send Back One"), "lower" ,0, this, SLOT( slotBackOne() ), + actionCollection() , "backone" ); + + forwardOneAction->plug(areaListView->upBtn); + backOneAction->plug(areaListView->downBtn); + + connect( areaListView->upBtn, SIGNAL(pressed()), forwardOneAction, SLOT(activate())); + connect( areaListView->downBtn, SIGNAL(pressed()), backOneAction, SLOT(activate())); + + new KAction( i18n("Configure KImageMapEditor..."), "configure", 0, + this, SLOT(slotShowPreferences()), + actionCollection(), "configure_kimagemapeditor" ); + + if (areaDock) { + configureShowAreaListAction = new KToggleAction( i18n("Show Area List"), 0L, 0, + this, SLOT(configureShowAreaList()), + actionCollection(), "configure_show_arealist" ); + + configureShowMapListAction = new KToggleAction( i18n("Show Map List"), 0L, 0, + this, SLOT(configureShowMapList()), + actionCollection(), "configure_show_maplist" ); + + configureShowImageListAction = new KToggleAction( i18n("Show Image List"), 0L, 0, + this, SLOT(configureShowImageList()), + actionCollection(), "configure_show_imagelist" ); +#if KDE_IS_VERSION(3,2,90) + configureShowAreaListAction->setCheckedState(i18n("Hide Area List")); + configureShowMapListAction->setCheckedState(i18n("Hide Map List")); + configureShowImageListAction->setCheckedState(i18n("Hide Image List")); +#endif + } + + updateActionAccess(); +} + +void KImageMapEditor::setupStatusBar() +{ + +// We can't do this with a KPart ! +// widget()->statusBar()->insertItem(i18n(" Cursor")+" : x: 0 ,y: 0",STATUS_CURSOR); +// widget()->statusBar()->insertItem(i18n(" Selection")+" : - ",STATUS_SELECTION); + emit setStatusBarText( i18n(" Selection: - Cursor: x: 0, y: 0 ")); +} + +void KImageMapEditor::slotShowPreferences() +{ + PreferencesDialog *dialog = new PreferencesDialog(widget(),config()); + connect(dialog, SIGNAL(applyClicked()), this, SLOT(slotConfigChanged())); + dialog->exec(); + delete dialog; +} + + +void KImageMapEditor::showPopupMenu(const QPoint & pos, const QString & name) +{ + QPopupMenu* pop = static_cast(factory()->container(name, this)); + + if (!pop) { + kdWarning() << QString("KImageMapEditorPart: Missing XML definition for %1\n").arg(name) << endl; + return; + } + + pop->popup(pos); +} + +void KImageMapEditor::slotShowMainPopupMenu(const QPoint & pos) +{ + showPopupMenu(pos,"popup_main"); +} + +void KImageMapEditor::slotShowMapPopupMenu(QListViewItem* item,const QPoint & pos) +{ + if (isReadWrite()) { + mapDeleteAction->setEnabled(item); + mapNameAction->setEnabled(item); + mapDefaultAreaAction->setEnabled(item); + } + + if (item) + mapsListView->selectMap(item); + + showPopupMenu(pos,"popup_map"); +} + +void KImageMapEditor::slotShowImagePopupMenu(QListViewItem* item,const QPoint & pos) +{ + imageRemoveAction->setEnabled(item); + imageUsemapAction->setEnabled(item); + + if (item) + imagesListView->setSelected(item,true); + + showPopupMenu(pos,"popup_image"); +} + +void KImageMapEditor::slotShowPopupMenu(QListViewItem* item,const QPoint & p) +{ + if (!item) + return; + + if (!item->isSelected()) + { + deselectAll(); + select(item); + } + + slotShowMainPopupMenu(p); +} + +void KImageMapEditor::updateStatusBar() +{ + emit setStatusBarText(selectionStatusText+" "+cursorStatusText); +} + +void KImageMapEditor::slotChangeStatusCoords(int x,int y) +{ +// statusBar()->changeItem(QString(" Cursor : x: %1 ,y: %2 ").arg(x).arg(y),STATUS_CURSOR); + cursorStatusText = i18n(" Cursor: x: %1, y: %2 ").arg(x).arg(y); + updateStatusBar(); +} + +void KImageMapEditor::slotUpdateSelectionCoords() { + if (selected()->count()>0) { + QRect r=selected()->rect(); +// statusBar()->changeItem( + selectionStatusText = i18n(" Selection: x: %1, y: %2, w: %3, h: %4 ").arg(r.left()).arg(r.top()).arg(r.width()).arg(r.height()); + +// ,STATUS_SELECTION); + kapp->processEvents(); + } else + selectionStatusText = i18n(" Selection: - "); + //statusBar()->changeItem(" Selection : - ",STATUS_SELECTION); + + updateStatusBar(); +} + +void KImageMapEditor::slotUpdateSelectionCoords( const QRect & r ) +{ + selectionStatusText = i18n(" Selection: x: %1, y: %2, w: %3, h: %4 ").arg(r.left()).arg(r.top()).arg(r.width()).arg(r.height()); + updateStatusBar(); + kapp->processEvents(); +} + +KApplication* KImageMapEditor::app() const +{ + return kapp; +} + + +void KImageMapEditor::drawToCenter(QPainter* p, const QString & str, int y, int width) { + int xmid = width / 2; + + QFontMetrics fm = p->fontMetrics(); + QRect strBounds = fm.boundingRect(str); + + p->drawText(xmid-(strBounds.width()/2),y,str); +} + + +QImage KImageMapEditor::getBackgroundImage() { + + // Lazy initialisation + if ( _backgroundImage.isNull() ) { + + +// QString filename = QString("dropimage_")+KGlobal::locale()->language()+".png"; +// QString path = QString::null; //KGlobal::dirs()->findResourceDir( "data", "kimagemapeditor/"+filename ) + "kimagemapeditor/"+filename; +// kdDebug() << "getBackgroundPic : loaded image : " << path << endl; + +// if ( ! QFileInfo(path).exists() ) { + int width = 400; + int height = 400; + int border = 20; + int fontSize = 58; + + QPixmap pix(width,height); + pix.fill(QColor(74,76,74)); + QPainter p(&pix); + + QFont font; + font.setFamily("Sans"); + font.setPixelSize(fontSize); + font.setBold(true); + p.setFont( font ); + + p.setRasterOp(Qt::CopyROP); + p.setPen(QPen(QColor(112,114,112),1)); + + // The translated string must be divided into + // parts with about the same size that fit to the image + QString str = i18n("Drop an image or HTML file"); + QStringList strList = QStringList::split(" ",str); + + // Get the string parts + QString tmp; + QStringList outputStrList; + QFontMetrics fm = p.fontMetrics(); + + for ( QStringList::Iterator it = strList.begin(); it != strList.end(); ++it ) { + QString tmp2 = tmp + *it; + + if (fm.boundingRect(tmp2).width() > width-border) { + outputStrList.append(tmp); + tmp = *it + " "; + } + else + tmp = tmp2 + " "; + } + + // Last one was forgotten so add it. + outputStrList.append(tmp); + + // Try to adjust the text vertically centered + int step = myround(float(height) / (outputStrList.size()+1)); + int y = step; + + for ( QStringList::Iterator it = outputStrList.begin(); it != outputStrList.end(); ++it ) { + drawToCenter(&p, *it, y, pix.width()); + y += step; + } + + p.end(); + + _backgroundImage = pix.convertToImage(); + } + + + return _backgroundImage; + +/* + QFontDatabase fdb; + QStringList families = fdb.families(); + for ( QStringList::Iterator f = families.begin(); f != families.end(); ++f ) { + QString family = *f; + qDebug( family ); + QStringList styles = fdb.styles( family ); + for ( QStringList::Iterator s = styles.begin(); s != styles.end(); ++s ) { + QString style = *s; + QString dstyle = "\t" + style + " ("; + QValueList smoothies = fdb.smoothSizes( family, style ); + for ( QValueList::Iterator points = smoothies.begin(); + points != smoothies.end(); ++points ) { + dstyle += QString::number( *points ) + " "; + } + dstyle = dstyle.left( dstyle.length() - 1 ) + ")"; + qDebug( dstyle ); + } + } + + + path = KGlobal::dirs()->saveLocation( "data", "kimagemapeditor/" ) +filename; + kdDebug() << "getBackgroundPic : save new image to : " << path << endl; + pix.save(path,"PNG",100); + } + + if ( ! QFileInfo(path).exists() ) { + kdError() << "Couldn't find needed " << filename << " file in " + "the data directory of KImageMapEditor.\n" + "Perhaps you have forgotten to do a make install !" << endl; + exit(1); + } +*/ +} + + +void KImageMapEditor::addArea(Area* area) { + if (!area) return; + + // Perhaps we've got a selection of areas + // so test it and add all areas of the selection + // nested selections are possible but doesn't exist + AreaSelection *selection=0L; + if ( (selection = dynamic_cast ( area ) ) ) + { + AreaList list = selection->getAreaList(); + + for (Area* a = list.first(); a != 0L; a = list.next() ) + { + areas->prepend(a); + a->setListViewItem(new QListViewItem(areaListView->listView,a->attribute("href"))); + a->listViewItem()->setPixmap(1,makeListViewPix(*a)); + } + } + else + { + areas->prepend(area); + area->setListViewItem(new QListViewItem(areaListView->listView,area->attribute("href"))); + area->listViewItem()->setPixmap(1,makeListViewPix(*area)); + } + + setModified(true); + +} + +void KImageMapEditor::addAreaAndEdit(Area* s) +{ + areas->prepend(s); + s->setListViewItem(new QListViewItem(areaListView->listView,s->attribute("href"))); + s->listViewItem()->setPixmap(1,makeListViewPix(*s)); + deselectAll(); + select(s); + if (!showTagEditor(selected())) { + // If the user has pressed cancel + // he undos the creation + commandHistory()->undo(); + } +} + +void KImageMapEditor::deleteArea( Area * area ) +{ + if (!area) return; + + // only for repaint reasons + QRect redrawRect = area->selectionRect(); + + // Perhaps we've got a selection of areas + // so test it and delete the whole selection + // nested selections are possible but doesn't exist + AreaSelection *selection=0L; + if ( (selection = dynamic_cast ( area ) ) ) + { + AreaList list = selection->getAreaList(); + + for (Area* a = list.first(); a != 0L; a = list.next() ) + { + currentSelected->remove(a); + areas->remove( a ); + a->deleteListViewItem(); + } + } + else + { + deselect( area ); + areas->remove( area ); + area->deleteListViewItem(); + } + + drawZone->repaintRect(redrawRect); + + + // Only to disable cut and copy actions + if (areas->count()==0) + deselectAll(); + + setModified(true); +} + +void KImageMapEditor::deleteSelected() { + + Area *a; + AreaList list=currentSelected->getAreaList(); + + for ( a=list.first(); a != 0; a=list.next() ) { + currentSelected->remove( a ); + areas->remove( a ); + delete a->listViewItem(); + } + + + drawZone->repaintArea( *currentSelected ); + // Only to disable cut and copy actions + if (areas->count()==0) + deselectAll(); + + setModified(true); +} + +void KImageMapEditor::deleteAllAreas() +{ + for (Area* a=areas->first();a!=0L;) + { + deselect( a ); + areas->remove( a ); + a->deleteListViewItem(); + a=areas->first(); // because the current is deleted + } + + drawZone->viewport()->repaint(); + +} + +void KImageMapEditor::updateAllAreas() +{ +// kdDebug() << "KImageMapEditor::updateAllAreas" << endl; + for (Area* a=areas->first();a!=0L;a=areas->next()) { + a->listViewItem()->setPixmap(1,makeListViewPix(*a)); + } + drawZone->viewport()->repaint(); +} + +void KImageMapEditor::updateSelection() const { + areaListView->listView->triggerUpdate(); +} + +AreaSelection* KImageMapEditor::selected() const { + return currentSelected; +} + +void KImageMapEditor::select(Area* a) +{ + if (!a) return; + + currentSelected->add(a); + updateActionAccess(); + slotUpdateSelectionCoords(); +// drawZone->repaintArea( *a); + +} + +void KImageMapEditor::selectWithoutUpdate(Area* a) +{ + if (!a) return; + currentSelected->add(a); +} + +void KImageMapEditor::slotSelectionChanged() +{ + AreaListIterator it = areaList(); + AreaList list = currentSelected->getAreaList(); + + for ( ; it.current() != 0L; ++it) + { + if ( it.current()->listViewItem()->isSelected() != (list.containsRef(it.current()) > 0) ) + { + it.current()->listViewItem()->isSelected() + ? select( it.current() ) + : deselect( it.current() ); + + drawZone->repaintArea( *it.current()); + } + } + +} + +void KImageMapEditor::select( QListViewItem* item) +{ + + AreaListIterator it = areaList(); + + for ( ; it.current() != 0L; ++it) + { + if (it.current()->listViewItem() == item ) + { + select( it.current() ); + drawZone->repaintArea( *it.current()); + } + } + + +} + +AreaListIterator KImageMapEditor::areaList() const { + AreaListIterator it(*areas); + return it; +} + + +void KImageMapEditor::slotAreaChanged(Area *area) +{ + if (!area) + return; + + setModified(true); + + AreaSelection *selection=0L; + if ( (selection = dynamic_cast ( area ) ) ) + { + AreaListIterator it = selection->getAreaListIterator(); + + for ( ; it.current() != 0L; ++it ) + { + if (it.current()->listViewItem()) { + it.current()->listViewItem()->setText(0,it.current()->attribute("href")); + it.current()->listViewItem()->setPixmap(1,makeListViewPix(*it.current())); + } + } + + } + else + if (area->listViewItem()) { + area->listViewItem()->setText(0,area->attribute("href")); + area->listViewItem()->setPixmap(1,makeListViewPix(*area)); + } + + drawZone->repaintArea(*area); + +} + +void KImageMapEditor::deselect(Area* a) +{ + if (a) { + currentSelected->remove(a); +// drawZone->repaintArea(*a); + updateActionAccess(); + slotUpdateSelectionCoords(); + } +} + +void KImageMapEditor::deselectWithoutUpdate(Area* a) +{ + if (a) { + currentSelected->remove(a); + } +} + + +/** +* Makes sure, that the actions cut, copy, delete and +* show properties +* can only be executed if sth. is selected. +**/ +void KImageMapEditor::updateActionAccess() +{ + if (!isReadWrite()) + return; + + if ( 0 < selected()->count()) + { + areaPropertiesAction->setEnabled(true); + deleteAction->setEnabled(true); + copyAction->setEnabled(true); + cutAction->setEnabled(true); + moveLeftAction->setEnabled(true); + moveRightAction->setEnabled(true); + moveUpAction->setEnabled(true); + moveDownAction->setEnabled(true); + toFrontAction->setEnabled(true); + toBackAction->setEnabled(true); + + if ( (selected()->count() == 1) ) + { + if (selected()->type()==Area::Polygon) + { + increaseWidthAction->setEnabled(false); + decreaseWidthAction->setEnabled(false); + increaseHeightAction->setEnabled(false); + decreaseHeightAction->setEnabled(false); + addPointAction->setEnabled(true); + removePointAction->setEnabled(true); + } + else + { + increaseWidthAction->setEnabled(true); + decreaseWidthAction->setEnabled(true); + increaseHeightAction->setEnabled(true); + decreaseHeightAction->setEnabled(true); + addPointAction->setEnabled(false); + removePointAction->setEnabled(false); + } + + } + else + { + increaseWidthAction->setEnabled(false); + decreaseWidthAction->setEnabled(false); + increaseHeightAction->setEnabled(false); + decreaseHeightAction->setEnabled(false); + addPointAction->setEnabled(false); + removePointAction->setEnabled(false); + } + + } + else + { + areaPropertiesAction->setEnabled(false); + deleteAction->setEnabled(false); + copyAction->setEnabled(false); + cutAction->setEnabled(false); + moveLeftAction->setEnabled(false); + moveRightAction->setEnabled(false); + moveUpAction->setEnabled(false); + moveDownAction->setEnabled(false); + increaseWidthAction->setEnabled(false); + decreaseWidthAction->setEnabled(false); + increaseHeightAction->setEnabled(false); + decreaseHeightAction->setEnabled(false); + toFrontAction->setEnabled(false); + toBackAction->setEnabled(false); + addPointAction->setEnabled(false); + removePointAction->setEnabled(false); + + } + + updateUpDownBtn(); +} + +void KImageMapEditor::updateUpDownBtn() +{ + if (!isReadWrite()) + return; + + AreaList list = currentSelected->getAreaList(); + + if (list.isEmpty() || (areas->count() < 2)) + { + forwardOneAction->setEnabled(false); + areaListView->upBtn->setEnabled(false); + backOneAction->setEnabled(false); + areaListView->downBtn->setEnabled(false); + return; + } + // if the first Area is in the selection can't move up + if (list.find( areas->getFirst() ) == -1) + { + forwardOneAction->setEnabled(true); + areaListView->upBtn->setEnabled(true); + } + else { + forwardOneAction->setEnabled(false); + areaListView->upBtn->setEnabled(false); + } + + drawZone->repaintArea(*currentSelected); + + // if the last Area is in the selection can't move down + if (list.find( areas->getLast() ) == -1) + { + backOneAction->setEnabled(true); + areaListView->downBtn->setEnabled(true); + } + else { + backOneAction->setEnabled(false); + areaListView->downBtn->setEnabled(false); + } + +} + +void KImageMapEditor::deselectAll() +{ + QRect redrawRect= currentSelected->selectionRect(); + currentSelected->reset(); + drawZone->repaintRect(redrawRect); + updateActionAccess(); +} + +Area* KImageMapEditor::onArea(const QPoint & p) const { + for (Area* s=areas->first();s!=0L;s=areas->next()) { + if (s->contains(p)) + return s; + } + return 0L; +} + + +int KImageMapEditor::showTagEditor(Area *a) { + if (!a) return 0; + drawZone->repaintArea(*a); + + AreaDialog *dialog= new AreaDialog(this,a); + connect (dialog, SIGNAL(areaChanged(Area*)), this, SLOT(slotAreaChanged(Area*))); + + int result = dialog->exec(); + + return result; + + +} + +int KImageMapEditor::showTagEditor(QListViewItem *item) { + if (!item) return 0; + for (Area* a=areas->first();a!=0L;a=areas->next()) { + if (a->listViewItem()==item) { + return showTagEditor(a); + } + } + return 0; +} + +int KImageMapEditor::showTagEditor() { + return showTagEditor(selected()); +} + + +QString KImageMapEditor::getHTMLImageMap() const { + QString retStr; + retStr+="\n"; + + for (Area* a=areas->first();a!=0L;a=areas->next()) { + retStr+=" "+a->getHTMLCode()+"\n"; + } + + if (defaultArea && defaultArea->finished()) + retStr+=" "+defaultArea->getHTMLCode()+"\n"; + + retStr+=""; + return retStr; +} + +QPixmap KImageMapEditor::makeListViewPix(Area & a) +{ + QPixmap pix=a.cutOut(drawZone->picture()); + + double shrinkFactor=1; + + // picture fits into max row height ? + if (maxAreaPreviewHeight < pix.height()) + shrinkFactor = ( (double) maxAreaPreviewHeight / pix.height() ); + + QPixmap pix2((int)(pix.width()*shrinkFactor), (int)(pix.height()*shrinkFactor)); + + // Give all pixels a defined color + pix2.fill(Qt::white); + + QPainter p(&pix2); + + p.scale(shrinkFactor,shrinkFactor); + p.drawPixmap(0,0,pix); + + return pix2; +} + +void KImageMapEditor::setMapName(const QString & s) { + mapsListView->changeMapName(_mapName, s); + _mapName=s; + currentMapElement->mapTag->name = s; +} + + +void KImageMapEditor::setPicture(const KURL & url) { + _imageUrl=url; + if (QFileInfo(url.path()).exists()) { + QImage img(url.path()); + + if (!img.isNull()) { + setPicture(img); + imageRemoveAction->setEnabled(true); + imageUsemapAction->setEnabled(true); + } + else + kdError() << QString("The image %1 could not be opened.").arg(url.path()) << endl; + } + else + kdError() << QString("The image %1 does not exist.").arg(url.path()) << endl; +} + +void KImageMapEditor::setPicture(const QImage & pix) { + drawZone->setPicture(pix); + updateAllAreas(); +} + + +void KImageMapEditor::slotDrawArrow() { + _currentToolType=KImageMapEditor::Selection; + +} + +void KImageMapEditor::slotDrawCircle() { + _currentToolType=KImageMapEditor::Circle; + +} + +void KImageMapEditor::slotDrawRectangle() { + _currentToolType=KImageMapEditor::Rectangle; + +} + +void KImageMapEditor::slotDrawPolygon() { + _currentToolType=KImageMapEditor::Polygon; +} + +void KImageMapEditor::slotDrawFreehand() { + _currentToolType=KImageMapEditor::Freehand; +} + +void KImageMapEditor::slotDrawAddPoint() { + _currentToolType=KImageMapEditor::AddPoint; +} + +void KImageMapEditor::slotDrawRemovePoint() { + _currentToolType=KImageMapEditor::RemovePoint; +} + + +void KImageMapEditor::slotZoom() { + + int i=zoomAction->currentItem(); + switch (i) { + case 0 : drawZone->setZoom(0.25);break; + case 1 : drawZone->setZoom(0.5);break; + case 2 : drawZone->setZoom(1);break; + case 3 : drawZone->setZoom(1.5);break; + case 4 : drawZone->setZoom(2.0);break; + case 5 : drawZone->setZoom(2.5);break; + case 6 : drawZone->setZoom(3);break; + case 7 : drawZone->setZoom(5);break; + case 8 : drawZone->setZoom(7.5);break; + case 9 : drawZone->setZoom(10);break; + } + if (i<10) + zoomInAction->setEnabled(true); + else + zoomInAction->setEnabled(false); + + if (i>0) + zoomOutAction->setEnabled(true); + else + zoomOutAction->setEnabled(false); +} + +void KImageMapEditor::slotZoomIn() { + if (zoomAction->currentItem()==(int)(zoomAction->items().count()-1)) + return; + + zoomAction->setCurrentItem(zoomAction->currentItem()+1); + slotZoom(); +} + +void KImageMapEditor::slotZoomOut() { + if (zoomAction->currentItem()==0) + return; + + zoomAction->setCurrentItem(zoomAction->currentItem()-1); + slotZoom(); +} + +void KImageMapEditor::mapDefaultArea() +{ + if (defaultArea) + showTagEditor(defaultArea); + else { + defaultArea= new DefaultArea(); + showTagEditor(defaultArea); + } + +} + +void KImageMapEditor::mapEditName() +{ + bool ok=false; +#if KDE_IS_VERSION(3, 1, 90) + QString input = KInputDialog::getText(i18n("Enter Map Name"), + i18n("Enter the name of the map:"), + _mapName,&ok,widget()); +#else + QString input = KLineEditDlg::getText(i18n("Enter Map Name"), + i18n("Enter the name of the map:"), + _mapName,&ok,widget()); +#endif + if (ok) { + if (input != _mapName) { + if (mapsListView->nameAlreadyExists(input)) + KMessageBox::sorry(this->widget(), i18n("The name %1 already exists.").arg(input)); + else { + setMapName(input); + } + } + } +} + +void KImageMapEditor::mapShowHTML() +{ + KDialogBase *dialog= new KDialogBase(widget(),QString::null,true,i18n("HTML Code of Map"),KDialogBase::Ok); + QMultiLineEdit *edit = new QMultiLineEdit(dialog); + + edit->setText(getHtmlCode()); + edit->setReadOnly(true); + edit->setWordWrap(QTextEdit::NoWrap); + dialog->setMainWidget(edit); +// dialog->resize(dialog->calculateSize(edit->maxLineWidth(),edit->numLines()*)); +// dialog->adjustSize(); + dialog->resize(600,400); + dialog->exec(); +} + +void KImageMapEditor::openFile(const KURL & url) { + if ( ! url.isEmpty()) { + QString ext=QFileInfo(url.path()).extension().lower(); + + if (ext=="png" || ext=="jpg" || ext=="jpeg" || ext=="gif" || + ext=="bmp" || ext=="xbm" || ext=="xpm" || ext=="mng" || ext=="pnm") + addImage(url); + else + openURL(url); + } +} + +bool KImageMapEditor::openURL(const KURL & url) { + // If a local file does not exist + // we start with an empty file, so + // that we can return true here. + // For non local files, we cannot check + // the existance + if (url.isLocalFile() && + ! QFile::exists(url.path())) + return true; + return KParts::ReadOnlyPart::openURL(url); +} + +void KImageMapEditor::fileOpen() { + + QString fileName = KFileDialog::getOpenFileName(QString::null, + i18n("*.png *.jpg *.jpeg *.gif *.htm *.html|Web File\n" + "*.png *.jpg *.jpeg *.gif *.bmp *.xbm *.xpm *.pnm *.mng|Images\n" + "*.htm *.html|HTML Files\n" + "*.png|PNG Images\n*.jpg *.jpeg|JPEG Images\n*.gif|GIF-Images\n*|All Files"), + widget(),i18n("Choose File to Open")); + + openFile(KURL( fileName )); +} + + + +void KImageMapEditor::fileClose() +{ + if (! closeURL()) + return; + + + setPicture(getBackgroundImage()); + recentFilesAction->setCurrentItem(-1); + setModified(false); +} + +void KImageMapEditor::fileSave() +{ + // if we aren't read-write, return immediately + if ( ! isReadWrite() ) + return; + + if (url().isEmpty()) { + fileSaveAs(); + } + else { + saveFile(); + setModified(false); + } + + +} + +void KImageMapEditor::fileSaveAs() { + + KURL url = KFileDialog::getSaveURL(0L,"*.htm *.html|" + i18n( "HTML File" ) + + "\n*.txt|" + i18n( "Text File" ) + "\n*|" + i18n( "All Files" ),widget()); + if (url.isEmpty() || !url.isValid()) { + return; + } + + + QFileInfo fileInfo(url.path()); + + if ( fileInfo.exists() ) + { + if (KMessageBox::warningContinueCancel(widget(), + i18n("The file %1 already exists.
Do you want to overwrite it?
").arg(fileInfo.fileName()), + i18n("Overwrite File?"), i18n("Overwrite"))==KMessageBox::Cancel) + return; + + if(!fileInfo.isWritable()) { + KMessageBox::sorry(widget(), i18n("You do not have write permission for the file %1.").arg(fileInfo.fileName())); + return; + } + } + + + saveAs(url); + recentFilesAction->addURL(url); + +} + + +bool KImageMapEditor::openFile() +{ + QFileInfo fileInfo(url().path()); + + if ( !fileInfo.exists() ) + { + KMessageBox::information(widget(), + i18n("The file %1 does not exist.").arg(fileInfo.fileName()), + i18n("File Does Not Exist")); + return false; + } + + openHTMLFile(url()); + + drawZone->viewport()->repaint(); + recentFilesAction->addURL(url()); + setModified(false); + backupFileCreated = false; + return true; +} + +/** + * This methods supposes that the given QTextStream s has just read + * the < of a tag. It now reads all attributes of the tag until a > + * The tagname itself is also read and stored as a tagname + * attribute. After parsing the whole tag it returns a QDict + * with all attributes and their values. It stores the whole read text in the + * parameter readText. + */ +QDict KImageMapEditor::getTagAttributes(QTextStream & s, QString & readText) +{ + QDict dict(17,false); + // the "<" is already read + QChar w; + QString attr,value; + + readText = QString::null; + + // get the tagname + while (!s.atEnd() && w!=" ") { + s >> w; + readText.append(w); + if (w==" " || w==">") { + dict.insert("tagname",new QString(value)); + break; + } + value+=w; + } + + + // do we have a comment ? + // read the comment and return + if (value.right(3)=="-->") + return dict; + + if (value.startsWith("!--")) { + while (!s.atEnd()) { + s >> w; + readText.append(w); + + if (w=="-") { + s >> w; + readText.append(w); + if (w=="-") { + s >> w; + readText.append(w); + if (w==">") + return dict; + } + } + } + } + + bool attrRead=true; // currently reading an attribute ? + bool equalSign=false; // an equalsign was read? + bool valueRead=false; // currently reading a value ? + QChar quotation='\0'; // currently reading a value with quotation marks ? + bool php=false; // currently reading a php script + attr=QString::null; + value=QString::null; + + //get the other attributes + while (!s.atEnd() && w!=">") + { + s >> w; + readText.append(w); + + // End of PHP Script ? + if (php && (w=="?") ) + { + s >> w; + readText.append(w); + + if (valueRead) + value+=w; + + if (w==">") + { + php = false; + s >> w; + readText.append(w); + } + } + + // Wrong syntax or PHP-Skript ! + if (!php && (w=="<")) + { + if (valueRead) + value+=w; + s >> w; + readText.append(w); + if (valueRead) + value+=w; + + if (w=="?") + { + php = true; + } + } else + // finished ? + if (w==">") { + if (valueRead) + dict.insert(attr,new QString(value)); + return dict; + } else + // currently reading an attribute ? + if (attrRead) { + // if there is a whitespace the attributename has finished + // possibly there isn't any value e.g. noshade + if (w==" ") + attrRead=false; + else + // an equal sign signals that the value follows + if (w=="=") { + attrRead=false; + equalSign=true; + } else + attr+=w; + } else + // an equal sign was read ? delete every whitespace + if (equalSign) { + if (w!=" ") { + equalSign=false; + valueRead=true; + if (w=="\"" || w=="'") + quotation=w; + } + } else + // currently reading the value + if (valueRead) { + // if php, read without regarding anything + if (php) + value+=w; + // if value within quotation marks is read + // only stop when another quotationmark is found + else + if (quotation != '\0') { + if (quotation!=w) { + value+=w; + } else { + quotation='\0'; + valueRead=false; + dict.insert(attr,new QString(value)); + attr = value = QString::null; + + } + } else + // a whitespace indicates that the value has finished + if (w==" ") { + valueRead=false; + dict.insert(attr,new QString(value)); + attr = value = QString::null; + } + } else { + if (w!=" ") { + attrRead=true; + attr+=w; + } + } + } + + return dict; + +} + + +bool KImageMapEditor::openHTMLFile(const KURL & url, const QString & mapName, const QString & imagePath) +{ + QFile f(url.path()); + if ( !f.exists () ) + return false; + f.open(IO_ReadOnly); + QTextStream s(&f); + QString str; + QChar w; + QDict *attr=0L; + QPtrList *images= new QPtrList; + MapTag *map=0L; + QPtrList *maps = new QPtrList; + + _htmlContent.clear(); + currentMapElement = 0L; + + QString temp; + QString origcode; + + bool readMap=false; + + while (!s.atEnd()) { + + s >> w; + if (w=="<") + { + if (!readMap && !origcode.isEmpty()) { + _htmlContent.append( new HtmlElement(origcode)); + origcode = QString::null; + } + + origcode.append("<"); + attr=new QDict(getTagAttributes(s,temp)); + origcode.append(temp); + + if (attr->find("tagname")) { + + if (attr->find("tagname")->lower()=="img") { + HtmlImgElement *el = new HtmlImgElement(origcode); + el->imgTag = static_cast(attr); + images->append(el->imgTag); + _htmlContent.append(el); + + origcode = QString::null; + } else + if (attr->find("tagname")->lower()=="map") { + map = new MapTag(); + map->name=(*attr->find("name")); + readMap=true; + } else + if (attr->find("tagname")->lower()=="/map") { + readMap=false; + maps->append(map); + HtmlMapElement *el = new HtmlMapElement(origcode); + el->mapTag = map; + _htmlContent.append(el); + + origcode = QString::null; + } else + if (readMap) { + if (attr->find("tagname")->lower()=="area") { + map->prepend(attr); + } + } else { + _htmlContent.append(new HtmlElement(origcode)); + origcode = QString::null; + } + + } + } // w != "<" + else { + origcode.append(w); + } + } + + if (!origcode.isEmpty()) { + _htmlContent.append(new HtmlElement(origcode)); + } + + f.close(); + + KURL imageUrl; + map = 0L; + + + + // If there is a preselection of map and image + // don't let the user choose something + if (imagePath.isNull() || mapName.isNull()) { + // If we have more than on map or more than one image + // Let the user choose, otherwise take the only ones + if (maps->count() == 1) { + map = maps->first(); + } + + if (images->count() == 1) { + if (images->first()) { + ImageTag* imgTag = images->first(); + QString *src = imgTag->find("src"); + if (src) + imageUrl = KURL(url,*src); + } + } + + // If there is only one map and more than one image + // try to find out the image with the according usemap tag + if (maps->count() == 1 && images->count() > 1) { + ImageTag* imageTag; + for ( imageTag = images->first(); imageTag; imageTag = images->next() ) + { + QString *usemap = imageTag->find("usemap"); + if (usemap) { + // Remove the # + QString usemapName = usemap->right(usemap->length()-1); + if (usemapName == map->name) { + QString *src = imageTag->find("src"); + if (src) + imageUrl = KURL(url,*src); + } + } + } + } + + + // If there are more than one map or there wasn't + // found a fitting image and there is something to choose + // let the user choose + if (maps->count() >1 || (imageUrl.isEmpty() && images->count() > 1)) + { + ImageMapChooseDialog dialog(widget(),maps,images,url); + dialog.exec(); + map=dialog.currentMap; + imageUrl=dialog.pixUrl; + } + } + else + imageUrl = imagePath; + + imagesListView->clear(); + imagesListView->setBaseUrl(url); + imagesListView->addImages(images); + + mapsListView->clear(); + mapsListView->addMaps(maps); + + + setMapActionsEnabled(false); + + if (map) { + mapsListView->selectMap(map->name); + } + else if ( ! mapName.isNull()) { + mapsListView->selectMap(mapName); + } else { + if (tabWidget) + tabWidget->showPage(mapsListView); + } + + if (!imageUrl.isEmpty()) { + setPicture(imageUrl); + } else { + setPicture(getBackgroundImage()); + if (tabWidget) + tabWidget->showPage(imagesListView); + } + + + emit setWindowCaption(url.fileName()); + setModified(false); + return true; +} + +/** + * Finds the first html element which contains the given text. + * Returns the first matching element. + * Returns 0L if no element was found. + */ +HtmlElement* KImageMapEditor::findHtmlElement(const QString & containingText) { + for (HtmlElement * el = _htmlContent.first(); el; el = _htmlContent.next() ) { + if (el->htmlCode.contains(containingText,false)) { + return el; + } + } + return 0L; +} + +/** + * Finds the first html element which contains the given ImageTag. + * Returns the first matching element. + * Returns 0L if no element was found. + */ +HtmlImgElement* KImageMapEditor::findHtmlImgElement(ImageTag* tag) { + for (HtmlElement * el = _htmlContent.first(); el; el = _htmlContent.next() ) { + HtmlImgElement* imgEl = dynamic_cast(el); + + if (imgEl && imgEl->imgTag == tag) + return imgEl; + } + return 0L; +} + +void KImageMapEditor::addMap(const QString & name = QString::null) { + HtmlMapElement* el = new HtmlMapElement("\n"); + MapTag* map = new MapTag(); + map->name = name; + el->mapTag = map; + + // Try to find the body tag + HtmlElement* bodyTag = findHtmlElement("addMap(name); + mapsListView->selectMap(name); +} + +/** + * Finds the HtmlMapElement in the HtmlContent, that corresponds + * to the given map name.
+ * Returns 0L if there exists no map with the given name + */ +HtmlMapElement* KImageMapEditor::findHtmlMapElement(const QString & mapName) { + for (HtmlElement * el = _htmlContent.first(); el; el = _htmlContent.next() ) { + if (dynamic_cast(el)) { + HtmlMapElement *tagEl = static_cast(el); + if (tagEl->mapTag->name == mapName) { + return tagEl; + } + } + } + + kdWarning() << "KImageMapEditor::findHtmlMapElement: couldn't find map '" << mapName << "'" << endl; + return 0L; +} + +/** + * Calls setMap with the HtmlMapElement with the given map name + */ +void KImageMapEditor::setMap(const QString & mapName) { + HtmlMapElement* el = findHtmlMapElement(mapName); + if (!el) { + kdWarning() << "KImageMapEditor::setMap : Couldn't set map '" << mapName << "', because it wasn't found !" << endl; + return; + } + + setMap(el); + +} + +void KImageMapEditor::setMap(MapTag* map) { + for (HtmlElement * el = _htmlContent.first(); el; el = _htmlContent.next() ) { + HtmlMapElement *tagEl = dynamic_cast(el); + if (tagEl) { + if (tagEl->mapTag == map) { + setMap(tagEl); + break; + } + } + } + +} + +void KImageMapEditor::saveAreasToMapTag(MapTag* map) { + map->clear(); + for (Area* a=areas->first();a!=0L;a=areas->next()) { + QDict *dict = new QDict(17,false); + QString *shapeStr = 0L; + + switch (a->type()) { + case Area::Rectangle : shapeStr = new QString("rect");break; + case Area::Circle : shapeStr = new QString("circle");break; + case Area::Polygon : shapeStr = new QString("poly");break; + default : continue; + } + + dict->insert("shape",shapeStr); + + for (AttributeIterator it = a->firstAttribute();it!=a->lastAttribute();++it) { + dict->insert(it.key(),new QString(it.data())); + } + + dict->insert("coords",new QString(a->coordsToString())); + + map->append(dict); + + } + + if (defaultArea && defaultArea->finished()) { + QDict *dict = new QDict(17,false); + dict->insert("shape",new QString("default")); + + for (AttributeIterator it = defaultArea->firstAttribute();it!=defaultArea->lastAttribute();++it) { + dict->insert(it.key(),new QString(it.data())); + } + + map->append(dict); + } + +} + +void KImageMapEditor::setMap(HtmlMapElement* mapElement) { + if (currentMapElement) { + currentMapElement->mapTag->modified=true; + currentMapElement->htmlCode = getHTMLImageMap(); + saveAreasToMapTag(currentMapElement->mapTag); + } + + currentMapElement = mapElement; + MapTag* map = currentMapElement->mapTag; + + // Remove old areas only if a new map is loaded + deleteAllAreas(); + delete defaultArea; + defaultArea = 0L; +// kdDebug() << "KImageMapEditor::setMap : Setting new map : " << map->name << endl; + _mapName = map->name; + for (AreaTag *tag=map->first();tag!=0L;tag=map->next()) + { + QString shape="rect"; + if (tag->find("shape")) + shape=*tag->find("shape"); + + Area::ShapeType type=Area::Rectangle; + if (shape=="circle") + type=Area::Circle; + else if (shape=="poly") + type=Area::Polygon; + else if (shape=="default") + type=Area::Default; + + Area* a=AreaCreator::create(type); + + if (tag->find("href")) + a->setAttribute("href",*tag->find("href")); + + if (tag->find("alt")) + a->setAttribute("alt",*tag->find("alt")); + + if (tag->find("target")) + a->setAttribute("target",*tag->find("target")); + + if (tag->find("title")) + a->setAttribute("title",*tag->find("title")); + + if (tag->find("onclick")) + a->setAttribute("onclick",*tag->find("onclick")); + + if (tag->find("onmousedown")) + a->setAttribute("onmousedown",*tag->find("onmousedown")); + + if (tag->find("onmouseup")) + a->setAttribute("onmouseup",*tag->find("onmouseup")); + + if (tag->find("onmouseover")) + a->setAttribute("onmouseover",*tag->find("onmouseover")); + + if (tag->find("onmousemove")) + a->setAttribute("onmousemove",*tag->find("onmousemove")); + + if (tag->find("onmouseout")) + a->setAttribute("onmouseout",*tag->find("onmouseout")); + + + + if (type==Area::Default) { + defaultArea=a; + defaultArea->setFinished(true); + continue; + } + + if (tag->find("coords")) + a->setCoords(*tag->find("coords")); + + a->setMoving(false); + addArea(a); + } + + updateAllAreas(); + + setMapActionsEnabled(true); +} + +/** + * Sets wether actions that depend on an selected map + * are enabled + */ +void KImageMapEditor::setMapActionsEnabled(bool b) { + mapDeleteAction->setEnabled(b); + mapDefaultAreaAction->setEnabled(b); + mapNameAction->setEnabled(b); + + arrowAction->setChecked(true); + slotDrawArrow(); + + arrowAction->setEnabled(b); + circleAction->setEnabled(b); + rectangleAction->setEnabled(b); + polygonAction->setEnabled(b); + freehandAction->setEnabled(b); + addPointAction->setEnabled(b); + removePointAction->setEnabled(b); + +} + +QString KImageMapEditor::getHtmlCode() { + if (currentMapElement) { + currentMapElement->htmlCode = getHTMLImageMap(); + } + + QString result; + + HtmlElement *el; + for ( el = _htmlContent.first(); el; el = _htmlContent.next() ) { + result += el->htmlCode; + //kdDebug() << "KImageMapEditor::getHtmlCode : Writing : " << el->htmlCode << endl; + + } + return result; +} + +void KImageMapEditor::saveImageMap(const KURL & url) +{ + QFileInfo fileInfo(url.path()); + + if (!QFileInfo(url.directory()).isWritable()) { + KMessageBox::error(widget(), + i18n("The file %1 could not be saved, because you do not have the required write permissions.").arg(url.path())); + return; + } + + if (!backupFileCreated) { + QString backupFile = url.path()+"~"; + KIO::file_copy(url, KURL::fromPathOrURL( backupFile ), -1, true, false, false); + backupFileCreated = true; + } + + setModified(false); + + if (mapName().isEmpty()) { + mapEditName(); + } + QFile file(url.path()); + file.open(IO_WriteOnly); + + QTextStream t(&file); + + if (_htmlContent.isEmpty()) { + t << "\n" + << "\n" + << " \n" + << "\n" + << "\n" + << " " << getHTMLImageMap() + << "\n" + << " picture().width() << "\"" + << " height=\"" << drawZone->picture().height() << "\">\n" + << "\n" + << ""; + } else + { + t << getHtmlCode(); + } + + file.close(); + +} + + +void KImageMapEditor::slotCut() +{ + if ( 0 == currentSelected->count() ) + return; + delete copyArea; + + copyArea= static_cast< AreaSelection* > (currentSelected->clone()); + pasteAction->setEnabled(true); + KCommand *command= new CutCommand(this,*currentSelected); + commandHistory()->addCommand( command ,true); +} + + +void KImageMapEditor::slotDelete() +{ + if ( 0 == currentSelected->count() ) + return; + + KCommand *command= new DeleteCommand(this,*currentSelected); + commandHistory()->addCommand( command ,true); +} + +void KImageMapEditor::slotCopy() +{ + delete copyArea; + + copyArea = static_cast< AreaSelection* > (currentSelected->clone()); + pasteAction->setEnabled(true); +} + +void KImageMapEditor::slotPaste() +{ + if (!copyArea) + return; + + copyArea->moveBy(5,5); + if (copyArea->rect().x()>= drawZone->getImageRect().width() || + copyArea->rect().y()>= drawZone->getImageRect().height()) + copyArea->moveTo(0,0); + + if (copyArea->rect().width()>drawZone->getImageRect().width() || + copyArea->rect().height()>drawZone->getImageRect().height()) + return; + + AreaSelection *a=static_cast< AreaSelection* > (copyArea->clone()); + commandHistory()->addCommand( new PasteCommand(this,*a),true); + delete a; +// addAreaAndEdit(a); +} + + + +void KImageMapEditor::slotBackOne() +{ + if (currentSelected->isEmpty()) + return; + + AreaList list = currentSelected->getAreaList(); + + + Area *a = 0L; + // move every selected Area one step lower + for (int i=areas->count()-2; i > -1; i--) + { + if (list.find( areas->at(i) ) > -1 ) + { + a = areas->at(i); + areas->remove(a); + areas->insert((uint)i+1,a); + a->listViewItem()->moveItem( areas->at(i)->listViewItem() ); + } + } + // to update the up and down buttons + updateUpDownBtn(); + +} + +void KImageMapEditor::slotForwardOne() +{ + if (currentSelected->isEmpty()) + return; + + AreaList list = currentSelected->getAreaList(); + + Area *a = 0L; + // move every selected Area one step higher + for (int i=1; i < (int)areas->count(); i++) + { + if (list.find( areas->at(i) ) > -1 ) + { + a = areas->at(i); + areas->remove(a); + areas->insert((uint)i-1,a); + areas->at(i)->listViewItem()->moveItem( a->listViewItem() ); + } + } + // to update the up and down buttons + updateUpDownBtn(); +} + +void KImageMapEditor::slotToBack() +{ + if (currentSelected->isEmpty()) + return; + + while (backOneAction->isEnabled()) + slotBackOne(); +} + +void KImageMapEditor::slotToFront() +{ + if (currentSelected->isEmpty()) + return; + + while (forwardOneAction->isEnabled()) + slotForwardOne(); +} + + +void KImageMapEditor::slotMoveUp() +{ + QRect r=selected()->rect(); + selected()->setMoving(true); + selected()->moveBy(0,-1); + + commandHistory()->addCommand( + new MoveCommand( this, selected(), r.topLeft() ) ,true ); + selected()->setMoving(false); + slotAreaChanged(selected()); + slotUpdateSelectionCoords(); +} + +void KImageMapEditor::slotMoveDown() +{ + QRect r=selected()->rect(); + selected()->setMoving(true); + selected()->moveBy(0,1); + + commandHistory()->addCommand( + new MoveCommand( this, selected(), r.topLeft() ) ,true ); + selected()->setMoving(false); + slotAreaChanged(selected()); + slotUpdateSelectionCoords(); +} + +void KImageMapEditor::slotMoveLeft() +{ + QRect r=selected()->rect(); + selected()->setMoving(true); + selected()->moveBy(-1,0); + + commandHistory()->addCommand( + new MoveCommand( this, selected(), r.topLeft() ) ,true ); + selected()->setMoving(false); + slotAreaChanged(selected()); + slotUpdateSelectionCoords(); +} + +void KImageMapEditor::slotMoveRight() +{ + QRect r=selected()->rect(); + selected()->setMoving(true); + selected()->moveBy(1,0); + + commandHistory()->addCommand( + new MoveCommand( this, selected(), r.topLeft() ) ,true ); + selected()->setMoving(false); + slotAreaChanged(selected()); + slotUpdateSelectionCoords(); +} + +void KImageMapEditor::slotCancelDrawing() +{ + drawZone->cancelDrawing(); +} + +void KImageMapEditor::slotIncreaseHeight() +{ + Area *oldArea=selected()->clone(); + + QRect r = selected()->rect(); + r.setHeight( r.height()+1 ); + r.moveBy(0,-1); + + selected()->setRect(r); + + commandHistory()->addCommand( + new ResizeCommand( this, selected(), oldArea ) ,true ); + slotAreaChanged(selected()); + slotUpdateSelectionCoords(); +} + +void KImageMapEditor::slotDecreaseHeight() +{ + Area *oldArea=selected()->clone(); + + QRect r = selected()->rect(); + r.setHeight( r.height()-1 ); + r.moveBy(0,1); + + selected()->setRect(r); + + commandHistory()->addCommand( + new ResizeCommand( this, selected(), oldArea ) ,true ); + slotAreaChanged(selected()); + slotUpdateSelectionCoords(); +} + +void KImageMapEditor::slotIncreaseWidth() +{ + Area *oldArea=selected()->clone(); + + QRect r = selected()->rect(); + r.setWidth( r.width()+1 ); + + selected()->setRect(r); + + commandHistory()->addCommand( + new ResizeCommand( this, selected(), oldArea ) ,true ); + slotAreaChanged(selected()); + slotUpdateSelectionCoords(); +} + +void KImageMapEditor::slotDecreaseWidth() +{ + Area *oldArea=selected()->clone(); + + QRect r = selected()->rect(); + r.setWidth( r.width()-1 ); + + selected()->setRect(r); + + commandHistory()->addCommand( + new ResizeCommand( this, selected(), oldArea ) ,true ); + slotAreaChanged(selected()); + slotUpdateSelectionCoords(); +} + +void KImageMapEditor::slotHightlightAreas() +{ + bool b = highlightAreasAction->isChecked(); + +// highlightAreasAction->setChecked(b); + Area::highlightArea = b; + updateAllAreas(); + drawZone->viewport()->repaint(); +} + +void KImageMapEditor::slotShowAltTag() +{ + bool b = showAltAction->isChecked(); +// showAltAction->setChecked(b); + Area::showAlt = b; + drawZone->viewport()->repaint(); +} + +void KImageMapEditor::mapNew() +{ + QString mapName = mapsListView->getUnusedMapName(); + addMap(mapName); + mapEditName(); +} + +void KImageMapEditor::mapDelete() +{ + if (mapsListView->count() == 0) + return; + + QString selectedMap = mapsListView->selectedMap(); + + int result = KMessageBox::warningContinueCancel(widget(), + i18n("Are you sure you want to delete the map %1?" + "
There is no way to undo this.
").arg(selectedMap), + i18n("Delete Map?"),KGuiItem(i18n("&Delete"),"editdelete")); + + if (result == KMessageBox::No) + return; + + + + mapsListView->removeMap(selectedMap); + HtmlMapElement* mapEl = findHtmlMapElement(selectedMap); + _htmlContent.remove(mapEl); + if (mapsListView->count() == 0) { + + currentMapElement = 0L; + deleteAllAreas(); + setMapActionsEnabled(false); + } + else { + // The old one was deleted, so the new one got selected + setMap(mapsListView->selectedMap()); + } +} + +void KImageMapEditor::mapPreview() { + HTMLPreviewDialog dialog(widget(), url(), getHtmlCode()); + dialog.exec(); +} + +void KImageMapEditor::deleteAllMaps() +{ + deleteAllAreas(); + mapsListView->clear(); + if (isReadWrite()) { + mapDeleteAction->setEnabled(false); + mapDefaultAreaAction->setEnabled(false); + mapNameAction->setEnabled(false); + } +} + +/** + * Doesn't call the closeURL method, because + * we need the URL for the session management + */ +bool KImageMapEditor::queryClose() { + if ( ! isModified() ) + return true; + + switch ( KMessageBox::warningYesNoCancel( widget(), + i18n("The file %1 has been modified.
Do you want to save it?
").arg(url().fileName()), QString::null, KStdGuiItem::save(), KStdGuiItem::discard()) ) { + case KMessageBox::Yes : + saveFile(); + return true; + case KMessageBox::No : + return true; + default: + return false; + } +} + +bool KImageMapEditor::closeURL() +{ + bool result = KParts::ReadWritePart::closeURL(); + if (!result) + return false; + + _htmlContent.clear(); + deleteAllMaps(); + imagesListView->clear(); + + delete copyArea; + copyArea=0L; + + delete defaultArea; + defaultArea=0L; + + currentMapElement = 0L; + + init(); + emit setWindowCaption(""); + + return true; + +} + +void KImageMapEditor::addImage(const KURL & imgUrl) { + if (imgUrl.isEmpty()) + return; + + QString relativePath ( QExtFileInfo::toRelative(imgUrl, KURL( url().directory() )).path() ); + + QString imgHtml = QString(""); + ImageTag *imgTag = new ImageTag(); + imgTag->insert("tagname",new QString("img")); + imgTag->insert("src", new QString(relativePath)); + + HtmlImgElement *imgEl = new HtmlImgElement(imgHtml); + imgEl->imgTag = imgTag; + + HtmlElement *bodyEl = findHtmlElement("addImage(imgTag); + imagesListView->selectImage(imgTag); + setImageActionsEnabled(true); + + setModified(true); +} + +/** + * Sets whether the image actions that depend on an + * selected image are enabled + */ +void KImageMapEditor::setImageActionsEnabled(bool b) { + imageRemoveAction->setEnabled(b); + imageUsemapAction->setEnabled(b); +} + + +void KImageMapEditor::imageAdd() { + KURL imgUrl = KFileDialog::getImageOpenURL(); + addImage(imgUrl); +} + +void KImageMapEditor::imageRemove() { + ImageTag* imgTag = imagesListView->selectedImage(); + HtmlImgElement* imgEl = findHtmlImgElement(imgTag); + imagesListView->removeImage(imgTag); + _htmlContent.remove(imgEl); + + if (imagesListView->childCount() == 0) { + setPicture(getBackgroundImage()); + setImageActionsEnabled(false); + } + else { + ImageTag* selected = imagesListView->selectedImage(); + if (selected) { + QString *url = selected->find("src"); + if (url) { + setPicture(KURL(*url)); + } + } + } + + setModified(true); +} + +void KImageMapEditor::imageUsemap() { + + bool ok=false; + ImageTag* imageTag = imagesListView->selectedImage(); + if ( ! imageTag) + return; + + QString usemap; + + if (imageTag->find("usemap")) + usemap=*imageTag->find("usemap"); + + QStringList maps = mapsListView->getMaps(); + int index = maps.findIndex(usemap); + if (index == -1) { + maps.prepend(""); + index = 0; + } + +#if KDE_IS_VERSION(3, 1, 90) + QString input = KInputDialog::getItem(i18n("Enter Usemap"), +#else + QString input = QInputDialog::getItem(i18n("Enter Usemap"), +#endif + i18n("Enter the usemap value:"), + maps,index,true,&ok,widget()); + if (ok) { + imageTag->replace("usemap", new QString(input)); + imagesListView->updateImage(imageTag); + setModified(true); + + // Update the htmlCode of the HtmlElement + HtmlImgElement* imgEl = findHtmlImgElement(imageTag); + + imgEl->htmlCode = "<"; + QString *tagName = imgEl->imgTag->find("tagname"); + imgEl->htmlCode += QString(*tagName); + + QDictIterator it( *imgEl->imgTag ); + for( ; it.current(); ++it ) { + if (it.currentKey() != "tagname") { + imgEl->htmlCode += " " + it.currentKey() + "=\""; + imgEl->htmlCode += *it.current(); + imgEl->htmlCode += "\""; + } + } + + imgEl->htmlCode += ">"; + + } +} + +void KImageMapEditor::configureShowAreaList() { + if (configureShowAreaListAction->isChecked()) + mainDock->makeDockVisible(areaDock); + else + mainDock->makeDockInvisible(areaDock); +} + +void KImageMapEditor::configureShowMapList() { + if (configureShowMapListAction->isChecked()) + mainDock->makeDockVisible(mapsDock); + else + mainDock->makeDockInvisible(mapsDock); +} + +void KImageMapEditor::configureShowImageList() { + if (configureShowImageListAction->isChecked()) + mainDock->makeDockVisible(imagesDock); + else + mainDock->makeDockInvisible(imagesDock); +} + +void KImageMapEditor::dockingStateChanged() { + if (areaDock) { + configureShowImageListAction->setChecked( imagesDock->isVisible() ); + configureShowAreaListAction->setChecked( areaDock->isVisible() ); + configureShowMapListAction->setChecked( mapsDock->isVisible() ); + } +} diff --git a/kimagemapeditor/kimagemapeditor.desktop b/kimagemapeditor/kimagemapeditor.desktop new file mode 100644 index 00000000..263c7536 --- /dev/null +++ b/kimagemapeditor/kimagemapeditor.desktop @@ -0,0 +1,55 @@ +[Desktop Entry] +Type=Application +MimeType=text/html; +Exec=kimagemapeditor -caption "%c" %i %m +Icon=kimagemapeditor +Terminal=false +Name=KImageMapEditor +Name[ne]=कà‡à¤Ħà€à¤ˆ à¤›à¤µà¤ż à¤à¤à¤¨à¤šà¤żà¤¤àà¤° सà¤àà¤Şà¤à¤Ĥक +Name[pt_BR]=KEditor de Mapeamento de Imagem +Name[sk]=KImage editor mapy +Name[sv]=Kimagemapeditor +Name[ta]=KàµàŸàżàµààŻ àµà°àŻˆàŞàŻàŞàŸààŻ à¤àżà°àŻà¤àŻà¤àż +Name[tg]=KœÑƒÒ³°Ñ€Ñ€¸Ñ€¸ т°Ñ²¸Ñ€¸ Ò³°Ñ€¸Ñ‚° +Name[tr]=K Resim HaritasÄħ Dĵzenleyicisi +GenericName=HTML Image Map Editor +GenericName[bg]= µ´°şÑ‚Ñ€ ½° ĵ°Ñ€ş¸Ñ€°½¸Ñ ½° ¸·ħр°ĥµ½¸Ñ ·° HTML +GenericName[ca]=Un editor de mapes d'imatge HTML +GenericName[cs]=Editor HTML map +GenericName[da]=HTML editor af kortbilleder +GenericName[de]=Editor fĵr HTML-Bildkarten (Imagemaps) +GenericName[el]=HTML επεÎεργÎħστÎς εÎıÎşÏŒÎ½Ï‰Î½ +GenericName[es]=Editor de mapas de imĦgenes HTML +GenericName[et]=Hĵperpildiredaktor +GenericName[eu]=HTML irudi-mapa editorea +GenericName[fa]=ویĜħĜ§ÛŒĜ´ÚŻĜħ Ù†ÚŻĜ§Ĝ´ĜŞ ĜŞĜµÙˆÛŒĜħ Ĝ²Ù†ÚŻĜ§Ù… +GenericName[fi]=HTML-kuvaeditori +GenericName[fr]=‰diteur d'hyperimages HTML +GenericName[gl]=Editor de mapas de imaxes HTML +GenericName[hu]=HTML-tİrkİpszerkesztĊ‘ +GenericName[is]=HTML myndakortsritill +GenericName[it]=Editor per le mappe di immagini HTML +GenericName[ja]=HTML ‚¤ƒĦƒĵ‚¸ƒžƒƒƒ—‚¨ƒ‡‚£‚ż +GenericName[ka]=HTML გამოáƒĦაáƒáƒ£áƒšáƒ”ბიáƒĦ რუáƒáƒ˜áƒĦ რედაáƒáƒ˘áƒáƒ áƒ˜ +GenericName[lt]=HTML paveikslėliĊ³ ĊemėlapiĊ³ rengyklė +GenericName[ms]=Penyunting Peta Imej HTML +GenericName[nds]=Editor fĥr HTML-Bildkoorten +GenericName[ne]=एचटà€à¤à¤à¤à¤² à¤›à¤µà¤ż à¤à¤à¤¨à¤šà¤żà¤¤àà¤° सà¤àà¤Şà¤à¤Ĥक +GenericName[nl]=HTML imagemap editor +GenericName[pa]=HTML à¨šà¨żàİħਤਰ ਨਕਸà¨ĵਠਸàİ°à¨Şà¨à¨Ĥਕ +GenericName[pl]=Edytor map obrazk³w HTML +GenericName[pt]=Editor de Mapas de Imagem HTML +GenericName[pt_BR]=Editor de Mapeamento de Imagem HTML +GenericName[sk]=Editor HTML mapy obrĦzkov +GenericName[sl]=Urejevalnik slikovnih zemljevidov v HTML +GenericName[sr]=£Ñ€µÑ’¸²°Ñ‡ HTML Ñğ¸ş²½µ ĵ°żµ +GenericName[sr@Latn]=Uređivač HTML slikovne mape +GenericName[sv]=Redigering av HTML-bildkartor +GenericName[ta]=HTML àµàŸàżàµààŻ àµà°àŻˆàŞàŻàŞàŸààŻ à¤àżà°àŻà¤àŻà¤àż +GenericName[tg]=œÑƒÒ³°Ñ€Ñ€¸Ñ€¸ т°Ñ²¸Ñ€¸ Ò³°Ñ€¸Ñ‚°¸ HTML +GenericName[tr]=HTML Resim HaritasÄħ Dĵzenleyicisi +GenericName[uk]= µ´°şÑ‚Ñ€ ş°Ñ€Ñ‚ ·ħр°ĥµ½ÑŒ HTML +GenericName[zh_CN]=HTML ċ›ċƒĉ˜ ċ°„çĵ–è‘ċ™¨ +GenericName[zh_HK]=HTML ċ½ħċƒċœ°ċœ–ç·¨èĵŻċ™¨ +GenericName[zh_TW]=HTML ċ½ħċƒċœ°ċœ–ç·¨èĵŻċ™¨ +Categories=Qt;KDE;Development;WebDevelopment; diff --git a/kimagemapeditor/kimagemapeditor.h b/kimagemapeditor/kimagemapeditor.h new file mode 100644 index 00000000..bf76349e --- /dev/null +++ b/kimagemapeditor/kimagemapeditor.h @@ -0,0 +1,460 @@ +/*************************************************************************** + imagemapeditor.h - description + ------------------- + begin : Wed Apr 4 2001 + copyright : (C) 2001 by Jan Sch?fer + email : janschaefer@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KIMAGEMAPDIALOG_H +#define KIMAGEMAPDIALOG_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "kimearea.h" + +/** + *@author Jan Schaefer + */ + + +class QListView; +class QPushButton; +class DrawZone; +class QComboBox; +class QListViewItem; +class KToggleAction; + + + + +/** + * Stores an area tag and all its attributes + */ +typedef QDict AreaTag; + +/** + * Stores an image tag and all its attributes + * the origcode attribute hold the original htmlcode + * of this tag + */ +typedef QDict ImageTag; + +/** + * Only a small class to give a list of AreaTags a name + */ +class MapTag : public QPtrList { +public: + MapTag(); + QString name; + bool modified; +}; + + +class HtmlElement { +public: + HtmlElement(const QString & s) { + htmlCode = s; + }; + virtual ~HtmlElement() {} + ; + QString htmlCode; +}; + +class HtmlMapElement : public HtmlElement { +public: + HtmlMapElement(const QString & s) : HtmlElement(s) { + mapTag = 0L; + }; + + virtual ~HtmlMapElement() {}; + + MapTag *mapTag; +}; + +class HtmlImgElement : public HtmlElement { +public: +HtmlImgElement(const QString & s) : HtmlElement(s) { + imgTag = 0L; + }; + virtual ~HtmlImgElement() {} + ; + ImageTag *imgTag; +}; + +/** + * Stores the hole HTML content in a List. + */ +class HtmlContent : public QPtrList {} +; + + +class KSelectAction; +class KRadioAction; +class KRecentFilesAction; +class KAction; +#if KDE_VERSION < 300 + class KAccel; +#endif +///class QListViewItem; +class KCommandHistory; +class KApplication; +class QTabWidget; +class AreaListView; +class ImagesListView; +class MapsListView; +class KDockWidget; +class KDockMainWindow; + +// needed by the statusbar +#define STATUS_CURSOR 1000 +#define STATUS_SELECTION 1001 + +class KImageMapEditor : public KParts::ReadWritePart { + Q_OBJECT +public : + enum ToolType { Selection, Rectangle, Circle, Polygon, Freehand, AddPoint, RemovePoint }; + + KImageMapEditor(QWidget *parentWidget, const char *, + QObject *parent, const char *name, const QStringList & args = QStringList()); + virtual ~KImageMapEditor(); + + static KAboutData *createAboutData(); + static KConfig *config(); + + /** + * Makes sure, that the actions cut, copy, delete and + * show properties + * can only be executed if sth. is selected. + **/ + void updateActionAccess(); + + DrawZone* getDrawZone() { + return drawZone; + }; + + void addAreaAndEdit(Area*); + void addArea(Area*); + AreaListIterator areaList() const; + KImageMapEditor::ToolType currentToolType() const; + void deleteSelected(); + void deleteArea( Area * area); + void deleteAllAreas(); + void deselectAll(); + void deselect(Area* s); + void deselectWithoutUpdate(Area*); + QString getHTMLImageMap() const; + Area* onArea(const QPoint & p) const; + QPixmap makeListViewPix(Area &) ; + QString mapName() const; + void select(Area*); + void selectWithoutUpdate(Area*); + void select(QListViewItem*); + AreaSelection* selected() const; + void setPicture(const QImage & pix); + int showTagEditor(Area *); + KCommandHistory *commandHistory() const; + + KApplication* app() const; + + // Only refreshes the listView + void updateSelection() const; + + void readConfig(); + void writeConfig(); + + virtual void readProperties(KConfig *); + virtual void saveProperties(KConfig *); + virtual bool closeURL(); + bool queryClose(); + virtual void setReadWrite(bool); + QString getHtmlCode(); + + /** + * Reimplemented to disable and enable Save action + */ + virtual void setModified(bool); + + /** + * Opens the given file. + * If it's an HTML file openURL is called + * If it's an Image, the image is added to the image list + */ + void openFile(const KURL &); + + /** + * Opens the last URL the user worked with. + * Sets also, the last map and the last image + */ + void openLastURL(KConfig*); + + void readConfig(KConfig*); + void writeConfig(KConfig*); + + virtual bool openURL(const KURL & url); + +protected: + void init(); + bool openHTMLFile(const KURL &, const QString & mapName = QString::null, const QString & imagePath = QString::null); + void saveImageMap(const KURL &); + + /** + * Returns a language dependend background picture, with + * the text : Drop an image or html file + */ + QImage getBackgroundImage(); + + + /** + * Saves information to restore the last working state + */ + void saveLastURL(KConfig*); + + +private: + // Stores the hole html file in a List + // The entries are either a MapTag an ImageTag or a QString + HtmlContent _htmlContent; + + // the url of the working image; + KURL _imageUrl; + QString _mapName; + QImage _backgroundImage; + + bool backupFileCreated; + + KImageMapEditor::ToolType _currentToolType; + AreaList *areas; + AreaSelection *currentSelected; + AreaSelection *copyArea; + Area *defaultArea; + DrawZone* drawZone; + QTabWidget* tabWidget; + AreaListView *areaListView; + ImagesListView* imagesListView; + MapsListView* mapsListView; + HtmlMapElement* currentMapElement; + + // + // Actions + // + KSelectAction* zoomAction; + KRadioAction *arrowAction; + KRadioAction *circleAction; + KRadioAction *rectangleAction; + KRadioAction *polygonAction; + KRadioAction *freehandAction; + KRadioAction *addPointAction; + KRadioAction *removePointAction; + + KAction *cutAction; + KAction *deleteAction; + KAction *copyAction; + KAction *pasteAction; + KAction *zoomInAction; + KAction *zoomOutAction; + + KAction *mapNewAction; + KAction *mapDeleteAction; + KAction *mapNameAction; + KAction *mapDefaultAreaAction; + + KAction *imageAddAction; + KAction *imageRemoveAction; + KAction *imageUsemapAction; + + KToggleAction *highlightAreasAction; + KToggleAction *showAltAction; + + KAction *areaPropertiesAction; + + KAction *moveLeftAction; + KAction *moveRightAction; + KAction *moveUpAction; + KAction *moveDownAction; + + KAction *increaseWidthAction; + KAction *decreaseWidthAction; + KAction *increaseHeightAction; + KAction *decreaseHeightAction; + + KAction *toFrontAction; + KAction *toBackAction; + KAction *forwardOneAction; + KAction *backOneAction; + + KToggleAction* configureShowAreaListAction; + KToggleAction* configureShowMapListAction; + KToggleAction* configureShowImageListAction; + + + KRecentFilesAction* recentFilesAction; + + #if KDE_VERSION < 300 + KAccel *accel; + #endif + + KDockMainWindow *mainDock; + KDockWidget* areaDock; + KDockWidget* mapsDock; + KDockWidget* imagesDock; + + KCommandHistory *_commandHistory; + int maxAreaPreviewHeight; + + QString cursorStatusText; + QString selectionStatusText; + + void setupActions(); + void setupStatusBar(); + void updateStatusBar(); + /* refreshes all Areas, only used by preferences dialog + * updates only the preview pictures*/ + void updateAllAreas(); + void updateUpDownBtn(); + + QDict getTagAttributes(QTextStream & s,QString &); + + void setMap(HtmlMapElement*); + void setMap(MapTag*); + void addMap(const QString &); + + // Returns the entire html file as a String + HtmlElement* findHtmlElement(const QString &); + HtmlImgElement* findHtmlImgElement(ImageTag*); + HtmlMapElement* findHtmlMapElement(const QString &); + void deleteAllMaps(); + void addImage(const KURL &); + void setImageActionsEnabled(bool); + void setMapActionsEnabled(bool); + + void saveAreasToMapTag(MapTag*); + void showPopupMenu(const QPoint &, const QString &); + void drawToCenter(QPainter* p, const QString & str, int y, int width); + +public slots: + void slotChangeStatusCoords(int x,int y); + void slotUpdateSelectionCoords(); + void slotUpdateSelectionCoords( const QRect &); + void slotAreaChanged(Area *); + void slotShowMainPopupMenu(const QPoint &); + void slotShowMapPopupMenu(QListViewItem *, const QPoint &); + void slotShowImagePopupMenu(QListViewItem *, const QPoint &); + void slotConfigChanged(); + void setPicture(const KURL & url); + void setMap(const QString &); + void setMapName(const QString & s); + + +protected slots: + // overriden from KReadWritePart + virtual bool openFile(); + + virtual bool saveFile() { + saveImageMap( url() ); +// setModified(false); + return true; + } + + void fileOpen(); + void fileSaveAs(); + void fileSave(); + void fileClose(); + + void slotShowPopupMenu(QListViewItem*,const QPoint &); + void slotShowPreferences(); + void slotHightlightAreas(); + void slotShowAltTag(); + void slotSelectionChanged(); + + int showTagEditor(QListViewItem *item); + int showTagEditor(); + + void slotZoom(); + void slotZoomIn(); + void slotZoomOut(); + + void slotCut(); + void slotCopy(); + void slotPaste(); + void slotDelete(); + + void slotDrawArrow(); + void slotDrawCircle(); + void slotDrawRectangle(); + void slotDrawPolygon(); + void slotDrawFreehand(); + void slotDrawAddPoint(); + void slotDrawRemovePoint(); + + void mapDefaultArea(); + void mapNew(); + void mapDelete(); + void mapEditName(); + void mapShowHTML(); + void mapPreview(); + + void slotBackOne(); + void slotForwardOne(); + void slotToBack(); + void slotToFront(); + + void slotMoveUp(); + void slotMoveDown(); + void slotMoveLeft(); + void slotMoveRight(); + + void slotIncreaseHeight(); + void slotDecreaseHeight(); + void slotIncreaseWidth(); + void slotDecreaseWidth(); + + void slotCancelDrawing(); + + void configureShowAreaList(); + void configureShowMapList(); + void configureShowImageList(); + + + // void slotPreferences(); + void imageAdd(); + void imageRemove(); + void imageUsemap(); + + void dockingStateChanged(); + +}; + + +inline KImageMapEditor::ToolType KImageMapEditor::currentToolType() const { + return _currentToolType; +} + +inline QString KImageMapEditor::mapName() const { + return _mapName; +} + +inline KCommandHistory* KImageMapEditor::commandHistory() const { + return _commandHistory; +} + + +#endif diff --git a/kimagemapeditor/kimagemapeditorpart.desktop b/kimagemapeditor/kimagemapeditorpart.desktop new file mode 100644 index 00000000..758b510a --- /dev/null +++ b/kimagemapeditor/kimagemapeditorpart.desktop @@ -0,0 +1,54 @@ +[Desktop Entry] +Type=Service +MimeType=text/html +Icon=kimagemapeditor +ServiceTypes=KParts/ReadWritePart +X-KDE-Library=libkimagemapeditor +Comment=An HTML imagemap editor +Comment[bg]= µ´°şÑ‚Ñ€ ½° ĵ°Ñ€ş¸Ñ€°½¸Ñ ½° ¸·ħр°ĥµ½¸Ñ ·° HTML +Comment[ca]=Un editor de mapes d'imatge HTML +Comment[cs]=Editor HTML map +Comment[da]=En HTML-editor af kortbilleder +Comment[de]=Ein Editor fĵr HTML-Bildkarten (Imagemaps) +Comment[el]=HTML επεÎεργÎħστÎς εÎıÎşÏŒÎ½Ï‰Î½ +Comment[es]=Un editor de mapas de imĦgenes HTML +Comment[et]=Hĵperpildiredaktor +Comment[eu]=HTML irudi-mapa editore bat +Comment[fa]=یÚİ ÙˆÛŒĜħĜ§ÛŒĜ´ÚŻĜħ Ù†ÚŻĜ§Ĝ´ĜŞ ĜŞĜµÙˆÛŒĜħ Ĝ²Ù†ÚŻĜ§Ù… +Comment[fi]=HTML-imagemap -editori +Comment[fr]=‰diteur d'hyperimages HTML +Comment[gl]=Un editor de mapas de imaxes HTML +Comment[hu]=HTML-tİrkİpszerkesztĊ‘ +Comment[is]=HTML myndakortsritill +Comment[it]=Un editor per le mappe di immagini HTML +Comment[ja]=HTML ‚¤ƒĦƒĵ‚¸ƒžƒƒƒ—‚¨ƒ‡‚£‚ż +Comment[ka]=HTML გამოáƒĦაáƒáƒ£áƒšáƒ”ბიáƒĦ რუáƒáƒ˜áƒĦ რედაáƒáƒ˘áƒáƒ áƒ˜ +Comment[lt]=HTML paveikslėliĊ³ ĊemėlapiĊ³ rengyklė +Comment[ms]=Penyunting Peta Imej HTML +Comment[nds]=En Editor fĥr HTML-Bildkoorten +Comment[ne]=एउटठएचटà€à¤à¤à¤à¤² à¤›à¤µà¤ż à¤à¤à¤¨à¤šà¤żà¤¤àà¤° सà¤àà¤Şà¤à¤Ĥकस +Comment[nl]=Een hulpmiddel om HTML imagemaps te maken +Comment[pl]=Edytor map obrazk³w HTML +Comment[pt]=Editor de Mapas de Imagem HTML +Comment[pt_BR]=Um editor de mapeamento de imagem HTML +Comment[ru]= µ´°şÑ‚Ñ€ HTML imagemap +Comment[sk]=Editor HTML mapy obrĦzkov +Comment[sl]=Urejevalnik slikovnih zemljevidov v HTML +Comment[sr]=£Ñ€µÑ’¸²°Ñ‡ HTML Ñğ¸ş²½µ ĵ°żµ +Comment[sr@Latn]=Uređivač HTML slikovne mape +Comment[sv]=En editor fĥr HTML-bildkartor +Comment[ta]=An HTML àµàŸàżàµààŻ àµà°àŻˆàŞàŻàŞàŸààŻ à¤àżà°àŻà¤àŻà¤àż +Comment[tg]=œÑƒÒ³°Ñ€Ñ€¸Ñ€¸ т°Ñ²¸Ñ€¸ Ò³°Ñ€¸Ñ‚°¸ HTML +Comment[tr]=Bir HTML resim_haritasÄħ dĵzenleyicisi +Comment[uk]= µ´°şÑ‚Ñ€ imagemap HTML +Comment[zh_CN]=HTML ċ›ċƒĉ˜ ċ°„çĵ–è‘ċ™¨ +Comment[zh_HK]=一ċ€‹ HTML ċ½ħċƒċœ°ċœ–çš„ç·¨èĵŻċ™¨ +Comment[zh_TW]=一ċ€‹ HTML ċ½ħċƒċœ°ċœ–çš„ç·¨èĵŻċ™¨ +Name=KImageMapEditor +Name[ne]=कà‡à¤Ħà€à¤ˆ à¤›à¤µà¤ż à¤à¤à¤¨à¤šà¤żà¤¤àà¤° सà¤àà¤Şà¤à¤Ĥक +Name[pt_BR]=KEditor de Mapeamento de Imagem +Name[sk]=KImage editor mapy +Name[sv]=Kimagemapeditor +Name[ta]=KàµàŸàżàµààŻ àµà°àŻˆàŞàŻàŞàŸààŻ à¤àżà°àŻà¤àŻà¤àż +Name[tg]=KœÑƒÒ³°Ñ€Ñ€¸Ñ€¸ т°Ñ²¸Ñ€¸ Ò³°Ñ€¸Ñ‚° +Name[tr]=K Resim HaritasÄħ Dĵzenleyicisi diff --git a/kimagemapeditor/kimagemapeditorpartui.rc b/kimagemapeditor/kimagemapeditorpartui.rc new file mode 100644 index 00000000..6f6df968 --- /dev/null +++ b/kimagemapeditor/kimagemapeditorpartui.rc @@ -0,0 +1,150 @@ + + + + + + + + + + + + + + &Edit + + + + + + + + + + + + + + + + + &View + + + + + + + + + &Tools + + + + + + + + + + &Map + + + + + + + + + + + &Image + + + + + &Settings + + + + + + + + + + + KImageMapEditor Main Toolbar + + + + + + + + + + + + + + + + + + + KImageMapEditor Draw Toolbar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kimagemapeditor/kimagemapeditorui.rc b/kimagemapeditor/kimagemapeditorui.rc new file mode 100644 index 00000000..68bb713a --- /dev/null +++ b/kimagemapeditor/kimagemapeditorui.rc @@ -0,0 +1,25 @@ + + + + &File + + + + + + + + + + + KImageMapEditor Main Toolbar + + + + + + + + + + diff --git a/kimagemapeditor/kimearea.cpp b/kimagemapeditor/kimearea.cpp new file mode 100644 index 00000000..cb873564 --- /dev/null +++ b/kimagemapeditor/kimearea.cpp @@ -0,0 +1,1749 @@ +/*************************************************************************** + kimearea.cpp - description + ------------------- + begin : Thu Jun 14 2001 + copyright : (C) 2001 by Jan Schaefer + email : janschaefer@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "kimearea.h" +#include "kimecommon.h" + + +#define SELSIZE 7 + + +bool Area::highlightArea; +bool Area::showAlt; + + +Area::Area() +{ + _coords=new QPointArray(); + _selectionPoints= new SelectionPointList(); + _selectionPoints->setAutoDelete(true); + _finished=false; + _isSelected=false; + _name=i18n("noname"); + _listViewItem=0L; + currentHighlighted=-1; + _type=Area::None; + _highlightedPixmap=0L; + +} + +Area* Area::clone() const +{ + Area* areaClone = new Area(); + areaClone->setArea( *this ); + return areaClone; +} + +QPointArray* Area::coords() const { + return _coords; +} + +QString Area::getHTMLAttributes() const +{ + QString retStr=""; + + for (AttributeIterator it = firstAttribute();it!=lastAttribute();++it) + { + retStr+=it.key()+"=\""+it.data()+"\" "; + } + + return retStr; +} + + +Area::~Area() { + delete _coords; + delete _selectionPoints; + delete _highlightedPixmap; + +} + +bool Area::contains(const QPoint &) const { + return false; +} + +QString Area::getHTMLCode() const { + return ""; +} + +QString Area::attribute(const QString & name) const +{ + return _attributes[name.lower()]; +} + +void Area::setAttribute(const QString & name, const QString & value) +{ + _attributes.replace(name.lower(),value); + if (value.isEmpty()) + _attributes.remove(name.lower()); +} + +AttributeIterator Area::firstAttribute() const +{ + return _attributes.begin(); +} + +AttributeIterator Area::lastAttribute() const +{ + return _attributes.end(); +} + + +bool Area::setCoords(const QString &) { + return true; +} + +void Area::moveSelectionPoint(QRect*, const QPoint &) +{} + + + // Default implementation; is specified by subclasses +QString Area::coordsToString() const +{ + return ""; +} + + +Area::ShapeType Area::type() const { + return _type; +} + +void Area::setArea(const Area & copy) +{ + delete _coords; + delete _selectionPoints; + _coords=new QPointArray(copy.coords()->copy()); + _selectionPoints= new SelectionPointList(); + currentHighlighted=-1; + + // Need a deep copy of the list + for (QRect *r=copy.selectionPoints()->first();r!=0L;r=copy.selectionPoints()->next()) + _selectionPoints->append(new QRect( r->topLeft(),r->bottomRight() ) ); + + _finished=copy.finished(); + _isSelected=copy.isSelected(); + _rect = copy.rect(); + + for (AttributeIterator it = copy.firstAttribute();it!=copy.lastAttribute();++it) + { + setAttribute(it.key(),it.data()); + } + + setMoving(copy.isMoving()); + +// _listViewItem=0L; + +} + +void Area::setListViewItem(QListViewItem* item) { + _listViewItem=item; +} + +void Area::deleteListViewItem() +{ + delete _listViewItem; + _listViewItem = 0L; +} + + +void Area::setRect(const QRect & r) +{ + _rect=r; + updateSelectionPoints(); +} + +QRect Area::rect() const { + return _rect; +} + +void Area::setMoving(bool b) { + _isMoving=b; +} + + +void Area::moveBy(int dx, int dy) { + _rect.moveBy(dx,dy); + for (uint i=0;i<_coords->size();i++) { + int newX=_coords->point(i).x()+dx; + int newY=_coords->point(i).y()+dy; + _coords->setPoint(i,newX,newY); + } + + for (QRect *r=_selectionPoints->first();r!=0L;r=_selectionPoints->next()) { + r->moveBy(dx,dy); + } +} + + +void Area::moveTo(int x, int y) { + int dx=x-rect().left(); + int dy=y-rect().top(); + moveBy(dx,dy); +} + +uint Area::countSelectionPoints() const +{ + return (uint) selectionPoints()->count(); +} + +int Area::addCoord(const QPoint & p) +{ + _coords->resize(_coords->size()+1); + _coords->setPoint(_coords->size()-1,p); + + QRect *r= new QRect(0,0,SELSIZE,SELSIZE); + r->moveCenter(p); + _selectionPoints->append(r); + setRect(_coords->boundingRect()); + + return _coords->size()-1; +} + +void Area::insertCoord(int pos, const QPoint & p) +{ + +/* + kdDebug() << p.x() << "," << p.y() << endl; + + if ( _coords->size()>0 ) + { + for (int i=0; i<_coords->size(); i++) + { + if (p==_coords->point(i)) + { + kdDebug() << "same Point already exists" << endl; + return; + } + + } + } +*/ + _coords->resize(_coords->size()+1); + + + for (int i=_coords->size()-1;i>pos;i--) { + _coords->setPoint(i,_coords->point(i-1)); + } + _coords->setPoint(pos, p); + + QRect *r= new QRect(0,0,SELSIZE,SELSIZE); + r->moveCenter(p); + _selectionPoints->insert(pos,r); + setRect(_coords->boundingRect()); +} + +void Area::removeCoord(int pos) { + + int count=_coords->size(); + + if (count<4) + { + kdDebug() << "Danger : trying to remove coordinate from Area with less then 4 coordinates !" << endl; + return; + } + + for (int i=pos;i<(count-1);i++) + _coords->setPoint(i, _coords->point(i+1)); + + _coords->resize(count-1); + _selectionPoints->remove(pos); + setRect(_coords->boundingRect()); +} + +bool Area::removeSelectionPoint(QRect * r) +{ + if (_selectionPoints->contains(r)) + { + removeCoord(_selectionPoints->find(r)); + return true; + } + + return false; +} + + +void Area::moveCoord(int pos, const QPoint & p) { + _coords->setPoint(pos,p); + _selectionPoints->at(pos)->moveCenter(p); + setRect(_coords->boundingRect()); +} + +void Area::setSelected(bool b) +{ + _isSelected=b; + if (_listViewItem) { + _listViewItem->setSelected(b); + } +} + +void Area::highlightSelectionPoint(int number){ + currentHighlighted=number; +} + +QRect Area::selectionRect() const { + QRect r = rect(); + r.moveBy(-SELSIZE*2,-SELSIZE*2); + r.setSize(r.size()+QSize(SELSIZE*4,SELSIZE*4)); + + return r; +} + +void Area::drawHighlighting(QPainter & p) +{ + if (Area::highlightArea && !isMoving() && _highlightedPixmap) + { + p.setRasterOp(Qt::CopyROP); + + QPoint point = QPoint(rect().x(),rect().y()); + if (point.x()<0) + point.setX(0); + if (point.y()<0) + point.setY(0); + + p.drawPixmap( point, *_highlightedPixmap); + + } +} + +void Area::drawAlt(QPainter & p) +{ + double x,y; + + double scalex = p.worldMatrix().m11(); +// double scaley = p.worldMatrix().m12(); + + QWMatrix oldMatrix = p.worldMatrix(); + + p.setWorldMatrix(QWMatrix(1,oldMatrix.m12(), oldMatrix.m21(), 1, oldMatrix.dx(), oldMatrix.dy() )); + + x = (rect().x()+rect().width()/2)*scalex; + y = (rect().y()+rect().height()/2)*scalex; + + QFontMetrics metrics = p.fontMetrics(); + + int w = metrics.width(attribute("alt")); + x -= w/2; + y += metrics.height()/4; + + + + if (highlightArea) + { + p.setRasterOp(Qt::CopyROP); + p.setPen(Qt::black); + } + else + { + p.setRasterOp(Qt::XorROP); + p.setPen(QPen(QColor("white"),1)); + } + + p.drawText(myround(x),myround(y),attribute("alt")); + + p.setWorldMatrix(oldMatrix); +} + +void Area::draw(QPainter & p) +{ + + // Only draw the selection points at base class + // the rest is done in the derived classes + if (_isSelected) + { + int i=0; + + double scalex = p.worldMatrix().m11(); +// double scaley = p.worldMatrix().m12(); + + QWMatrix oldMatrix = p.worldMatrix(); + + p.setWorldMatrix(QWMatrix(1,oldMatrix.m12(), oldMatrix.m21(), 1, oldMatrix.dx(), oldMatrix.dy() )); + + for (QRect *r=_selectionPoints->first();r!=0L;r=_selectionPoints->next()) { + + // Draw a green circle around the selected point ( only when editing a polygon ) + if (i==currentHighlighted) { + QRect r2(0,0,15,15); + r2.moveCenter(r->center()*scalex); + p.setRasterOp(Qt::CopyROP); + p.setPen(QPen(QColor("lightgreen"),2)); + p.drawEllipse(r2); + p.setRasterOp(Qt::XorROP); + p.setPen(QPen(QColor("white"),1)); + } + + // Draw the selection point + p.setRasterOp(Qt::XorROP); + + QRect r3(*r); + int d = 1; + if (scalex > 2) d=0; + + r3.moveCenter( QPoint((int)(r3.center().x()*scalex),(int)(r3.center().y()*scalex)) ); + + p.fillRect(r3,QBrush("white")); +/* + QRect r3(*r); + r3.moveTopLeft( QPoint(r3.left()*scalex+2*(scalex-1), r3.top()*scalex+2*(scalex-1)) ); + + r3.setSize(r3.size()+QSize(2,2)); +//+ r3.moveBy(-1,-1); + p.setRasterOp(Qt::CopyROP); + p.setPen(QPen(QColor("lightgreen"),1)); + p.setBrush(QColor("lightgreen")); + p.drawPie(r3,0,5760); + p.setPen(QPen(QColor("black"),1)); + r3.setSize(r3.size()+QSize(2,2)); + r3.moveBy(-1,-1); + p.drawEllipse(r3); +*/ + i++; + } + p.setWorldMatrix(oldMatrix); + + + } + + if (showAlt) + { + drawAlt(p); + } + p.setRasterOp(Qt::XorROP); + +} + +QRect* Area::onSelectionPoint(const QPoint & p, double zoom) const +{ + for (QRect *r=_selectionPoints->first();r!=0L;r=_selectionPoints->next()) + { + QRect r2(r->topLeft(),r->bottomRight()); + + r2.moveCenter(r2.center()*zoom); + + if (r2.contains(p)) + { + + return r; + } + } + + return 0L; +} + + + + +/** + * returns only the part of the image which is + * covered by the area + */ +QPixmap Area::cutOut(const QImage & image) +{ + if ( 0>=rect().width() || + 0>=rect().height() || + !rect().intersects(image.rect()) ) + { + QPixmap dummyPix(10,10); + dummyPix.fill(); + delete _highlightedPixmap; + _highlightedPixmap = 0L; + return dummyPix; + } + + // Get the mask from the subclasses + QBitmap mask=getMask(); + + // The rectangle which is part of the image + QRect partOfImage=rect(); + QRect partOfMask(0,0,mask.width(),mask.height()); + + + // If the area is outside of the image make the + // preview smaller + if ( (rect().x()+rect().width()) > image.width() ) { + partOfImage.setWidth( image.width()-rect().x() ); + partOfMask.setWidth( image.width()-rect().x() ); + } + + if ( (rect().x() < 0) ) { + partOfImage.setX(0); + partOfMask.setX(myabs(rect().x())); + } + + if ( (rect().y()+rect().height()) > image.height() ) { + partOfImage.setHeight( image.height()-rect().y() ); + partOfMask.setHeight ( image.height()-rect().y() ); + } + + if ( (rect().y() < 0) ) { + partOfImage.setY(0); + partOfMask.setY(myabs(rect().y())); + } + + QImage tempImage=mask.convertToImage().copy(partOfMask); + mask.convertFromImage(tempImage); + +// partOfImage = partOfImage.normalize(); + QImage cut=image.copy(partOfImage); + + QPixmap pix; + +// partOfMask = partOfMask.normalize(); + if (!partOfMask.isValid()) + kdDebug() << "PartofMask not valid : " << partOfMask.x() << "," << partOfMask.y() << "," + << partOfMask.width() << "," << partOfMask.height() << "," << endl; + +/* + QBitmap mask2(partOfMask.width(), partOfMask.height()); + QPainter p4(&mask2); + p4.drawPixmap( QPoint(0,0) ,mask,partOfMask); + p4.flush(); + p4.end(); +*/ + + pix.convertFromImage(cut); + + setHighlightedPixmap(cut, mask); + + QPixmap retPix(pix.width(),pix.height()); + QPainter p3(&retPix); + + // if transparent image fill the background + // with gimp-like rectangles + if (pix.mask()) { + QPixmap backPix(32,32); + + // Gimp like transparent rectangle + QPainter p2(&backPix); + p2.fillRect(0,0,32,32,QColor(156,149,156)); + p2.fillRect(0,16,16,16,QColor(98,105,98)); + p2.fillRect(16,0,16,16,QColor(98,105,98)); + p2.flush(); + + p3.setPen(QPen()); + p3.fillRect(0,0,pix.width(),pix.height(),QBrush(QColor("black"),backPix)); + } + + + p3.drawPixmap(QPoint(0,0),pix); + p3.flush(); + p3.end(); + retPix.setMask(mask); + + return retPix; +} + +QBitmap Area::getMask() const +{ + QBitmap b; + return b; +} + +void Area::setHighlightedPixmap( QImage & im, QBitmap & mask ) +{ + if (!Area::highlightArea) + return; + + delete _highlightedPixmap; + + QImage image = im.convertDepth( 32 ); + QSize size = image.size(); + QColor pixel; + double r,g,b; + + + // highlight every pixel + for (int y=0; y < size.height(); y++) + { + for (int x=0; x < size.width(); x++) + { + r = qRed(image.pixel(x,y)); + g = qGreen(image.pixel(x,y)); + b = qBlue(image.pixel(x,y)); + r = (r *123 / 255)+132; + g = (g *123 / 255)+132; + b = (b *123 / 255)+132; + + pixel.setRgb( (int) r, (int) g, (int) b); + image.setPixel(x,y, pixel.rgb()); + } + } + + _highlightedPixmap = new QPixmap(); + _highlightedPixmap->convertFromImage( image ); + _highlightedPixmap->setMask( mask ); + + if (_highlightedPixmap->isNull()) + kdDebug() << "HighlightedPixmap is null" << endl; + +} + +/******************************************************************** + * RECTANGLE + *******************************************************************/ + + +RectArea::RectArea() + : Area() +{ + QRect *p = new QRect(0,0,SELSIZE,SELSIZE); + _selectionPoints->append(p); + p = new QRect(0,0,SELSIZE,SELSIZE); + _selectionPoints->append(p); + p = new QRect(0,0,SELSIZE,SELSIZE); + _selectionPoints->append(p); + p = new QRect(0,0,SELSIZE,SELSIZE); + _selectionPoints->append(p); + _type=Area::Rectangle; + +} + +RectArea::~RectArea() { +} + +Area* RectArea::clone() const +{ + Area* areaClone = new RectArea(); + areaClone->setArea( *this ); + return areaClone; +} + +void RectArea::draw(QPainter & p) +{ + + drawHighlighting(p); +// p.setRasterOp(Qt::CopyROP); +// p.setRasterOp(Qt:: OrROP); +// QBrush b(QBrush::SolidPattern); +// QBrush b(QBrush::Dense4Pattern); +// QBrush b(QBrush::BDiagPattern); +// b.setColor(QColor(32,32,32)); +// p.fillRect(rect(), b); + + p.setRasterOp(Qt::XorROP); + p.setPen(QPen(QColor("white"),1)); + QRect r(rect()); + r.setWidth(r.width()+1); + r.setHeight(r.height()+1); + p.drawRect(r); + + Area::draw(p); +} + +QBitmap RectArea::getMask() const +{ + QBitmap mask(rect().width(),rect().height()); + + mask.fill(Qt::color0); + QPainter p(&mask); + p.setBackgroundColor(Qt::color0); + p.setPen(Qt::color1); + p.setBrush(Qt::color1); + mask.fill(Qt::color1); + p.end(); + + return mask; +} + +QString RectArea::coordsToString() const +{ + QString retStr=QString("%1,%2,%3,%4") + .arg(rect().left()) + .arg(rect().top()) + .arg(rect().right()) + .arg(rect().bottom()); + + return retStr; +} + +bool RectArea::contains(const QPoint & p) const{ + return rect().contains(p); +} + +void RectArea::moveSelectionPoint(QRect* selectionPoint, const QPoint & p) +{ + selectionPoint->moveCenter(p); + int i=0; + for (QRect *r=_selectionPoints->first();r!=0L;r=_selectionPoints->next()) { + if (r==selectionPoint) + break; + i++; + } + QRect r2(_rect); + switch (i) { + case 0 : _rect.setLeft(p.x()); + _rect.setTop(p.y()); + break; + case 1 : _rect.setRight(p.x()); + _rect.setTop(p.y()); + break; + case 2 : _rect.setLeft(p.x()); + _rect.setBottom(p.y()); + break; + case 3 : _rect.setRight(p.x()); + _rect.setBottom(p.y()); + break; + } + if ( ! _rect.isValid()) + _rect=r2; + + updateSelectionPoints(); +} + +void RectArea::updateSelectionPoints() +{ + _selectionPoints->first()->moveCenter(_rect.topLeft()); + _selectionPoints->next()->moveCenter(_rect.topRight()+QPoint(1,0)); + _selectionPoints->next()->moveCenter(_rect.bottomLeft()+QPoint(0,1)); + _selectionPoints->next()->moveCenter(_rect.bottomRight()+QPoint(1,1)); +} + +bool RectArea::setCoords(const QString & s) +{ + _finished=true; + + QStringList list=QStringList::split(",",s); + QRect r; + bool ok=true; + QStringList::Iterator it = list.begin(); + r.setLeft((*it).toInt(&ok,10));it++; + r.setTop((*it).toInt(&ok,10));it++; + r.setRight((*it).toInt(&ok,10));it++; + r.setBottom((*it).toInt(&ok,10)); + if (ok) { + setRect(r); + return true; + } else + return false; +} + +QString RectArea::getHTMLCode() const { + QString retStr; + retStr+="append(p); + p = new QRect(0,0,SELSIZE,SELSIZE); + _selectionPoints->append(p); + p = new QRect(0,0,SELSIZE,SELSIZE); + _selectionPoints->append(p); + p = new QRect(0,0,SELSIZE,SELSIZE); + _selectionPoints->append(p); +} + +CircleArea::~CircleArea() { +} + +Area* CircleArea::clone() const +{ + Area* areaClone = new CircleArea(); + areaClone->setArea( *this ); + return areaClone; +} + +void CircleArea::draw(QPainter & p) +{ + drawHighlighting(p); + +/* + p.setRasterOp(Qt::CopyROP); + QBrush bold = p.brush(); + QBrush b(QBrush::Dense5Pattern); + b.setColor(QColor("green")); + p.setBrush(b); + QRect r = _rect; + r.moveBy(1,1); + r.setSize( r.size()-QSize(2,2) ); + p.drawChord(r,0,5760); + p.setBrush(bold); +*/ + p.setRasterOp(Qt::XorROP); + p.setPen(QPen(QColor("white"),1)); + + QRect r(_rect); + r.setWidth(r.width()+1); + r.setHeight(r.height()+1); + p.drawEllipse(r); + + Area::draw(p); +} + +QBitmap CircleArea::getMask() const +{ + QBitmap mask(_rect.width(),_rect.height()); + + mask.fill(Qt::color0); + QPainter p(&mask); + p.setBackgroundColor(Qt::color0); + p.setPen(Qt::color1); + p.setBrush(Qt::color1); + p.drawPie(QRect(0,0,_rect.width(),_rect.height()),0,5760); + p.flush(); + p.end(); + + + return mask; + +} + +QString CircleArea::coordsToString() const +{ + QString retStr=QString("%1,%2,%3") + .arg(_rect.center().x()) + .arg(_rect.center().y()) + .arg(_rect.width()/2); + + return retStr; +} + +bool CircleArea::contains(const QPoint & p) const +{ + QRegion r(_rect,QRegion::Ellipse); + return r.contains(p); +} + +void CircleArea::moveSelectionPoint(QRect* selectionPoint, const QPoint & p) +{ + selectionPoint->moveCenter(p); + + int i=0; + for (QRect *r=_selectionPoints->first();r!=0L;r=_selectionPoints->next()) { + if (r==selectionPoint) + break; + i++; + } + + // The code below really sucks, but I have no better idea. + // it only makes sure that the circle is perfektly round + QPoint newPoint; + int diff=myabs(p.x()-_rect.center().x()); + if (myabs(p.y()-_rect.center().y())>diff) + diff=myabs(p.y()-_rect.center().y()); + + newPoint.setX( p.x()-_rect.center().x()<0 + ? _rect.center().x()-diff + : _rect.center().x()+diff); + + newPoint.setY( p.y()-_rect.center().y()<0 + ? _rect.center().y()-diff + : _rect.center().y()+diff); + + switch (i) { + case 0 : if (newPoint.x() < _rect.center().x() && + newPoint.y() < _rect.center().y()) + { + _rect.setLeft(newPoint.x()); + _rect.setTop(newPoint.y()); + } + break; + case 1 : if (newPoint.x() > _rect.center().x() && + newPoint.y() < _rect.center().y()) + { + _rect.setRight(newPoint.x()); + _rect.setTop(newPoint.y()); + } + break; + case 2 : if (newPoint.x() < _rect.center().x() && + newPoint.y() > _rect.center().y()) + { + _rect.setLeft(newPoint.x()); + _rect.setBottom(newPoint.y()); + } + break; + case 3 : if (newPoint.x() > _rect.center().x() && + newPoint.y() > _rect.center().y()) + { + _rect.setRight(newPoint.x()); + _rect.setBottom(newPoint.y()); + } + break; + } + + + + updateSelectionPoints(); + +} + +void CircleArea::setRect(const QRect & r) +{ + QRect r2 = r; + if ( r2.height() != r2.width() ) + r2.setHeight( r2.width() ); + + Area::setRect(r2); +} + + +void CircleArea::updateSelectionPoints() +{ + _selectionPoints->first()->moveCenter(_rect.topLeft()); + _selectionPoints->next()->moveCenter(_rect.topRight()); + _selectionPoints->next()->moveCenter(_rect.bottomLeft()); + _selectionPoints->next()->moveCenter(_rect.bottomRight()); +} + +bool CircleArea::setCoords(const QString & s) +{ + _finished=true; + QStringList list=QStringList::split(",",s); + bool ok=true; + QStringList::Iterator it = list.begin(); + int x=(*it).toInt(&ok,10);it++; + int y=(*it).toInt(&ok,10);it++; + int rad=(*it).toInt(&ok,10); + if (!ok) return false; + QRect r; + r.setWidth(rad*2); + r.setHeight(rad*2); + r.moveCenter(QPoint(x,y)); + setRect(r); + return true; +} + +QString CircleArea::getHTMLCode() const { + QString retStr; + retStr+="setArea( *this ); + return areaClone; +} + +void PolyArea::draw(QPainter & p) +{ + drawHighlighting(p); + + p.setRasterOp(Qt::XorROP); + p.setPen(QPen(QColor("white"),1)); + if (_coords->count()==0) return; + + + + if (_finished) + p.drawPolygon ( *_coords,false,0,_coords->count()); + else + p.drawPolyline ( *_coords,0,_coords->count()); + +/* + p.moveTo(_coords->point(0)); + for (int i=1;i<_coords->count();i++) + p.lineTo(_coords->point(i)); + + if (_finished) + p.lineTo(_coords->point(0)); +*/ + Area::draw(p); +} + +QBitmap PolyArea::getMask() const +{ + QBitmap mask(_rect.width(),_rect.height()); + + mask.fill(Qt::color0); + QPainter p(&mask); + p.setBackgroundColor(Qt::color0); + p.setPen(Qt::color1); + p.setBrush(Qt::color1); + p.setClipping(true); + QRegion r(*_coords); + r.translate(-_rect.left(),-_rect.top()); + p.setClipRegion(r); + p.fillRect(QRect(0,0,_rect.width(),_rect.height()),Qt::color1); + p.flush(); + p.end(); + + return mask; +} + +QString PolyArea::coordsToString() const +{ + QString retStr; + + for (uint i=0;i<_coords->count();i++) { + retStr.append(QString("%1,%2,") + .arg(_coords->point(i).x()) + .arg(_coords->point(i).y())); + } + + retStr.remove(retStr.length()-1,1); + + return retStr; +} + +int PolyArea::distance(const QPoint &p1, const QPoint &p2) +{ + QPoint temp = p1-p2; + return temp.manhattanLength(); +} + +bool PolyArea::isBetween(const QPoint &p, const QPoint &p1, const QPoint &p2) +{ + int dist = distance(p,p1)+distance(p,p2)-distance(p1,p2); + + if (myabs(dist)<1) + return true; + else + return false; +} + +void PolyArea::simplifyCoords() +{ + if (_coords->size()<4) + return; + + QPoint p = _coords->point(0) - _coords->point(1); + + uint i = 1; + + + while( (i<_coords->size()) && (_coords->size() > 3) ) + { + p = _coords->point(i-1) - _coords->point(i); + + if (p.manhattanLength() < 3) + removeCoord(i); + else + i++; + } + + p = _coords->point(0) - _coords->point(1); + + double angle2; + double angle1; + + if (p.y()==0) + angle1 = 1000000000; + else + angle1 = (double) p.x() / (double) p.y(); + + i=2; + + while( (i<_coords->size()) && (_coords->size() > 3) ) + { + p = _coords->point(i-1) - _coords->point(i); + + if (p.y()==0) + angle2 = 1000000000; + else + angle2 = (double) p.x() / (double) p.y(); + + if ( angle2==angle1 ) + { + kdDebug() << "removing " << i-1 << endl; + removeCoord(i-1); + } + else + { + i++; + kdDebug() << "skipping " << i-1 << " cause " << angle1 << "!= " << angle2 << endl; + angle1 = angle2; + + } + + } + + + +} + + +int PolyArea::addCoord(const QPoint & p) +{ + if (_coords->size()<3) + { + return Area::addCoord(p); + } + + if (_coords->point(_coords->size()-1) == p) + { + kdDebug() << "equal Point added" << endl; + return -1; + + } + + int n=_coords->size(); + +// QPoint temp = p-_coords->point(0); + int nearest = 0; + int olddist = distance(p,_coords->point(0)); + int mindiff = 999999999; + + // find the two points, which are the nearest one to the new point + for (int i=1; i <= n; i++) + { + int dist = distance(p,_coords->point(i%n)); + int dist2 = distance(_coords->point(i-1),_coords->point(i%n)); + int diff = myabs(dist+olddist-dist2); + if ( diffcount() >2 ) { + QRegion r(*_coords); + return r.contains(p); + } + else + return false; +} + +void PolyArea::moveSelectionPoint(QRect* selectionPoint, const QPoint & p) +{ + selectionPoint->moveCenter(p); + + int i=0; + for (QRect *r=_selectionPoints->first();r!=0L;r=_selectionPoints->next()) { + if (r==selectionPoint) + break; + i++; + } + _coords->setPoint(i,p); + _rect=_coords->boundingRect(); +} + +void PolyArea::updateSelectionPoints() +{ + QRect *r; + r=_selectionPoints->first(); + + for (uint i=0;i<_coords->size();i++) + { + r->moveCenter(_coords->point(i)); + r=_selectionPoints->next(); + } + +} + +bool PolyArea::setCoords(const QString & s) +{ + _finished=true; + QStringList list=QStringList::split(",",s); + _coords=new QPointArray(); + _selectionPoints= new SelectionPointList(); + + for (QStringList::Iterator it = list.begin(); it !=list.end(); ++it) + { + bool ok=true; + int newXCoord=(*it).toInt(&ok,10); + if (!ok) return false; + it++; + if (it==list.end()) break; + int newYCoord=(*it).toInt(&ok,10); + if (!ok) return false; + insertCoord(_coords->size(), QPoint(newXCoord,newYCoord)); + } + + return true; + +} + +QString PolyArea::getHTMLCode() const { + QString retStr; + retStr+="resize(_coords->size()-1); + _selectionPoints->removeLast(); + _finished=b; +} + +QRect PolyArea::selectionRect() const +{ + QRect r = _rect; + + r.moveBy(-10,-10); + r.setSize(r.size()+QSize(21,21)); + + return r; +} + + + +/******************************************************************** + * DEFAULT + *******************************************************************/ + + +DefaultArea::DefaultArea() + : Area() +{ + _type=Area::Default; +} + +DefaultArea::~DefaultArea() { +} + +Area* DefaultArea::clone() const +{ + Area* areaClone = new DefaultArea(); + areaClone->setArea( *this ); + return areaClone; +} + +void DefaultArea::draw(QPainter &) +{} + + +QString DefaultArea::getHTMLCode() const { + QString retStr; + retStr+="add( it.current()->clone() ); + } + +// areaClone->setArea( *this ); + + return areaClone; +} + + +void AreaSelection::add(Area *a) +{ + + // if a selection of areas was added get the areas of it + AreaSelection *selection=0L; + if ( (selection = dynamic_cast ( a ) ) ) + { + AreaList list = selection->getAreaList(); + + for (Area* area = list.first(); area != 0L; area = list.next() ) + { + if ( _areas->find( area ) == -1 ) { + _areas->append( area ); // Must come before area->setSelected + area->setSelected( true ); + } + } + } + else + { + if ( _areas->find( a ) == -1 ) { + _areas->append( a ); // Must come before a->setSelected + a->setSelected( true ); + } + } + + invalidate(); +} + +void AreaSelection::remove(Area *a) +{ + if (_areas->find(a) == -1) + return; + + a->setSelected( false ); + _areas->remove( a ); + invalidate(); +} + +void AreaSelection::reset() +{ + AreaListIterator it=getAreaListIterator(); + + for ( ; it.current() != 0L; ++it ) + { + it.current()->setSelected( false ); + } + + _areas->clear(); + invalidate(); +} + +bool AreaSelection::contains(const QPoint & p) const +{ + bool b=false; + AreaListIterator it=getAreaListIterator(); + + for ( ; it.current() != 0L; ++it ) + { + if ( it.current()->contains( p ) ) + { + b=true; + break; + } + } + + return b; +} + +QRect* AreaSelection::onSelectionPoint(const QPoint & p, double zoom) const +{ + AreaListIterator it=getAreaListIterator(); + + if (it.count() != 1) + return 0L; + + QRect* retRect=0L; + + for ( ; it.current() != 0L; ++it ) + { + if ( (retRect = it.current()->onSelectionPoint( p , zoom) ) ) + { + break; + } + } + + return retRect; +} + +void AreaSelection::moveSelectionPoint(QRect* selectionPoint, const QPoint & p) +{ + // It's only possible to move a SelectionPoint if only one Area is selected + if (_areas->count() != 1) + return; + + _areas->getFirst()->moveSelectionPoint(selectionPoint,p); + + invalidate(); +} + + +void AreaSelection::moveBy(int dx, int dy) +{ + AreaListIterator it=getAreaListIterator(); + + for ( ; it.current() != 0L; ++it ) + it.current()->moveBy(dx,dy); + + Area::moveBy( dx, dy ); + + invalidate(); +} + +QString AreaSelection::typeString() const +{ + // if there is only one Area selected + // show the name of that Area + if ( _areas->count()==0 ) + return ""; + else if ( _areas->count()==1 ) + return _areas->getFirst()->typeString(); + else + return i18n("Number of Areas"); + +} + +Area::ShapeType AreaSelection::type() const +{ + // if there is only one Area selected + // take the type of that Area + if ( _areas->count()==0 ) + return Area::None; + else if ( _areas->count()==1 ) + return _areas->getFirst()->type(); + else + return Area::Selection; +} + +void AreaSelection::updateSelectionPoints() +{ + + AreaListIterator it=getAreaListIterator(); + + for ( ; it.current() != 0L; ++it ) + { + it.current()->updateSelectionPoints(); + } + + invalidate(); + +} + + + +QRect AreaSelection::selectionRect() const +{ + if (!_selectionCacheValid) + { + _selectionCacheValid=true; + QRect r; + AreaListIterator it=getAreaListIterator(); + + for ( ; it.current() != 0L; ++it ) + r = r | it.current()->selectionRect(); + + _cachedSelectionRect=r; + } + + return _cachedSelectionRect; +} + +uint AreaSelection::count() const { + return _areas->count(); +} + +bool AreaSelection::isEmpty() const +{ + return _areas->isEmpty(); +} + + +AreaList AreaSelection::getAreaList() const { + AreaList list(*_areas); + return list; +} + +AreaListIterator AreaSelection::getAreaListIterator() const { + AreaListIterator it(*_areas); + return it; +} + +void AreaSelection::setArea(const Area & copy) +{ + Area *area = copy.clone(); + AreaSelection *selection = dynamic_cast(area); + if (selection) + setAreaSelection(*selection); + else { + Area::setArea(copy); + invalidate(); + } +} + +void AreaSelection::setAreaSelection(const AreaSelection & copy) +{ + AreaListIterator it=getAreaListIterator(); + AreaListIterator it2=copy.getAreaListIterator(); + + if (it.count() != it2.count()) + return; + + for ( ; it.current() != 0L; ++it, ++it2 ) + it.current()->setArea(*it2.current()); + + Area::setArea(copy); + invalidate(); +} + +void AreaSelection::setAreaList( const AreaList & areas ) +{ + delete _areas; + _areas = new AreaList(areas); + invalidate(); +} + +void AreaSelection::setRect(const QRect & r) +{ + if ( _areas->count()==1 ) + { + _areas->getFirst()->setRect(r); + } + + invalidate(); + _rect=rect(); + updateSelectionPoints(); +} + +QRect AreaSelection::rect() const +{ + if (!_rectCacheValid) + { + _rectCacheValid=true; + QRect r; + AreaListIterator it=getAreaListIterator(); + + for ( ; it.current() != 0L; ++it ) + r = r | it.current()->rect(); + + _cachedRect=r; + } + + return _cachedRect; +} + + +int AreaSelection::addCoord(const QPoint & p) +{ + if ( _areas->count()==1 ) + { + return _areas->getFirst()->addCoord(p); + invalidate(); + } + + return 0; +} + +void AreaSelection::insertCoord(int pos, const QPoint & p) +{ + if ( _areas->count()==1 ) + { + _areas->getFirst()->insertCoord(pos, p); + invalidate(); + } +} + +void AreaSelection::removeCoord(int pos) +{ + if ( _areas->count()==1 ) + { + _areas->getFirst()->removeCoord(pos); + invalidate(); + } +} + +bool AreaSelection::removeSelectionPoint(QRect * r) +{ + bool result=false; + + if ( _areas->count()==1 ) + { + result = _areas->getFirst()->removeSelectionPoint(r); + invalidate(); + } + + return result; +} + +SelectionPointList* AreaSelection::selectionPoints() const +{ + if ( _areas->count()==1 ) + { + return _areas->getFirst()->selectionPoints(); + } + + return _selectionPoints; +} + + +void AreaSelection::moveCoord(int pos,const QPoint & p) +{ + if ( _areas->count()==1 ) + { + _areas->getFirst()->moveCoord(pos,p); + invalidate(); + } +} + +void AreaSelection::highlightSelectionPoint(int i) +{ + if ( _areas->count()==1 ) + { + _areas->getFirst()->highlightSelectionPoint(i); + invalidate(); + } +} + + +QPointArray* AreaSelection::coords() const +{ + if ( _areas->count()==1 ) + { + return _areas->getFirst()->coords(); + } + + return Area::coords(); +} + +QString AreaSelection::attribute(const QString & name) const +{ + if ( _areas->count()==1 ) + { + return _areas->getFirst()->attribute(name); + } + + return Area::attribute(name); +} + +void AreaSelection::setAttribute(const QString & name, const QString & value) +{ + AreaListIterator it=getAreaListIterator(); + + for ( ; it.current() != 0L; ++it ) + it.current()->setAttribute(name,value); + + Area::setAttribute(name,value); +} + +AttributeIterator AreaSelection::firstAttribute() const +{ + if ( _areas->count()==1 ) + { + return _areas->getFirst()->firstAttribute(); + } + + return _attributes.begin(); +} + +AttributeIterator AreaSelection::lastAttribute() const +{ + if ( _areas->count()==1 ) + { + return _areas->getFirst()->lastAttribute(); + } + + return _attributes.end(); +} + +void AreaSelection::setMoving(bool b) +{ + AreaListIterator it=getAreaListIterator(); + + for ( ; it.current() != 0L; ++it ) + it.current()->setMoving(b); + + Area::setMoving(b); +} + +bool AreaSelection::isMoving() const +{ + if ( _areas->count()==1 ) + { + return _areas->getFirst()->isMoving(); + } + + return Area::isMoving(); +} + + +/** + * Checks if an area is outside the rectangle parameter + * returns false if an area has no pixel in common with the rectangle parameter + **/ +bool AreaSelection::allAreasWithin(const QRect & r) const +{ + if ( ! r.contains(rect()) ) + { + AreaListIterator it=getAreaListIterator(); + + for ( ; it.current() != 0L; ++it ) + if (!it.current()->rect().intersects(r)) + return false; + } + + return true; +} + + +void AreaSelection::draw(QPainter &) +{} + + diff --git a/kimagemapeditor/kimearea.h b/kimagemapeditor/kimearea.h new file mode 100644 index 00000000..581bba94 --- /dev/null +++ b/kimagemapeditor/kimearea.h @@ -0,0 +1,392 @@ +/*************************************************************************** + kimearea.h - description + ------------------- + begin : Thu Jun 14 2001 + copyright : (C) 2001 by Jan Schäfer + email : janschaefer@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KIMEAREA_H +#define KIMEAREA_H + +#include +#include +#include +#include +#include + +#include "kdeversion.h" + +class QPainter; +class QPointArray; +class QListViewItem; +class QBitmap; + +typedef QPtrList SelectionPointList; + +typedef QMap AttributeMap; +typedef QMapConstIterator AttributeIterator; + + + +class Area +{ +public: + enum ShapeType { None, Rectangle, Circle, Polygon, Default, Selection }; + static bool highlightArea; + static bool showAlt; + +protected: + QRect _rect; + ShapeType _type; + QString _name; + QString _href; + QString _alt; + QString _target; + AttributeMap _attributes; + bool _isSelected; + bool _finished; + bool _isMoving; + int currentHighlighted; + QListViewItem* _listViewItem; + // Only used for Polygons + QPointArray *_coords; + SelectionPointList *_selectionPoints; + QPixmap *_highlightedPixmap; + + void drawHighlighting(QPainter & p); + void drawAlt(QPainter & p); + QString getHTMLAttributes() const; + +public: + Area(); + virtual ~Area(); + + virtual Area* clone() const; + // Default implementation; is specified by subclasses + virtual bool contains(const QPoint &) const; + // Default implementation; is specified by subclasses + virtual QString coordsToString() const; + virtual void draw(QPainter &); + + virtual QBitmap getMask() const; + virtual QString getHTMLCode() const; + + virtual void setHighlightedPixmap( QImage &, QBitmap &); + + virtual void moveBy(int, int); + virtual void moveTo(int, int); + virtual void moveSelectionPoint(QRect*, const QPoint &); + + virtual QRect* onSelectionPoint(const QPoint &,double zoom) const; + virtual bool removeSelectionPoint(QRect * r); + virtual SelectionPointList* selectionPoints() const { return _selectionPoints; } + + virtual QRect rect() const; + + virtual QRect selectionRect() const; + virtual void setArea(const Area &); + virtual bool setCoords(const QString &); + /** finished drawing only important for polygon */ + virtual void setFinished(bool b) { _finished=b; } + virtual void setRect(const QRect &); + virtual void setMoving(bool b); + virtual bool isMoving() const; + // Default implementation; is specified by subclasses + virtual QString typeString() const { return ""; } + virtual ShapeType type() const; + + virtual void updateSelectionPoints() {}; + + // Only interesting for Polygons + virtual void simplifyCoords() {}; + virtual int addCoord(const QPoint &); + virtual void insertCoord(int, const QPoint &); + virtual void removeCoord(int); + virtual void moveCoord(int,const QPoint &); + virtual QPointArray* coords() const; + virtual void highlightSelectionPoint(int); + + virtual QString attribute(const QString &) const; + virtual void setAttribute(const QString &, const QString &); + virtual AttributeIterator firstAttribute() const; + virtual AttributeIterator lastAttribute() const; + + QPixmap cutOut(const QImage &) ; + void setListViewItem(QListViewItem*); + void deleteListViewItem(); + QListViewItem* listViewItem() const; + void setName(const QString &); + QString name() const; + void setSelected(bool b); + bool isSelected() const; + bool finished() const; + uint countSelectionPoints() const; + +}; + + + +inline QListViewItem* Area::listViewItem() const { + return _listViewItem; +} + +inline void Area::setName(const QString & name) { + _name=name; +} + +inline QString Area::name() const { + return _name; +} + +inline bool Area::isMoving() const { + return _isMoving; +} + + +inline bool Area::isSelected() const { + return _isSelected; +} + + +inline bool Area::finished() const { + return _finished; +} + +/** + * Represents a Rectangle Area + **/ +class RectArea : public Area +{ + public: + RectArea(); + virtual ~RectArea(); + + virtual Area* clone() const; + virtual bool contains(const QPoint & p) const; + virtual QString coordsToString() const; + virtual void draw(QPainter & p); + virtual void moveSelectionPoint(QRect* selectionPoint, const QPoint & p); + virtual bool setCoords(const QString & s); + virtual QString typeString() const { return i18n("Rectangle"); } + virtual QBitmap getMask() const; + virtual QString getHTMLCode() const; + virtual void updateSelectionPoints(); +}; + + +/** + * Represents a Circle Area + **/ +class CircleArea : public Area +{ + public: + CircleArea(); + virtual ~CircleArea(); + + virtual Area* clone() const; + virtual bool contains(const QPoint & p) const; + virtual QString coordsToString() const; + virtual void draw(QPainter & p); + virtual void moveSelectionPoint(QRect* selectionPoint, const QPoint & p); + virtual bool setCoords(const QString & s); + virtual void setRect(const QRect & r); + virtual QString typeString() const { return i18n("Circle"); } + virtual QBitmap getMask() const; + virtual QString getHTMLCode() const; + virtual void updateSelectionPoints(); + +}; + +/** + * Represents a Rectangle Area + **/ +class PolyArea :public Area +{ + public: + PolyArea(); + virtual ~PolyArea(); + + virtual Area* clone() const; + virtual bool contains(const QPoint & p) const; + virtual QString coordsToString() const; + virtual void draw(QPainter & p); + virtual void moveSelectionPoint(QRect* selectionPoint, const QPoint & p); + virtual void simplifyCoords(); + virtual int addCoord(const QPoint & p); + virtual bool setCoords(const QString & s); + virtual QRect selectionRect() const; + virtual void setFinished(bool b); + virtual QString typeString() const { return i18n("Polygon"); } + virtual QBitmap getMask() const; + virtual QString getHTMLCode() const; + virtual void updateSelectionPoints(); + + private: + static int distance(const QPoint &p1, const QPoint &p2); + static bool isBetween(const QPoint &p, const QPoint &p1, const QPoint &p2); + +}; + +/** + * Represents the default Area + **/ +class DefaultArea :public Area +{ + public: + DefaultArea(); + virtual ~DefaultArea(); + + virtual Area* clone() const; + // the default area isn't drawn + virtual void draw(QPainter & p); + virtual QString typeString() const { return i18n("Default"); } + virtual QString getHTMLCode() const; + +}; + + +typedef QPtrList AreaList; +typedef QPtrListIterator AreaListIterator; + +/** + * This class represents a selection of areas + * all operations performed on this class + * will be performed on the selected Areas + * the only actions that can be used is the + * move action + **/ +class AreaSelection : public Area { + public : + AreaSelection(); + virtual ~AreaSelection(); + + /** + * New Methods + */ + + // Adding automatically selects the area + void add(Area *a); + + // Removing automatically deselects the area + void remove(Area *a); + + // Removes all areas from the list and deselects them + void reset(); + + uint count() const; + + AreaList getAreaList() const; + AreaListIterator getAreaListIterator() const; + void setAreaList( const AreaList & areas ); + + bool isEmpty() const; + + /** + * Overiden Methods of the Area class + */ + virtual bool contains(const QPoint & p) const; + + /** + * + **/ + virtual QRect* onSelectionPoint(const QPoint & p, double zoom) const; + + /** + * Only if one Area is selected the moveSelectionPoint method + * of that Area will be called + **/ + virtual void moveSelectionPoint(QRect* selectionPoint, const QPoint & p); + + virtual SelectionPointList* selectionPoints() const; + + /** + * All Areas will be moved by dx and dy + **/ + virtual void moveBy(int dx, int dy); + + /** + * Calls for every selected Area the setArea with the + * corresponding Area in the copy Selection. + * IMPORTANT : works only if the copy Area is an AreaSelection + * and have the same number of Areas + **/ + virtual void setArea(const Area & copy); + virtual void setAreaSelection(const AreaSelection & copy); + + /** + * If only one Area is selected the setRect method of that Area + * will be called + **/ + virtual void setRect(const QRect & r); + virtual QRect rect() const; + + + virtual QString typeString() const; + virtual ShapeType type() const; + + // The selection is only a container + // so it is never drawn + virtual void draw(QPainter & p); + + + /** + * A deep copy of the Areas + **/ + virtual Area* clone() const; + + virtual void updateSelectionPoints(); + virtual int addCoord(const QPoint & p); + virtual void insertCoord(int pos, const QPoint & p); + virtual void removeCoord(int pos); + virtual bool removeSelectionPoint(QRect * r); + virtual void moveCoord(int pos,const QPoint & p); + virtual QPointArray* coords() const; + virtual void highlightSelectionPoint(int); + + virtual QRect selectionRect() const; + + virtual QString attribute(const QString & name) const; + virtual void setAttribute(const QString & name, const QString & value); + virtual AttributeIterator firstAttribute() const; + virtual AttributeIterator lastAttribute() const; + + virtual void setMoving(bool b); + virtual bool isMoving() const; + + + bool allAreasWithin(const QRect & r) const; + + // makes the cache invalid + void invalidate(); + private : + + AreaList *_areas; + + // The selectionRect and the rect are cached + // so even in const functions they must be changeable + mutable QRect _cachedSelectionRect; + mutable QRect _cachedRect; + mutable bool _selectionCacheValid; + mutable bool _rectCacheValid; + +}; + + +inline void AreaSelection::invalidate() { + _selectionCacheValid=false; + _rectCacheValid=false; +} + +#endif + + diff --git a/kimagemapeditor/kimecommands.cpp b/kimagemapeditor/kimecommands.cpp new file mode 100644 index 00000000..e061a463 --- /dev/null +++ b/kimagemapeditor/kimecommands.cpp @@ -0,0 +1,384 @@ +/*************************************************************************** + kimecommands.cpp - description + ------------------- + begin : Fri May 25 2001 + copyright : (C) 2001 by Jan Schäfer + email : j_schaef@informatik.uni-kl.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +#include +#include +#include + +#include "kimagemapeditor.h" +#include "kimecommands.h" +#include "drawzone.h" + +CutCommand::CutCommand(KImageMapEditor * document, const AreaSelection & a) + : + +#if KDE_VERSION < 300 +KCommand +#else +KNamedCommand +#endif + (i18n( "Cut %1" ).arg( a.typeString() )) +{ + _document=document; + _cutAreaSelection=new AreaSelection(); + _cutAreaSelection->setAreaList( a.getAreaList() ); + _cutted=true; +} + + +CutCommand::~CutCommand() +{ + if (_cutted) + { + AreaList list = _cutAreaSelection->getAreaList(); + for ( Area *a=list.first(); a != 0; a=list.next() ) { + delete a; + } + } + + delete _cutAreaSelection; +} + +void CutCommand::execute() +{ + // The Area won't be really delete + // it only gets removed from the AreaList + _document->deleteArea(_cutAreaSelection ); + _document->updateActionAccess(); + _cutted=true; +} + +void CutCommand::unexecute() +{ + if (_document) { + _document->addArea( _cutAreaSelection ); + _document->select( _cutAreaSelection ); + _document->slotAreaChanged( _cutAreaSelection ); + _cutted=false; + } +} + +DeleteCommand::DeleteCommand(KImageMapEditor * document, const AreaSelection & a) + : CutCommand(document,a) +{ + setName(i18n( "Delete %1" ).arg( a.typeString() )); +} + +PasteCommand::PasteCommand(KImageMapEditor *document, const AreaSelection & a) + : +#if KDE_VERSION < 300 +KCommand +#else +KNamedCommand +#endif + (i18n( "Paste %1" ).arg( a.typeString() )) +{ + _document=document; + _pasteAreaSelection=new AreaSelection(); + _pasteAreaSelection->setAreaList( a.getAreaList() ); + _pasted=true; + _wasUndoed=false; +} + +PasteCommand::~PasteCommand () +{ + if ( ! _pasted ) { + AreaList list=_pasteAreaSelection->getAreaList(); + for (Area* a=list.first(); a != 0; a=list.next() ) { + delete a; + } + } + + delete _pasteAreaSelection; +} + +void PasteCommand::execute() +{ + _document->deselectAll(); + _document->addArea( _pasteAreaSelection ); + _document->select( _pasteAreaSelection ); + _document->slotAreaChanged( _pasteAreaSelection ); + _pasted=true; +} + +void PasteCommand::unexecute() +{ + _document->deleteArea(_pasteAreaSelection ); + _pasted=false; + _wasUndoed=true; +} + + +MoveCommand::MoveCommand (KImageMapEditor *document, AreaSelection * a, const QPoint & oldPoint) + : +#if KDE_VERSION < 300 +KCommand +#else +KNamedCommand +#endif +(i18n( "Move %1" ).arg( a->typeString() )) +{ + _document=document; + _areaSelection=new AreaSelection(); + _areaSelection->setAreaList( a->getAreaList() ); + _oldPoint.setX(oldPoint.x()); + _oldPoint.setY(oldPoint.y()); + + _newPoint.setX(a->rect().left()); + _newPoint.setY(a->rect().top()); +} + +MoveCommand::~MoveCommand () { + delete _areaSelection; +} + +void MoveCommand::execute() +{ + // only for repainting reasons + Area* tempArea = _areaSelection->clone(); + + _areaSelection->moveTo( _newPoint.x(), _newPoint.y() ); + + if (!_areaSelection->allAreasWithin(_document->getDrawZone()->getImageRect())) + _areaSelection->moveTo( _oldPoint.x(), _oldPoint.y() ); + + _document->selected()->invalidate(); + + + _document->slotAreaChanged( tempArea ); + _document->slotAreaChanged( _areaSelection ); + + delete tempArea; + +} + +void MoveCommand::unexecute() +{ + // only to erase the old Area + Area* tempArea = _areaSelection->clone(); + + _areaSelection->setMoving(true); + _areaSelection->moveTo( _oldPoint.x(), _oldPoint.y() ); + _areaSelection->setMoving(false); + + _document->selected()->invalidate(); + + _document->slotAreaChanged( tempArea ); + _document->slotAreaChanged( _areaSelection ); + + delete tempArea; + +} + + +ResizeCommand::ResizeCommand (KImageMapEditor *document, AreaSelection *a, Area *oldArea) + : +#if KDE_VERSION < 300 +KCommand +#else +KNamedCommand +#endif +(i18n( "Resize %1" ).arg( a->typeString() )) +{ + _areaSelection=new AreaSelection(); + _areaSelection->setAreaList( a->getAreaList() ); + + _newArea = a->clone(); + _oldArea = oldArea->clone(); + _document=document; +} + +ResizeCommand::~ResizeCommand () +{ + delete _newArea; + delete _oldArea; + delete _areaSelection; +} + +void ResizeCommand::execute() +{ + _areaSelection->setArea ( *_newArea); + _areaSelection->setMoving(false); + + _document->slotAreaChanged( _areaSelection ); + _document->slotAreaChanged( _oldArea ); + + +} + +void ResizeCommand::unexecute() +{ + _areaSelection->setArea ( *_oldArea); + _areaSelection->setMoving(false); + + _document->slotAreaChanged( _areaSelection ); + _document->slotAreaChanged( _newArea ); + +} + + + +AddPointCommand::AddPointCommand (KImageMapEditor *document, AreaSelection *a, const QPoint & p) + : +#if KDE_VERSION < 300 +KCommand +#else +KNamedCommand +#endif +(i18n( "Add point to %1" ).arg( a->typeString() )) +{ + if (a->type()!=Area::Polygon) + { + kdDebug() << "trying to add a point to a " << a->typeString() << endl; + return; + } + + _areaSelection=new AreaSelection(); + _areaSelection->setAreaList( a->getAreaList() ); + + _point = p; + _document=document; +} + +AddPointCommand::~AddPointCommand () +{ + delete _areaSelection; +} + +void AddPointCommand::execute() +{ + _coordpos = _areaSelection->addCoord(_point); + _areaSelection->setMoving(false); + + _document->slotAreaChanged( _areaSelection ); +} + +void AddPointCommand::unexecute() +{ +// QRect *selectionPoint = _areaSelection->onSelectionPoint(_point); + Area* repaintArea = _areaSelection->clone(); + + _areaSelection->removeCoord(_coordpos); + _areaSelection->setMoving(false); + + _document->slotAreaChanged( _areaSelection ); + _document->slotAreaChanged( repaintArea ); + + delete repaintArea; +} + +RemovePointCommand::RemovePointCommand (KImageMapEditor *document, AreaSelection *a, Area *oldArea) + : +#if KDE_VERSION < 300 +KCommand +#else +KNamedCommand +#endif +(i18n( "Remove point from %1" ).arg( a->typeString() )) +{ + if (a->type()!=Area::Polygon) + { + kdDebug() << "trying to remove a point to a " << a->typeString() << endl; + return; + } + + _areaSelection=new AreaSelection(); + _areaSelection->setAreaList( a->getAreaList() ); + + _newArea = a->clone(); + _oldArea = oldArea->clone(); + _document=document; +} + +RemovePointCommand::~RemovePointCommand () +{ + delete _newArea; + delete _oldArea; + delete _areaSelection; +} + +void RemovePointCommand::execute() +{ + _areaSelection->setArea ( *_newArea); + _areaSelection->setMoving(false); + + _document->slotAreaChanged( _areaSelection ); + _document->slotAreaChanged( _oldArea ); + + +} + +void RemovePointCommand::unexecute() +{ + _areaSelection->setArea ( *_oldArea); + _areaSelection->setMoving(false); + + _document->slotAreaChanged( _areaSelection ); + _document->slotAreaChanged( _newArea ); + +} + + + +CreateCommand::CreateCommand (KImageMapEditor *document, Area *area) + : +#if KDE_VERSION < 300 +KCommand +#else +KNamedCommand +#endif +(i18n( "Create %1" ).arg( area->typeString() )) +{ + _document=document; + _area=area; + _created=true; + _wasUndoed=false; + +} + +CreateCommand::~CreateCommand () +{ + if ( ! _created) + delete _area; +} + +void CreateCommand::execute() +{ + if (_document) { + + if ( _wasUndoed ) { + _document->addArea( _area ); + _document->deselectAll(); + _document->select( _area ); + _document->slotAreaChanged( _area ); + } + else + _document->addAreaAndEdit( _area ); + + _created=true; + } + +} + +void CreateCommand::unexecute() +{ + if (_document) { + _document->deleteArea( _area ); + _created=false; + _wasUndoed=true; + } + +} diff --git a/kimagemapeditor/kimecommands.h b/kimagemapeditor/kimecommands.h new file mode 100644 index 00000000..946c09b4 --- /dev/null +++ b/kimagemapeditor/kimecommands.h @@ -0,0 +1,198 @@ +/*************************************************************************** + kimecommands.h - description + ------------------- + begin : Fri May 25 2001 + copyright : (C) 2001 by Jan Schäfer + email : janschaefer@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KIMECOMMANDS_H +#define KIMECOMMANDS_H + + +#include + +#include + +class KImageMapEditor; +class AreaSelection; + + + +class CutCommand : public + +#if KDE_VERSION < 300 +KCommand +#else +KNamedCommand +#endif + +{ + public: + CutCommand (KImageMapEditor * document, const AreaSelection & selection); + virtual ~CutCommand(); + + virtual void execute(); + virtual void unexecute(); + + protected: + AreaSelection *_cutAreaSelection; + KImageMapEditor* _document; + bool _cutted; +}; + +/** + * Does the same like the cut command + * only have a different name in the Undo-History + **/ +class DeleteCommand : public CutCommand +{ + public : + DeleteCommand (KImageMapEditor * document, const AreaSelection & selection); +}; + +class PasteCommand : public +#if KDE_VERSION < 300 +KCommand +#else +KNamedCommand +#endif +{ + public: + PasteCommand (KImageMapEditor * document, const AreaSelection & selection); + ~PasteCommand (); + + virtual void execute(); + virtual void unexecute(); + + protected: + AreaSelection *_pasteAreaSelection; + KImageMapEditor* _document; + bool _pasted; + bool _wasUndoed; + +}; + +class MoveCommand : public +#if KDE_VERSION < 300 +KCommand +#else +KNamedCommand +#endif +{ + public: + MoveCommand (KImageMapEditor *document, AreaSelection *a,const QPoint & oldPoint); + ~MoveCommand (); + + virtual void execute(); + virtual void unexecute(); + + protected: + QPoint _newPoint; + QPoint _oldPoint; + + KImageMapEditor* _document; + AreaSelection *_areaSelection; +//- Area *_oldArea; +}; + +class ResizeCommand : public +#if KDE_VERSION < 300 +KCommand +#else +KNamedCommand +#endif +{ + public: + ResizeCommand (KImageMapEditor *document, AreaSelection *a, Area *oldArea); + ~ResizeCommand (); + + virtual void execute(); + virtual void unexecute(); + + protected: + + KImageMapEditor* _document; + AreaSelection *_areaSelection; + Area *_oldArea; + Area *_newArea; +}; + +class AddPointCommand : public +#if KDE_VERSION < 300 +KCommand +#else +KNamedCommand +#endif +{ + public: + AddPointCommand (KImageMapEditor *document, AreaSelection *a, const QPoint & p); + ~AddPointCommand (); + + virtual void execute(); + virtual void unexecute(); + + protected: + + KImageMapEditor* _document; + AreaSelection *_areaSelection; + QPoint _point; + int _coordpos; +}; + +class RemovePointCommand : public +#if KDE_VERSION < 300 +KCommand +#else +KNamedCommand +#endif +{ + public: + RemovePointCommand (KImageMapEditor *document, AreaSelection *a, Area *oldArea); + ~RemovePointCommand (); + + virtual void execute(); + virtual void unexecute(); + + protected: + + KImageMapEditor* _document; + AreaSelection *_areaSelection; + Area *_oldArea; + Area *_newArea; +}; + + +class CreateCommand : public +#if KDE_VERSION < 300 +KCommand +#else +KNamedCommand +#endif +{ + public: + CreateCommand (KImageMapEditor *document, Area *area); + ~CreateCommand (); + + virtual void execute(); + virtual void unexecute(); + + protected: + + KImageMapEditor* _document; + Area *_area; + bool _created; + bool _wasUndoed; +}; + + +#endif diff --git a/kimagemapeditor/kimecommon.h b/kimagemapeditor/kimecommon.h new file mode 100644 index 00000000..4cc2d59f --- /dev/null +++ b/kimagemapeditor/kimecommon.h @@ -0,0 +1,52 @@ +/*************************************************************************** + kimecommon.h - description + ------------------- + begin : Thu Apr 23 2002 + copyright : (C) 2002 by Jan Schäfer + email : janschaefer@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + + +#ifndef __KIMECOMMON_H__ +#define __KIMECOMMON_H__ + +inline int myabs(int i) { + if (i < 0) + return -i; + else + return i; +} + +inline double myabs(double i) { + if (i < 0) + return -i; + else + return i; +} + +inline int myround(double d) { + if ( (d-((int) d)) < 0.5 ) + return (int) d; + else + return ((int) d)+1; +} + +inline int roundUp(double d) +{ + if ( (d-((int) d)) == 0) + return (int) d; + else + return ((int) d)+1; +} + + +#endif diff --git a/kimagemapeditor/kimedialogs.cpp b/kimagemapeditor/kimedialogs.cpp new file mode 100644 index 00000000..27f104cb --- /dev/null +++ b/kimagemapeditor/kimedialogs.cpp @@ -0,0 +1,874 @@ +/*************************************************************************** + kimedialogs.cpp - description + ------------------- + begin : Tue Apr 17 2001 + copyright : (C) 2001 by Jan Schïż½er + email : j_schaef@informatik.uni-kl.de +***************************************************************************/ + +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +// QT +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +// KDE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// LOCAL +#include "kimedialogs.h" + +CoordsEdit::CoordsEdit(QWidget *parent, Area* a) + : QWidget(parent) +{ + area=a; +} + +void CoordsEdit::applyChanges() { + return; +} + +void CoordsEdit::slotTriggerUpdate() { + applyChanges(); + emit update(); +} + +CoordsEdit::~CoordsEdit() +{ +} + +RectCoordsEdit::RectCoordsEdit(QWidget *parent, Area* a) + : CoordsEdit(parent,a) +{ + QGridLayout *layout= new QGridLayout(this,5,2,5,5); + + topXSpin = new QSpinBox(this); + topXSpin->setMaxValue(INT_MAX); + topXSpin->setMinValue(0); + topXSpin->setValue(a->rect().left()); + layout->addWidget(topXSpin,0,1); + connect( topXSpin, SIGNAL(valueChanged(const QString &)), this, SLOT(slotTriggerUpdate())); + + QLabel *lbl= new QLabel(i18n("Top &X:"),this); + lbl->setBuddy(topXSpin); + layout->addWidget(lbl,0,0); + + topYSpin = new QSpinBox(this); + topYSpin->setMaxValue(INT_MAX); + topYSpin->setMinValue(0); + topYSpin->setValue(a->rect().top()); + layout->addWidget(topYSpin,1,1); + connect( topYSpin, SIGNAL(valueChanged(const QString &)), this, SLOT(slotTriggerUpdate())); + + lbl= new QLabel(i18n("Top &Y:"),this); + lbl->setBuddy(topYSpin); + layout->addWidget(lbl,1,0); + + widthSpin = new QSpinBox(this); + widthSpin->setMaxValue(INT_MAX); + widthSpin->setMinValue(0); + widthSpin->setValue(a->rect().width()); + layout->addWidget(widthSpin,2,1); + connect( widthSpin, SIGNAL(valueChanged(const QString &)), this, SLOT(slotTriggerUpdate())); + + lbl= new QLabel(i18n("&Width:"),this); + lbl->setBuddy(widthSpin); + layout->addWidget(lbl,2,0); + + heightSpin = new QSpinBox(this); + heightSpin->setMaxValue(INT_MAX); + heightSpin->setMinValue(0); + heightSpin->setValue(a->rect().height()); + layout->addWidget(heightSpin,3,1); + connect( heightSpin, SIGNAL(valueChanged(const QString &)), this, SLOT(slotTriggerUpdate())); + + lbl= new QLabel(i18n("Hei&ght:"),this); + lbl->setBuddy(heightSpin); + layout->addWidget(lbl,3,0); + + layout->setRowStretch(4,10); +} + +void RectCoordsEdit::applyChanges() { + QRect r; + r.setLeft(topXSpin->text().toInt()); + r.setTop(topYSpin->text().toInt()); + r.setWidth(widthSpin->text().toInt()); + r.setHeight(heightSpin->text().toInt()); + area->setRect(r); +} + +CircleCoordsEdit::CircleCoordsEdit(QWidget *parent, Area* a) + : CoordsEdit(parent,a) +{ + QGridLayout *layout= new QGridLayout(this,4,2,5,5); + + centerXSpin = new QSpinBox(this); + centerXSpin->setMaxValue(INT_MAX); + centerXSpin->setMinValue(0); + centerXSpin->setValue(a->rect().center().x()); + layout->addWidget(centerXSpin,0,1); + connect( centerXSpin, SIGNAL(valueChanged(const QString &)), this, SLOT(slotTriggerUpdate())); + + QLabel *lbl= new QLabel(i18n("Center &X:"),this); + lbl->setBuddy(centerXSpin); + layout->addWidget(lbl,0,0); + + centerYSpin = new QSpinBox(this); + centerYSpin->setMaxValue(INT_MAX); + centerYSpin->setMinValue(0); + centerYSpin->setValue(a->rect().center().y()); + layout->addWidget(centerYSpin,1,1); + connect( centerYSpin, SIGNAL(valueChanged(const QString &)), this, SLOT(slotTriggerUpdate())); + + + lbl= new QLabel(i18n("Center &Y:"),this); + lbl->setBuddy(centerYSpin); + layout->addWidget(lbl,1,0); + + radiusSpin = new QSpinBox(this); + radiusSpin->setMaxValue(INT_MAX); + radiusSpin->setMinValue(0); + radiusSpin->setValue(a->rect().width()/2); + layout->addWidget(radiusSpin,2,1); + connect( radiusSpin, SIGNAL(valueChanged(const QString &)), this, SLOT(slotTriggerUpdate())); + + + lbl= new QLabel(i18n("&Radius:"),this); + lbl->setBuddy(radiusSpin); + layout->addWidget(lbl,2,0); + + layout->setRowStretch(3,10); + +} + +void CircleCoordsEdit::applyChanges() { + QRect r; + r.setWidth(radiusSpin->text().toInt()*2); + r.setHeight(radiusSpin->text().toInt()*2); + r.moveCenter(QPoint(centerXSpin->text().toInt(), + centerYSpin->text().toInt())); + area->setRect(r); +} + +PolyCoordsEdit::PolyCoordsEdit(QWidget *parent, Area* a) + : CoordsEdit(parent,a) +{ + if (!a) return; + QVBoxLayout *layout= new QVBoxLayout(this); + int numPoints=a->coords()->count(); + coordsTable= new QTable(numPoints,2,this); + coordsTable->horizontalHeader()->setLabel(0,"X"); + coordsTable->horizontalHeader()->setLabel(1,"Y"); + coordsTable->verticalHeader()->hide(); + coordsTable->setLeftMargin(0); + coordsTable->setSelectionMode( QTable::Single ); + + + for (int i=0;isetText(i,0, QString::number(area->coords()->point(i).x()) ); + coordsTable->setText(i,1, QString::number(area->coords()->point(i).y()) ); + } + + connect( coordsTable, SIGNAL(currentChanged(int,int)), this, SLOT(slotHighlightPoint(int))); + +// coordsTable->setMinimumHeight(50); +// coordsTable->setMaximumHeight(400); +// coordsTable->resizeContents(100,100); + coordsTable->resize(coordsTable->width(),100); + layout->addWidget(coordsTable); + layout->setStretchFactor(coordsTable,-1); + QHBox *hbox= new QHBox(this); + QPushButton *addBtn=new QPushButton(i18n("Add"),hbox); + connect( addBtn, SIGNAL(pressed()), this, SLOT(slotAddPoint())); + QPushButton *removeBtn=new QPushButton(i18n("Remove"),hbox); + connect( removeBtn, SIGNAL(pressed()), this, SLOT(slotRemovePoint())); + + layout->addWidget(hbox); + slotHighlightPoint(1); +} + +PolyCoordsEdit::~PolyCoordsEdit() { + if (area) + area->highlightSelectionPoint(-1); +} + +void PolyCoordsEdit::slotHighlightPoint(int row) { + if (!area) return; + area->highlightSelectionPoint(row); + emit update(); +} + + +void PolyCoordsEdit::slotAddPoint() { + int newPos= coordsTable->currentRow(); + QPoint currentPoint=area->coords()->point(newPos); + area->insertCoord(newPos,currentPoint); + + int count=area->coords()->size(); + + coordsTable->setNumRows(count); + + for (int i=0;isetText(i,0, QString::number(area->coords()->point(i).x()) ); + coordsTable->setText(i,1, QString::number(area->coords()->point(i).y()) ); + } + + emit update(); +} + +void PolyCoordsEdit::slotRemovePoint() { + int currentPos= coordsTable->currentRow(); + + area->removeCoord(currentPos); + + int count=area->coords()->size(); + + coordsTable->setNumRows(count); + + for (int i=0;isetText(i,0, QString::number(area->coords()->point(i).x()) ); + coordsTable->setText(i,1, QString::number(area->coords()->point(i).y()) ); + } + + emit update(); +} + +void PolyCoordsEdit::applyChanges() { + int count=coordsTable->numRows(); + + for (int i=0;itext(i,0).toInt(), + coordsTable->text(i,1).toInt()); + + area->moveCoord(i,newPoint); + } +} + +SelectionCoordsEdit::SelectionCoordsEdit(QWidget *parent, Area* a) + : CoordsEdit(parent,a) +{ + QGridLayout *layout= new QGridLayout(this,2,2); + + topXSpin = new QSpinBox(this); + topXSpin->setMaxValue(INT_MAX); + topXSpin->setMinValue(0); + topXSpin->setValue(a->rect().left()); + layout->addWidget(topXSpin,0,1); + connect( topXSpin, SIGNAL(valueChanged(const QString &)), this, SLOT(slotTriggerUpdate())); + + QLabel *lbl= new QLabel(i18n("Top &X"),this); + lbl->setBuddy(topXSpin); + layout->addWidget(lbl,0,0); + + topYSpin = new QSpinBox(this); + topYSpin->setMaxValue(INT_MAX); + topYSpin->setMinValue(0); + topYSpin->setValue(a->rect().top()); + layout->addWidget(topYSpin,1,1); + connect( topYSpin, SIGNAL(valueChanged(const QString &)), this, SLOT(slotTriggerUpdate())); + + lbl= new QLabel(i18n("Top &Y"),this); + lbl->setBuddy(topYSpin); + layout->addWidget(lbl,1,0); +} + +void SelectionCoordsEdit::applyChanges() { + area->moveTo(topXSpin->text().toInt(), topYSpin->text().toInt()); +} + + + +QLineEdit* AreaDialog::createLineEdit(QWidget* parent, QGridLayout *layout, int y, const QString & value, const QString & name) +{ + QLineEdit* edit=new QLineEdit(value,parent); + layout->addWidget(edit,y,2); + QLabel* lbl=new QLabel(name,parent); + lbl->setBuddy(edit); + layout->addWidget(lbl,y,1); + + return edit; +} + +QWidget* AreaDialog::createGeneralPage() +{ + QFrame* page = new QFrame(this); + QGridLayout* layout = new QGridLayout(page,5,2,5,5); + + + QHBox *hbox= new QHBox(page); + hrefEdit = new QLineEdit(area->attribute("href"),hbox); + QPushButton *btn = new QPushButton("",hbox); + btn->setPixmap(SmallIcon("fileopen")); + connect( btn, SIGNAL(pressed()), this, SLOT(slotChooseHref())); + hbox->setMinimumHeight(hbox->height()); + + layout->addWidget(hbox,0,2); + QLabel *lbl=new QLabel(i18n( "&HREF:" ),page); + lbl->setBuddy(hrefEdit); + layout->addWidget(lbl,0,1); + + altEdit = createLineEdit(page,layout,1,area->attribute("alt"),i18n("Alt. &Text:")); + targetEdit = createLineEdit(page,layout,2,area->attribute("target"),i18n("Tar&get:")); + titleEdit = createLineEdit(page,layout,3,area->attribute("title"),i18n("Tit&le:")); + + if (area->type()==Area::Default) + { + defaultAreaChk = new QCheckBox(i18n("Enable default map"),page); + if (area->finished()) + defaultAreaChk->setChecked(true); + layout->addWidget(defaultAreaChk,3,2); + } + + + layout->setRowStretch(4,10); + + return page; +} + +QWidget* AreaDialog::createCoordsPage() +{ + QFrame* page = new QFrame(this); + QVBoxLayout *layout = new QVBoxLayout(page); + layout->setMargin(5); + + coordsEdit = createCoordsEdit(page,area); + layout->addWidget(coordsEdit); + connect( coordsEdit, SIGNAL(update()), this, SLOT(slotUpdateArea())); + + return page; +} + +QWidget* AreaDialog::createJavascriptPage() +{ + QFrame* page = new QFrame(this); + QGridLayout* layout = new QGridLayout(page,8,2,5,5); + + onClickEdit = createLineEdit(page,layout,0,area->attribute("onClick"),i18n("OnClick:")); + onDblClickEdit = createLineEdit(page,layout,1,area->attribute("onDblClick"),i18n("OnDblClick:")); + onMouseDownEdit = createLineEdit(page,layout,2,area->attribute("onMouseDown"),i18n("OnMouseDown:")); + onMouseUpEdit = createLineEdit(page,layout,3,area->attribute("onMouseUp"),i18n("OnMouseUp:")); + onMouseOverEdit = createLineEdit(page,layout,4,area->attribute("onMouseOver"),i18n("OnMouseOver:")); + onMouseMoveEdit = createLineEdit(page,layout,5,area->attribute("onMouseMove"),i18n("OnMouseMove:")); + onMouseOutEdit = createLineEdit(page,layout,6,area->attribute("onMouseOut"),i18n("OnMouseOut:")); + + layout->setRowStretch(7,10); + + + return page; +} + +QWidget* AreaDialog::createButtonBar() +{ + QHBox *box = new QHBox(this); + QWidget *spacer = new QWidget(box); + QPushButton *okBtn = new KPushButton(KStdGuiItem::ok(),box); + QPushButton *applyBtn = new KPushButton(KStdGuiItem::apply(),box); + QPushButton *cancelBtn = new KPushButton(KStdGuiItem::cancel(),box); + + connect(okBtn, SIGNAL(clicked()), this, SLOT(slotOk())); + connect(applyBtn, SIGNAL(clicked()), this, SLOT(slotApply())); + connect(cancelBtn, SIGNAL(clicked()), this, SLOT(slotCancel())); + + box->setSpacing(5); + box->setStretchFactor(spacer,10); + + okBtn->setDefault(true); + + return box; + +} + +AreaDialog::AreaDialog(KImageMapEditor* parent,Area * a) + : KDialog(parent->widget(),"",true) +// : KDialogBase(Tabbed,i18n("Area Tag Editor"),Ok|Apply|Cancel,Ok,parent,"") +// : KDialogBase(parent,"",true,"Area Tag Editor",Ok|Apply|Cancel,Ok,true) +{ + if (!a) { + slotCancel(); + return; + } + + _document=parent; + + setCaption(i18n("Area Tag Editor")); + + area=a; + QString shape="Default"; + areaCopy= a->clone(); + oldArea= new Area(); + oldArea->setRect( a->rect() ); + + switch (a->type()) { + case Area::Rectangle : shape=i18n("Rectangle");break; + case Area::Circle : shape=i18n("Circle");break; + case Area::Polygon : shape=i18n("Polygon");break; + case Area::Selection : shape=i18n("Selection");break; + default : break; + } + + + // To get a margin around everything + + QVBoxLayout *layout = new QVBoxLayout(this); + + layout->setMargin(5); + + QLabel *lbl = new QLabel(""+shape+"",this); + lbl->setTextFormat(Qt::RichText); + layout->addWidget(lbl); + + QFrame *line = new QFrame(this); + line->setFrameStyle(QFrame::HLine | QFrame::Sunken); + line->setFixedHeight(10); + layout->addWidget(line); + + QTabWidget *tab = new QTabWidget(this); + + layout->addWidget(tab); + + tab->addTab(createGeneralPage(),i18n("&General")); + + if (a->type()==Area::Default) + { + shape=i18n("Default"); + } + else + tab->addTab(createCoordsPage(),i18n("Coor&dinates")); + + tab->addTab(createJavascriptPage(),i18n("&JavaScript")); + + line = new QFrame(this); + line->setFrameStyle(QFrame::HLine | QFrame::Sunken); + line->setFixedHeight(10); + layout->addWidget(line); + + layout->addWidget(createButtonBar()); + + setMinimumHeight(360); + setMinimumWidth(327); + + resize(327,360); +} + +AreaDialog::~AreaDialog() { + delete areaCopy; + delete oldArea; +} + +CoordsEdit* AreaDialog::createCoordsEdit(QWidget *parent, Area *a) { + if (!a) return 0; + switch (a->type()) { + case Area::Rectangle : + return new RectCoordsEdit(parent,a); + break; + case Area::Circle : + return new CircleCoordsEdit(parent,a); + break; + case Area::Polygon : + return new PolyCoordsEdit(parent,a); + break; + case Area::Selection : + return new SelectionCoordsEdit(parent,a); + break; + case Area::Default : return new CoordsEdit(parent,a); break; + default : return new CoordsEdit(parent,a);break; + } +} + +void AreaDialog::slotChooseHref() { + KURL url=KFileDialog::getOpenURL(QString::null, "*|" + i18n( "All Files" ), this, i18n("Choose File")); + if (!url.isEmpty()) { + hrefEdit->setText(url.url()); + } +} + +void AreaDialog::slotOk() { + if (area) + { + area->highlightSelectionPoint(-1); + if (area->type()==Area::Default) + area->setFinished(defaultAreaChk->isChecked()); + } + slotApply(); + accept(); + +} + +void AreaDialog::slotApply() { + if (area) { + if (area->type()!=Area::Default) + coordsEdit->applyChanges(); + + area->setAttribute("href",hrefEdit->text()); + area->setAttribute("alt",altEdit->text()); + area->setAttribute("target",targetEdit->text()); + area->setAttribute("title",titleEdit->text()); + area->setAttribute("onclick",onClickEdit->text()); + area->setAttribute("ondblclick",onDblClickEdit->text()); + area->setAttribute("onmousedown",onMouseDownEdit->text()); + area->setAttribute("onmouseup",onMouseUpEdit->text()); + area->setAttribute("onmousemove",onMouseMoveEdit->text()); + area->setAttribute("onmouseover",onMouseOverEdit->text()); + area->setAttribute("onmouseout",onMouseOutEdit->text()); + + // redraw old area to get rid of it + emit areaChanged(oldArea); + // draw new area + emit areaChanged(area); + oldArea->setRect(area->rect()); + } +} + +void AreaDialog::slotCancel() { + if (area) { + AreaSelection *selection=0L; + if ( (selection=dynamic_cast(areaCopy)) ) + area->setArea(*selection); + else + area->setArea(*areaCopy); + area->highlightSelectionPoint(-1); + emit areaChanged(oldArea); + emit areaChanged(area); + } + reject(); +} + +void AreaDialog::slotUpdateArea() { + emit areaChanged(oldArea); + // draw new area + emit areaChanged(area); + oldArea->setRect(area->rect()); +} + +ImageMapChooseDialog::ImageMapChooseDialog(QWidget* parent,QPtrList *_maps,QPtrList *_images,const KURL & _baseUrl) + : KDialogBase(parent,"",true,i18n( "Choose Map & Image to Edit" ),Ok,Ok,true) +{ + baseUrl=_baseUrl; + maps=_maps; + images=_images; + currentMap=0L; + QWidget *page=new QWidget(this); + setMainWidget(page); + setCaption(baseUrl.fileName()); + QVBoxLayout *layout = new QVBoxLayout(page,5,5); + + QLabel *lbl= new QLabel(i18n("Select an image and/or a map that you want to edit"),page); + lbl->setFont(QFont("Sans Serif",12, QFont::Bold)); + layout->addWidget(lbl); + QFrame *line= new QFrame(page); + line->setFrameStyle(QFrame::HLine | QFrame::Sunken); + line->setFixedHeight(10); + layout->addWidget(line,0); + + QGridLayout *gridLayout= new QGridLayout(layout,2,3,5); + gridLayout->setRowStretch(0,0); + gridLayout->setRowStretch(1,100); + lbl=new QLabel(i18n("&Maps"),page); + mapListBox= new QListBox(page); + lbl->setBuddy(mapListBox); + gridLayout->addWidget(lbl,0,0); + gridLayout->addWidget(mapListBox,1,0); + + line= new QFrame(page); + line->setFrameStyle(QFrame::VLine | QFrame::Sunken); + line->setFixedWidth(10); +// line->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding)); + gridLayout->addWidget(line,1,1); + + lbl=new QLabel(i18n("Image Preview"),page); + gridLayout->addWidget(lbl,0,2); + + imagePreview= new QLabel(page); + imagePreview->setFixedSize(310,210); + imagePreview->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding)); + imagePreview->setFrameStyle(QLabel::Panel | QLabel::Sunken); + imagePreview->setIndent(5); + imagePreview->setBackgroundColor(QColor("white")); +// imagePreview->setLineWidth(2); +// imagePreview->setScaledContents(true); +// lbl= new QLabel(i18n("&Maps"),page); +// lbl->setBuddy(mapListBox); + gridLayout->addWidget(imagePreview,1,2); +// layout->addLayout(gridLayout,1); + + line= new QFrame(page); + line->setFrameStyle(QFrame::HLine | QFrame::Sunken); + line->setFixedHeight(10); + layout->addWidget(line,0); + + + if (maps->isEmpty()) { + mapListBox->insertItem(i18n("No maps found")); + mapListBox->setEnabled(false); + } + else { + for (MapTag *tag = maps->first(); tag!=0L; tag=maps->next()) { + mapListBox->insertItem(tag->name); + } + connect (mapListBox, SIGNAL(highlighted(int)), this, SLOT(slotMapChanged(int))); + } + + initImageListTable(page); + + if (! maps->isEmpty()) { + mapListBox->setCurrentItem(0); + slotMapChanged(0); + } + + resize(510,460); +} + +void ImageMapChooseDialog::initImageListTable(QWidget* parent) { + + + if (images->isEmpty()) { + imageListTable= new QTable(1,1,parent); + imageListTable->setText(0,0,i18n("No images found")); + imageListTable->setEnabled(false); + imageListTable->horizontalHeader()->hide(); + imageListTable->setTopMargin(0); + imageListTable->setColumnStretchable(0,true); + } else { + imageListTable= new QTable(images->count(),2,parent); + imageListTable->setColumnStretchable(0,true); + } + + imageListTable->verticalHeader()->hide(); + imageListTable->setLeftMargin(0); + + QLabel *lbl= new QLabel(i18n("&Images"),parent); + lbl->setBuddy(imageListTable); + + parent->layout()->add(lbl); + parent->layout()->add(imageListTable); + + if (images->isEmpty()) + return; + + imageListTable->horizontalHeader()->setLabel(0,i18n("Path")); + imageListTable->horizontalHeader()->setLabel(1,"usemap"); + + imageListTable->setSelectionMode(QTable::SingleRow); + imageListTable->setFocusStyle(QTable::FollowStyle); + imageListTable->clearSelection(true); + + + int row=0; + for (ImageTag *tag = images->first(); tag!=0L; tag=images->next()) { + QString src=""; + QString usemap=""; + if (tag->find("src")) + src=*tag->find("src"); + if (tag->find("usemap")) + usemap=*tag->find("usemap"); + + imageListTable->setText(row,0,src); + imageListTable->setText(row,1,usemap); + row++; + } + connect (imageListTable, SIGNAL(selectionChanged()), this, SLOT(slotImageChanged())); + + imageListTable->selectRow(0); + slotImageChanged(); + + +} + +ImageMapChooseDialog::~ImageMapChooseDialog() { +} + +void ImageMapChooseDialog::slotImageChanged() +{ + int i=imageListTable->currentRow(); + QImage pix; + if (images->at(i)->find("src")) { + QString str=*images->at(i)->find("src"); + // relative url + pixUrl=KURL(baseUrl,str); + pix=QImage(pixUrl.path()); + double zoom1=1; + double zoom2=1; + if (pix.width()>300) + zoom1=(double) 300/pix.width(); + if (pix.height()>200) + zoom2=(double) 200/pix.height(); + + + zoom1= zoom1 < zoom2 ? zoom1 : zoom2; + pix=pix.smoothScale((int)(pix.width()*zoom1),int(pix.height()*zoom1)); + } + QPixmap pix2; + pix2.convertFromImage(pix); + imagePreview->setPixmap(pix2); + +// imagePreview->repaint(); +} + +void ImageMapChooseDialog::selectImageWithUsemap(const QString & usemap) { + for (int i=0; inumRows(); i++) { + if (imageListTable->text(i,1)==usemap) { + imageListTable->selectRow(i); + slotImageChanged(); + return; + } + } +} + +void ImageMapChooseDialog::slotMapChanged(int i) { + currentMap=maps->at(i); + selectImageWithUsemap(currentMap->name); +} + +PreferencesDialog::PreferencesDialog(QWidget *parent, KConfig* conf) + : KDialogBase(parent,"",true,i18n("Preferences"),Ok|Apply|Cancel,Ok,true) +{ + config = conf; + QVBox *page=new QVBox(this); + page->setSpacing(6); + setMainWidget(page); + + QHBox *hbox= new QHBox(page); + + QLabel *lbl = new QLabel(i18n("&Maximum image preview height:")+" ",hbox); + rowHeightSpinBox = new QSpinBox(hbox); + lbl->setBuddy(rowHeightSpinBox); + + config->setGroup("Appearance"); + rowHeightSpinBox->setMaxValue(1000); + rowHeightSpinBox->setMinValue(15); + rowHeightSpinBox->setFixedWidth(60); + rowHeightSpinBox->setValue(config->readNumEntry("maximum-preview-height",50)); + + config->setGroup("General"); + + hbox= new QHBox(page); + lbl = new QLabel(i18n("&Undo limit:")+" ",hbox); + undoSpinBox = new QSpinBox(hbox); + undoSpinBox->setFixedWidth(60); + lbl->setBuddy(undoSpinBox); + + undoSpinBox->setMaxValue(100); + undoSpinBox->setMinValue(1); + undoSpinBox->setValue(config->readNumEntry("undo-level",20)); + + hbox= new QHBox(page); + lbl = new QLabel(i18n("&Redo limit:")+" ",hbox); + + redoSpinBox = new QSpinBox(hbox); + redoSpinBox->setFixedWidth(60); + redoSpinBox->setMaxValue(100); + redoSpinBox->setMinValue(1); + redoSpinBox->setValue(config->readNumEntry("redo-level",20)); + lbl->setBuddy(redoSpinBox); + + startWithCheck = new QCheckBox(i18n("&Start with last used document"),page); + startWithCheck->setChecked(config->readBoolEntry("start-with-last-used-document",true)); + +/* + hbox= new QHBox(page); + (void)new QLabel(i18n("Highlight Areas")+" ",hbox); + + colorizeAreaChk = new QCheckBox(hbox); + colorizeAreaChk->setFixedWidth(60); + colorizeAreaChk->setChecked(kapp->config()->readBoolEntry("highlightareas",true)); + + hbox= new QHBox(page); + (void)new QLabel(i18n("Show alternative text")+" ",hbox); + + showAltChk = new QCheckBox(hbox); + showAltChk->setFixedWidth(60); + showAltChk->setChecked(kapp->config()->readBoolEntry("showalt",true)); +*/ +} + +PreferencesDialog::~PreferencesDialog() { +} + +void PreferencesDialog::slotDefault( void ) { + rowHeightSpinBox->setValue(50); +} + +void PreferencesDialog::slotOk( void ) { + slotApply(); + accept(); +} + +void PreferencesDialog::slotApply( void ) { + config->setGroup("Appearance"); + config->writeEntry("maximum-preview-height",rowHeightSpinBox->cleanText().toInt()); + + config->setGroup("General Options"); + config->writeEntry("undo-level",undoSpinBox->cleanText().toInt()); + config->writeEntry("redo-level",redoSpinBox->cleanText().toInt()); + config->writeEntry("start-with-last-used-document", startWithCheck->isChecked()); + + config->sync(); + emit applyClicked(); +} + +HTMLPreviewDialog::HTMLPreviewDialog(QWidget* parent, KURL url, const QString & htmlCode) + : KDialogBase(parent, "", true, i18n("Preview"), KDialogBase::Ok) +{ + tempFile = new KTempFile(url.directory(false), ".html"); + tempFile->setAutoDelete(true); + (*tempFile->textStream()) << htmlCode; + kdDebug() << "HTMLPreviewDialog: TempFile : " << tempFile->name() << endl; + tempFile->close(); + + QVBox *page = makeVBoxMainWidget(); + + htmlPart = new KHTMLPart(page,"htmlpart"); +// htmlView = new KHTMLView(htmlPart, page); +// htmlView->setVScrollBarMode(QScrollView::Auto); +// htmlView->setHScrollBarMode(QScrollView::Auto); +// dialog->resize(dialog->calculateSize(edit->maxLineWidth(),edit->numLines()*)); +// dialog->adjustSize(); + QLabel* lbl = new QLabel(page,"urllabel"); + + connect( htmlPart, SIGNAL( onURL(const QString&)), lbl, SLOT( setText(const QString&))); +} + +HTMLPreviewDialog::~HTMLPreviewDialog() { + delete tempFile; + delete htmlPart; +} + +void HTMLPreviewDialog::show() { + KDialogBase::show(); + htmlPart->openURL(KURL( tempFile->name() )); +// htmlView->layout(); +// htmlView->repaint(); + resize(800,600); +} + +#include "kimedialogs.moc" diff --git a/kimagemapeditor/kimedialogs.h b/kimagemapeditor/kimedialogs.h new file mode 100644 index 00000000..c87f8dfe --- /dev/null +++ b/kimagemapeditor/kimedialogs.h @@ -0,0 +1,207 @@ +/*************************************************************************** + kimedialogs.h - description + ------------------- + begin : Tue Apr 17 2001 + copyright : (C) 2001 by Jan Schäfer + email : janschaefer@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KIMEDIALOGS_H +#define KIMEDIALOGS_H + +#include +#include + +#include +#include "kimagemapeditor.h" + +#include "kdeversion.h" + +class QLineEdit; +class QMultiLineEdit; +class QSpinBox; + + +class CoordsEdit : public QWidget { +Q_OBJECT + public : + CoordsEdit(QWidget *parent, Area* a); + virtual ~CoordsEdit(); + virtual void applyChanges(); + protected: + Area *area; // The working area + protected slots: + void slotTriggerUpdate(); + signals: + void update(); +}; + +class RectCoordsEdit : public CoordsEdit { + public: + RectCoordsEdit(QWidget *parent, Area* a); + virtual void applyChanges(); + private: + QSpinBox *topXSpin; + QSpinBox *topYSpin; + QSpinBox *widthSpin; + QSpinBox *heightSpin; +}; + +class CircleCoordsEdit : public CoordsEdit { + public: + CircleCoordsEdit(QWidget *parent, Area* a); + virtual void applyChanges(); + private: + QSpinBox *centerXSpin; + QSpinBox *centerYSpin; + QSpinBox *radiusSpin; +}; + +class QTable; + +class PolyCoordsEdit : public CoordsEdit { +Q_OBJECT + public: + PolyCoordsEdit(QWidget *parent, Area* a); + ~PolyCoordsEdit(); + virtual void applyChanges(); + private: + QTable *coordsTable; + protected slots: + void slotAddPoint(); + void slotRemovePoint(); + void slotHighlightPoint(int); + +}; + +class SelectionCoordsEdit : public CoordsEdit { +Q_OBJECT + public: + SelectionCoordsEdit(QWidget *parent, Area* a); + virtual void applyChanges(); + private: + QSpinBox *topXSpin; + QSpinBox *topYSpin; + +}; + + +class QCheckBox; +class QGridLayout; + +class AreaDialog : public KDialog { +Q_OBJECT + private: + Area *area; + Area *oldArea; // Only for drawing reasons + Area *areaCopy; // A copy for restoring the original area if user press cancel + QLineEdit *hrefEdit; + QLineEdit *altEdit; + QLineEdit *targetEdit; + QLineEdit *titleEdit; + + QLineEdit *onClickEdit; + QLineEdit *onDblClickEdit; + QLineEdit *onMouseDownEdit; + QLineEdit *onMouseUpEdit; + QLineEdit *onMouseOverEdit; + QLineEdit *onMouseMoveEdit; + QLineEdit *onMouseOutEdit; + + CoordsEdit *coordsEdit; + CoordsEdit* createCoordsEdit(QWidget *parent, Area *a); + QCheckBox *defaultAreaChk; + KImageMapEditor *_document; + + + public: + AreaDialog(KImageMapEditor* parent,Area * a); + ~AreaDialog(); + protected slots: + virtual void slotOk(); + virtual void slotApply(); + virtual void slotCancel(); + void slotChooseHref(); + void slotUpdateArea(); + + QLineEdit* createLineEdit(QWidget* parent, QGridLayout *layout, int y, const QString & value, const QString & name); + QWidget* createGeneralPage(); + QWidget* createCoordsPage(); + QWidget* createJavascriptPage(); + QWidget* createButtonBar(); + signals: + void areaChanged(Area* a); +}; + +class QLineEdit; +class QListBox; +class QLabel; + + +class ImageMapChooseDialog : public KDialogBase { +Q_OBJECT + private: + QTable *imageListTable; + QLabel *imagePreview; + QListBox *mapListBox; + QLineEdit *mapNameEdit; + QPtrList *maps; + QPtrList *images; + KURL baseUrl; + void initImageListTable(QWidget*); + public: + ImageMapChooseDialog(QWidget* parent,QPtrList *_maps,QPtrList *_images, const KURL & _baseUrl); + ~ImageMapChooseDialog(); + KURL pixUrl; + MapTag* currentMap; + protected slots: + void slotImageChanged(); + void slotMapChanged(int i); + void selectImageWithUsemap(const QString & usemap); + +}; + +class KConfig; + +class PreferencesDialog : public KDialogBase { +Q_OBJECT + public: + PreferencesDialog(QWidget *parent,KConfig*); + ~PreferencesDialog(); + protected slots: + virtual void slotDefault( void ); + virtual void slotOk( void ); + virtual void slotApply( void ); + private: + QSpinBox *rowHeightSpinBox; + QSpinBox *undoSpinBox; + QSpinBox *redoSpinBox; +// QCheckBox *colorizeAreaChk; +// QCheckBox *showAltChk; + QCheckBox *startWithCheck; + KConfig *config; +}; + +class KHTMLPart; +class KTempFile; + +class HTMLPreviewDialog : public KDialogBase { + public: + HTMLPreviewDialog(QWidget *, KURL, const QString &); + ~HTMLPreviewDialog(); + virtual void show(); + private: + KHTMLPart* htmlPart; + KTempFile* tempFile; +}; + +#endif diff --git a/kimagemapeditor/kimeshell.cpp b/kimagemapeditor/kimeshell.cpp new file mode 100644 index 00000000..d919d2b7 --- /dev/null +++ b/kimagemapeditor/kimeshell.cpp @@ -0,0 +1,296 @@ +/*************************************************************************** + kimepart.cpp - description + ------------------- + begin : Mon Aug 5 2002 + copyright : (C) 2002 by Jan Schïż½er + email : janschaefer@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "drawzone.h" +#include "kimagemapeditor.h" // the KPart +#include "kimeshell.h" +#include "kimeshell.moc" + +KimeShell::KimeShell(const char *name ) + : KParts::DockMainWindow( 0L, name ) +{ + setXMLFile("kimagemapeditorui.rc"); + + + KDockWidget* mainDock; + mainDock = createDockWidget( "MainDockWidget", 0L, 0L, "main_dock_widget"); + QWidget *w = new QHBox( mainDock ); +// QLayout* layout = new QGridLayout( mainDock ); + + mainDock->setWidget( w ); + // allow others to dock to the 4 sides + mainDock->setDockSite(KDockWidget::DockCorner); + // forbit docking abilities of mainDock itself + mainDock->setEnableDocking(KDockWidget::DockNone); + setView( mainDock); // central widget in a KDE mainwindow + setMainDockWidget( mainDock); // master dockwidget + m_part = new KImageMapEditor( w, "kimagemapeditor", this, "kimagemapeditor"); + + +// setCentralWidget( part->widget() ); + + setupActions(); + + _stdout=false; + +// createGUI( part ); + createShellGUI( true ); + guiFactory()->addClient( m_part ); + KParts::GUIActivateEvent ev( true ); + QApplication::sendEvent( m_part, &ev ); + //setCentralWidget(part->widget()); + + if (!initialGeometrySet()) + resize( QSize(725, 525).expandedTo(minimumSizeHint())); + + connect( m_part, SIGNAL(setStatusBarText(const QString &)), + this, SLOT(slotSetStatusBarText ( const QString & ))); + + connect( m_part, SIGNAL(setWindowCaption(const QString &)), + this, SLOT(setCaption( const QString &))); + + setAutoSaveSettings( "General Options" ); + +} + +KimeShell::~KimeShell() +{ +// delete part; +} + +bool KimeShell::queryClose() +{ + if (_stdout) { + std::cout << m_part->getHtmlCode() << std::endl; + } + + return m_part->queryClose(); +} + + +bool KimeShell::queryExit() +{ +// writeConfig(); + saveProperties(kapp->config()); + + return true; +} + + +void KimeShell::setupActions() +{ + (void)KStdAction::openNew(this, SLOT(fileNew()), actionCollection()); + + // File Quit + (void)KStdAction::quit(this, SLOT(close()),actionCollection()); + + + (void)KStdAction::showToolbar(this, SLOT(optionsShowToolbar()), actionCollection()); + (void)KStdAction::keyBindings(this, SLOT(optionsConfigureKeys()), actionCollection()); + (void)KStdAction::configureToolbars(this, SLOT(optionsConfigureToolbars()), actionCollection()); + (void)KStdAction::showStatusbar(this, SLOT(optionsShowStatusbar()), actionCollection()); + + +} + +void KimeShell::fileNew() +{ + // this slot is called whenever the File->New menu is selected, + // the New shortcut is pressed (usually CTRL+N) or the New toolbar + // button is clicked + + // About this function, the style guide ( + // http://developer.kde.org/documentation/standards/kde/style/basics/index.html ) + // says that it should open a new window if the document is _not_ + // in its initial state. This is what we do here.. + if ( ! m_part->url().isEmpty() || m_part->isModified() ) + { + KimeShell * newShell = new KimeShell(); + + newShell->show(); + newShell->readConfig(); + }; +} + +void KimeShell::openFile(const KURL & url) +{ + m_part->openFile(url); +} + +void KimeShell::openLastFile() +{ + if (m_part->config()->readBoolEntry("start-with-last-used-document",true)) + m_part->openLastURL(m_part->config()); +} + +void KimeShell::fileOpen() +{ + KURL url=KFileDialog::getOpenURL(QString::null, + "*.png *.jpg *.jpeg *.gif *.htm *.html|" + i18n( "Web Files" ) + "\n" + "*.png *.jpg *.jpeg *.gif *.bmp *.xbm *.xpm *.pnm *.mng|" + i18n( "Images" ) + "\n" + "*.htm *.html|" + i18n( "HTML Files" ) + "\n" + "*.png|" + i18n( "PNG Images" ) + "\n*.jpg *.jpeg|" + i18n( "JPEG Images" ) + "\n*.gif|" + i18n( "GIF Images" ) + "\n*|" + i18n( "All Files" ) + ,this,i18n("Choose Picture to Open")); + + if (!url.isEmpty()) { + // About this function, the style guide ( + // http://developer.kde.org/documentation/standards/kde/style/basics/index.html ) + // says that it should open a new window if the document is _not_ + // in its initial state. This is what we do here.. + if ( m_part->url().isEmpty() && ! m_part->isModified() ) + { + // we open the file in this window... + m_part->openURL(url); + } + else + { + // we open the file in a new window... + KimeShell* newWin = new KimeShell; + newWin->openFile( url ); + newWin->show(); + } + } +} + + + +void KimeShell::readConfig() { + KConfig *config; + + config = kapp->config(); + + config->setGroup("General Options"); + readConfig(config); + +} + +void KimeShell::readConfig(KConfig* config) { +// applyMainWindowSettings(config); +// restoreWindowSize(config); + readDockConfig(config); +} + +void KimeShell::writeConfig() { + KConfig *config; + + config = kapp->config(); + + config->setGroup("General Options"); + writeConfig(config); +} + +void KimeShell::writeConfig(KConfig* config) { + saveMainWindowSettings(config); + saveWindowSize(config); + writeDockConfig(config); + config->sync(); + +} + + +void KimeShell::saveProperties(KConfig *config) +{ + //writeConfig(config); + m_part->saveProperties(config); + writeConfig(); + +} + +void KimeShell::readProperties(KConfig *config) +{ + readConfig(); + m_part->readProperties(config); + + +} + + +void KimeShell::optionsConfigureKeys() { +// KKeyDialog::configureKeys(actionCollection(), "testprog_shell.rc"); + + KKeyDialog dlg; + dlg.insert(actionCollection()); + dlg.insert(m_part->actionCollection()); + dlg.configure(); +} + +void KimeShell::optionsConfigureToolbars() +{ +#if defined(KDE_MAKE_VERSION) +# if KDE_VERSION >= KDE_MAKE_VERSION(3,1,0) + saveMainWindowSettings(KGlobal::config(), autoSaveGroup()); +# else + saveMainWindowSettings(KGlobal::config() ); +# endif +#else + saveMainWindowSettings(KGlobal::config() ); +#endif + + // use the standard toolbar editor + KEditToolbar dlg(factory()); + connect(&dlg, SIGNAL(newToolbarConfig()), + this, SLOT(applyNewToolbarConfig())); + dlg.exec(); +} + +void KimeShell::applyNewToolbarConfig() +{ +#if defined(KDE_MAKE_VERSION) +# if KDE_VERSION >= KDE_MAKE_VERSION(3,1,0) + applyMainWindowSettings(KGlobal::config(), autoSaveGroup()); +# else + applyMainWindowSettings(KGlobal::config()); +# endif +#else + applyMainWindowSettings(KGlobal::config()); +#endif +} + + +void KimeShell::optionsShowToolbar() +{ + if (toolBar()->isVisible()) + toolBar()->hide(); + else + toolBar()->show(); +} + +void KimeShell::optionsShowStatusbar() +{ + if (statusBar()->isVisible()) + statusBar()->hide(); + else + statusBar()->show(); +} + + diff --git a/kimagemapeditor/kimeshell.h b/kimagemapeditor/kimeshell.h new file mode 100644 index 00000000..28026524 --- /dev/null +++ b/kimagemapeditor/kimeshell.h @@ -0,0 +1,81 @@ +/*************************************************************************** + kimeshell.h - description + ------------------- + begin : Mon Aug 5 2002 + copyright : (C) 2002 by Jan Schäfer + email : janschaefer@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KIMESHELL_H +#define KIMESHELL_H + +#include + +class KImageMapEditor; + +class KimeShell : public KParts::DockMainWindow +{ + Q_OBJECT + +public: + KimeShell( const char *name=0 ); + virtual ~KimeShell(); + + void setStdout(bool b); + void openFile(const KURL & url); + + /** + * Opens the last open file, if the + * user has configured to open the last + * file. Otherwise does nothing + */ + void openLastFile(); + void readConfig(); + void writeConfig(); + +protected: + void setupActions(); + void readConfig(KConfig*); + void writeConfig(KConfig*); + +// virtual bool queryClose(); + virtual void readProperties(KConfig *config); + virtual void saveProperties(KConfig *config); + + virtual bool queryClose(); + virtual bool queryExit(); + + +private slots: + void fileNew(); + void fileOpen(); + void optionsShowToolbar(); + void optionsShowStatusbar(); + void optionsConfigureKeys(); + void optionsConfigureToolbars(); + + void applyNewToolbarConfig(); +private: + KImageMapEditor *m_part; + + bool _stdout; // write HTML-Code to stdout on exit ? + + + +}; + +inline void KimeShell::setStdout(bool b) { + _stdout=b; +} + + +#endif diff --git a/kimagemapeditor/main.cpp b/kimagemapeditor/main.cpp new file mode 100644 index 00000000..626a6e44 --- /dev/null +++ b/kimagemapeditor/main.cpp @@ -0,0 +1,91 @@ +/*************************************************************************** + main.cpp - description + ------------------- + begin : Die Apr 10 19:46:49 CEST 2001 + copyright : (C) 2001 by Jan Schïż½er + email : j_schaef@informatik.uni-kl.de +***************************************************************************/ + +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#include +#include +#include +#include +#include + +#include "kimeshell.h" +#include + +static const char *description = + I18N_NOOP("An HTML imagemap editor"); + + +static KCmdLineOptions options[] = +{ + { "c", 0, 0 }, + { "stdout", I18N_NOOP("Write HTML-Code to stdout on exit"), 0 }, + { "+[File]", I18N_NOOP("File to open"), 0 }, + { 0, 0, 0 } + // INSERT YOUR COMMANDLINE OPTIONS HERE +}; + +int main(int argc, char *argv[]) +{ + + KAboutData aboutData( "kimagemapeditor", I18N_NOOP("KImageMapEditor"), + VERSION, description, KAboutData::License_GPL, + "(C) 2001-2008 Jan Schaefer", 0, "http://www.nongnu.org/kimagemap/", "janschaefer@users.sourceforge.net"); + aboutData.addAuthor("Jan Schaefer",0, "janschaefer@users.sourceforge.net"); + aboutData.addCredit("Joerg Jaspert",I18N_NOOP("For helping me with the Makefiles, and creating the Debian package")); + aboutData.addCredit("Aaron Seigo and Michael",I18N_NOOP("For helping me fixing --enable-final mode")); + aboutData.addCredit("Antonio Crevillen",I18N_NOOP("For the Spanish translation")); + aboutData.addCredit("Fabrice Mous",I18N_NOOP("For the Dutch translation")); + aboutData.addCredit("Germain Chazot",I18N_NOOP("For the French translation")); + KCmdLineArgs::init( argc, argv, &aboutData ); + KCmdLineArgs::addCmdLineOptions( options ); // Add our own options. + + KApplication a; + a.dcopClient()->registerAs(a.name()); + + + + if (a.isRestored()) + { + RESTORE(KimeShell); + } + else + { + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + if ( args->count() == 0 ) + { + KimeShell *kimeShell = new KimeShell(); + kimeShell->setStdout(args->isSet("stdout")); + kimeShell->readConfig(); + kimeShell->show(); + kimeShell->openLastFile(); + } + else + { + int i = 0; + for (; i < args->count(); i++ ) + { + KimeShell *kimeShell = new KimeShell(); + kimeShell->setStdout(args->isSet("stdout")); + kimeShell->readConfig(); + kimeShell->show(); + kimeShell->openFile(args->url(i)); + } + } + args->clear(); + } + + return a.exec(); +} diff --git a/kimagemapeditor/mapslistview.cpp b/kimagemapeditor/mapslistview.cpp new file mode 100644 index 00000000..ec89ae4a --- /dev/null +++ b/kimagemapeditor/mapslistview.cpp @@ -0,0 +1,174 @@ +/*************************************************************************** + mapslistview.cpp - description + ------------------- + begin : Weg Feb 26 2003 + copyright : (C) 2003 by Jan Schƒ?fer + email : janschaefer@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +// KDE +#include +#include +#include + +// locale +#include "mapslistview.h" + + +MapsListView::MapsListView(QWidget *parent, const char *name) +: QVBox(parent, name) { + _listView = new KListView(this); + _listView->addColumn(i18n("Maps")); + _listView->setFullWidth(true); + _listView->setSelectionMode(QListView::Single); + _listView->setItemsRenameable(true); + + connect( _listView, SIGNAL( selectionChanged(QListViewItem*)), + this, SLOT( slotSelectionChanged(QListViewItem*))); + + connect( _listView, SIGNAL( itemRenamed(QListViewItem*)), + this, SLOT( slotItemRenamed(QListViewItem*))); +} + + +MapsListView::~MapsListView() { +} + +void MapsListView::addMap(const QString & name = QString::null) { + new QListViewItem(_listView,name); + //kdDebug() << "MapsListView::addMap : Added map '" << name << "'" << endl; + +} + +void MapsListView::addMaps(QPtrList * maps) { + + for (MapTag *tag = maps->first(); tag!=0L; tag=maps->next()) { + addMap(tag->name); + } +} + +void MapsListView::selectMap(const QString & name) { + QListViewItem* item = _listView->findItem(name,0); + if (item) { + selectMap(item); + } else + kdWarning() << "MapsListView::selectMap : Couldn't found map '" << name << "'" << endl; + +} + +void MapsListView::selectMap(QListViewItem* item) { + if (item) + _listView->setSelected(item,true); +} + + +QString MapsListView::selectedMap() { + QString result; + + QListViewItem* item = _listView->selectedItem(); + if (item) + result = item->text(0); + else + kdWarning() << "MapsListView::selectedMap : No map selected !" << endl; + + return result; +} + +void MapsListView::removeMap(const QString & name) { + QListViewItem* item = _listView->findItem(name,0); + if (item) { + _listView->takeItem(item); + _listView->setSelected(_listView->currentItem(),true); +// kdDebug() << "MapsListView::removeMap : Removed map '" << name << "'" << endl; + } else + kdWarning() << "MapsListView::removeMap : Couldn't found map '" << name << "'" << endl; +} + +void MapsListView::clear() { + _listView->clear(); +} + +void MapsListView::slotSelectionChanged(QListViewItem* item) { + QString name = item->text(0); + emit mapSelected(name); +} + +void MapsListView::slotItemRenamed(QListViewItem* item) { + QString name = item->text(0); + emit mapRenamed(name); +} + +void MapsListView::changeMapName(const QString & oldName, const QString & newName) { +// kdDebug() << "MapsListView::changeMapName : " << oldName << " to " << newName << endl; + QListViewItem* item = _listView->findItem(oldName,0); + if (item) { + item->setText(0,newName); +// kdDebug() << "MapsListView::changeMapName : successful" << endl; + } + else { + kdWarning() << "MapsListView::changeMapName : Chouldn't find map with name '" << oldName << "'" << endl; + } + +} + + +bool MapsListView::nameAlreadyExists(const QString & name) { +// kdDebug() << "MapsListView::nameAlreadyExists : " << name << " ? " << endl; + bool result = false; + QListViewItem* item = 0L; + for(item = _listView->firstChild(); item; item = item->nextSibling()) { + QString otherMap = item->text(0); + if(name == otherMap) { + result = true; + break; + } + } + +// kdDebug() << "MapsListView::nameAlreadyExists : " << name << " : " << result << endl; + + return result; +} + +QStringList MapsListView::getMaps() { + QStringList result; + + QListViewItem* item = 0L; + for(item = _listView->firstChild(); item; item = item->nextSibling()) { + QString map = item->text(0); + result << map; + } + + return result; +} + +QString MapsListView::getUnusedMapName() { + QString result; + QString attempt; + int i=0; + while(result.isEmpty()) { + i++; + attempt = i18n("unnamed"); + attempt += QString::number(i); + if (nameAlreadyExists(attempt)) + continue; + + result = attempt; + } + +// kdDebug() << "MapsListView::getUnusedMapName : Found an unused name : '" << result << "'" << endl; + return result; +} + +uint MapsListView::count() { + return _listView->childCount(); +} + +#include "mapslistview.moc" diff --git a/kimagemapeditor/mapslistview.h b/kimagemapeditor/mapslistview.h new file mode 100644 index 00000000..559725a2 --- /dev/null +++ b/kimagemapeditor/mapslistview.h @@ -0,0 +1,126 @@ +/*************************************************************************** + mapslistview.h - description + ------------------- + begin : Weg Feb 26 2003 + copyright : (C) 2003 by Jan Schäfer + email : janschaefer@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef _MAPSLISTVIEW_H_ +#define _MAPSLISTVIEW_H_ + +#include + +#include "kimagemapeditor.h" +class KListView; + +/** + * Simple class that shows all map tags of the current open html file in a ListView + * + * Jan Schaefer + **/ +class MapsListView : public QVBox +{ +Q_OBJECT +public: + MapsListView(QWidget *parent, const char *name); + ~MapsListView(); + + /** + * Adds the given map to the ListView + */ + void addMap(const QString &); + + /** + * Adds all maps of the given QList to the ListView + */ + void addMaps(QPtrList *); + + /** + * Removes the given map from the ListView + */ + void removeMap(const QString &); + + /** + * Set the the given map selected in the ListView. + * it does not emit mapSelected afterwards. + */ + void selectMap(const QString &); + + /** + * Selects the given ListViewItem and deselects the current selected item + */ + void selectMap(QListViewItem* item); + + /** + * Changes the name of the map with the @p oldName to @p newName + */ + void changeMapName(const QString & oldName, const QString & newName); + + /** + * Returns the current selected map + */ + QString selectedMap(); + + + /** + * Removes all maps from the ListView + */ + void clear(); + + /** + * Returns a name for a map which is not used yet. + * Returns for example Unnamed1 + */ + QString getUnusedMapName(); + + /** + * Wether or not the given map name already exists + */ + bool nameAlreadyExists(const QString &); + + /** + * Returns a QStringList of all maps + */ + QStringList getMaps(); + + /** + * Returns the number of maps + */ + uint count(); + + KListView* listView() { return _listView; } +protected: + KListView* _listView; + +protected slots: + void slotSelectionChanged(QListViewItem*); + void slotItemRenamed(QListViewItem*); + +signals: + + /** + * Gets emitted when the user selects a map in + * the ListView + */ + void mapSelected(const QString &); + + + /** + * Emitted when the user has renamed a map in the ListView + */ + void mapRenamed(const QString & newName); + + +}; + +#endif diff --git a/kimagemapeditor/pics/Makefile.am b/kimagemapeditor/pics/Makefile.am new file mode 100644 index 00000000..4d7ead61 --- /dev/null +++ b/kimagemapeditor/pics/Makefile.am @@ -0,0 +1,8 @@ +KDE_ICON = kimagemapeditor + +appicondir = $(kde_datadir)/kimagemapeditor/icons +appicon_ICON = addpoint arrow circle circle2 freehand lower polygon raise rectangle removepoint + +picturesdir = $(kde_datadir)/kimagemapeditor +pictures_DATA = addpointcursor.png freehandcursor.png polygoncursor.png removepointcursor.png + diff --git a/kimagemapeditor/pics/addpointcursor.png b/kimagemapeditor/pics/addpointcursor.png new file mode 100644 index 00000000..0fe9f853 Binary files /dev/null and b/kimagemapeditor/pics/addpointcursor.png differ diff --git a/kimagemapeditor/pics/freehandcursor.png b/kimagemapeditor/pics/freehandcursor.png new file mode 100644 index 00000000..2f7f1163 Binary files /dev/null and b/kimagemapeditor/pics/freehandcursor.png differ diff --git a/kimagemapeditor/pics/hi16-app-kimagemapeditor.png b/kimagemapeditor/pics/hi16-app-kimagemapeditor.png new file mode 100644 index 00000000..cfdea0a0 Binary files /dev/null and b/kimagemapeditor/pics/hi16-app-kimagemapeditor.png differ diff --git a/kimagemapeditor/pics/hi22-action-addpoint.png b/kimagemapeditor/pics/hi22-action-addpoint.png new file mode 100644 index 00000000..51114fdf Binary files /dev/null and b/kimagemapeditor/pics/hi22-action-addpoint.png differ diff --git a/kimagemapeditor/pics/hi22-action-arrow.png b/kimagemapeditor/pics/hi22-action-arrow.png new file mode 100644 index 00000000..dfbeabaa Binary files /dev/null and b/kimagemapeditor/pics/hi22-action-arrow.png differ diff --git a/kimagemapeditor/pics/hi22-action-circle.png b/kimagemapeditor/pics/hi22-action-circle.png new file mode 100644 index 00000000..e0e616ce Binary files /dev/null and b/kimagemapeditor/pics/hi22-action-circle.png differ diff --git a/kimagemapeditor/pics/hi22-action-circle2.png b/kimagemapeditor/pics/hi22-action-circle2.png new file mode 100644 index 00000000..45394d3b Binary files /dev/null and b/kimagemapeditor/pics/hi22-action-circle2.png differ diff --git a/kimagemapeditor/pics/hi22-action-freehand.png b/kimagemapeditor/pics/hi22-action-freehand.png new file mode 100644 index 00000000..7ff9ce46 Binary files /dev/null and b/kimagemapeditor/pics/hi22-action-freehand.png differ diff --git a/kimagemapeditor/pics/hi22-action-lower.png b/kimagemapeditor/pics/hi22-action-lower.png new file mode 100644 index 00000000..18742bf0 Binary files /dev/null and b/kimagemapeditor/pics/hi22-action-lower.png differ diff --git a/kimagemapeditor/pics/hi22-action-polygon.png b/kimagemapeditor/pics/hi22-action-polygon.png new file mode 100644 index 00000000..66786d16 Binary files /dev/null and b/kimagemapeditor/pics/hi22-action-polygon.png differ diff --git a/kimagemapeditor/pics/hi22-action-raise.png b/kimagemapeditor/pics/hi22-action-raise.png new file mode 100644 index 00000000..3e2e1287 Binary files /dev/null and b/kimagemapeditor/pics/hi22-action-raise.png differ diff --git a/kimagemapeditor/pics/hi22-action-rectangle.png b/kimagemapeditor/pics/hi22-action-rectangle.png new file mode 100644 index 00000000..8ff0b2b7 Binary files /dev/null and b/kimagemapeditor/pics/hi22-action-rectangle.png differ diff --git a/kimagemapeditor/pics/hi22-action-removepoint.png b/kimagemapeditor/pics/hi22-action-removepoint.png new file mode 100644 index 00000000..065912bf Binary files /dev/null and b/kimagemapeditor/pics/hi22-action-removepoint.png differ diff --git a/kimagemapeditor/pics/hi32-app-kimagemapeditor.png b/kimagemapeditor/pics/hi32-app-kimagemapeditor.png new file mode 100644 index 00000000..cb7558c2 Binary files /dev/null and b/kimagemapeditor/pics/hi32-app-kimagemapeditor.png differ diff --git a/kimagemapeditor/pics/hi48-app-kimagemapeditor.png b/kimagemapeditor/pics/hi48-app-kimagemapeditor.png new file mode 100644 index 00000000..c95bd08c Binary files /dev/null and b/kimagemapeditor/pics/hi48-app-kimagemapeditor.png differ diff --git a/kimagemapeditor/pics/lo16-app-kimagemapeditor.png b/kimagemapeditor/pics/lo16-app-kimagemapeditor.png new file mode 100644 index 00000000..0985586b Binary files /dev/null and b/kimagemapeditor/pics/lo16-app-kimagemapeditor.png differ diff --git a/kimagemapeditor/pics/lo32-app-kimagemapeditor.png b/kimagemapeditor/pics/lo32-app-kimagemapeditor.png new file mode 100644 index 00000000..12542c8a Binary files /dev/null and b/kimagemapeditor/pics/lo32-app-kimagemapeditor.png differ diff --git a/kimagemapeditor/pics/polygoncursor.png b/kimagemapeditor/pics/polygoncursor.png new file mode 100644 index 00000000..e315aa51 Binary files /dev/null and b/kimagemapeditor/pics/polygoncursor.png differ diff --git a/kimagemapeditor/pics/removepointcursor.png b/kimagemapeditor/pics/removepointcursor.png new file mode 100644 index 00000000..91187d1d Binary files /dev/null and b/kimagemapeditor/pics/removepointcursor.png differ diff --git a/kimagemapeditor/qextfileinfo.cpp b/kimagemapeditor/qextfileinfo.cpp new file mode 100644 index 00000000..c52c48b5 --- /dev/null +++ b/kimagemapeditor/qextfileinfo.cpp @@ -0,0 +1,347 @@ +/* + From WebMaker - KDE HTML Editor + Copyright (C) 1998, 1999 Alexei Dets + + Rewritten for Quanta Plus: (C) 2002 Andras Mantia + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + + +//qt includes +#include +#include +#include +#include +#include +#include + +//kde includes +#include +#include +#include +#include +#include +#include +#include +#include + +//app includes +#include "qextfileinfo.h" + +QString QExtFileInfo::lastErrorMsg = ""; + +/** create a relative short url based in baseURL*/ +KURL QExtFileInfo::toRelative(const KURL& urlToConvert,const KURL& baseURL) +{ + KURL resultURL = urlToConvert; + if (urlToConvert.protocol() == baseURL.protocol()) + { + QString path = urlToConvert.path(); + QString basePath = baseURL.path(1); + if (path.startsWith("/")) + { + path.remove(0, 1); + basePath.remove(0, 1); + if ( basePath.right(1) != "/" ) basePath.append("/"); + + int pos=0; + int pos1=0; + for (;;) + { + pos=path.find("/"); + pos1=basePath.find("/"); + if ( pos<0 || pos1<0 ) break; + if ( path.left(pos+1 ) == basePath.left(pos1+1) ) + { + path.remove(0, pos+1); + basePath.remove(0, pos1+1); + } + else + break; + }; + + if ( basePath == "/" ) basePath=""; + int level = basePath.contains("/"); + for (int i=0; i=0 ) + { + cutname.remove( 0, pos+3 ); + cutdir.remove( cutdir.length()-1, 1 ); + cutdir.remove( cutdir.findRev('/')+1 , 1000); + } + resultURL.setPath(QDir::cleanDirPath(cutdir+cutname)); + } + + if (urlToConvert.path().endsWith("/")) resultURL.adjustPath(1); + return resultURL; +} + +/** All files in a dir. + The return will also contain the name of the subdirectories. + This is needed for empty directory adding/handling. (Andras) + Currently works only for local directories +*/ +KURL::List QExtFileInfo::allFiles( const KURL& path, const QString& mask) +{ + QExtFileInfo internalFileInfo; + return internalFileInfo.allFilesInternal(path, mask); +} + +KURL::List QExtFileInfo::allFilesRelative( const KURL& path, const QString& mask) +{ + QExtFileInfo internalFileInfo; + KURL::List r = internalFileInfo.allFilesInternal( path, mask); + + KURL::List::Iterator it; + for ( it = r.begin(); it != r.end(); ++it ) + { + *it = QExtFileInfo::toRelative( *it, path ); + } + + return r; +} + +bool QExtFileInfo::createDir( const KURL& path ) +{ + int i=0; + bool result; + KURL dir1, dir2 = KURL(); + while ( !exists(path) && dir2.path() != path.path() ) + { + dir1 = path; + dir2 = path; + + dir1=cdUp(dir1); + while ( !exists(dir1) && dir1.path() != "/" ) + { + dir1=cdUp(dir1); + dir2=cdUp(dir2); + // debug(d1); + } + // dir2.setPath(dir2.path(-1)); + result = KIO::NetAccess::mkdir(dir2, 0L, -1); + i++; + } + result = exists(path); + return result; +} + +KURL QExtFileInfo::cdUp(const KURL &url) +{ + KURL u = url; + QString dir = u.path(-1); + while ( !dir.isEmpty() && dir.right(1) != "/" ) + { + dir.remove( dir.length()-1,1); + } + u.setPath(dir); + return u; +} + +QString QExtFileInfo::shortName(const QString &fname) +{ + return fname.section("/",-1); +} + +KURL QExtFileInfo::path( const KURL &url ) +{ + return KURL( url.directory(false,false) ); +} + +KURL QExtFileInfo::home() +{ + KURL url; + url.setPath(QDir::currentDirPath()+"/"); + return url; +} + + +bool QExtFileInfo::exists(const KURL& a_url) +{ +// Andras: Don't use it now, as it brings up an extra dialog and need manual +// intervention when usign fish +// return KIO::NetAccess::exists(a_url, false); + +// No dialog when stating. + if ( a_url.isLocalFile() ) + { + return QFile::exists( a_url.path() ); + } else + { + QExtFileInfo internalFileInfo; + return internalFileInfo.internalExists(a_url); + } +} + +/* Synchronouse copy, like NetAccess::file_copy in KDE 3.2 */ +bool QExtFileInfo::copy( const KURL& src, const KURL& target, int permissions, + bool overwrite, bool resume, QWidget* window ) +{ + QExtFileInfo internalFileInfo; + return internalFileInfo.internalCopy( src, target, permissions, overwrite, resume, window ); +} + +/** No descriptions */ +KURL::List QExtFileInfo::allFilesInternal(const KURL& startURL, const QString& mask) +{ + dirListItems.clear(); + if (internalExists(startURL)) + { + lstFilters.setAutoDelete(true); + lstFilters.clear(); + // Split on white space + QStringList list = QStringList::split( ' ', mask ); + for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) + lstFilters.append( new QRegExp(*it, false, true ) ); + + bJobOK = true; + KIO::ListJob *job = KIO::listRecursive(startURL, false, true); + connect(job, SIGNAL(entries(KIO::Job *, const KIO::UDSEntryList&)), + this, SLOT(slotNewEntries(KIO::Job *, const KIO::UDSEntryList&))); + connect( job, SIGNAL( result (KIO::Job *) ), + this, SLOT( slotResult (KIO::Job *) ) ); + + // kdDebug(24000) << "Now listing: " << startURL.url() << endl; + enter_loop(); + lstFilters.clear(); + if (!bJobOK) + { + // kdDebug(24000) << "Error while listing "<< startURL.url() << endl; + dirListItems.clear(); + } + } + return dirListItems; +} + + +//Some hackery from KIO::NetAccess as they do not do exactly what we want +/* return true if the url exists*/ +bool QExtFileInfo::internalExists(const KURL& url) +{ + bJobOK = true; + // kdDebug(24000)<<"QExtFileInfo::internalExists"<setDetails(0); + job->setSide(false); //check the url for writing + connect( job, SIGNAL( result (KIO::Job *) ), + this, SLOT( slotResult (KIO::Job *) ) ); + + //To avoid lock-ups, start a timer. + QTimer::singleShot(10*1000, this,SLOT(slotTimeout())); +// kdDebug(24000)<<"QExtFileInfo::internalExists:before enter_loop"<setWindow (window); + connect( job, SIGNAL( result (KIO::Job *) ), + this, SLOT( slotResult (KIO::Job *) ) ); + + enter_loop(); + return bJobOK; +} + + +void qt_enter_modal( QWidget *widget ); +void qt_leave_modal( QWidget *widget ); + +void QExtFileInfo::enter_loop() +{ + QWidget dummy(0,0,WType_Dialog | WShowModal); + dummy.setFocusPolicy( QWidget::NoFocus ); + qt_enter_modal(&dummy); +// kdDebug(24000)<<"QExtFileInfo::enter_loop:before qApp->enter_loop()"<enter_loop(); +// kdDebug(24000)<<"QExtFileInfo::enter_loop:after qApp->enter_loop()"<error(); + if ( !bJobOK ) + { + if ( !lastErrorMsg ) + lastErrorMsg = job->errorString(); + } + if ( job->isA("KIO::StatJob") ) + m_entry = static_cast(job)->statResult(); + qApp->exit_loop(); +} + +void QExtFileInfo::slotNewEntries(KIO::Job *job, const KIO::UDSEntryList& udsList) +{ + KURL url = static_cast(job)->url(); + url.adjustPath(-1); + // avoid creating these QStrings again and again + static const QString& dot = KGlobal::staticQString("."); + static const QString& dotdot = KGlobal::staticQString(".."); + + KIO::UDSEntryListConstIterator it = udsList.begin(); + KIO::UDSEntryListConstIterator end = udsList.end(); + KURL itemURL; + for ( ; it != end; ++it ) + { + QString name; + + // find out about the name + KIO::UDSEntry::ConstIterator entit = (*it).begin(); + for( ; entit != (*it).end(); ++entit ) + if ( (*entit).m_uds == KIO::UDS_NAME ) + { + name = (*entit).m_str; + break; + } + + if ( ! name.isEmpty() && name != dot && name != dotdot) + { + KFileItem* item = new KFileItem( *it, url, false, true ); + itemURL = item->url(); + if (item->isDir()) itemURL.adjustPath(1); + for ( QPtrListIterator filterIt( lstFilters ); filterIt.current(); ++filterIt ) + if ( filterIt.current()->exactMatch( item->text() ) ) + dirListItems.append(itemURL); + delete item; + } + } +} + +/** Timeout occured while waiting for some network function to return. */ +void QExtFileInfo::slotTimeout() +{ + bJobOK = false; + qApp->exit_loop(); +} +#include "qextfileinfo.moc" diff --git a/kimagemapeditor/qextfileinfo.h b/kimagemapeditor/qextfileinfo.h new file mode 100644 index 00000000..20294bde --- /dev/null +++ b/kimagemapeditor/qextfileinfo.h @@ -0,0 +1,75 @@ +/* + From WebMaker - KDE HTML Editor + Copyright (C) 1998, 1999 Alexei Dets + Rewritten for Quanta Plus: (C) 2002 Andras Mantia + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#ifndef _QEXTFILEINFO_H_ +#define _QEXTFILEINFO_H_ + +#include +#include +#include +#include + +#include +#include +#include + +class QExtFileInfo:public QObject +{ + Q_OBJECT +public: + QExtFileInfo() {}; + ~QExtFileInfo() {}; + + /** create to ralative short name */ + static KURL toRelative(const KURL& urlToConvert,const KURL& baseURL); + /** convert relative filename to absolute */ + static KURL toAbsolute(const KURL& urlToConvert,const KURL& baseURL); + /** recurse function for all files in dir */ + static KURL::List allFiles( const KURL& path, const QString &mask); + static KURL::List allFilesRelative( const KURL& path, const QString &mask); + /** create dir if don't exists */ + static bool createDir(const KURL & path ); + static KURL cdUp(const KURL &dir); + static QString shortName(const QString &fname ); + static KURL path(const KURL &); + static KURL home(); + static bool exists(const KURL& url); + static bool copy( const KURL& src, const KURL& dest, int permissions=-1, + bool overwrite=false, bool resume=false, QWidget* window = 0L ); + + void enter_loop(); + +private: + bool internalExists(const KURL& url); + bool internalCopy(const KURL& src, const KURL& target, int permissions, + bool overwrite, bool resume, QWidget* window); + + bool bJobOK; + static QString lastErrorMsg; + KIO::UDSEntry m_entry; + KURL::List dirListItems; + QPtrList lstFilters; + + /** No descriptions */ + KURL::List allFilesInternal(const KURL& startURL, const QString& mask); + +// friend class I_like_this_class; + +private slots: + void slotResult( KIO::Job * job ); + void slotNewEntries(KIO::Job *job, const KIO::UDSEntryList& udsList); +public slots: // Public slots + /** Timeout occured while waiting for some network function to return. */ + void slotTimeout(); +}; + + +#endif diff --git a/klinkstatus/AUTHORS b/klinkstatus/AUTHORS new file mode 100644 index 00000000..9fc838ae --- /dev/null +++ b/klinkstatus/AUTHORS @@ -0,0 +1 @@ +Paulo Moura Guedes diff --git a/klinkstatus/COPYING b/klinkstatus/COPYING new file mode 100644 index 00000000..c13faf0d --- /dev/null +++ b/klinkstatus/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/klinkstatus/ChangeLog b/klinkstatus/ChangeLog new file mode 100644 index 00000000..c278c40e --- /dev/null +++ b/klinkstatus/ChangeLog @@ -0,0 +1,122 @@ +Changes for 0.3.1 +----------------------------------------------------- + +- Add the possibility to configure the User-Agent sent to the HTTP server. +- Fix a problem with redirections different than 301 (moved permanently) +- Don't require unsermake no more, in order to build the application +- Added the possibility to set the document root for protocols different than HTTP + (to resolve URLs started with '/') +- Improved behaviour in the layout of results columns +- Context menu actions in results are more clear now +- Fixed linkage order to build in IRIX +- Added support for links in maps (area element) +- Don't crash when checking anchors (bug #118495) +- Properly disable close tab button +- Other bug fixes and improvements + + +Changes for 0.3.0 +----------------------------------------------------- + +- Results can be exported to HTML (BUG #85592). + Users are invited to improve the XSLT stylesheet and propose it to the author. + +- Improved interface + - ability to show/hide the search options + - option to control whether the list view should follow the last link checked + - option to reset the search options + - standard open/close tab widget tool buttons + - Replace the search buttons by toolbar actions + - ability to close the tabs on hover + - Revamped toolbars and usability in general + +- Search bar where one can filter links by text and status. +- Fix a bug where the title of a URL was being set in the wrong page, if it wasn't the current. +- Other bug fixes and improvements + + +Changes for 0.2.3 +----------------------------------------------------- + +- Display correctly the page title with HTML entities (BUG #113560). +- Find anchors identified with id attribute (BUG #112030). +- Check anchors of all documents even if not searched yet (no more "URL ... not checked yet"). +- Remember port when resolving relative links (BUG 112249). +- Display correctly link labels with HTML entities (BUG #111694). +- Remember layout (order of columns, etc) of the result tree view. +- Show the filename on the root link. +- Add a folder button in the search field so one can easily set the URL to search. +- Fixed the KIO problem in kdelibs that was causing random crashes. +- New KLinkStatus logo from Alberto Gamez. + + +Changes for 0.2.2 +----------------------------------------------------- + +- Compare domains in a case insensitive way (BUG #105415) +- Fix crash when using File -> Quit (BUG #82617) + + +Changes for 0.2.1 +----------------------------------------------------- + +- New feature: don't check URLs given a regular expression. +- Fix current search settings being reseted when check button is pressed. + + +Changes for 0.2.0 +----------------------------------------------------- + +- Added a tree view that reflects the structure of the website. +It is possible to switch choose a tree view or a flat view in settings. +- Other bugfixes and minor improvements. + +Changes for 0.1.3 +----------------------------------------------------- + +- Added some shortcuts and improve their configuration. +- Improved settings update. +- Use Quanta project preview prefix on the URL to check. +- Improved 'Edit referrer with Quanta' action. +- Other bugfixes and minor improvements. + + +Changes for 0.1.2 +----------------------------------------------------- + +- Dialog for configuring settings added. +- Tool button to clear the combo url. +- Pause and resume feature. +- View menu to display good, broken, etc, links. +- Use title page for tab labels. +- Validate URLs with reference (#) +- Edit referrers in Quanta (can open all at a time). + Quanta needs to be run with --unique or embed KLinkStatus (for now...) +- other minor improvements and bug fixes. + + +Changes for 0.1.1 +----------------------------------------------------- + +- KConfigXT (no GUI yet) +- File Dialog opens remote files now. +- Fixed error status when URL is a directory +- Combo url saves history and has autocompletion +- Combo url navigation improved (like Konqueror) +- Improved display of relative URLs +- Show horizontal scroll when URL is too long +- other improvements and bug fixes. + + +Changes for 0.1.0 +----------------------------------------------------- +- compilation fixes +- fixed external links and parent directories judgment +- different defaults for search +- several other fixes and improvements that I can't remember + + +Changes for 0.1-b1 +----------------------------------------------------- + Initial beta release + diff --git a/klinkstatus/FEATURES b/klinkstatus/FEATURES new file mode 100644 index 00000000..33a328e4 --- /dev/null +++ b/klinkstatus/FEATURES @@ -0,0 +1,18 @@ +- Support several protocols (allowing fast checking of local documents): http, ftp, ssh (fish or sftp) and file. +- Proxy support +- Allows authentication when checking restricted documents +- Supports the latest Web standards-- HTML 4.0, HTTP 1.1 +- Server-Side Includes (SSI, aka SHTML) are supported and checked +- Regular expressions to restrict which URLs are searched +- Show link results as they are checked +- Tree like view (that reflects the file structure of the documents) or flat view +- Limit the search depth +- Fragment identifiers ("#" anchor links that point to a specific section in a document) are supported and checked +- Find and respect the charset of the documents +- Pause/Resume of checking session +- History of checked URLs +- Tabbed checking (allow multiple sessions at the same time) +- Filter checked links (good, broken, malformed and undetermined) +- Configurable number of simultaneous connections (performance tunning) +- Other configurable options like "check external links", "check parent folders", "timeout" +- Good integration with Quanta+ \ No newline at end of file diff --git a/klinkstatus/INSTALL b/klinkstatus/INSTALL new file mode 100644 index 00000000..02a4a074 --- /dev/null +++ b/klinkstatus/INSTALL @@ -0,0 +1,167 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes a while. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Type `make install' to install the programs and any data files and + documentation. + + 4. You can remove the program binaries and object files from the + source code directory by typing `make clean'. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. + diff --git a/klinkstatus/Makefile.am b/klinkstatus/Makefile.am new file mode 100644 index 00000000..3da2d71a --- /dev/null +++ b/klinkstatus/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = data src diff --git a/klinkstatus/NEWS b/klinkstatus/NEWS new file mode 100644 index 00000000..0519ecba --- /dev/null +++ b/klinkstatus/NEWS @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/klinkstatus/README b/klinkstatus/README new file mode 100644 index 00000000..eaf5b045 --- /dev/null +++ b/klinkstatus/README @@ -0,0 +1,5 @@ +KLinkStatus is a link checker for KDE, based in LinkStatus. + +You can report bugs at http://linkstatus.paradigma.co.pt/bugs/ + +Contact: pmg@netcabo.pt diff --git a/klinkstatus/TODO b/klinkstatus/TODO new file mode 100644 index 00000000..36f28fb0 --- /dev/null +++ b/klinkstatus/TODO @@ -0,0 +1,24 @@ +Do list: + +- Option to skip already timed-out hosts + +- Ability to do edit actions after a search is finished, + like findind links, etc + +- GUI for search stats + +- GUI for info about a page/URL + +- Send email with broken links + +- Check the size for complete request on homepage + +- Use proper charset for the pages + +- Advanced search features like: + - check only files modified recently + - check only files matching given regular expression + - check only files in given path + +- Write better documentation + diff --git a/klinkstatus/configure.in.in b/klinkstatus/configure.in.in new file mode 100644 index 00000000..3a2e3182 --- /dev/null +++ b/klinkstatus/configure.in.in @@ -0,0 +1,6 @@ +#MIN_CONFIG(3.2) + +AM_INIT_AUTOMAKE(klinkstatus, 0.1.0) +AC_C_BIGENDIAN +AC_CHECK_KDEMAXPATHLEN + diff --git a/klinkstatus/data/Makefile.am b/klinkstatus/data/Makefile.am new file mode 100644 index 00000000..f8219dbf --- /dev/null +++ b/klinkstatus/data/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = icons styles + +klinkstatusicondir = $(kde_datadir)/klinkstatus/icons diff --git a/klinkstatus/data/icons/16x16/304.png b/klinkstatus/data/icons/16x16/304.png new file mode 100644 index 00000000..036bff9b Binary files /dev/null and b/klinkstatus/data/icons/16x16/304.png differ diff --git a/klinkstatus/data/icons/16x16/Makefile.am b/klinkstatus/data/icons/16x16/Makefile.am new file mode 100644 index 00000000..1d19c3a3 --- /dev/null +++ b/klinkstatus/data/icons/16x16/Makefile.am @@ -0,0 +1,4 @@ +klinkstatusicondir = $(kde_datadir)/klinkstatuspart/pics + +klinkstatusicon_DATA = 304.png +KDE_ICON = bug diff --git a/klinkstatus/data/icons/16x16/cr16-action-bug.png b/klinkstatus/data/icons/16x16/cr16-action-bug.png new file mode 100644 index 00000000..827d5f8e Binary files /dev/null and b/klinkstatus/data/icons/16x16/cr16-action-bug.png differ diff --git a/klinkstatus/data/icons/22x22/Makefile.am b/klinkstatus/data/icons/22x22/Makefile.am new file mode 100644 index 00000000..bdcbfad2 --- /dev/null +++ b/klinkstatus/data/icons/22x22/Makefile.am @@ -0,0 +1 @@ +klinkstatusicondir = $(kde_datadir)/klinkstatuspart/pics diff --git a/klinkstatus/data/icons/32x32/Makefile.am b/klinkstatus/data/icons/32x32/Makefile.am new file mode 100644 index 00000000..5d234f12 --- /dev/null +++ b/klinkstatus/data/icons/32x32/Makefile.am @@ -0,0 +1,2 @@ +klinkstatusicondir = $(kde_datadir)/klinkstatuspart/pics + diff --git a/klinkstatus/data/icons/Makefile.am b/klinkstatus/data/icons/Makefile.am new file mode 100644 index 00000000..14f1949a --- /dev/null +++ b/klinkstatus/data/icons/Makefile.am @@ -0,0 +1,2 @@ +SUBDIRS = 32x32 22x22 16x16 +KDE_ICON = klinkstatus diff --git a/klinkstatus/data/icons/hi128-app-klinkstatus.png b/klinkstatus/data/icons/hi128-app-klinkstatus.png new file mode 100644 index 00000000..2aec7026 Binary files /dev/null and b/klinkstatus/data/icons/hi128-app-klinkstatus.png differ diff --git a/klinkstatus/data/icons/hi16-app-klinkstatus.png b/klinkstatus/data/icons/hi16-app-klinkstatus.png new file mode 100644 index 00000000..ea405926 Binary files /dev/null and b/klinkstatus/data/icons/hi16-app-klinkstatus.png differ diff --git a/klinkstatus/data/icons/hi22-app-klinkstatus.png b/klinkstatus/data/icons/hi22-app-klinkstatus.png new file mode 100644 index 00000000..6d359296 Binary files /dev/null and b/klinkstatus/data/icons/hi22-app-klinkstatus.png differ diff --git a/klinkstatus/data/icons/hi32-app-klinkstatus.png b/klinkstatus/data/icons/hi32-app-klinkstatus.png new file mode 100644 index 00000000..fc4b9eff Binary files /dev/null and b/klinkstatus/data/icons/hi32-app-klinkstatus.png differ diff --git a/klinkstatus/data/icons/hi48-app-klinkstatus.png b/klinkstatus/data/icons/hi48-app-klinkstatus.png new file mode 100644 index 00000000..68e67f4a Binary files /dev/null and b/klinkstatus/data/icons/hi48-app-klinkstatus.png differ diff --git a/klinkstatus/data/icons/hi64-app-klinkstatus.png b/klinkstatus/data/icons/hi64-app-klinkstatus.png new file mode 100644 index 00000000..47b4668f Binary files /dev/null and b/klinkstatus/data/icons/hi64-app-klinkstatus.png differ diff --git a/klinkstatus/data/styles/Makefile.am b/klinkstatus/data/styles/Makefile.am new file mode 100644 index 00000000..7f17fbd9 --- /dev/null +++ b/klinkstatus/data/styles/Makefile.am @@ -0,0 +1,6 @@ +styles_DATA = \ + results_stylesheet.xsl + +stylesdir = $(kde_datadir)/klinkstatus/styles +EXTRA_DIST = $(styles_DATA) + diff --git a/klinkstatus/data/styles/results_stylesheet.xsl b/klinkstatus/data/styles/results_stylesheet.xsl new file mode 100644 index 00000000..d0b0c10d --- /dev/null +++ b/klinkstatus/data/styles/results_stylesheet.xsl @@ -0,0 +1,99 @@ + + + + + + + + + + URL: + +
+ Depth: + +
+ Check Parent Folders: + +
+ Check external links: + +
+ + Do not check links matching regular expression: + +
+
+
+ + + + + + + + + + + + + + + + + + + + +
URLStatusLabelReferrers
+ + + + + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + +
+
+ + + +
+
+ + + + + + + + + + +
+
+ +
diff --git a/klinkstatus/klinkstatus.kdevelop b/klinkstatus/klinkstatus.kdevelop new file mode 100644 index 00000000..5abf4488 --- /dev/null +++ b/klinkstatus/klinkstatus.kdevelop @@ -0,0 +1,267 @@ + + + + Paulo Moura Guedes + moura@kdewebdev.org + 0.2.2 + KDevKDEAutoProject + C++ + + C++ + Code + Qt + KDE + + . + false + + + + + + + + src/klinkstatus + default + + + klinkstatus/src/klinkstatus + build + / + + false + true + + + + + optimized + kdevgccoptions + kdevgppoptions + kdevg77options + -O2 -g0 + + + --enable-debug=full + debug + kdevgccoptions + kdevgppoptions + kdevg77options + -DKDE_NO_COMPAT -DQT_NO_COMPAT -DQT_FATAL_ASSERT + .. + + + + + + + + + + + + + + + + --enable-debug=full + + .. + + + kdevgccoptions + kdevgppoptions + kdevg77options + + + + + -DQT_FATAL_ASSERT + + + + + + + + + false + 1 + false + + 0 + false + + + + + + + + + + false + false + + + *.o,*.lo,CVS + true + false + + + + + ada + ada_bugs_gcc + bash + bash_bugs + clanlib + w3c-dom-level2-html + fortran_bugs_gcc + gnome1 + gnustep + gtk + gtk_bugs + haskell + haskell_bugs_ghc + java_bugs_gcc + java_bugs_sun + pascal_bugs_fp + php + php_bugs + perl + perl_bugs + python + python_bugs + ruby + ruby_bugs + sdl + w3c-svg + sw + w3c-uaag10 + wxwidgets_bugs + + + qmake User Guide + + + html/ + html/ + + + + + + + + libtool + + + + + + true + false + false + + + false + true + 10 + + + + + + + + + + + + + .h + .cpp + + + + + true + true + true + true + false + false + true + 250 + 400 + 250 + + + Qt + KDElibs + + + true + 3 + /usr/lib/qt-3.3 + + + + set + m_,_ + theValue + true + true + + + + false + false + %n-%v + + 0.1.0 + + + + + + + + + false + false + false + 0 + false + false + false + false + + + + true + true + true + true + -C + + + -f + + + + -dP + -f + -C -d -P + -u3 -p + + + + + + + + + + diff --git a/klinkstatus/src/Makefile.am b/klinkstatus/src/Makefile.am new file mode 100644 index 00000000..590957a2 --- /dev/null +++ b/klinkstatus/src/Makefile.am @@ -0,0 +1,62 @@ +# set the include path for X, qt and KDE +INCLUDES = -I$(top_srcdir)/src/cfg -I./ui -I./ui/settings $(all_includes) + +# these are the headers for your project + + +# let automoc handle all of the meta source files (moc) +METASOURCES = AUTO + +# this Makefile creates both a KPart application and a KPart +######################################################################### +# APPLICATION SECTION +######################################################################### +# this is the program that gets installed. it's name is used for all +# of the other Makefile.am variables +bin_PROGRAMS = klinkstatus + +# the application source, library search path, and link libraries + +klinkstatus_LDFLAGS = $(KDE_RPATH) $(all_libraries) +klinkstatus_LDADD = $(LIB_KPARTS) + +xdg_apps_DATA = klinkstatus.desktop + +# this is where the shell's XML-GUI resource file goes +shellrcdir = $(kde_datadir)/klinkstatus +shellrc_DATA = klinkstatus_shell.rc + + +######################################################################### +# KPART SECTION +######################################################################### +kde_module_LTLIBRARIES = libklinkstatuspart.la + +# the Part's source, library search path, and link libraries + +libklinkstatuspart_la_LDFLAGS = -module -no-undefined $(KDE_PLUGIN) $(all_libraries) +libklinkstatuspart_la_LIBADD = ui/settings/libsettings.la \ + ui/libui.la engine/libengine.la \ + parser/libparser.la utils/libutils.la $(LIB_KPARTS) $(LIB_KFILE) + +# this is where the desktop file will go +partdesktopdir = $(kde_servicesdir) +partdesktop_DATA = klinkstatus_part.desktop + +# this is where the part's XML-GUI resource file goes +partrcdir = $(kde_datadir)/klinkstatuspart +partrc_DATA = klinkstatus_part.rc +noinst_HEADERS = klinkstatus.h klinkstatus_part.h global.h actionmanager.h +klinkstatus_SOURCES = klinkstatus.cpp main.cpp +libklinkstatuspart_la_SOURCES = klinkstatus_part.cpp global.cpp \ + actionmanager.cpp +SUBDIRS = cfg utils parser engine ui + +messages: rc.cpp + LIST=`find . -name \*.ui -o -name \*.kcfg -o -name \*.rc` ;\ + if test -n "$$LIST"; then $(EXTRACTRC) $$LIST >> rc.cpp; fi + LIST=`find . -name \*.h -o -name \*.hh -o -name \*.H -o -name \*.hxx -o -name \*.hpp -o -name \*.cpp -o -name \*.cc -o -name \*.cxx -o -name \*.ecpp -o -name \*.C`; \ + if test -n "$$LIST"; then \ + $(XGETTEXT) $$LIST -o $(podir)/klinkstatus.pot; \ + fi + diff --git a/klinkstatus/src/actionmanager.cpp b/klinkstatus/src/actionmanager.cpp new file mode 100644 index 00000000..9f60e7bf --- /dev/null +++ b/klinkstatus/src/actionmanager.cpp @@ -0,0 +1,273 @@ +/*************************************************************************** + * Copyright (C) 2004 by Paulo Moura Guedes * + * moura@kdewebdev.org * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "actionmanager.h" + +#include +#include +#include +#include +#include + +#include + +#include "klinkstatus_part.h" +#include "ui/sessionwidget.h" +#include "ui/tabwidgetsession.h" +#include "cfg/klsconfig.h" + + +ActionManager* ActionManager::m_self = 0; + +ActionManager* ActionManager::getInstance() +{ + Q_ASSERT(m_self); + + return m_self; +} + +void ActionManager::setInstance(ActionManager* manager) +{ + Q_ASSERT(manager); + + m_self = manager; +} + +class ActionManager::ActionManagerPrivate +{ +public: + ActionManagerPrivate() + : part(0), tabWidgetSession(0), sessionWidget(0) + {} + + KActionCollection* actionCollection; + + KLinkStatusPart* part; + TabWidgetSession* tabWidgetSession; + SessionWidget* sessionWidget; +}; + +ActionManager::ActionManager(QObject *parent, const char *name) + : QObject(parent, name), d(new ActionManagerPrivate) +{} + +ActionManager::~ActionManager() +{ + delete d; + d = 0; +} + +void ActionManager::initPart(KLinkStatusPart* part) +{ + Q_ASSERT(part); + + if(d->part) + return; + + d->part = part; + d->actionCollection = part->actionCollection(); + + KAction* action = 0; + + // *************** File menu ********************* + + new KAction(i18n("New Link Check"), "filenew", + 0, + d->part, SLOT(slotNewLinkCheck()), + d->actionCollection, "new_link_check"); + + new KAction(i18n("Open URL..."), "fileopen", + 0, + d->part, SLOT(slotOpenLink()), + d->actionCollection, "open_link"); + + action = new KAction(i18n("Close Tab"), "fileclose", + 0, + d->part, SLOT(slotClose()), + d->actionCollection, "close_tab"); + action->setEnabled(false); + + // *************** Settings menu ********************* + + (void) new KAction(i18n("Configure KLinkStatus..."), "configure", + 0, d->part, SLOT(slotConfigureKLinkStatus()), + d->actionCollection, "configure_klinkstatus"); + + // *************** Help menu ********************* + + (void) new KAction(i18n("About KLinkStatus"), "klinkstatus", + 0, d->part, SLOT(slotAbout()), + d->actionCollection, "about_klinkstatus"); + + (void) new KAction(i18n("&Report Bug..."), 0, 0, d->part, + SLOT(slotReportBug()), d->actionCollection, "report_bug"); + + // *************** View menu ********************* +} + +void ActionManager::initTabWidget(TabWidgetSession* tabWidgetSession) +{ + Q_ASSERT(tabWidgetSession); + + if (d->tabWidgetSession) + return; + + d->tabWidgetSession = tabWidgetSession; + + // *************** File menu ********************* + + KAction* action = new KAction(i18n("E&xport Results as HTML..."), "filesave", 0, + d->tabWidgetSession, SLOT(slotExportAsHTML()), + d->actionCollection, "file_export_html"); + action->setEnabled(false); + + // *************** View menu ********************* + + // this action must be in the tabwidget because the slot can't be connected to a particular sessionWidget + KToggleAction* toggle_action = new KToggleAction(i18n("&Follow last Link checked"), + "make_kdevelop", "Ctrl+f", + d->tabWidgetSession, SLOT(slotFollowLastLinkChecked()), + d->actionCollection, "follow_last_link_checked"); + toggle_action->setChecked(KLSConfig::followLastLinkChecked()); + + // this action must be in the tabwidget because the slot can't be connected to a particular sessionWidget + toggle_action = new KToggleAction(i18n("&Hide Search Panel"), "bottom", "Ctrl+h", + d->tabWidgetSession, SLOT(slotHideSearchPanel()), + d->actionCollection, "hide_search_bar"); + KGuiItem item(i18n("&Show Search Panel"), "top", "Show Search Panel"); + toggle_action->setCheckedState(item); + + new KAction(i18n("&Reset Search Options"), "reload", "F5", + d->tabWidgetSession, SLOT(slotResetSearchOptions()), + d->actionCollection, "reset_search_bar"); + + // *************** Search menu ********************* + + toggle_action = new KToggleAction(i18n("&Start Search"), + "player_play", "Ctrl+s", + d->tabWidgetSession, SLOT(slotStartSearch()), + d->actionCollection, "start_search"); + toggle_action->setEnabled(false); + + toggle_action = new KToggleAction(i18n("&Pause Search"), + "player_pause", "Ctrl+p", + d->tabWidgetSession, SLOT(slotPauseSearch()), + d->actionCollection, "pause_search"); + toggle_action->setEnabled(false); + + action = new KAction(i18n("St&op Search"), + "player_stop", "Ctrl+c", + d->tabWidgetSession, SLOT(slotStopSearch()), + d->actionCollection, "stop_search"); + action->setEnabled(false); +} + +void ActionManager::initSessionWidget(SessionWidget* sessionWidget) +{ + Q_ASSERT(sessionWidget); + + if (d->sessionWidget) + return; + + d->sessionWidget = sessionWidget; + +} + +QWidget* ActionManager::container(const char* name) +{ + return d->part->factory()->container(name, d->part); +} + +KActionCollection* ActionManager::actionCollection() +{ + return d->actionCollection; +} + +KAction* ActionManager::action(const char* name, const char* classname) +{ + return d->actionCollection != 0 ? d->actionCollection->action(name, classname) : 0; +} + +void ActionManager::slotUpdateSessionWidgetActions(SessionWidget* page) +{ + KToggleAction* start_search_action_ = static_cast (action("start_search")); + KToggleAction* pause_search_action_ = static_cast (action("pause_search")); + KAction* stop_search_action_ = action("stop_search"); + + if(page->inProgress()) + { + Q_ASSERT(!page->stopped()); + + start_search_action_->setEnabled(true); + start_search_action_->setChecked(true); + + pause_search_action_->setEnabled(true); + + stop_search_action_->setEnabled(true); + } + if(page->paused()) + { + Q_ASSERT(page->inProgress()); + Q_ASSERT(!page->stopped()); + + start_search_action_->setEnabled(true); + start_search_action_->setChecked(true); + + pause_search_action_->setEnabled(true); + pause_search_action_->setChecked(true); + + stop_search_action_->setEnabled(true); + } + if(page->stopped()) + { + Q_ASSERT(!page->inProgress()); + Q_ASSERT(!page->paused()); + + start_search_action_->setEnabled(true); + start_search_action_->setChecked(false); + + pause_search_action_->setEnabled(false); + pause_search_action_->setChecked(false); + + stop_search_action_->setEnabled(false); + } + +// ____________________________________________________________________ + + KToggleAction* toggleAction = static_cast (action("follow_last_link_checked")); + + if(!toggleAction) // the first sessionWidget is created before initSessionWidget is called + { + initSessionWidget(page); + toggleAction = static_cast (action("follow_last_link_checked")); + } + Q_ASSERT(toggleAction); + toggleAction->setChecked(page->followLastLinkChecked()); + + toggleAction = static_cast (action("hide_search_bar")); + Q_ASSERT(toggleAction); + toggleAction->setChecked(page->buttongroup_search->isHidden()); + + // ____________________________________________________________________ + + action("file_export_html")->setEnabled(!page->isEmpty()); +} + + +#include "actionmanager.moc" diff --git a/klinkstatus/src/actionmanager.h b/klinkstatus/src/actionmanager.h new file mode 100644 index 00000000..a33c37f4 --- /dev/null +++ b/klinkstatus/src/actionmanager.h @@ -0,0 +1,69 @@ +/*************************************************************************** + * Copyright (C) 2004 by Paulo Moura Guedes * + * moura@kdewebdev.org * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef ACTIONMANAGER_H +#define ACTIONMANAGER_H + +#include + +class KAction; +class KActionCollection; + +class SessionWidget; +class KLinkStatusPart; +class TabWidgetSession; + +/** + @author Paulo Moura Guedes + + interface for accessing actions, popup menus etc. from widgets. +*/ +class ActionManager : public QObject +{ + Q_OBJECT +public: + ActionManager(QObject* parent=0, const char* name=0); + virtual ~ActionManager(); + + static ActionManager* getInstance(); + static void setInstance(ActionManager* manager); + + virtual KAction* action(const char* name, const char* classname=0); + virtual QWidget* container(const char* name); + + void initPart(KLinkStatusPart* part); + void initSessionWidget(SessionWidget* sessionWidget); + void initTabWidget(TabWidgetSession* tabWidgetSession); + +public slots: + void slotUpdateSessionWidgetActions(SessionWidget*); + +protected: + + KActionCollection* actionCollection(); + +private: + + static ActionManager* m_self; + + class ActionManagerPrivate; + ActionManagerPrivate* d; +}; + +#endif diff --git a/klinkstatus/src/cfg/Makefile.am b/klinkstatus/src/cfg/Makefile.am new file mode 100644 index 00000000..2e74b2ad --- /dev/null +++ b/klinkstatus/src/cfg/Makefile.am @@ -0,0 +1,6 @@ +kde_kcfg_DATA = klinkstatus.kcfg +METASOURCES = AUTO +libcfg_la_LDFLAGS = $(all_libraries) +noinst_LTLIBRARIES = libcfg.la +libcfg_la_SOURCES = dummy.cpp klsconfig.kcfgc +AM_CPPFLAGS=$(all_includes) \ No newline at end of file diff --git a/klinkstatus/src/cfg/dummy.cpp b/klinkstatus/src/cfg/dummy.cpp new file mode 100644 index 00000000..e69de29b diff --git a/klinkstatus/src/cfg/klinkstatus.kcfg b/klinkstatus/src/cfg/klinkstatus.kcfg new file mode 100644 index 00000000..ae43c6b1 --- /dev/null +++ b/klinkstatus/src/cfg/klinkstatus.kcfg @@ -0,0 +1,91 @@ + + + + + + + + + 50 + + + + + 5 + + + + + 35 + + + + + + + + + true + + + + + 0 + + + + + true + + + + + true + + + + + false + + + + + true + + + + + true + + + + + false + + + + + false + + + + + true + + + + + false + + + + + true + + + + + + + + diff --git a/klinkstatus/src/cfg/klsconfig.kcfgc b/klinkstatus/src/cfg/klsconfig.kcfgc new file mode 100644 index 00000000..089abab7 --- /dev/null +++ b/klinkstatus/src/cfg/klsconfig.kcfgc @@ -0,0 +1,7 @@ +# Code generation options for kconfig_compiler +File=klinkstatus.kcfg +#IncludeFiles=defines.h +ClassName=KLSConfig +Singleton=true +#CustomAdditions=true +Mutators=true diff --git a/klinkstatus/src/engine/Makefile.am b/klinkstatus/src/engine/Makefile.am new file mode 100644 index 00000000..1bd3ba88 --- /dev/null +++ b/klinkstatus/src/engine/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I$(top_srcdir)/src/ui $(all_includes) +METASOURCES = AUTO +noinst_HEADERS = linkchecker.h linkstatus.h linkstatus_impl.h searchmanager.h \ + searchmanager_impl.h linkfilter.h +libengine_la_LDFLAGS = $(all_libraries) +noinst_LTLIBRARIES = libengine.la +libengine_la_SOURCES = linkchecker.cpp linkstatus.cpp searchmanager.cpp \ + linkfilter.cpp +libengine_la_LIBADD = $(LIB_KHTML) diff --git a/klinkstatus/src/engine/linkchecker.cpp b/klinkstatus/src/engine/linkchecker.cpp new file mode 100644 index 00000000..bcc503ad --- /dev/null +++ b/klinkstatus/src/engine/linkchecker.cpp @@ -0,0 +1,703 @@ +/*************************************************************************** + * Copyright (C) 2004 by Puto Moura * + * mojo@localhost.localdomain * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "linkchecker.h" +#include "searchmanager.h" +#include "../utils/utils.h" +#include "../parser/htmlparser.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +int LinkChecker::count_ = 0; + +LinkChecker::LinkChecker(LinkStatus* linkstatus, int time_out, + QObject *parent, const char *name) + : QObject(parent, name), search_manager_(0), + linkstatus_(linkstatus), t_job_(0), time_out_(time_out), checker_(0), document_charset_(), + redirection_(false), header_checked_(false), finnished_(false), + parsing_(false), is_charset_checked_(false), has_defined_charset_(false) +{ + Q_ASSERT(linkstatus_); + Q_ASSERT(!linkstatus_->checked()); + + kdDebug(23100) << endl << ++count_ << ": " << "Checking " << linkstatus_->absoluteUrl().url() << endl; +} + +LinkChecker::~LinkChecker() +{} + +void LinkChecker::setSearchManager(SearchManager* search_manager) +{ + Q_ASSERT(search_manager); + search_manager_ = search_manager; +} + +void LinkChecker::check() +{ + Q_ASSERT(!finnished_); + + KURL url(linkStatus()->absoluteUrl()); + Q_ASSERT(url.isValid()); + + if(url.hasRef()) { + KMimeType::Ptr mimeType = KMimeType::findByURL(url); + if(mimeType->is("text/html") || mimeType->is("application/xml")) { + checkRef(); + return; + } + } + + t_job_ = KIO::get(url, false, false); + + t_job_->addMetaData("PropagateHttpHeader", "true"); // to have the http header + + if (linkstatus_->parent()) { + t_job_->addMetaData("referrer", linkstatus_->parent()->absoluteUrl().prettyURL()); + } + + if(search_manager_->sendIdentification()) + { + t_job_->addMetaData("SendUserAgent", "true"); + t_job_->addMetaData("UserAgent", search_manager_->userAgent()); + } + else + t_job_->addMetaData("SendUserAgent", "false"); + + + QObject::connect(t_job_, SIGNAL(data(KIO::Job *, const QByteArray &)), + this, SLOT(slotData(KIO::Job *, const QByteArray &))); + QObject::connect(t_job_, SIGNAL(mimetype(KIO::Job *, const QString &)), + this, SLOT(slotMimetype(KIO::Job *, const QString &))); + QObject::connect(t_job_, SIGNAL(result(KIO::Job *)), + this, SLOT(slotResult(KIO::Job *))); + QObject::connect(t_job_, SIGNAL(redirection(KIO::Job *, const KURL &)), + this, SLOT(slotRedirection(KIO::Job *, const KURL &))); + + QTimer::singleShot( time_out_ * 1000, this, SLOT(slotTimeOut()) ); + + t_job_->setInteractive(false); +} + +void LinkChecker::slotTimeOut() +{ + if(!finnished_ && !parsing_) + { + kdDebug(23100) << "timeout: " << linkstatus_->absoluteUrl().url() << endl; + if(t_job_ && t_job_->slave()) + kdDebug(23100) << " - " << t_job_->slave() << "/" << t_job_->slave()->slave_pid() << endl; + else + kdDebug(23100) << endl; + + +// Q_ASSERT(t_job_); // can happen: e.g. bad result signal + if(t_job_->error() != KIO::ERR_USER_CANCELED) + { + linkstatus_->setErrorOccurred(true); + linkstatus_->setChecked(true); + linkstatus_->setError(i18n("Timeout")); + linkstatus_->setStatus(LinkStatus::TIMEOUT); + + killJob(); + finnish(); + } + } +} + +void LinkChecker::slotMimetype (KIO::Job* /*job*/, const QString &type) +{ + if(finnished_) + return; + +// kdDebug(23100) << "LinkChecker::slotMimetype:" << type << "-> " << linkstatus_->absoluteUrl().url() +// << " - " << t_job_->slave() << "/" << t_job_->slave()->slave_pid() << endl; + + Q_ASSERT(t_job_); + + LinkStatus* ls = 0; +/* if(redirection_) + ls = linkStatus()->redirection(); + else*/ + ls = linkstatus_; + Q_ASSERT(ls); + + ls->setMimeType(type); + KURL url = ls->absoluteUrl(); + + // we doesn't do nothing if file is http or https because we need the header + // which is only available in the data response + if(!t_job_->error()) // if a error happened let result() handle that + { + if(ls->onlyCheckHeader()) + { + //kdDebug(23100) << "only check header: " << ls->absoluteUrl().prettyURL() << endl; + + // file is OK (http can have an error page though job->error() is false) + if(!url.protocol().startsWith("http")) + { + ls->setStatusText("OK"); + ls->setStatus(LinkStatus::SUCCESSFULL); + + killJob(); + finnish(); + } + } + else // !ls->onlyCheckHeader() + { + //kdDebug(23100) << "NOT only check header: " << ls->absoluteUrl().prettyURL() << endl; + + // file is OK (http can have an error page though job->error() is false) + if(!url.protocol().startsWith("http")) // if not, it have to go trough slotData to get the http header + { + // it's not an html page, so we don't want the file content + if(type != "text/html"/* && type != "text/plain"*/) + { + //kdDebug(23100) << "mimetype: " << type << endl; + ls->setStatusText("OK"); + ls->setStatus(LinkStatus::SUCCESSFULL); + + killJob(); + finnish(); + } + } + } + } +} + +void LinkChecker::slotData(KIO::Job* /*job*/, const QByteArray& data) +{ + if(finnished_) + return; + + kdDebug(23100) << "LinkChecker::slotData -> " << linkstatus_->absoluteUrl().url() + << " - " << t_job_->slave() << "/" << t_job_->slave()->slave_pid() << endl; + + Q_ASSERT(t_job_); + + LinkStatus* ls = 0; +/* if(redirection_) + ls = linkStatus()->redirection(); + else*/ + ls = linkstatus_; + Q_ASSERT(ls); + + KURL url = ls->absoluteUrl(); + + if(!t_job_->error()) + { + if(ls->onlyCheckHeader()) + { + Q_ASSERT(header_checked_ == false); + // the job should have been killed in slotMimetype + Q_ASSERT(url.protocol() == "http" || url.protocol() == "https"); + + // get the header and quit + if(url.protocol().startsWith("http")) + { + // get the header + ls->setHttpHeader(getHttpHeader(t_job_)); + + if(t_job_->isErrorPage()) + ls->setIsErrorPage(true); + + if(header_checked_) + { + killJob(); + linkstatus_->setStatus(getHttpStatus()); + linkstatus_->setChecked(true); + finnish(); + return; + } + } + } + else + { + if(url.protocol().startsWith("http")) + { + if(!header_checked_) + { + ls->setHttpHeader(getHttpHeader(t_job_)); + } + if(ls->mimeType() != "text/html" && header_checked_) + { + //kdDebug(23100) << "mimetype of " << ls->absoluteUrl().prettyURL() << ": " << ls->mimeType() << endl; + ls->setStatus(getHttpStatus()); + killJob(); + finnish(); // if finnish is called before kill what you get is a segfault, don't know why + return; + } + else if(t_job_->isErrorPage() && header_checked_) + { + //kdDebug(23100) << "ERROR PAGE" << endl; + ls->setIsErrorPage(true); + ls->setStatus(getHttpStatus()); + killJob(); + finnish(); + return; + } + } + else + { + Q_ASSERT(ls->mimeType() == "text/html"); + } + if(!is_charset_checked_) + findDocumentCharset(data); + + QTextCodec* codec = 0; + if(has_defined_charset_) + codec = QTextCodec::codecForName(document_charset_); + if(!codec) + codec = QTextCodec::codecForName("iso8859-1"); // default + + doc_html_ += codec->toUnicode(data); + } + } +} + +void LinkChecker::findDocumentCharset(QString const& doc) +{ + Q_ASSERT(!is_charset_checked_); + + is_charset_checked_ = true; // only check the first stream of data + + if(header_checked_) + document_charset_ = linkstatus_->httpHeader().charset(); + + // try to look in the meta elements + if(document_charset_.isNull() || document_charset_.isEmpty()) + document_charset_ = HtmlParser::findCharsetInMetaElement(doc); + + if(!document_charset_.isNull() && !document_charset_.isEmpty()) + has_defined_charset_ = true; +} + +// only comes here if an error happened or in case of a clean html page +// if onlyCheckHeader is false +void LinkChecker::slotResult(KIO::Job* /*job*/) +{ + if(finnished_) + return; + + kdDebug(23100) << "LinkChecker::slotResult -> " << linkstatus_->absoluteUrl().url() << endl; + + Q_ASSERT(t_job_); + if(!t_job_) + return; + + if(redirection_) { + if(!processRedirection(redirection_url_)) { + t_job_ = 0; + linkstatus_->setChecked(true); + finnish(); + return; + } + } + + KIO::TransferJob* job = t_job_; + t_job_ = 0; + + emit jobFinnished(this); + + if(job->error() == KIO::ERR_USER_CANCELED) + { + // FIXME This can happen! If the job is non interactive... + kdWarning(23100) << endl << "Job killed quietly, yet signal result was emited..." << endl; + kdDebug(23100) << linkstatus_->toString() << endl; + finnish(); + return; + } + + LinkStatus* ls = 0; + if(redirection_) + ls = linkStatus()->redirection(); + else + ls = linkstatus_; + Q_ASSERT(ls); + + if(!(!ls->onlyCheckHeader() || + job->error() || + !header_checked_)) + kdWarning(23100) << ls->toString() << endl; + + Q_ASSERT(!ls->onlyCheckHeader() || job->error() || !header_checked_); + + if(ls->isErrorPage()) + kdWarning(23100) << "\n\n" << ls->toString() << endl << endl; + + Q_ASSERT(!job->isErrorPage()); + + if(job->error()) + { + kdDebug(23100) << "Job error: " << job->errorString() << endl; + kdDebug(23100) << "Job error code: " << job->error() << endl; + + if(job->error() == KIO::ERR_IS_DIRECTORY) + { + ls->setStatusText("OK"); + ls->setStatus(LinkStatus::SUCCESSFULL); + } + else + { + ls->setErrorOccurred(true); + if(job->error() == KIO::ERR_SERVER_TIMEOUT) + ls->setStatus(LinkStatus::TIMEOUT); + else + ls->setStatus(LinkStatus::BROKEN); + + if(job->errorString().isEmpty()) + kdWarning(23100) << "\n\nError string is empty, error = " << job->error() << "\n\n\n"; + if(job->error() != KIO::ERR_NO_CONTENT) + ls->setError(job->errorString()); + else + ls->setError(i18n("No Content")); + } + } + + else + { + if(!ls->absoluteUrl().protocol().startsWith("http")) { + ls->setStatusText("OK"); + ls->setStatus(LinkStatus::SUCCESSFULL); + } + else + { + if(!header_checked_) + { + kdDebug(23100) << "\n\nheader not received... checking again...\n\n\n"; + //check again + check(); + return; + } + Q_ASSERT(header_checked_); + + ls->setStatus(getHttpStatus()); + } + + if(!doc_html_.isNull() && !doc_html_.isEmpty()) + { + ls->setDocHtml(doc_html_); + + parsing_ = true; + HtmlParser parser(doc_html_); + + if(parser.hasBaseUrl()) + ls->setBaseURI(KURL(parser.baseUrl().url())); + if(parser.hasTitle()) + ls->setHtmlDocTitle(parser.title().attributeTITLE()); + + ls->setChildrenNodes(parser.nodes()); + parsing_ = false; + } + } + finnish(); +} + + +void LinkChecker::slotRedirection (KIO::Job* /*job*/, const KURL &url) +{ + kdDebug(23100) << "LinkChecker::slotRedirection -> " << + linkstatus_->absoluteUrl().url() << " -> " << url.url() << endl; +// << " - " << t_job_->slave() << "/" << t_job_->slave()->slave_pid() << endl; + + redirection_ = true; + redirection_url_ = url; +} + +bool LinkChecker::processRedirection(KURL const& toUrl) +{ + if(finnished_) + return true; + + kdDebug(23100) << "LinkChecker::processRedirection -> " << linkstatus_->absoluteUrl().url() << " -> " << toUrl.url() << endl; + + Q_ASSERT(t_job_); + Q_ASSERT(linkstatus_->absoluteUrl().protocol().startsWith("http")); + Q_ASSERT(redirection_); + + linkstatus_->setHttpHeader(getHttpHeader(t_job_, false)); + linkstatus_->setIsRedirection(true); + linkstatus_->setStatusText("redirection"); + linkstatus_->setStatus(LinkStatus::HTTP_REDIRECTION); + linkstatus_->setChecked(true); + + LinkStatus* ls_red = new LinkStatus(*linkstatus_); + ls_red->setAbsoluteUrl(toUrl); + ls_red->setRootUrl(linkstatus_->rootUrl()); + + if(!linkstatus_->onlyCheckHeader()) + ls_red->setOnlyCheckHeader(false); + + linkstatus_->setRedirection(ls_red); + ls_red->setParent(linkstatus_); + ls_red->setOriginalUrl(toUrl.url()); + + Q_ASSERT(search_manager_); + + if(search_manager_->localDomain(ls_red->absoluteUrl())) + ls_red->setExternalDomainDepth(-1); + else + { + if(search_manager_->localDomain(linkstatus_->absoluteUrl())) + ls_red->setExternalDomainDepth(linkstatus_->externalDomainDepth() + 1); + else + ls_red->setExternalDomainDepth(linkstatus_->externalDomainDepth()); + } + + if(!toUrl.isValid() || search_manager_->existUrl(toUrl, linkstatus_->absoluteUrl())) + { + ls_red->setChecked(false); + return false; + } + else + { + ls_red->setChecked(true); + return true; + } +} + +void LinkChecker::finnish() +{ + Q_ASSERT(!t_job_); + + if(!finnished_) + { + kdDebug(23100) << "LinkChecker::finnish -> " << linkstatus_->absoluteUrl().url() << endl; + + finnished_ = true; + + if(redirection_) + Q_ASSERT(linkstatus_->checked()); + else + linkstatus_->setChecked(true); + + emit transactionFinished(linkstatus_, this); + } +} + +HttpResponseHeader LinkChecker::getHttpHeader(KIO::Job* /*job*/, bool remember_check) +{ + //kdDebug(23100) << "LinkChecker::getHttpHeader -> " << linkstatus_->absoluteUrl().url() << endl; + + Q_ASSERT(!finnished_); + Q_ASSERT(t_job_); + + QString header_string = t_job_->queryMetaData("HTTP-Headers"); + // Q_ASSERT(!header_string.isNull() && !header_string.isEmpty()); +// kdDebug(23100) << "HTTP header: " << endl << header_string << endl; +// kdDebug(23100) << "Keys: " << HttpResponseHeader(header_string).keys() << endl; +// kdDebug(23100) << "Content-type: " << HttpResponseHeader(header_string).contentType() << endl; +// kdDebug(23100) << "Content-type: " << HttpResponseHeader(header_string).value("content-type") << endl; + + if(header_string.isNull() || header_string.isEmpty()) + { + header_checked_ = false; + kdWarning(23100) << "header_string.isNull() || header_string.isEmpty(): " + << linkstatus_->toString() << endl; + } + else if(remember_check) + header_checked_ = true; + + return HttpResponseHeader(header_string); +} + +void LinkChecker::checkRef() +{ + KURL url(linkStatus()->absoluteUrl()); + Q_ASSERT(url.hasRef()); + + QString ref = url.ref(); + if(ref == "" || ref == "top") { + linkstatus_->setStatusText("OK"); + linkstatus_->setStatus(LinkStatus::SUCCESSFULL); + finnish(); + return; + } + + QString url_base; + LinkStatus const* ls_parent = 0; + int i_ref = -1; + + if(linkStatus()->originalUrl().startsWith("#")) + ls_parent = linkStatus()->parent(); + + else + { + i_ref = url.url().find("#"); + url_base = url.url().left(i_ref); + //kdDebug(23100) << "url_base: " << url_base << endl; + + Q_ASSERT(search_manager_); + + ls_parent = search_manager_->linkStatus(url_base); + } + + if(ls_parent) + checkRef(ls_parent); + else + { + url = KURL::fromPathOrURL(url.url().left(i_ref)); + checkRef(url); + } +} + +void LinkChecker::checkRef(KURL const& url) +{ + Q_ASSERT(search_manager_); + + QString url_string = url.url(); + KHTMLPart* html_part = search_manager_->htmlPart(url_string); + if(!html_part) + { + kdDebug() << "new KHTMLPart: " + url_string << endl; + + html_part = new KHTMLPart(); + html_part->setOnlyLocalReferences(true); + + QString tmpFile; + if(KIO::NetAccess::download(url, tmpFile, 0)) + { + QString doc_html = FileManager::read(tmpFile); + html_part->begin(); + html_part->write(doc_html); + html_part->end(); + + KIO::NetAccess::removeTempFile(tmpFile); + } + else + { + kdDebug(23100) << KIO::NetAccess::lastErrorString() << endl; + } + + search_manager_->addHtmlPart(url_string, html_part); + } + + if(hasAnchor(html_part, linkStatus()->absoluteUrl().ref())) + { + linkstatus_->setStatusText("OK"); + linkstatus_->setStatus(LinkStatus::SUCCESSFULL); + } + else + { + linkstatus_->setErrorOccurred(true); + linkstatus_->setError(i18n( "Link destination not found." )); + linkstatus_->setStatus(LinkStatus::BROKEN); + } + + finnish(); +} + +void LinkChecker::checkRef(LinkStatus const* linkstatus_parent) +{ + Q_ASSERT(search_manager_); + + QString url_string = linkstatus_parent->absoluteUrl().url(); + KHTMLPart* html_part = search_manager_->htmlPart(url_string); + if(!html_part) + { + kdDebug() << "new KHTMLPart: " + url_string << endl; + + html_part = new KHTMLPart(); + html_part->setOnlyLocalReferences(true); + + html_part->begin(); + html_part->write(linkstatus_parent->docHtml()); + html_part->end(); + + search_manager_->addHtmlPart(url_string, html_part); + } + + if(hasAnchor(html_part, linkStatus()->absoluteUrl().ref())) + { + linkstatus_->setStatusText("OK"); + linkstatus_->setStatus(LinkStatus::SUCCESSFULL); + } + else + { + linkstatus_->setErrorOccurred(true); + linkstatus_->setError(i18n( "Link destination not found." )); + linkstatus_->setStatus(LinkStatus::BROKEN); + } + + finnish(); +} + +bool LinkChecker::hasAnchor(KHTMLPart* html_part, QString const& anchor) +{ + DOM::HTMLDocument htmlDocument = html_part->htmlDocument(); + DOM::HTMLCollection anchors = htmlDocument.anchors(); + + DOM::DOMString name_ref(anchor); + Q_ASSERT(!name_ref.isNull()); + + DOM::Node node = anchors.namedItem(name_ref); + if(node.isNull()) + { + node = htmlDocument.getElementById(name_ref); + } + + if(!node.isNull()) + return true; + else + return false; +} + +void LinkChecker::killJob() +{ + if(!t_job_) + return; + + KIO::TransferJob* aux = t_job_; + t_job_ = 0; + aux->disconnect(this); + aux->kill(true); // quietly +} + +LinkStatus::Status LinkChecker::getHttpStatus() const +{ + QString status_code = QString::number(linkstatus_->httpHeader().statusCode()); + + if(status_code[0] == '2') + return LinkStatus::SUCCESSFULL; + else if(status_code[0] == '3') + return LinkStatus::HTTP_REDIRECTION; + else if(status_code[0] == '4') + return LinkStatus::HTTP_CLIENT_ERROR; + else if(status_code[0] == '5') + return LinkStatus::HTTP_SERVER_ERROR; + else + return LinkStatus::UNDETERMINED; +} + +#include "linkchecker.moc" diff --git a/klinkstatus/src/engine/linkchecker.h b/klinkstatus/src/engine/linkchecker.h new file mode 100644 index 00000000..a992e5fd --- /dev/null +++ b/klinkstatus/src/engine/linkchecker.h @@ -0,0 +1,128 @@ +/*************************************************************************** + * Copyright (C) 2004 by Paulo Moura Guedes * + * moura@kdewebdev.org * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef LINKCHECKER_H +#define LINKCHECKER_H + +#include +#include +#include + +#include +class KHTMLPart; + +#include "../parser/http.h" +#include "linkstatus.h" +class SearchManager; + +#include +using namespace std; + +/** +@author Paulo Moura Guedes +*/ +class LinkChecker : public QObject +{ + Q_OBJECT +public: + LinkChecker(LinkStatus* linkstatus, int time_out = 50, + QObject *parent = 0, const char *name = 0); + ~LinkChecker(); + + //virtual void run(); + void check(); + void setSearchManager(SearchManager* search_manager); + + LinkStatus const* linkStatus() const; + + static bool hasAnchor(KHTMLPart* html_part, QString const& anchor); + +signals: + + void transactionFinished(const LinkStatus * linkstatus, + LinkChecker * checker); + void jobFinnished(LinkChecker * checker); + +protected slots: + + void slotData(KIO::Job *, const QByteArray &data); + void slotRedirection (KIO::Job *, const KURL &url); + void slotMimetype(KIO::Job *, const QString &type); + void slotResult(KIO::Job* job); + void slotTimeOut(); + +protected: + + void finnish(); + HttpResponseHeader getHttpHeader(KIO::Job* job, bool remember_check = true); + void checkRef(); // #... + +private: + + LinkStatus::Status getHttpStatus() const; + void checkRef(LinkStatus const* linkstatus_parent); + void checkRef(KURL const& url); + void killJob(); + /** + * @param url + * @return false if the redirection was already checked by the search manager + */ + bool processRedirection(KURL const& url); + + void findDocumentCharset(QString const& data); + +private: + + SearchManager* search_manager_; + LinkStatus* const linkstatus_; + KIO::TransferJob* t_job_; + int time_out_; + LinkChecker* checker_; + QString document_charset_; +/* A redirection has appened, with the current URL. Several redirections + can happen until the final URL is reached.*/ + bool redirection_; + KURL redirection_url_; + QString doc_html_; + bool header_checked_; + bool finnished_; + bool parsing_; + + /** + * Whether the charset of the document is already checked. + * (e.g. ) + */ + bool is_charset_checked_; + /** + * Wheter the page define the enconding (latin1, utf8, etc). + * According to the spec (http://www.w3.org/TR/html4/charset.html), + * it first check the server response and then the info in the html meta element. + */ + bool has_defined_charset_; + + static int count_; // debug attribute that counts how many links were checked +}; + +inline LinkStatus const* LinkChecker::linkStatus() const +{ + return linkstatus_; +} + + +#endif diff --git a/klinkstatus/src/engine/linkfilter.cpp b/klinkstatus/src/engine/linkfilter.cpp new file mode 100644 index 00000000..4d15f2e6 --- /dev/null +++ b/klinkstatus/src/engine/linkfilter.cpp @@ -0,0 +1,46 @@ +/*************************************************************************** + * Copyright (C) 2004 by Paulo Moura Guedes * + * moura@kdewebdev.org * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "linkfilter.h" + +#include "linkstatus.h" + + +LinkMatcher::LinkMatcher(QString const& text, ResultView::Status status) + : m_text(text), m_status(status) +{ +} + +LinkMatcher::~LinkMatcher() +{ +} + +bool LinkMatcher::matches(LinkStatus const& link ) const +{ +/* kdDebug() << link.absoluteUrl().url() << endl; + kdDebug() << link.label() << endl; + kdDebug() << link.absoluteUrl().url().contains(m_text) << endl; + kdDebug() << link.label().contains(m_text) << endl; + */ + return (link.absoluteUrl().url().contains(m_text, false) || link.label().contains(m_text, false)) && + ResultView::displayableWithStatus(&link, m_status); +} + + + diff --git a/klinkstatus/src/engine/linkfilter.h b/klinkstatus/src/engine/linkfilter.h new file mode 100644 index 00000000..84da16cb --- /dev/null +++ b/klinkstatus/src/engine/linkfilter.h @@ -0,0 +1,49 @@ +/*************************************************************************** + * Copyright (C) 2004 by Paulo Moura Guedes * + * moura@kdewebdev.org * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef LINKFILTER_H +#define LINKFILTER_H + +#include "../ui/resultview.h" + +/** + @author Paulo Moura Guedes +*/ +class LinkMatcher +{ +public: + LinkMatcher(QString const& text, ResultView::Status status); + ~LinkMatcher(); + + bool matches(LinkStatus const& link) const; + + void setText(const QString& text) { m_text = text; } + QString text() const { return m_text; } + + void setStatus(ResultView::Status status) { m_status = status; } + ResultView::Status status() const { return m_status; } + + bool nullFilter() const { return m_text.isEmpty() && m_status == ResultView::none; } + +private: + QString m_text; + ResultView::Status m_status; +}; + +#endif diff --git a/klinkstatus/src/engine/linkstatus.cpp b/klinkstatus/src/engine/linkstatus.cpp new file mode 100644 index 00000000..c8b359ed --- /dev/null +++ b/klinkstatus/src/engine/linkstatus.cpp @@ -0,0 +1,214 @@ +/*************************************************************************** + * Copyright (C) 2004 by Paulo Moura Guedes * + * moura@kdewebdev.org * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include "linkstatus.h" +#include "../parser/node.h" +#include "../ui/treeview.h" + +#include +#include + +#include + + +LinkStatus::~LinkStatus() +{ + //kdDebug(23100) << "|"; + + for(uint i = 0; i != children_nodes_.size(); ++i) + { + if(children_nodes_[i]) + { + delete children_nodes_[i]; + children_nodes_[i] = 0; + } + } + + children_nodes_.clear(); + + if(isRedirection()) + { + if(redirection_) + { + delete redirection_; + redirection_ = 0; + } + } +} + +void LinkStatus::reset() +{ + depth_ = -1; + external_domain_depth_ = -1; + is_root_ = false; + error_occurred_ = false; + is_redirection_ = false; + checked_ = false; + only_check_header_ = true; + malformed_ = false; + Q_ASSERT(!node_); + has_base_URI_ = false; + label_ = ""; + absolute_url_ = ""; + doc_html_ = ""; + http_header_ = HttpResponseHeader(); + error_ = ""; + + for(uint i = 0; i != children_nodes_.size(); ++i) + { + if(children_nodes_[i]) + { + delete children_nodes_[i]; + children_nodes_[i] = 0; + } + } + + children_nodes_.clear(); + + if(isRedirection()) + { + if(redirection_) + { + delete redirection_; + redirection_ = 0; + } + } + Q_ASSERT(!parent_); + base_URI_ = ""; +} + +QString const LinkStatus::toString() const +{ + QString aux; + + if(!is_root_) + { + Q_ASSERT(parent_); + aux += i18n( "Parent: %1" ).arg( parent()->absoluteUrl().prettyURL() ) + "\n"; + } + Q_ASSERT(!original_url_.isNull()); + + aux += i18n( "URL: %1" ).arg( absoluteUrl().prettyURL() ) + "\n"; + aux += i18n( "Original URL: %1" ).arg( originalUrl() ) + "\n"; + if(node()) + aux += i18n( "Node: %1" ).arg( node()->content() ) + "\n"; + + return aux; +} + + +LinkStatus* LinkStatus::lastRedirection(LinkStatus* ls) +{ + if(ls->isRedirection()) + if(ls->redirection()) + return lastRedirection(ls->redirection()); + else + return ls; + else + return ls; +} + +void LinkStatus::loadNode() +{ + Q_ASSERT(node_); + + setOriginalUrl(node_->url()); + setLabel(node_->linkLabel()); + + if(malformed()) + { + setErrorOccurred(true); + setError(i18n( "Malformed" )); + setStatus(LinkStatus::MALFORMED); + kdDebug(23100) << "Malformed:" << endl; + kdDebug(23100) << "Node: " << node()->content() << endl; + //kdDebug(23100) << toString() << endl; // probable segfault + } +} + +bool LinkStatus::malformed() const // don't inline please (#include "node.h") +{ + return (malformed_ || node_->malformed()); +} + +void LinkStatus::setChildrenNodes(vector const& nodes) // don't inline please (#include "node.h") +{ + children_nodes_.reserve(nodes.size()); + children_nodes_ = nodes; +} + +void LinkStatus::setMalformed(bool flag) +{ + malformed_ = flag; + if(flag) + { + setErrorOccurred(true); + setError(i18n( "Malformed" )); + setStatus(LinkStatus::MALFORMED); + kdDebug(23100) << "Malformed!" << endl; + kdDebug(23100) << node()->content() << endl; + //kdDebug(23100) << toString() << endl; // probable segfault + } + else if(error() == i18n( "Malformed" )) + { + setErrorOccurred(false); + setError(""); + setStatus(LinkStatus::UNDETERMINED); + } +} + +void LinkStatus::save(QDomElement& element) const +{ + QDomElement child_element = element.ownerDocument().createElement("link"); + + // + QDomElement tmp_1 = element.ownerDocument().createElement("url"); + tmp_1.appendChild(element.ownerDocument().createTextNode(absoluteUrl().prettyURL())); + child_element.appendChild(tmp_1); + + // + tmp_1 = element.ownerDocument().createElement("status"); + tmp_1.setAttribute("broken", + ResultView::displayableWithStatus(this, ResultView::bad) ? + "true" : "false"); + tmp_1.appendChild(element.ownerDocument().createTextNode(statusText())); + child_element.appendChild(tmp_1); + + //